diff options
author | David Robillard <d@drobilla.net> | 2020-07-15 16:27:19 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2020-07-16 23:37:49 +0200 |
commit | 133de18003a7fe1d7ab4b88beeeef413d1eb28ac (patch) | |
tree | 4720a92b811032b0905b532d5df44706150ab0b8 | |
parent | 35177a5becb4955ad3c48eaabd83bcc0fa60ef94 (diff) | |
download | lilv-133de18003a7fe1d7ab4b88beeeef413d1eb28ac.tar.gz lilv-133de18003a7fe1d7ab4b88beeeef413d1eb28ac.tar.bz2 lilv-133de18003a7fe1d7ab4b88beeeef413d1eb28ac.zip |
Split test suite up into several independent programs
-rw-r--r-- | test/lilv_test.c | 2137 | ||||
-rw-r--r-- | test/lilv_test_utils.h | 14 | ||||
-rw-r--r-- | test/test_bad_port_index.c | 58 | ||||
-rw-r--r-- | test/test_bad_port_symbol.c | 58 | ||||
-rw-r--r-- | test/test_classes.c | 75 | ||||
-rw-r--r-- | test/test_discovery.c | 96 | ||||
-rw-r--r-- | test/test_get_symbol.c | 81 | ||||
-rw-r--r-- | test/test_no_author.c | 87 | ||||
-rw-r--r-- | test/test_no_verify.c | 48 | ||||
-rw-r--r-- | test/test_plugin.c | 296 | ||||
-rw-r--r-- | test/test_port.c | 331 | ||||
-rw-r--r-- | test/test_preset.c | 93 | ||||
-rw-r--r-- | test/test_project.c | 97 | ||||
-rw-r--r-- | test/test_project_no_author.c | 87 | ||||
-rw-r--r-- | test/test_prototype.c | 100 | ||||
-rw-r--r-- | test/test_reload_bundle.c | 92 | ||||
-rw-r--r-- | test/test_replace_version.c | 105 | ||||
-rw-r--r-- | test/test_state.c | 581 | ||||
-rw-r--r-- | test/test_string.c | 94 | ||||
-rw-r--r-- | test/test_ui.c | 180 | ||||
-rw-r--r-- | test/test_util.c | 63 | ||||
-rw-r--r-- | test/test_value.c | 173 | ||||
-rw-r--r-- | test/test_verify.c | 57 | ||||
-rw-r--r-- | test/test_world.c | 51 | ||||
-rw-r--r-- | wscript | 57 |
25 files changed, 2961 insertions, 2150 deletions
diff --git a/test/lilv_test.c b/test/lilv_test.c deleted file mode 100644 index 92e98be..0000000 --- a/test/lilv_test.c +++ /dev/null @@ -1,2137 +0,0 @@ -/* - Copyright 2007-2019 David Robillard <http://drobilla.net> - Copyright 2008 Krzysztof Foltman - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#define _POSIX_C_SOURCE 200809L /* for setenv */ -#define _XOPEN_SOURCE 600 /* for mkstemp */ - -#undef NDEBUG - -#include "lilv_test_utils.h" - -#include "../src/lilv_internal.h" - -#ifdef _WIN32 -# include <direct.h> -# include <io.h> -# define mkdir(path, flags) _mkdir(path) -# define setenv(n, v, r) SetEnvironmentVariable((n), (v)) -# define unsetenv(n) SetEnvironmentVariable((n), NULL) -# define mkstemp(pat) _mktemp(pat) -#else -# include <unistd.h> -#endif - -#include "lilv/lilv.h" -#include "lv2/core/lv2.h" -#include "lv2/presets/presets.h" -#include "lv2/state/state.h" -#include "lv2/urid/urid.h" -#include "serd/serd.h" - -#include <assert.h> -#include <errno.h> -#include <float.h> -#include <math.h> -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#define TEST_PATH_MAX 1024 - -#if defined(__APPLE__) -# define SHLIB_EXT ".dylib" -#elif defined(_WIN32) -# define SHLIB_EXT ".dll" -#else -# define SHLIB_EXT ".so" -#endif - -#define TEST_CASE(name) { #name, test_##name } - -typedef int (*TestFunc)(LilvTestEnv*); - -struct TestCase { - const char* title; - TestFunc func; -}; - -static int -test_value(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin\" ;" - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"Foo\" ; " - "] .")) { - return 1; - } - - LilvNode* uval = lilv_new_uri(world, "http://example.org"); - LilvNode* sval = lilv_new_string(world, "Foo"); - LilvNode* ival = lilv_new_int(world, 42); - LilvNode* fval = lilv_new_float(world, 1.6180); - - assert(lilv_node_is_uri(uval)); - assert(lilv_node_is_string(sval)); - assert(lilv_node_is_int(ival)); - assert(lilv_node_is_float(fval)); - - assert(!lilv_node_is_literal(NULL)); - assert(!lilv_node_is_literal(uval)); - assert(lilv_node_is_literal(sval)); - assert(lilv_node_is_literal(ival)); - assert(lilv_node_is_literal(fval)); - assert(!lilv_node_get_path(fval, NULL)); - - assert(!strcmp(lilv_node_as_uri(uval), "http://example.org")); - assert(!strcmp(lilv_node_as_string(sval), "Foo")); - assert(lilv_node_as_int(ival) == 42); - assert(fabs(lilv_node_as_float(fval) - 1.6180) < FLT_EPSILON); - assert(isnan(lilv_node_as_float(sval))); - -#if defined(__clang__) -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - - assert(!strcmp(lilv_uri_to_path("file:///foo"), "/foo")); - -#if defined(__clang__) -# pragma clang diagnostic pop -#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) -# pragma GCC diagnostic pop -#endif - - LilvNode* loc_abs = lilv_new_file_uri(world, NULL, "/foo/bar"); - LilvNode* loc_rel = lilv_new_file_uri(world, NULL, "foo"); - LilvNode* host_abs = lilv_new_file_uri(world, "host", "/foo/bar"); - LilvNode* host_rel = lilv_new_file_uri(world, "host", "foo"); - - assert(!strcmp(lilv_node_as_uri(loc_abs), "file:///foo/bar")); - assert(!strncmp(lilv_node_as_uri(loc_rel), "file:///", 8)); - assert(!strcmp(lilv_node_as_uri(host_abs), "file://host/foo/bar")); - assert(!strncmp(lilv_node_as_uri(host_rel), "file://host/", 12)); - - lilv_node_free(host_rel); - lilv_node_free(host_abs); - lilv_node_free(loc_rel); - lilv_node_free(loc_abs); - - char* tok = lilv_node_get_turtle_token(uval); - assert(!strcmp(tok, "<http://example.org>")); - lilv_free(tok); - tok = lilv_node_get_turtle_token(sval); - assert(!strcmp(tok, "Foo")); - lilv_free(tok); - tok = lilv_node_get_turtle_token(ival); - assert(!strcmp(tok, "42")); - lilv_free(tok); - tok = lilv_node_get_turtle_token(fval); - assert(!strncmp(tok, "1.6180", 6)); - lilv_free(tok); - - LilvNode* uval_e = lilv_new_uri(world, "http://example.org"); - LilvNode* sval_e = lilv_new_string(world, "Foo"); - LilvNode* ival_e = lilv_new_int(world, 42); - LilvNode* fval_e = lilv_new_float(world, 1.6180); - LilvNode* uval_ne = lilv_new_uri(world, "http://no-example.org"); - LilvNode* sval_ne = lilv_new_string(world, "Bar"); - LilvNode* ival_ne = lilv_new_int(world, 24); - LilvNode* fval_ne = lilv_new_float(world, 3.14159); - - assert(lilv_node_equals(uval, uval_e)); - assert(lilv_node_equals(sval, sval_e)); - assert(lilv_node_equals(ival, ival_e)); - assert(lilv_node_equals(fval, fval_e)); - - assert(!lilv_node_equals(uval, uval_ne)); - assert(!lilv_node_equals(sval, sval_ne)); - assert(!lilv_node_equals(ival, ival_ne)); - assert(!lilv_node_equals(fval, fval_ne)); - - assert(!lilv_node_equals(uval, sval)); - assert(!lilv_node_equals(sval, ival)); - assert(!lilv_node_equals(ival, fval)); - - LilvNode* uval_dup = lilv_node_duplicate(uval); - assert(lilv_node_equals(uval, uval_dup)); - - LilvNode* ifval = lilv_new_float(world, 42.0); - assert(!lilv_node_equals(ival, ifval)); - lilv_node_free(ifval); - - LilvNode* nil = NULL; - assert(!lilv_node_equals(uval, nil)); - assert(!lilv_node_equals(nil, uval)); - assert(lilv_node_equals(nil, nil)); - - LilvNode* nil2 = lilv_node_duplicate(nil); - assert(lilv_node_equals(nil, nil2)); - - lilv_node_free(uval); - lilv_node_free(sval); - lilv_node_free(ival); - lilv_node_free(fval); - lilv_node_free(uval_e); - lilv_node_free(sval_e); - lilv_node_free(ival_e); - lilv_node_free(fval_e); - lilv_node_free(uval_ne); - lilv_node_free(sval_ne); - lilv_node_free(ival_ne); - lilv_node_free(fval_ne); - lilv_node_free(uval_dup); - lilv_node_free(nil2); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_util(LilvTestEnv* env) -{ - assert(!lilv_realpath(NULL)); - - char a_path[16]; - char b_path[16]; - strncpy(a_path, "copy_a_XXXXXX", sizeof(a_path)); - strncpy(b_path, "copy_b_XXXXXX", sizeof(b_path)); - mkstemp(a_path); - mkstemp(b_path); - - FILE* fa = fopen(a_path, "w"); - FILE* fb = fopen(b_path, "w"); - fprintf(fa, "AA\n"); - fprintf(fb, "AB\n"); - fclose(fa); - fclose(fb); - - assert(lilv_copy_file("does/not/exist", "copy")); - assert(lilv_copy_file(a_path, "not/a/dir/copy")); - assert(!lilv_copy_file(a_path, "copy_c")); - assert(!lilv_file_equals(a_path, b_path)); - assert(lilv_file_equals(a_path, a_path)); - assert(lilv_file_equals(a_path, "copy_c")); - assert(!lilv_file_equals("does/not/exist", b_path)); - assert(!lilv_file_equals(a_path, "does/not/exist")); - assert(!lilv_file_equals("does/not/exist", "/does/not/either")); - return 0; -} - -/*****************************************************************************/ - -static int discovery_plugin_found = 0; - -static void -discovery_verify_plugin(const LilvTestEnv* env, const LilvPlugin* plugin) -{ - const LilvNode* value = lilv_plugin_get_uri(plugin); - if (lilv_node_equals(value, env->plugin1_uri)) { - const LilvNode* lib_uri = NULL; - assert(!lilv_node_equals(value, env->plugin2_uri)); - discovery_plugin_found = 1; - lib_uri = lilv_plugin_get_library_uri(plugin); - assert(lib_uri); - assert(lilv_node_is_uri(lib_uri)); - assert(lilv_node_as_uri(lib_uri)); - assert(strstr(lilv_node_as_uri(lib_uri), "foo" SHLIB_EXT)); - assert(lilv_plugin_verify(plugin)); - } -} - -static int -test_discovery(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ;" - "doap:name \"Test plugin\" ;" - "lv2:port [ a lv2:ControlPort ; a lv2:InputPort ;" - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; ] .")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - assert(lilv_plugins_size(plugins) > 0); - - const LilvPlugin* explug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(explug != NULL); - const LilvPlugin* explug2 = lilv_plugins_get_by_uri(plugins, env->plugin2_uri); - assert(explug2 == NULL); - - if (explug) { - LilvNode* name = lilv_plugin_get_name(explug); - assert(!strcmp(lilv_node_as_string(name), "Test plugin")); - lilv_node_free(name); - } - - discovery_plugin_found = 0; - LILV_FOREACH(plugins, i, plugins) - discovery_verify_plugin(env, lilv_plugins_get(plugins, i)); - - assert(discovery_plugin_found); - plugins = NULL; - - return 0; -} - -/*****************************************************************************/ - -static int -test_verify(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"Test plugin\" ;" - "lv2:port [ a lv2:ControlPort ; a lv2:InputPort ;" - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ] .")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* explug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(explug); - assert(lilv_plugin_verify(explug)); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_no_verify(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin . ")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* explug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(explug); - assert(!lilv_plugin_verify(explug)); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_classes(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin\" ;" - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"Foo\" ; " - "] .")) { - return 1; - } - - const LilvPluginClass* plugin = lilv_world_get_plugin_class(world); - const LilvPluginClasses* classes = lilv_world_get_plugin_classes(world); - LilvPluginClasses* children = lilv_plugin_class_get_children(plugin); - - assert(lilv_plugin_class_get_parent_uri(plugin) == NULL); - assert(lilv_plugin_classes_size(classes) > lilv_plugin_classes_size(children)); - assert(!strcmp(lilv_node_as_string(lilv_plugin_class_get_label(plugin)), "Plugin")); - assert(!strcmp(lilv_node_as_string(lilv_plugin_class_get_uri(plugin)), - "http://lv2plug.in/ns/lv2core#Plugin")); - - LILV_FOREACH(plugin_classes, i, children) { - assert(lilv_node_equals( - lilv_plugin_class_get_parent_uri(lilv_plugin_classes_get(children, i)), - lilv_plugin_class_get_uri(plugin))); - } - - LilvNode* some_uri = lilv_new_uri(world, "http://example.org/whatever"); - assert(lilv_plugin_classes_get_by_uri(classes, some_uri) == NULL); - lilv_node_free(some_uri); - - lilv_plugin_classes_free(children); - - lilv_plugin_class_free(NULL); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_plugin(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin\" ;" - "lv2:optionalFeature lv2:hardRTCapable ; " - "lv2:requiredFeature <http://lv2plug.in/ns/ext/event> ; " - "lv2:extensionData <http://example.org/extdata> ;" - ":foo 1.6180 ; " - ":bar true ; " - ":baz false ; " - ":blank [ a <http://example.org/blank> ] ; " - "doap:maintainer [ foaf:name \"David Robillard\" ; " - " foaf:homepage <http://drobilla.net> ; foaf:mbox <mailto:d@drobilla.net> ] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - ":thing doap:name \"Something else\" .\n")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - const LilvPluginClass* klass = lilv_plugin_get_class(plug); - const LilvNode* klass_uri = lilv_plugin_class_get_uri(klass); - assert(!strcmp(lilv_node_as_string(klass_uri), - "http://lv2plug.in/ns/lv2core#CompressorPlugin")); - - LilvNode* rdf_type = lilv_new_uri( - world, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); - assert(lilv_world_ask(world, - lilv_plugin_get_uri(plug), - rdf_type, - klass_uri)); - lilv_node_free(rdf_type); - - assert(!lilv_plugin_is_replaced(plug)); - assert(!lilv_plugin_get_related(plug, NULL)); - - const LilvNode* plug_bundle_uri = lilv_plugin_get_bundle_uri(plug); - assert(!strcmp(lilv_node_as_string(plug_bundle_uri), env->test_bundle_uri)); - - const LilvNodes* data_uris = lilv_plugin_get_data_uris(plug); - assert(lilv_nodes_size(data_uris) == 2); - - LilvNode* project = lilv_plugin_get_project(plug); - assert(!project); - - char* manifest_uri = (char*)malloc(TEST_PATH_MAX); - char* data_uri = (char*)malloc(TEST_PATH_MAX); - snprintf(manifest_uri, TEST_PATH_MAX, "%s%s", - lilv_node_as_string(plug_bundle_uri), "manifest.ttl"); - snprintf(data_uri, TEST_PATH_MAX, "%s%s", - lilv_node_as_string(plug_bundle_uri), "plugin.ttl"); - - LilvNode* manifest_uri_val = lilv_new_uri(world, manifest_uri); - assert(lilv_nodes_contains(data_uris, manifest_uri_val)); - lilv_node_free(manifest_uri_val); - - LilvNode* data_uri_val = lilv_new_uri(world, data_uri); - assert(lilv_nodes_contains(data_uris, data_uri_val)); - lilv_node_free(data_uri_val); - - LilvNode* unknown_uri_val = lilv_new_uri(world, "http://example.org/unknown"); - assert(!lilv_nodes_contains(data_uris, unknown_uri_val)); - lilv_node_free(unknown_uri_val); - - free(manifest_uri); - free(data_uri); - - float mins[3]; - float maxs[3]; - float defs[3]; - lilv_plugin_get_port_ranges_float(plug, mins, maxs, defs); - assert(mins[0] == -1.0f); - assert(maxs[0] == 1.0f); - assert(defs[0] == 0.5f); - - LilvNode* audio_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#AudioPort"); - LilvNode* control_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#ControlPort"); - LilvNode* in_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#InputPort"); - LilvNode* out_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#OutputPort"); - - assert(lilv_plugin_get_num_ports_of_class(plug, control_class, NULL) == 3); - assert(lilv_plugin_get_num_ports_of_class(plug, audio_class, NULL) == 0); - assert(lilv_plugin_get_num_ports_of_class(plug, in_class, NULL) == 2); - assert(lilv_plugin_get_num_ports_of_class(plug, out_class, NULL) == 1); - assert(lilv_plugin_get_num_ports_of_class(plug, control_class, in_class, NULL) == 2); - assert(lilv_plugin_get_num_ports_of_class(plug, control_class, out_class, NULL) == 1); - assert(lilv_plugin_get_num_ports_of_class(plug, audio_class, in_class, NULL) == 0); - assert(lilv_plugin_get_num_ports_of_class(plug, audio_class, out_class, NULL) == 0); - - assert(lilv_plugin_has_latency(plug)); - assert(lilv_plugin_get_latency_port_index(plug) == 2); - - LilvNode* lv2_latency = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#latency"); - const LilvPort* latency_port = lilv_plugin_get_port_by_designation( - plug, out_class, lv2_latency); - lilv_node_free(lv2_latency); - - assert(latency_port); - assert(lilv_port_get_index(plug, latency_port) == 2); - assert(lilv_node_is_blank(lilv_port_get_node(plug, latency_port))); - - LilvNode* rt_feature = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#hardRTCapable"); - LilvNode* event_feature = lilv_new_uri(world, - "http://lv2plug.in/ns/ext/event"); - LilvNode* pretend_feature = lilv_new_uri(world, - "http://example.org/solvesWorldHunger"); - - assert(lilv_plugin_has_feature(plug, rt_feature)); - assert(lilv_plugin_has_feature(plug, event_feature)); - assert(!lilv_plugin_has_feature(plug, pretend_feature)); - - lilv_node_free(rt_feature); - lilv_node_free(event_feature); - lilv_node_free(pretend_feature); - - LilvNodes* supported = lilv_plugin_get_supported_features(plug); - LilvNodes* required = lilv_plugin_get_required_features(plug); - LilvNodes* optional = lilv_plugin_get_optional_features(plug); - assert(lilv_nodes_size(supported) == 2); - assert(lilv_nodes_size(required) == 1); - assert(lilv_nodes_size(optional) == 1); - lilv_nodes_free(supported); - lilv_nodes_free(required); - lilv_nodes_free(optional); - - LilvNode* foo_p = lilv_new_uri(world, "http://example.org/foo"); - LilvNodes* foos = lilv_plugin_get_value(plug, foo_p); - assert(lilv_nodes_size(foos) == 1); - assert(fabs(lilv_node_as_float(lilv_nodes_get_first(foos)) - 1.6180) < FLT_EPSILON); - lilv_node_free(foo_p); - lilv_nodes_free(foos); - - LilvNode* bar_p = lilv_new_uri(world, "http://example.org/bar"); - LilvNodes* bars = lilv_plugin_get_value(plug, bar_p); - assert(lilv_nodes_size(bars) == 1); - assert(lilv_node_as_bool(lilv_nodes_get_first(bars)) == true); - lilv_node_free(bar_p); - lilv_nodes_free(bars); - - LilvNode* baz_p = lilv_new_uri(world, "http://example.org/baz"); - LilvNodes* bazs = lilv_plugin_get_value(plug, baz_p); - assert(lilv_nodes_size(bazs) == 1); - assert(lilv_node_as_bool(lilv_nodes_get_first(bazs)) == false); - lilv_node_free(baz_p); - lilv_nodes_free(bazs); - - LilvNode* blank_p = lilv_new_uri(world, "http://example.org/blank"); - LilvNodes* blanks = lilv_plugin_get_value(plug, blank_p); - assert(lilv_nodes_size(blanks) == 1); - LilvNode* blank = lilv_nodes_get_first(blanks); - assert(lilv_node_is_blank(blank)); - const char* blank_str = lilv_node_as_blank(blank); - char* blank_tok = lilv_node_get_turtle_token(blank); - assert(!strncmp(blank_tok, "_:", 2)); - assert(!strcmp(blank_tok + 2, blank_str)); - lilv_free(blank_tok); - lilv_node_free(blank_p); - lilv_nodes_free(blanks); - - LilvNode* author_name = lilv_plugin_get_author_name(plug); - assert(!strcmp(lilv_node_as_string(author_name), "David Robillard")); - lilv_node_free(author_name); - - LilvNode* author_email = lilv_plugin_get_author_email(plug); - assert(!strcmp(lilv_node_as_string(author_email), "mailto:d@drobilla.net")); - lilv_node_free(author_email); - - LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); - assert(!strcmp(lilv_node_as_string(author_homepage), "http://drobilla.net")); - lilv_node_free(author_homepage); - - LilvNode* thing_uri = lilv_new_uri(world, "http://example.org/thing"); - LilvNode* name_p = lilv_new_uri(world, "http://usefulinc.com/ns/doap#name"); - LilvNodes* thing_names = lilv_world_find_nodes(world, thing_uri, name_p, NULL); - assert(lilv_nodes_size(thing_names) == 1); - LilvNode* thing_name = lilv_nodes_get_first(thing_names); - assert(thing_name); - assert(lilv_node_is_string(thing_name)); - assert(!strcmp(lilv_node_as_string(thing_name), "Something else")); - LilvNode* thing_name2 = lilv_world_get(world, thing_uri, name_p, NULL); - assert(lilv_node_equals(thing_name, thing_name2)); - - LilvUIs* uis = lilv_plugin_get_uis(plug); - assert(lilv_uis_size(uis) == 0); - lilv_uis_free(uis); - - LilvNode* extdata = lilv_new_uri(world, "http://example.org/extdata"); - LilvNode* noextdata = lilv_new_uri(world, "http://example.org/noextdata"); - LilvNodes* extdatas = lilv_plugin_get_extension_data(plug); - assert(lilv_plugin_has_extension_data(plug, extdata)); - assert(!lilv_plugin_has_extension_data(plug, noextdata)); - assert(lilv_nodes_size(extdatas) == 1); - assert(lilv_node_equals(lilv_nodes_get_first(extdatas), extdata)); - lilv_node_free(noextdata); - lilv_node_free(extdata); - lilv_nodes_free(extdatas); - - lilv_nodes_free(thing_names); - lilv_node_free(thing_uri); - lilv_node_free(thing_name2); - lilv_node_free(name_p); - lilv_node_free(control_class); - lilv_node_free(audio_class); - lilv_node_free(in_class); - lilv_node_free(out_class); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_project(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin with project\" ;" - "lv2:project [ " - " doap:maintainer [ " - " foaf:name \"David Robillard\" ; " - " foaf:homepage <http://drobilla.net> ; foaf:mbox <mailto:d@drobilla.net> ] ; " - "] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - ":thing doap:name \"Something else\" .\n")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvNode* author_name = lilv_plugin_get_author_name(plug); - assert(!strcmp(lilv_node_as_string(author_name), "David Robillard")); - lilv_node_free(author_name); - - LilvNode* author_email = lilv_plugin_get_author_email(plug); - assert(!strcmp(lilv_node_as_string(author_email), "mailto:d@drobilla.net")); - lilv_node_free(author_email); - - LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); - assert(!strcmp(lilv_node_as_string(author_homepage), "http://drobilla.net")); - lilv_node_free(author_homepage); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_no_author(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin with project\" ;" - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - ":thing doap:name \"Something else\" .\n")) { - return 1; - } - - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvNode* author_name = lilv_plugin_get_author_name(plug); - assert(!author_name); - - LilvNode* author_email = lilv_plugin_get_author_email(plug); - assert(!author_email); - - LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); - assert(!author_homepage); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_project_no_author(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin with project\" ;" - "lv2:project [ " - " doap:name \"Fake project\" ;" - "] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - ":thing doap:name \"Something else\" .\n")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvNode* author_name = lilv_plugin_get_author_name(plug); - assert(!author_name); - - LilvNode* author_email = lilv_plugin_get_author_email(plug); - assert(!author_email); - - LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); - assert(!author_homepage); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_preset(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin with project\" ;" - "lv2:project [ " - " doap:name \"Fake project\" ;" - "] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - "<http://example.org/preset> a pset:Preset ;" - " lv2:appliesTo :plug ;" - " rdfs:label \"some preset\" .\n")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvNode* pset_Preset = lilv_new_uri(world, LV2_PRESETS__Preset); - LilvNodes* related = lilv_plugin_get_related(plug, pset_Preset); - - assert(lilv_nodes_size(related) == 1); - - lilv_node_free(pset_Preset); - lilv_nodes_free(related); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_prototype(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":prot a lv2:PluginBase ; rdfs:seeAlso <plugin.ttl> .\n" - ":plug a lv2:Plugin ; lv2:binary <inst" SHLIB_EXT "> ; lv2:prototype :prot .\n", - ":prot a lv2:Plugin ; a lv2:CompressorPlugin ; " - "lv2:project [ " - " doap:name \"Fake project\" ;" - "] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency ; " - " lv2:designation lv2:latency " - "] . \n" - ":plug doap:name \"Instance\" .\n")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - // Test non-inherited property - LilvNode* name = lilv_plugin_get_name(plug); - assert(!strcmp(lilv_node_as_string(name), "Instance")); - lilv_node_free(name); - - // Test inherited property - const LilvNode* binary = lilv_plugin_get_library_uri(plug); - assert(strstr(lilv_node_as_string(binary), "inst" SHLIB_EXT)); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_port(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - "@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> . \n" - ":plug a lv2:Plugin ; " - "doap:name \"Test plugin\" ;" - "doap:homepage <http://example.org/someplug> ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; " - " lv2:name \"store\" ; " - " lv2:name \"Laden\"@de-de ; lv2:name \"Geschaeft\"@de-at ; " - " lv2:name \"tienda\"@es ; " - " rdfs:comment \"comment\"@en , \"commentaires\"@fr ; " - " lv2:portProperty lv2:integer ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 ; " - " lv2:scalePoint [ rdfs:label \"Sin\"; rdf:value 3 ] ; " - " lv2:scalePoint [ rdfs:label \"Cos\"; rdf:value 4 ] " - "] , [\n" - " a lv2:EventPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"event_in\" ; " - " lv2:name \"Event Input\" ; " - " lv2ev:supportsEvent <http://example.org/event> ;" - " atom:supports <http://example.org/atomEvent> " - "] , [\n" - " a lv2:AudioPort ; a lv2:InputPort ; " - " lv2:index 2 ; lv2:symbol \"audio_in\" ; " - " lv2:name \"Audio Input\" ; " - "] , [\n" - " a lv2:AudioPort ; a lv2:OutputPort ; " - " lv2:index 3 ; lv2:symbol \"audio_out\" ; " - " lv2:name \"Audio Output\" ; " - "] .")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvNode* psym = lilv_new_string(world, "foo"); - const LilvPort* p = lilv_plugin_get_port_by_index(plug, 0); - const LilvPort* p2 = lilv_plugin_get_port_by_symbol(plug, psym); - lilv_node_free(psym); - assert(p != NULL); - assert(p2 != NULL); - assert(p == p2); - - LilvNode* nopsym = lilv_new_string(world, "thisaintnoportfoo"); - const LilvPort* p3 = lilv_plugin_get_port_by_symbol(plug, nopsym); - assert(p3 == NULL); - lilv_node_free(nopsym); - - // Try getting an invalid property - LilvNode* num = lilv_new_int(world, 1); - LilvNodes* nothing = lilv_port_get_value(plug, p, num); - assert(!nothing); - lilv_node_free(num); - - LilvNode* audio_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#AudioPort"); - LilvNode* control_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#ControlPort"); - LilvNode* in_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#InputPort"); - LilvNode* out_class = lilv_new_uri(world, - "http://lv2plug.in/ns/lv2core#OutputPort"); - - assert(lilv_nodes_size(lilv_port_get_classes(plug, p)) == 2); - assert(lilv_plugin_get_num_ports(plug) == 4); - assert(lilv_port_is_a(plug, p, control_class)); - assert(lilv_port_is_a(plug, p, in_class)); - assert(!lilv_port_is_a(plug, p, audio_class)); - - LilvNodes* port_properties = lilv_port_get_properties(plug, p); - assert(lilv_nodes_size(port_properties) == 1); - lilv_nodes_free(port_properties); - - // Untranslated name (current locale is set to "C" in main) - assert(!strcmp(lilv_node_as_string(lilv_port_get_symbol(plug, p)), "foo")); - LilvNode* name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "store")); - lilv_node_free(name); - - // Exact language match - set_env("LANG", "de_DE"); - name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "Laden")); - lilv_node_free(name); - - // Exact language match (with charset suffix) - set_env("LANG", "de_AT.utf8"); - name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "Geschaeft")); - lilv_node_free(name); - - // Partial language match (choose value translated for different country) - set_env("LANG", "de_CH"); - name = lilv_port_get_name(plug, p); - assert((!strcmp(lilv_node_as_string(name), "Laden")) - ||(!strcmp(lilv_node_as_string(name), "Geschaeft"))); - lilv_node_free(name); - - // Partial language match (choose country-less language tagged value) - set_env("LANG", "es_MX"); - name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "tienda")); - lilv_node_free(name); - - // No language match (choose untranslated value) - set_env("LANG", "cn"); - name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "store")); - lilv_node_free(name); - - // Invalid language - set_env("LANG", "1!"); - name = lilv_port_get_name(plug, p); - assert(!strcmp(lilv_node_as_string(name), "store")); - lilv_node_free(name); - - set_env("LANG", "en_CA.utf-8"); - - // Language tagged value with no untranslated values - LilvNode* rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment"); - LilvNodes* comments = lilv_port_get_value(plug, p, rdfs_comment); - assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)), - "comment")); - LilvNode* comment = lilv_port_get(plug, p, rdfs_comment); - assert(!strcmp(lilv_node_as_string(comment), "comment")); - lilv_node_free(comment); - lilv_nodes_free(comments); - - set_env("LANG", "fr"); - - comments = lilv_port_get_value(plug, p, rdfs_comment); - assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)), - "commentaires")); - lilv_nodes_free(comments); - - set_env("LANG", "cn"); - - comments = lilv_port_get_value(plug, p, rdfs_comment); - assert(!comments); - lilv_nodes_free(comments); - - lilv_node_free(rdfs_comment); - - set_env("LANG", "C"); // Reset locale - - LilvScalePoints* points = lilv_port_get_scale_points(plug, p); - assert(lilv_scale_points_size(points) == 2); - - LilvIter* sp_iter = lilv_scale_points_begin(points); - const LilvScalePoint* sp0 = lilv_scale_points_get(points, sp_iter); - assert(sp0); - sp_iter = lilv_scale_points_next(points, sp_iter); - const LilvScalePoint* sp1 = lilv_scale_points_get(points, sp_iter); - assert(sp1); - - assert( - ((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), "Sin") - && lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 3) - && - (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), "Cos") - && lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 4)) - || - ((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), "Cos") - && lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 4) - && - (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), "Sin") - && lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 3))); - - LilvNode* homepage_p = lilv_new_uri(world, "http://usefulinc.com/ns/doap#homepage"); - LilvNodes* homepages = lilv_plugin_get_value(plug, homepage_p); - assert(lilv_nodes_size(homepages) == 1); - assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(homepages)), - "http://example.org/someplug")); - - LilvNode *min, *max, *def; - lilv_port_get_range(plug, p, &def, &min, &max); - assert(def); - assert(min); - assert(max); - assert(lilv_node_as_float(def) == 0.5); - assert(lilv_node_as_float(min) == -1.0); - assert(lilv_node_as_float(max) == 1.0); - - LilvNode* integer_prop = lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#integer"); - LilvNode* toggled_prop = lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#toggled"); - - assert(lilv_port_has_property(plug, p, integer_prop)); - assert(!lilv_port_has_property(plug, p, toggled_prop)); - - const LilvPort* ep = lilv_plugin_get_port_by_index(plug, 1); - - LilvNode* event_type = lilv_new_uri(world, "http://example.org/event"); - LilvNode* event_type_2 = lilv_new_uri(world, "http://example.org/otherEvent"); - LilvNode* atom_event = lilv_new_uri(world, "http://example.org/atomEvent"); - assert(lilv_port_supports_event(plug, ep, event_type)); - assert(!lilv_port_supports_event(plug, ep, event_type_2)); - assert(lilv_port_supports_event(plug, ep, atom_event)); - - LilvNode* name_p = lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#name"); - LilvNodes* names = lilv_port_get_value(plug, p, name_p); - assert(lilv_nodes_size(names) == 1); - assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), - "store")); - lilv_nodes_free(names); - - LilvNode* true_val = lilv_new_bool(world, true); - LilvNode* false_val = lilv_new_bool(world, false); - - assert(!lilv_node_equals(true_val, false_val)); - - lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, false_val); - names = lilv_port_get_value(plug, p, name_p); - assert(lilv_nodes_size(names) == 4); - lilv_nodes_free(names); - lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, true_val); - - lilv_node_free(false_val); - lilv_node_free(true_val); - - names = lilv_port_get_value(plug, ep, name_p); - assert(lilv_nodes_size(names) == 1); - assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), - "Event Input")); - - const LilvPort* ap_in = lilv_plugin_get_port_by_index(plug, 2); - - assert(lilv_port_is_a(plug, ap_in, in_class)); - assert(!lilv_port_is_a(plug, ap_in, out_class)); - assert(lilv_port_is_a(plug, ap_in, audio_class)); - assert(!lilv_port_is_a(plug, ap_in, control_class)); - - const LilvPort* ap_out = lilv_plugin_get_port_by_index(plug, 3); - - assert(lilv_port_is_a(plug, ap_out, out_class)); - assert(!lilv_port_is_a(plug, ap_out, in_class)); - assert(lilv_port_is_a(plug, ap_out, audio_class)); - assert(!lilv_port_is_a(plug, ap_out, control_class)); - - assert(lilv_plugin_get_num_ports_of_class(plug, control_class, in_class , NULL) == 1); - assert(lilv_plugin_get_num_ports_of_class(plug, audio_class , in_class , NULL) == 1); - assert(lilv_plugin_get_num_ports_of_class(plug, audio_class , out_class, NULL) == 1); - - lilv_nodes_free(names); - lilv_node_free(name_p); - - lilv_node_free(integer_prop); - lilv_node_free(toggled_prop); - lilv_node_free(event_type); - lilv_node_free(event_type_2); - lilv_node_free(atom_event); - - lilv_node_free(min); - lilv_node_free(max); - lilv_node_free(def); - - lilv_node_free(homepage_p); - lilv_nodes_free(homepages); - - lilv_scale_points_free(points); - lilv_node_free(control_class); - lilv_node_free(audio_class); - lilv_node_free(out_class); - lilv_node_free(in_class); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static unsigned -ui_supported(const char* container_type_uri, - const char* ui_type_uri) -{ - return !strcmp(container_type_uri, ui_type_uri); -} - -static int -test_ui(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - "@prefix lv2ui: <http://lv2plug.in/ns/extensions/ui#> .\n" - ":plug a lv2:Plugin ; a lv2:CompressorPlugin ; " - "doap:name \"Test plugin\" ;" - "lv2:optionalFeature lv2:hardRTCapable ; " - "lv2:requiredFeature <http://lv2plug.in/ns/ext/event> ; " - "lv2ui:ui :ui , :ui2 , :ui3 , :ui4 ; " - "doap:maintainer [ foaf:name \"David Robillard\" ; " - " foaf:homepage <http://drobilla.net> ; foaf:mbox <mailto:d@drobilla.net> ] ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"foo\" ; lv2:name \"bar\" ; " - " lv2:minimum -1.0 ; lv2:maximum 1.0 ; lv2:default 0.5 " - "] , [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 1 ; lv2:symbol \"bar\" ; lv2:name \"Baz\" ; " - " lv2:minimum -2.0 ; lv2:maximum 2.0 ; lv2:default 1.0 " - "] , [ " - " a lv2:ControlPort ; a lv2:OutputPort ; " - " lv2:index 2 ; lv2:symbol \"latency\" ; lv2:name \"Latency\" ; " - " lv2:portProperty lv2:reportsLatency " - "] .\n" - ":ui a lv2ui:GtkUI ; " - " lv2ui:requiredFeature lv2ui:makeResident ; " - " lv2ui:binary <ui" SHLIB_EXT "> ; " - " lv2ui:optionalFeature lv2ui:ext_presets . " - ":ui2 a lv2ui:GtkUI ; lv2ui:binary <ui2" SHLIB_EXT "> . " - ":ui3 a lv2ui:GtkUI ; lv2ui:binary <ui3" SHLIB_EXT "> . " - ":ui4 a lv2ui:GtkUI ; lv2ui:binary <ui4" SHLIB_EXT "> . ")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - LilvUIs* uis = lilv_plugin_get_uis(plug); - assert(lilv_uis_size(uis) == 4); - - const LilvUI* ui0 = lilv_uis_get(uis, lilv_uis_begin(uis)); - assert(ui0); - - LilvNode* ui_uri = lilv_new_uri(world, "http://example.org/ui"); - LilvNode* ui2_uri = lilv_new_uri(world, "http://example.org/ui3"); - LilvNode* ui3_uri = lilv_new_uri(world, "http://example.org/ui4"); - LilvNode* noui_uri = lilv_new_uri(world, "http://example.org/notaui"); - - const LilvUI* ui0_2 = lilv_uis_get_by_uri(uis, ui_uri); - assert(ui0 == ui0_2); - assert(lilv_node_equals(lilv_ui_get_uri(ui0_2), ui_uri)); - - const LilvUI* ui2 = lilv_uis_get_by_uri(uis, ui2_uri); - assert(ui2 != ui0); - - const LilvUI* ui3 = lilv_uis_get_by_uri(uis, ui3_uri); - assert(ui3 != ui0); - - const LilvUI* noui = lilv_uis_get_by_uri(uis, noui_uri); - assert(noui == NULL); - - const LilvNodes* classes = lilv_ui_get_classes(ui0); - assert(lilv_nodes_size(classes) == 1); - - LilvNode* ui_class_uri = lilv_new_uri(world, - "http://lv2plug.in/ns/extensions/ui#GtkUI"); - - LilvNode* unknown_ui_class_uri = lilv_new_uri(world, - "http://example.org/mysteryUI"); - - assert(lilv_node_equals(lilv_nodes_get_first(classes), ui_class_uri)); - assert(lilv_ui_is_a(ui0, ui_class_uri)); - - const LilvNode* ui_type = NULL; - assert(lilv_ui_is_supported(ui0, ui_supported, ui_class_uri, &ui_type)); - assert(!lilv_ui_is_supported(ui0, ui_supported, unknown_ui_class_uri, &ui_type)); - assert(lilv_node_equals(ui_type, ui_class_uri)); - - const LilvNode* plug_bundle_uri = lilv_plugin_get_bundle_uri(plug); - const LilvNode* ui_bundle_uri = lilv_ui_get_bundle_uri(ui0); - assert(lilv_node_equals(plug_bundle_uri, ui_bundle_uri)); - - char* ui_binary_uri_str = (char*)malloc(TEST_PATH_MAX); - snprintf(ui_binary_uri_str, TEST_PATH_MAX, "%s%s", - lilv_node_as_string(plug_bundle_uri), "ui" SHLIB_EXT); - - const LilvNode* ui_binary_uri = lilv_ui_get_binary_uri(ui0); - - LilvNode* expected_uri = lilv_new_uri(world, ui_binary_uri_str); - assert(lilv_node_equals(expected_uri, ui_binary_uri)); - - free(ui_binary_uri_str); - lilv_node_free(unknown_ui_class_uri); - lilv_node_free(ui_class_uri); - lilv_node_free(ui_uri); - lilv_node_free(ui2_uri); - lilv_node_free(ui3_uri); - lilv_node_free(noui_uri); - lilv_node_free(expected_uri); - lilv_uis_free(uis); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -#ifndef _WIN32 - -uint32_t atom_Float = 0; -float in = 1.0; -float out = 42.0; -float control = 1234.0; - -static const void* -get_port_value(const char* port_symbol, - void* user_data, - uint32_t* size, - uint32_t* type) -{ - if (!strcmp(port_symbol, "input")) { - *size = sizeof(float); - *type = atom_Float; - return ∈ - } else if (!strcmp(port_symbol, "output")) { - *size = sizeof(float); - *type = atom_Float; - return &out; - } else if (!strcmp(port_symbol, "control")) { - *size = sizeof(float); - *type = atom_Float; - return &control; - } else { - fprintf(stderr, "error: get_port_value for nonexistent port `%s'\n", - port_symbol); - *size = *type = 0; - return NULL; - } -} - -static void -set_port_value(const char* port_symbol, - void* user_data, - const void* value, - uint32_t size, - uint32_t type) -{ - if (!strcmp(port_symbol, "input")) { - in = *(const float*)value; - } else if (!strcmp(port_symbol, "output")) { - out = *(const float*)value; - } else if (!strcmp(port_symbol, "control")) { - control = *(const float*)value; - } else { - fprintf(stderr, "error: set_port_value for nonexistent port `%s'\n", - port_symbol); - } -} - -char** uris = NULL; -size_t n_uris = 0; - -static LV2_URID -map_uri(LV2_URID_Map_Handle handle, - const char* uri) -{ - for (size_t i = 0; i < n_uris; ++i) { - if (!strcmp(uris[i], uri)) { - return i + 1; - } - } - - assert(serd_uri_string_has_scheme((const uint8_t*)uri)); - uris = (char**)realloc(uris, ++n_uris * sizeof(char*)); - uris[n_uris - 1] = lilv_strdup(uri); - return n_uris; -} - -static const char* -unmap_uri(LV2_URID_Map_Handle handle, - LV2_URID urid) -{ - if (urid > 0 && urid <= n_uris) { - return uris[urid - 1]; - } - return NULL; -} - -static char* temp_dir = NULL; - -static char* -lilv_make_path(LV2_State_Make_Path_Handle handle, - const char* path) -{ - return lilv_path_join(temp_dir, path); -} - -static void -lilv_free_path(LV2_State_Free_Path_Handle handle, char* path) -{ - lilv_free(path); -} - -static int -test_state(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(LILV_TEST_BUNDLE); - SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); - LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); - LilvNode* plugin_uri = lilv_new_uri(world, - "http://example.org/lilv-test-plugin"); - lilv_world_load_bundle(world, bundle_uri); - free(abs_bundle); - serd_node_free(&bundle); - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); - assert(plugin); - - LV2_URID_Map map = { NULL, map_uri }; - LV2_Feature map_feature = { LV2_URID_MAP_URI, &map }; - LV2_URID_Unmap unmap = { NULL, unmap_uri }; - LV2_Feature unmap_feature = { LV2_URID_UNMAP_URI, &unmap }; - const LV2_Feature* features[] = { &map_feature, &unmap_feature, NULL }; - - atom_Float = map.map(map.handle, "http://lv2plug.in/ns/ext/atom#Float"); - - LilvNode* num = lilv_new_int(world, 5); - LilvState* nostate = lilv_state_new_from_file(world, &map, num, "/junk"); - assert(!nostate); - - LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, features); - assert(instance); - lilv_instance_activate(instance); - lilv_instance_connect_port(instance, 0, &in); - lilv_instance_connect_port(instance, 1, &out); - lilv_instance_run(instance, 1); - assert(in == 1.0); - assert(out == 1.0); - - temp_dir = lilv_realpath("temp"); - - const char* scratch_dir = NULL; - char* copy_dir = NULL; - char* link_dir = NULL; - char* save_dir = NULL; - - // Get instance state state - LilvState* state = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, save_dir, - get_port_value, world, 0, NULL); - - // Get another instance state - LilvState* state2 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, save_dir, - get_port_value, world, 0, NULL); - - // Ensure they are equal - assert(lilv_state_equals(state, state2)); - - // Check that we can't delete unsaved state - assert(lilv_state_delete(world, state)); - - // Check that state has no URI - assert(!lilv_state_get_uri(state)); - - // Check that we can't save a state with no URI - char* bad_state_str = lilv_state_to_string( - world, &map, &unmap, state, NULL, NULL); - assert(!bad_state_str); - - // Check that we can't restore the NULL string (and it doesn't crash) - LilvState* bad_state = lilv_state_new_from_string(world, &map, NULL); - assert(!bad_state); - - // Save state to a string - char* state1_str = lilv_state_to_string( - world, &map, &unmap, state, "http://example.org/state1", NULL); - - // Restore from string - LilvState* from_str = lilv_state_new_from_string(world, &map, state1_str); - - // Ensure they are equal - assert(lilv_state_equals(state, from_str)); - lilv_free(state1_str); - - const LilvNode* state_plugin_uri = lilv_state_get_plugin_uri(state); - assert(lilv_node_equals(state_plugin_uri, plugin_uri)); - - // Tinker with the label of the first state - assert(lilv_state_get_label(state) == NULL); - lilv_state_set_label(state, "Test State Old Label"); - assert(!strcmp(lilv_state_get_label(state), "Test State Old Label")); - lilv_state_set_label(state, "Test State"); - assert(!strcmp(lilv_state_get_label(state), "Test State")); - - assert(!lilv_state_equals(state, state2)); // Label changed - - // Run and get a new instance state (which should now differ) - lilv_instance_run(instance, 1); - LilvState* state3 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, save_dir, - get_port_value, world, 0, NULL); - assert(!lilv_state_equals(state2, state3)); // num_runs changed - - // Restore instance state to original state - lilv_state_restore(state2, instance, set_port_value, NULL, 0, NULL); - - // Take a new snapshot and ensure it matches the set state - LilvState* state4 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, save_dir, - get_port_value, world, 0, NULL); - assert(lilv_state_equals(state2, state4)); - - // Set some metadata properties - lilv_state_set_metadata(state, map.map(map.handle, LILV_NS_RDFS "comment"), - "This is a comment", - strlen("This is a comment") + 1, - map.map(map.handle, "http://lv2plug.in/ns/ext/atom#Literal"), - LV2_STATE_IS_POD); - lilv_state_set_metadata(state, map.map(map.handle, "http://example.org/metablob"), - "LIVEBEEF", - strlen("LIVEBEEF") + 1, - map.map(map.handle, "http://example.org/MetaBlob"), - 0); - - // Save state to a directory - int ret = lilv_state_save(world, &map, &unmap, state, NULL, - "state/state.lv2", "state.ttl"); - assert(!ret); - - // Load state from directory - LilvState* state5 = lilv_state_new_from_file(world, &map, NULL, - "state/state.lv2/state.ttl"); - - assert(lilv_state_equals(state, state5)); // Round trip accuracy - assert(lilv_state_get_num_properties(state) == 8); - - // Attempt to save state to nowhere (error) - ret = lilv_state_save(world, &map, &unmap, state, NULL, NULL, NULL); - assert(ret); - - // Save another state to the same directory (update manifest) - ret = lilv_state_save(world, &map, &unmap, state, NULL, - "state/state.lv2", "state2.ttl"); - assert(!ret); - - // Save state with URI to a directory - const char* state_uri = "http://example.org/state"; - ret = lilv_state_save(world, &map, &unmap, state, state_uri, - "state/state6.lv2", "state6.ttl"); - assert(!ret); - - // Load state bundle into world and verify it matches - { - uint8_t* state6_path = (uint8_t*)lilv_path_absolute("state/state6.lv2/"); - SerdNode state6_uri = serd_node_new_file_uri(state6_path, 0, 0, true); - LilvNode* state6_bundle = lilv_new_uri(world, (const char*)state6_uri.buf); - LilvNode* state6_node = lilv_new_uri(world, state_uri); - lilv_world_load_bundle(world, state6_bundle); - lilv_world_load_resource(world, state6_node); - serd_node_free(&state6_uri); - lilv_free(state6_path); - - LilvState* state6 = lilv_state_new_from_world(world, &map, state6_node); - assert(lilv_state_equals(state, state6)); // Round trip accuracy - - // Check that loaded state has correct URI - assert(lilv_state_get_uri(state6)); - assert(!strcmp(lilv_node_as_string(lilv_state_get_uri(state6)), - state_uri)); - - // Unload state from world - lilv_world_unload_resource(world, state6_node); - lilv_world_unload_bundle(world, state6_bundle); - - // Ensure that it is no longer present - assert(!lilv_state_new_from_world(world, &map, state6_node)); - lilv_node_free(state6_bundle); - lilv_node_free(state6_node); - - // Delete state - lilv_state_delete(world, state6); - lilv_state_free(state6); - } - - // Make directories and test files support - mkdir("temp", 0700); - scratch_dir = temp_dir; - mkdir("files", 0700); - copy_dir = lilv_realpath("files"); - mkdir("links", 0700); - link_dir = lilv_realpath("links"); - - LV2_State_Make_Path make_path = { NULL, lilv_make_path }; - LV2_Feature make_path_feature = { LV2_STATE__makePath, &make_path }; - LV2_State_Free_Path free_path = { NULL, lilv_free_path }; - LV2_Feature free_path_feature = { LV2_STATE__freePath, &free_path }; - const LV2_Feature* ffeatures[] = { - &make_path_feature, &map_feature, &free_path_feature, NULL - }; - - lilv_instance_deactivate(instance); - lilv_instance_free(instance); - instance = lilv_plugin_instantiate(plugin, 48000.0, ffeatures); - lilv_instance_activate(instance); - lilv_instance_connect_port(instance, 0, &in); - lilv_instance_connect_port(instance, 1, &out); - lilv_instance_run(instance, 1); - - // Test instantiating twice - LilvInstance* instance2 = lilv_plugin_instantiate(plugin, 48000.0, ffeatures); - if (!instance2) { - fprintf(stderr, - "Failed to create multiple instances of <%s>\n", - lilv_node_as_uri(state_plugin_uri)); - return 1; - } - lilv_instance_free(instance2); - - // Get instance state state - LilvState* fstate = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, "state/fstate.lv2", - get_port_value, world, 0, ffeatures); - - { - // Get another instance state - LilvState* fstate2 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, "state/fstate2.lv2", - get_port_value, world, 0, ffeatures); - - // Check that it is identical - assert(lilv_state_equals(fstate, fstate2)); - - lilv_state_delete(world, fstate2); - lilv_state_free(fstate2); - } - - // Run, writing more to rec file - lilv_instance_run(instance, 2); - - // Get yet another instance state - LilvState* fstate3 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, "state/fstate3.lv2", - get_port_value, world, 0, ffeatures); - - // Should be different - assert(!lilv_state_equals(fstate, fstate3)); - - // Save state to a directory - ret = lilv_state_save(world, &map, &unmap, fstate, NULL, - "state/fstate.lv2", "fstate.ttl"); - assert(!ret); - - // Load state from directory - LilvState* fstate4 = lilv_state_new_from_file( - world, &map, NULL, "state/fstate.lv2/fstate.ttl"); - assert(lilv_state_equals(fstate, fstate4)); // Round trip accuracy - - // Restore instance state to loaded state - lilv_state_restore(fstate4, instance, set_port_value, NULL, 0, ffeatures); - - // Take a new snapshot and ensure it matches - LilvState* fstate5 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, "state/fstate5.lv2", - get_port_value, world, 0, ffeatures); - assert(lilv_state_equals(fstate3, fstate5)); - - // Save state to a (different) directory again - ret = lilv_state_save(world, &map, &unmap, fstate, NULL, - "state/fstate6.lv2", "fstate6.ttl"); - assert(!ret); - - // Reload it and ensure it's identical to the other loaded version - LilvState* fstate6 = lilv_state_new_from_file( - world, &map, NULL, "state/fstate6.lv2/fstate6.ttl"); - assert(lilv_state_equals(fstate4, fstate6)); - - // Run, changing rec file (without changing size) - lilv_instance_run(instance, 3); - - // Take a new snapshot - LilvState* fstate7 = lilv_state_new_from_instance( - plugin, instance, &map, - scratch_dir, copy_dir, link_dir, "state/fstate7.lv2", - get_port_value, world, 0, ffeatures); - assert(!lilv_state_equals(fstate6, fstate7)); - - // Save the changed state to a (different) directory again - ret = lilv_state_save(world, &map, &unmap, fstate7, NULL, - "state/fstate7.lv2", "fstate7.ttl"); - assert(!ret); - - // Reload it and ensure it's changed - LilvState* fstate72 = lilv_state_new_from_file( - world, &map, NULL, "state/fstate7.lv2/fstate7.ttl"); - assert(lilv_state_equals(fstate72, fstate7)); - assert(!lilv_state_equals(fstate6, fstate72)); - - // Delete saved state we still have a state in memory that points to - lilv_state_delete(world, fstate7); - lilv_state_delete(world, fstate6); - lilv_state_delete(world, fstate5); - lilv_state_delete(world, fstate3); - lilv_state_delete(world, fstate); - lilv_state_delete(world, state2); - lilv_state_delete(world, state); - - // Delete remaining states on disk we've lost a reference to - const char* const old_state_paths[] = {"state/state.lv2/state.ttl", - "state/state.lv2/state2.ttl", - "state/fstate.lv2/fstate.ttl", - NULL}; - - for (const char*const* p = old_state_paths; *p; ++p) { - const char* path = *p; - LilvState* old_state = - lilv_state_new_from_file(world, &map, NULL, path); - lilv_state_delete(world, old_state); - lilv_state_free(old_state); - } - - lilv_instance_deactivate(instance); - lilv_instance_free(instance); - - lilv_node_free(num); - - lilv_state_free(state); - lilv_state_free(from_str); - lilv_state_free(state2); - lilv_state_free(state3); - lilv_state_free(state4); - lilv_state_free(state5); - lilv_state_free(fstate); - lilv_state_free(fstate3); - lilv_state_free(fstate4); - lilv_state_free(fstate5); - lilv_state_free(fstate6); - lilv_state_free(fstate7); - lilv_state_free(fstate72); - - rmdir("state"); - - // Free URI map - for (size_t i = 0; i < n_uris; ++i) { - free(uris[i]); - } - free(uris); - n_uris = 0; - - lilv_node_free(plugin_uri); - lilv_node_free(bundle_uri); - free(link_dir); - free(copy_dir); - free(temp_dir); - - return 0; -} -#endif - -/*****************************************************************************/ - -static int -test_bad_port_symbol(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"Test plugin\" ;" - "doap:homepage <http://example.org/someplug> ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index 0 ; lv2:symbol \"0invalid\" ;" - " lv2:name \"Invalid\" ; " - "] .")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - - uint32_t n_ports = lilv_plugin_get_num_ports(plug); - assert(n_ports == 0); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_bad_port_index(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"Test plugin\" ;" - "doap:homepage <http://example.org/someplug> ; " - "lv2:port [ " - " a lv2:ControlPort ; a lv2:InputPort ; " - " lv2:index \"notaninteger\" ; lv2:symbol \"invalid\" ;" - " lv2:name \"Invalid\" ; " - "] .")) { - return 1; - } - - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - - uint32_t n_ports = lilv_plugin_get_num_ports(plug); - assert(n_ports == 0); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -static int -test_string(LilvTestEnv* env) -{ - char* s = NULL; - - assert(!strcmp((s = lilv_dirname("/foo/bar")), "/foo")); free(s); - assert(!strcmp((s = lilv_dirname("/foo/bar/")), "/foo")); free(s); - assert(!strcmp((s = lilv_dirname("/foo///bar/")), "/foo")); free(s); - assert(!strcmp((s = lilv_dirname("/foo///bar//")), "/foo")); free(s); - assert(!strcmp((s = lilv_dirname("foo")), ".")); free(s); - assert(!strcmp((s = lilv_dirname("/foo")), "/")); free(s); - assert(!strcmp((s = lilv_dirname("/")), "/")); free(s); - assert(!strcmp((s = lilv_dirname("//")), "/")); free(s); - assert(!strcmp((s = lilv_path_relative_to("/a/b", "/a/")), "b")); free(s); - assert(!strcmp((s = lilv_path_relative_to("/a", "/b/c/")), "/a")); free(s); - assert(!strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/")), "../c")); free(s); - assert(!strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/e/")), "../../c")); free(s); - assert(!strcmp((s = lilv_path_join("/a", "b")), "/a/b")); free(s); - assert(!strcmp((s = lilv_path_join("/a", "/b")), "/a/b")); free(s); - assert(!strcmp((s = lilv_path_join("/a/", "/b")), "/a/b")); free(s); - assert(!strcmp((s = lilv_path_join("/a/", "b")), "/a/b")); free(s); - assert(!strcmp((s = lilv_path_join("/a", NULL)), "/a/")); free(s); - assert(!strcmp((s = lilv_path_join(NULL, "/b")), "/b")); free(s); - -#ifndef _WIN32 - setenv("LILV_TEST_1", "test", 1); - char* home_foo = lilv_strjoin(getenv("HOME"), "/foo", NULL); - assert(!strcmp((s = lilv_expand("$LILV_TEST_1")), "test")); free(s); - assert(!strcmp((s = lilv_expand("~")), getenv("HOME"))); free(s); - assert(!strcmp((s = lilv_expand("~foo")), "~foo")); free(s); - assert(!strcmp((s = lilv_expand("~/foo")), home_foo)); free(s); - assert(!strcmp((s = lilv_expand("$NOT_A_VAR")), "$NOT_A_VAR")); free(s); - free(home_foo); - unsetenv("LILV_TEST_1"); -#endif - - return 0; -} - -/*****************************************************************************/ - -static int -test_world(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - LilvNode* num = lilv_new_int(env->world, 4); - LilvNode* uri = lilv_new_uri(env->world, "http://example.org/object"); - - LilvNodes* matches = lilv_world_find_nodes(world, num, NULL, NULL); - assert(!matches); - - matches = lilv_world_find_nodes(world, NULL, num, NULL); - assert(!matches); - - matches = lilv_world_find_nodes(world, NULL, uri, NULL); - assert(!matches); - - lilv_node_free(uri); - lilv_node_free(num); - - lilv_world_unload_bundle(world, NULL); - - return 0; -} - -/*****************************************************************************/ - -static int -test_reload_bundle(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - // Create a simple plugin bundle - create_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"First name\" ."); - - lilv_world_load_specifications(world); - - // Load bundle - LilvNode* bundle_uri = lilv_new_uri(world, env->test_bundle_uri); - lilv_world_load_bundle(world, bundle_uri); - - // Check that plugin is present - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug); - - // Check that plugin name is correct - LilvNode* name = lilv_plugin_get_name(plug); - assert(!strcmp(lilv_node_as_string(name), "First name")); - lilv_node_free(name); - - // Unload bundle from world and delete it - lilv_world_unload_bundle(world, bundle_uri); - delete_bundle(env); - - // Create a new version of the same bundle, but with a different name - create_bundle(env, - ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"Second name\" ."); - - // Check that plugin is no longer in the world's plugin list - assert(lilv_plugins_size(plugins) == 0); - - // Load new bundle - lilv_world_load_bundle(world, bundle_uri); - - // Check that plugin is present again and is the same LilvPlugin - const LilvPlugin* plug2 = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); - assert(plug2); - assert(plug2 == plug); - - // Check that plugin now has new name - LilvNode* name2 = lilv_plugin_get_name(plug2); - assert(name2); - assert(!strcmp(lilv_node_as_string(name2), "Second name")); - lilv_node_free(name2); - - // Load new bundle again (noop) - lilv_world_load_bundle(world, bundle_uri); - - lilv_node_free(bundle_uri); - delete_bundle(env); - - return 0; -} - -/*****************************************************************************/ - -static int -test_replace_version(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - LilvNode* plug_uri = lilv_new_uri(world, "http://example.org/versioned"); - LilvNode* lv2_minorVersion = lilv_new_uri(world, LV2_CORE__minorVersion); - LilvNode* lv2_microVersion = lilv_new_uri(world, LV2_CORE__microVersion); - LilvNode* minor = NULL; - LilvNode* micro = NULL; - - char* old_bundle_path = lilv_strjoin(LILV_TEST_DIR, "old_version.lv2/", 0); - - // Load plugin from old bundle - LilvNode* old_bundle = lilv_new_file_uri(world, NULL, old_bundle_path); - lilv_world_load_bundle(world, old_bundle); - lilv_world_load_resource(world, plug_uri); - - // Check version - const LilvPlugins* plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* old_plug = lilv_plugins_get_by_uri(plugins, plug_uri); - assert(old_plug); - minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); - micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); - assert(!strcmp(lilv_node_as_string(minor), "1")); - assert(!strcmp(lilv_node_as_string(micro), "0")); - lilv_node_free(micro); - lilv_node_free(minor); - - char* new_bundle_path = lilv_strjoin(LILV_TEST_DIR, "new_version.lv2/", 0); - - // Load plugin from new bundle - LilvNode* new_bundle = lilv_new_file_uri(world, NULL, new_bundle_path); - lilv_world_load_bundle(world, new_bundle); - lilv_world_load_resource(world, plug_uri); - - // Check that version in the world model has changed - plugins = lilv_world_get_all_plugins(world); - const LilvPlugin* new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); - assert(new_plug); - assert(lilv_node_equals(lilv_plugin_get_bundle_uri(new_plug), new_bundle)); - minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); - micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); - assert(!strcmp(lilv_node_as_string(minor), "2")); - assert(!strcmp(lilv_node_as_string(micro), "1")); - lilv_node_free(micro); - lilv_node_free(minor); - - // Try to load the old version again - lilv_world_load_bundle(world, old_bundle); - lilv_world_load_resource(world, plug_uri); - - // Check that version in the world model has not changed - plugins = lilv_world_get_all_plugins(world); - new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); - assert(new_plug); - minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); - micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); - assert(!strcmp(lilv_node_as_string(minor), "2")); - assert(!strcmp(lilv_node_as_string(micro), "1")); - lilv_node_free(micro); - lilv_node_free(minor); - - lilv_node_free(new_bundle); - lilv_node_free(old_bundle); - free(new_bundle_path); - free(old_bundle_path); - lilv_node_free(plug_uri); - lilv_node_free(lv2_minorVersion); - lilv_node_free(lv2_microVersion); - return 0; -} - -/*****************************************************************************/ - -static int -test_get_symbol(LilvTestEnv* env) -{ - LilvWorld* const world = env->world; - - if (start_bundle(env, - ":plug a lv2:Plugin ; lv2:symbol \"plugsym\" ; lv2:binary <foo" SHLIB_EXT "> ; rdfs:seeAlso <plugin.ttl> .\n", - ":plug a lv2:Plugin ; " - "doap:name \"Test plugin\" ;" - "lv2:symbol \"plugsym\" .")) { - return 1; - } - - LilvNode* plug_sym = lilv_world_get_symbol(world, env->plugin1_uri); - LilvNode* path = lilv_new_uri(world, "http://example.org/foo"); - LilvNode* path_sym = lilv_world_get_symbol(world, path); - LilvNode* query = lilv_new_uri(world, "http://example.org/foo?bar=baz"); - LilvNode* query_sym = lilv_world_get_symbol(world, query); - LilvNode* frag = lilv_new_uri(world, "http://example.org/foo#bar"); - LilvNode* frag_sym = lilv_world_get_symbol(world, frag); - LilvNode* queryfrag = lilv_new_uri(world, "http://example.org/foo?bar=baz#quux"); - LilvNode* queryfrag_sym = lilv_world_get_symbol(world, queryfrag); - LilvNode* nonuri = lilv_new_int(world, 42); - - assert(lilv_world_get_symbol(world, nonuri) == NULL); - assert(!strcmp(lilv_node_as_string(plug_sym), "plugsym")); - assert(!strcmp(lilv_node_as_string(path_sym), "foo")); - assert(!strcmp(lilv_node_as_string(query_sym), "bar_baz")); - assert(!strcmp(lilv_node_as_string(frag_sym), "bar")); - assert(!strcmp(lilv_node_as_string(queryfrag_sym), "quux")); - - lilv_node_free(nonuri); - lilv_node_free(queryfrag_sym); - lilv_node_free(queryfrag); - lilv_node_free(frag_sym); - lilv_node_free(frag); - lilv_node_free(query_sym); - lilv_node_free(query); - lilv_node_free(path_sym); - lilv_node_free(path); - lilv_node_free(plug_sym); - - delete_bundle(env); - return 0; -} - -/*****************************************************************************/ - -/* add tests here */ -static struct TestCase tests[] = { - TEST_CASE(util), - TEST_CASE(value), - TEST_CASE(verify), - TEST_CASE(no_verify), - TEST_CASE(discovery), - TEST_CASE(classes), - TEST_CASE(plugin), - TEST_CASE(project), - TEST_CASE(no_author), - TEST_CASE(project_no_author), - TEST_CASE(preset), - TEST_CASE(prototype), - TEST_CASE(port), - TEST_CASE(ui), - TEST_CASE(bad_port_symbol), - TEST_CASE(bad_port_index), - TEST_CASE(bad_port_index), - TEST_CASE(string), - TEST_CASE(world), - // FIXME: State is not currently working on Windows -#ifndef _WIN32 - TEST_CASE(state), -#endif - TEST_CASE(reload_bundle), - TEST_CASE(replace_version), - TEST_CASE(get_symbol), - { NULL, NULL } -}; - -static unsigned -run_tests(void) -{ - unsigned n_failures = 0; - - for (int i = 0; tests[i].title; ++i) { - printf("*** Test %s\n", tests[i].title); - LilvTestEnv* env = lilv_test_env_new(); - if (tests[i].func(env)) { - fprintf(stderr, "\nTest %s failed\n", tests[i].title); - ++n_failures; - } - lilv_test_env_free(env); - } - - return n_failures; -} - -int -main(int argc, char* argv[]) -{ - if (argc != 1) { - printf("Usage: %s\n", argv[0]); - return 1; - } - - set_env("LANG", "C"); - - const unsigned n_failures = run_tests(); - - if (n_failures == 0) { - fprintf(stderr, "\n*** All tests passed\n"); - } else { - fprintf(stderr, "\n*** %u tests failed\n", n_failures); - } - - return n_failures; -} diff --git a/test/lilv_test_utils.h b/test/lilv_test_utils.h index 88e1fcd..f027c80 100644 --- a/test/lilv_test_utils.h +++ b/test/lilv_test_utils.h @@ -33,6 +33,20 @@ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .\n\ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .\n" +#define SIMPLE_MANIFEST_TTL \ + "\ +:plug a lv2:Plugin ;\n\ + lv2:binary <foo" SHLIB_EXT "> ;\n\ + rdfs:seeAlso <plugin.ttl> .\n" + +#if defined(__APPLE__) +# define SHLIB_EXT ".dylib" +#elif defined(_WIN32) +# define SHLIB_EXT ".dll" +#else +# define SHLIB_EXT ".so" +#endif + typedef struct { LilvWorld* world; diff --git a/test/test_bad_port_index.c b/test/test_bad_port_index.c new file mode 100644 index 0000000..a4d9ad2 --- /dev/null +++ b/test/test_bad_port_index.c @@ -0,0 +1,58 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <stdint.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + doap:homepage <http://example.org/someplug> ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index \"notaninteger\" ;\n\ + lv2:symbol \"invalid\" ;\n\ + lv2:name \"Invalid\" ;\n\ + ] ."; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + + uint32_t n_ports = lilv_plugin_get_num_ports(plug); + assert(n_ports == 0); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_bad_port_symbol.c b/test/test_bad_port_symbol.c new file mode 100644 index 0000000..be00986 --- /dev/null +++ b/test/test_bad_port_symbol.c @@ -0,0 +1,58 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <stdint.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + doap:homepage <http://example.org/someplug> ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"0invalid\" ;\n\ + lv2:name \"Invalid\" ;\n\ + ] ."; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + + uint32_t n_ports = lilv_plugin_get_num_ports(plug); + assert(n_ports == 0); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_classes.c b/test/test_classes.c new file mode 100644 index 0000000..2c74c07 --- /dev/null +++ b/test/test_classes.c @@ -0,0 +1,75 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"Foo\" ;\n\ +] ."; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPluginClass* plugin = lilv_world_get_plugin_class(world); + const LilvPluginClasses* classes = lilv_world_get_plugin_classes(world); + LilvPluginClasses* children = lilv_plugin_class_get_children(plugin); + + assert(lilv_plugin_class_get_parent_uri(plugin) == NULL); + assert(lilv_plugin_classes_size(classes) > + lilv_plugin_classes_size(children)); + assert(!strcmp(lilv_node_as_string(lilv_plugin_class_get_label(plugin)), + "Plugin")); + assert(!strcmp(lilv_node_as_string(lilv_plugin_class_get_uri(plugin)), + "http://lv2plug.in/ns/lv2core#Plugin")); + + LILV_FOREACH (plugin_classes, i, children) { + assert(lilv_node_equals(lilv_plugin_class_get_parent_uri( + lilv_plugin_classes_get(children, i)), + lilv_plugin_class_get_uri(plugin))); + } + + LilvNode* some_uri = lilv_new_uri(world, "http://example.org/whatever"); + assert(lilv_plugin_classes_get_by_uri(classes, some_uri) == NULL); + lilv_node_free(some_uri); + + lilv_plugin_classes_free(children); + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_discovery.c b/test/test_discovery.c new file mode 100644 index 0000000..2585959 --- /dev/null +++ b/test/test_discovery.c @@ -0,0 +1,96 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + ] .\n"; + +static int discovery_plugin_found = 0; + +static void +discovery_verify_plugin(const LilvTestEnv* env, const LilvPlugin* plugin) +{ + const LilvNode* value = lilv_plugin_get_uri(plugin); + if (lilv_node_equals(value, env->plugin1_uri)) { + const LilvNode* lib_uri = NULL; + assert(!lilv_node_equals(value, env->plugin2_uri)); + discovery_plugin_found = 1; + lib_uri = lilv_plugin_get_library_uri(plugin); + assert(lib_uri); + assert(lilv_node_is_uri(lib_uri)); + assert(lilv_node_as_uri(lib_uri)); + assert(strstr(lilv_node_as_uri(lib_uri), "foo" SHLIB_EXT)); + assert(lilv_plugin_verify(plugin)); + } +} + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + assert(lilv_plugins_size(plugins) > 0); + + const LilvPlugin* plug1 = + lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + + const LilvPlugin* plug2 = + lilv_plugins_get_by_uri(plugins, env->plugin2_uri); + + assert(plug1); + assert(!plug2); + + { + LilvNode* name = lilv_plugin_get_name(plug1); + assert(!strcmp(lilv_node_as_string(name), "Test plugin")); + lilv_node_free(name); + } + + discovery_plugin_found = 0; + LILV_FOREACH (plugins, i, plugins) { + discovery_verify_plugin(env, lilv_plugins_get(plugins, i)); + } + + assert(discovery_plugin_found); + plugins = NULL; + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_get_symbol.c b/test/test_get_symbol.c new file mode 100644 index 0000000..0427447 --- /dev/null +++ b/test/test_get_symbol.c @@ -0,0 +1,81 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +static const char* const manifest_ttl = "\ + :plug a lv2:Plugin ;\n\ + lv2:symbol \"plugsym\" ;\n\ + lv2:binary <foo" SHLIB_EXT "> ;\n\ + rdfs:seeAlso <plugin.ttl> .\n"; + +static const char* const plugin_ttl = "\ + :plug a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:symbol \"plugsym\" .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, manifest_ttl, plugin_ttl)) { + return 1; + } + + LilvNode* plug_sym = lilv_world_get_symbol(world, env->plugin1_uri); + LilvNode* path = lilv_new_uri(world, "http://example.org/foo"); + LilvNode* path_sym = lilv_world_get_symbol(world, path); + LilvNode* query = lilv_new_uri(world, "http://example.org/foo?bar=baz"); + LilvNode* query_sym = lilv_world_get_symbol(world, query); + LilvNode* frag = lilv_new_uri(world, "http://example.org/foo#bar"); + LilvNode* frag_sym = lilv_world_get_symbol(world, frag); + LilvNode* queryfrag = + lilv_new_uri(world, "http://example.org/foo?bar=baz#quux"); + LilvNode* queryfrag_sym = lilv_world_get_symbol(world, queryfrag); + LilvNode* nonuri = lilv_new_int(world, 42); + + assert(lilv_world_get_symbol(world, nonuri) == NULL); + assert(!strcmp(lilv_node_as_string(plug_sym), "plugsym")); + assert(!strcmp(lilv_node_as_string(path_sym), "foo")); + assert(!strcmp(lilv_node_as_string(query_sym), "bar_baz")); + assert(!strcmp(lilv_node_as_string(frag_sym), "bar")); + assert(!strcmp(lilv_node_as_string(queryfrag_sym), "quux")); + + lilv_node_free(nonuri); + lilv_node_free(queryfrag_sym); + lilv_node_free(queryfrag); + lilv_node_free(frag_sym); + lilv_node_free(frag); + lilv_node_free(query_sym); + lilv_node_free(query); + lilv_node_free(path_sym); + lilv_node_free(path); + lilv_node_free(plug_sym); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_no_author.c b/test/test_no_author.c new file mode 100644 index 0000000..9cceedc --- /dev/null +++ b/test/test_no_author.c @@ -0,0 +1,87 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> + +static const char* const plugin_ttl = "\ + :plug\n\ + a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin with project\" ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5 \n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ + ] . \n\ +\n\ + :thing doap:name \"Something else\" .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvNode* author_name = lilv_plugin_get_author_name(plug); + assert(!author_name); + + LilvNode* author_email = lilv_plugin_get_author_email(plug); + assert(!author_email); + + LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); + assert(!author_homepage); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_no_verify.c b/test/test_no_verify.c new file mode 100644 index 0000000..70812a5 --- /dev/null +++ b/test/test_no_verify.c @@ -0,0 +1,48 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> + +static const char* const plugin_ttl = ":plug a lv2:Plugin .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* explug = + lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + + assert(explug); + assert(!lilv_plugin_verify(explug)); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_plugin.c b/test/test_plugin.c new file mode 100644 index 0000000..6eab638 --- /dev/null +++ b/test/test_plugin.c @@ -0,0 +1,296 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "../src/lilv_internal.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <float.h> +#include <math.h> +#include <stdbool.h> +#include <stdlib.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +:plug\n\ + a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:optionalFeature lv2:hardRTCapable ;\n\ + lv2:requiredFeature <http://lv2plug.in/ns/ext/event> ;\n\ + lv2:extensionData <http://example.org/extdata> ;\n\ + :foo 1.6180 ;\n\ + :bar true ;\n\ + :baz false ;\n\ + :blank [ a <http://example.org/blank> ] ;\n\ + doap:maintainer [\n\ + foaf:name \"David Robillard\" ;\n\ + foaf:homepage <http://drobilla.net> ;\n\ + foaf:mbox <mailto:d@drobilla.net>\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ +] .\n\ +\n\ +:thing doap:name \"Something else\" .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + const LilvPluginClass* klass = lilv_plugin_get_class(plug); + const LilvNode* klass_uri = lilv_plugin_class_get_uri(klass); + assert(!strcmp(lilv_node_as_string(klass_uri), + "http://lv2plug.in/ns/lv2core#CompressorPlugin")); + + LilvNode* rdf_type = + lilv_new_uri(world, "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); + assert( + lilv_world_ask(world, lilv_plugin_get_uri(plug), rdf_type, klass_uri)); + lilv_node_free(rdf_type); + + assert(!lilv_plugin_is_replaced(plug)); + assert(!lilv_plugin_get_related(plug, NULL)); + + const LilvNode* plug_bundle_uri = lilv_plugin_get_bundle_uri(plug); + assert(!strcmp(lilv_node_as_string(plug_bundle_uri), env->test_bundle_uri)); + + const LilvNodes* data_uris = lilv_plugin_get_data_uris(plug); + assert(lilv_nodes_size(data_uris) == 2); + + LilvNode* project = lilv_plugin_get_project(plug); + assert(!project); + + char* manifest_uri = lilv_strjoin(lilv_node_as_string(plug_bundle_uri), + "manifest.ttl", + NULL); + + char* data_uri = + lilv_strjoin(lilv_node_as_string(plug_bundle_uri), "plugin.ttl", NULL); + + LilvNode* manifest_uri_val = lilv_new_uri(world, manifest_uri); + assert(lilv_nodes_contains(data_uris, manifest_uri_val)); + lilv_node_free(manifest_uri_val); + + LilvNode* data_uri_val = lilv_new_uri(world, data_uri); + assert(lilv_nodes_contains(data_uris, data_uri_val)); + lilv_node_free(data_uri_val); + + LilvNode* unknown_uri_val = + lilv_new_uri(world, "http://example.org/unknown"); + assert(!lilv_nodes_contains(data_uris, unknown_uri_val)); + lilv_node_free(unknown_uri_val); + + free(manifest_uri); + free(data_uri); + + float mins[3]; + float maxs[3]; + float defs[3]; + lilv_plugin_get_port_ranges_float(plug, mins, maxs, defs); + assert(mins[0] == -1.0f); + assert(maxs[0] == 1.0f); + assert(defs[0] == 0.5f); + + LilvNode* audio_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#AudioPort"); + LilvNode* control_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#ControlPort"); + LilvNode* in_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#InputPort"); + LilvNode* out_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#OutputPort"); + + assert(lilv_plugin_get_num_ports_of_class(plug, control_class, NULL) == 3); + assert(lilv_plugin_get_num_ports_of_class(plug, audio_class, NULL) == 0); + assert(lilv_plugin_get_num_ports_of_class(plug, in_class, NULL) == 2); + assert(lilv_plugin_get_num_ports_of_class(plug, out_class, NULL) == 1); + assert(lilv_plugin_get_num_ports_of_class( + plug, control_class, in_class, NULL) == 2); + assert(lilv_plugin_get_num_ports_of_class( + plug, control_class, out_class, NULL) == 1); + assert( + lilv_plugin_get_num_ports_of_class(plug, audio_class, in_class, NULL) == + 0); + assert(lilv_plugin_get_num_ports_of_class( + plug, audio_class, out_class, NULL) == 0); + + assert(lilv_plugin_has_latency(plug)); + assert(lilv_plugin_get_latency_port_index(plug) == 2); + + LilvNode* lv2_latency = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#latency"); + const LilvPort* latency_port = + lilv_plugin_get_port_by_designation(plug, out_class, lv2_latency); + lilv_node_free(lv2_latency); + + assert(latency_port); + assert(lilv_port_get_index(plug, latency_port) == 2); + assert(lilv_node_is_blank(lilv_port_get_node(plug, latency_port))); + + LilvNode* rt_feature = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#hardRTCapable"); + LilvNode* event_feature = + lilv_new_uri(world, "http://lv2plug.in/ns/ext/event"); + LilvNode* pretend_feature = + lilv_new_uri(world, "http://example.org/solvesWorldHunger"); + + assert(lilv_plugin_has_feature(plug, rt_feature)); + assert(lilv_plugin_has_feature(plug, event_feature)); + assert(!lilv_plugin_has_feature(plug, pretend_feature)); + + lilv_node_free(rt_feature); + lilv_node_free(event_feature); + lilv_node_free(pretend_feature); + + LilvNodes* supported = lilv_plugin_get_supported_features(plug); + LilvNodes* required = lilv_plugin_get_required_features(plug); + LilvNodes* optional = lilv_plugin_get_optional_features(plug); + assert(lilv_nodes_size(supported) == 2); + assert(lilv_nodes_size(required) == 1); + assert(lilv_nodes_size(optional) == 1); + lilv_nodes_free(supported); + lilv_nodes_free(required); + lilv_nodes_free(optional); + + LilvNode* foo_p = lilv_new_uri(world, "http://example.org/foo"); + LilvNodes* foos = lilv_plugin_get_value(plug, foo_p); + assert(lilv_nodes_size(foos) == 1); + assert(fabs(lilv_node_as_float(lilv_nodes_get_first(foos)) - 1.6180) < + FLT_EPSILON); + lilv_node_free(foo_p); + lilv_nodes_free(foos); + + LilvNode* bar_p = lilv_new_uri(world, "http://example.org/bar"); + LilvNodes* bars = lilv_plugin_get_value(plug, bar_p); + assert(lilv_nodes_size(bars) == 1); + assert(lilv_node_as_bool(lilv_nodes_get_first(bars)) == true); + lilv_node_free(bar_p); + lilv_nodes_free(bars); + + LilvNode* baz_p = lilv_new_uri(world, "http://example.org/baz"); + LilvNodes* bazs = lilv_plugin_get_value(plug, baz_p); + assert(lilv_nodes_size(bazs) == 1); + assert(lilv_node_as_bool(lilv_nodes_get_first(bazs)) == false); + lilv_node_free(baz_p); + lilv_nodes_free(bazs); + + LilvNode* blank_p = lilv_new_uri(world, "http://example.org/blank"); + LilvNodes* blanks = lilv_plugin_get_value(plug, blank_p); + assert(lilv_nodes_size(blanks) == 1); + LilvNode* blank = lilv_nodes_get_first(blanks); + assert(lilv_node_is_blank(blank)); + const char* blank_str = lilv_node_as_blank(blank); + char* blank_tok = lilv_node_get_turtle_token(blank); + assert(!strncmp(blank_tok, "_:", 2)); + assert(!strcmp(blank_tok + 2, blank_str)); + lilv_free(blank_tok); + lilv_node_free(blank_p); + lilv_nodes_free(blanks); + + LilvNode* author_name = lilv_plugin_get_author_name(plug); + assert(!strcmp(lilv_node_as_string(author_name), "David Robillard")); + lilv_node_free(author_name); + + LilvNode* author_email = lilv_plugin_get_author_email(plug); + assert(!strcmp(lilv_node_as_string(author_email), "mailto:d@drobilla.net")); + lilv_node_free(author_email); + + LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); + assert( + !strcmp(lilv_node_as_string(author_homepage), "http://drobilla.net")); + lilv_node_free(author_homepage); + + LilvNode* thing_uri = lilv_new_uri(world, "http://example.org/thing"); + LilvNode* name_p = lilv_new_uri(world, "http://usefulinc.com/ns/doap#name"); + LilvNodes* thing_names = + lilv_world_find_nodes(world, thing_uri, name_p, NULL); + assert(lilv_nodes_size(thing_names) == 1); + LilvNode* thing_name = lilv_nodes_get_first(thing_names); + assert(thing_name); + assert(lilv_node_is_string(thing_name)); + assert(!strcmp(lilv_node_as_string(thing_name), "Something else")); + LilvNode* thing_name2 = lilv_world_get(world, thing_uri, name_p, NULL); + assert(lilv_node_equals(thing_name, thing_name2)); + + LilvUIs* uis = lilv_plugin_get_uis(plug); + assert(lilv_uis_size(uis) == 0); + lilv_uis_free(uis); + + LilvNode* extdata = lilv_new_uri(world, "http://example.org/extdata"); + LilvNode* noextdata = lilv_new_uri(world, "http://example.org/noextdata"); + LilvNodes* extdatas = lilv_plugin_get_extension_data(plug); + assert(lilv_plugin_has_extension_data(plug, extdata)); + assert(!lilv_plugin_has_extension_data(plug, noextdata)); + assert(lilv_nodes_size(extdatas) == 1); + assert(lilv_node_equals(lilv_nodes_get_first(extdatas), extdata)); + lilv_node_free(noextdata); + lilv_node_free(extdata); + lilv_nodes_free(extdatas); + + lilv_nodes_free(thing_names); + lilv_node_free(thing_uri); + lilv_node_free(thing_name2); + lilv_node_free(name_p); + lilv_node_free(control_class); + lilv_node_free(audio_class); + lilv_node_free(in_class); + lilv_node_free(out_class); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_port.c b/test/test_port.c new file mode 100644 index 0000000..63f8bd0 --- /dev/null +++ b/test/test_port.c @@ -0,0 +1,331 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <stdbool.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +@prefix lv2ev: <http://lv2plug.in/ns/ext/event#> . \n\ +:plug\n\ + a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + doap:homepage <http://example.org/someplug> ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"store\" ;\n\ + lv2:name \"Laden\"@de-de ;\n\ + lv2:name \"Geschaeft\"@de-at ;\n\ + lv2:name \"tienda\"@es ;\n\ + rdfs:comment \"comment\"@en , \"commentaires\"@fr ;\n\ + lv2:portProperty lv2:integer ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5 ;\n\ + lv2:scalePoint [\n\ + rdfs:label \"Sin\";\n\ + rdf:value 3\n\ + ] ;\n\ + lv2:scalePoint [\n\ + rdfs:label \"Cos\";\n\ + rdf:value 4\n\ + ]\n\ + ] , [\n\ + a lv2:EventPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"event_in\" ;\n\ + lv2:name \"Event Input\" ;\n\ + lv2ev:supportsEvent <http://example.org/event> ;\n\ + atom:supports <http://example.org/atomEvent>\n\ + ] , [\n\ + a lv2:AudioPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"audio_in\" ;\n\ + lv2:name \"Audio Input\" ;\n\ + ] , [\n\ + a lv2:AudioPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 3 ;\n\ + lv2:symbol \"audio_out\" ;\n\ + lv2:name \"Audio Output\" ;\n\ + ] .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvNode* psym = lilv_new_string(world, "foo"); + const LilvPort* p = lilv_plugin_get_port_by_index(plug, 0); + const LilvPort* p2 = lilv_plugin_get_port_by_symbol(plug, psym); + lilv_node_free(psym); + assert(p != NULL); + assert(p2 != NULL); + assert(p == p2); + + LilvNode* nopsym = lilv_new_string(world, "thisaintnoportfoo"); + const LilvPort* p3 = lilv_plugin_get_port_by_symbol(plug, nopsym); + assert(p3 == NULL); + lilv_node_free(nopsym); + + // Try getting an invalid property + LilvNode* num = lilv_new_int(world, 1); + LilvNodes* nothing = lilv_port_get_value(plug, p, num); + assert(!nothing); + lilv_node_free(num); + + LilvNode* audio_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#AudioPort"); + LilvNode* control_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#ControlPort"); + LilvNode* in_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#InputPort"); + LilvNode* out_class = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#OutputPort"); + + assert(lilv_nodes_size(lilv_port_get_classes(plug, p)) == 2); + assert(lilv_plugin_get_num_ports(plug) == 4); + assert(lilv_port_is_a(plug, p, control_class)); + assert(lilv_port_is_a(plug, p, in_class)); + assert(!lilv_port_is_a(plug, p, audio_class)); + + LilvNodes* port_properties = lilv_port_get_properties(plug, p); + assert(lilv_nodes_size(port_properties) == 1); + lilv_nodes_free(port_properties); + + // Untranslated name (current locale is set to "C" in main) + assert(!strcmp(lilv_node_as_string(lilv_port_get_symbol(plug, p)), "foo")); + LilvNode* name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "store")); + lilv_node_free(name); + + // Exact language match + set_env("LANG", "de_DE"); + name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "Laden")); + lilv_node_free(name); + + // Exact language match (with charset suffix) + set_env("LANG", "de_AT.utf8"); + name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "Geschaeft")); + lilv_node_free(name); + + // Partial language match (choose value translated for different country) + set_env("LANG", "de_CH"); + name = lilv_port_get_name(plug, p); + assert((!strcmp(lilv_node_as_string(name), "Laden")) || + (!strcmp(lilv_node_as_string(name), "Geschaeft"))); + lilv_node_free(name); + + // Partial language match (choose country-less language tagged value) + set_env("LANG", "es_MX"); + name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "tienda")); + lilv_node_free(name); + + // No language match (choose untranslated value) + set_env("LANG", "cn"); + name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "store")); + lilv_node_free(name); + + // Invalid language + set_env("LANG", "1!"); + name = lilv_port_get_name(plug, p); + assert(!strcmp(lilv_node_as_string(name), "store")); + lilv_node_free(name); + + set_env("LANG", "en_CA.utf-8"); + + // Language tagged value with no untranslated values + LilvNode* rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment"); + LilvNodes* comments = lilv_port_get_value(plug, p, rdfs_comment); + assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)), + "comment")); + LilvNode* comment = lilv_port_get(plug, p, rdfs_comment); + assert(!strcmp(lilv_node_as_string(comment), "comment")); + lilv_node_free(comment); + lilv_nodes_free(comments); + + set_env("LANG", "fr"); + + comments = lilv_port_get_value(plug, p, rdfs_comment); + assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(comments)), + "commentaires")); + lilv_nodes_free(comments); + + set_env("LANG", "cn"); + + comments = lilv_port_get_value(plug, p, rdfs_comment); + assert(!comments); + lilv_nodes_free(comments); + + lilv_node_free(rdfs_comment); + + set_env("LANG", "C"); // Reset locale + + LilvScalePoints* points = lilv_port_get_scale_points(plug, p); + assert(lilv_scale_points_size(points) == 2); + + LilvIter* sp_iter = lilv_scale_points_begin(points); + const LilvScalePoint* sp0 = lilv_scale_points_get(points, sp_iter); + assert(sp0); + sp_iter = lilv_scale_points_next(points, sp_iter); + const LilvScalePoint* sp1 = lilv_scale_points_get(points, sp_iter); + assert(sp1); + + assert(((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), + "Sin") && + lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 3) && + (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), + "Cos") && + lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 4)) || + ((!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp0)), + "Cos") && + lilv_node_as_float(lilv_scale_point_get_value(sp0)) == 4) && + (!strcmp(lilv_node_as_string(lilv_scale_point_get_label(sp1)), + "Sin") && + lilv_node_as_float(lilv_scale_point_get_value(sp1)) == 3))); + + LilvNode* homepage_p = + lilv_new_uri(world, "http://usefulinc.com/ns/doap#homepage"); + LilvNodes* homepages = lilv_plugin_get_value(plug, homepage_p); + assert(lilv_nodes_size(homepages) == 1); + assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(homepages)), + "http://example.org/someplug")); + + LilvNode *min, *max, *def; + lilv_port_get_range(plug, p, &def, &min, &max); + assert(def); + assert(min); + assert(max); + assert(lilv_node_as_float(def) == 0.5); + assert(lilv_node_as_float(min) == -1.0); + assert(lilv_node_as_float(max) == 1.0); + + LilvNode* integer_prop = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#integer"); + LilvNode* toggled_prop = + lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#toggled"); + + assert(lilv_port_has_property(plug, p, integer_prop)); + assert(!lilv_port_has_property(plug, p, toggled_prop)); + + const LilvPort* ep = lilv_plugin_get_port_by_index(plug, 1); + + LilvNode* event_type = lilv_new_uri(world, "http://example.org/event"); + LilvNode* event_type_2 = + lilv_new_uri(world, "http://example.org/otherEvent"); + LilvNode* atom_event = lilv_new_uri(world, "http://example.org/atomEvent"); + assert(lilv_port_supports_event(plug, ep, event_type)); + assert(!lilv_port_supports_event(plug, ep, event_type_2)); + assert(lilv_port_supports_event(plug, ep, atom_event)); + + LilvNode* name_p = lilv_new_uri(world, "http://lv2plug.in/ns/lv2core#name"); + LilvNodes* names = lilv_port_get_value(plug, p, name_p); + assert(lilv_nodes_size(names) == 1); + assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), "store")); + lilv_nodes_free(names); + + LilvNode* true_val = lilv_new_bool(world, true); + LilvNode* false_val = lilv_new_bool(world, false); + + assert(!lilv_node_equals(true_val, false_val)); + + lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, false_val); + names = lilv_port_get_value(plug, p, name_p); + assert(lilv_nodes_size(names) == 4); + lilv_nodes_free(names); + lilv_world_set_option(world, LILV_OPTION_FILTER_LANG, true_val); + + lilv_node_free(false_val); + lilv_node_free(true_val); + + names = lilv_port_get_value(plug, ep, name_p); + assert(lilv_nodes_size(names) == 1); + assert(!strcmp(lilv_node_as_string(lilv_nodes_get_first(names)), + "Event Input")); + + const LilvPort* ap_in = lilv_plugin_get_port_by_index(plug, 2); + + assert(lilv_port_is_a(plug, ap_in, in_class)); + assert(!lilv_port_is_a(plug, ap_in, out_class)); + assert(lilv_port_is_a(plug, ap_in, audio_class)); + assert(!lilv_port_is_a(plug, ap_in, control_class)); + + const LilvPort* ap_out = lilv_plugin_get_port_by_index(plug, 3); + + assert(lilv_port_is_a(plug, ap_out, out_class)); + assert(!lilv_port_is_a(plug, ap_out, in_class)); + assert(lilv_port_is_a(plug, ap_out, audio_class)); + assert(!lilv_port_is_a(plug, ap_out, control_class)); + + assert(lilv_plugin_get_num_ports_of_class( + plug, control_class, in_class, NULL) == 1); + assert( + lilv_plugin_get_num_ports_of_class(plug, audio_class, in_class, NULL) == + 1); + assert(lilv_plugin_get_num_ports_of_class( + plug, audio_class, out_class, NULL) == 1); + + lilv_nodes_free(names); + lilv_node_free(name_p); + + lilv_node_free(integer_prop); + lilv_node_free(toggled_prop); + lilv_node_free(event_type); + lilv_node_free(event_type_2); + lilv_node_free(atom_event); + + lilv_node_free(min); + lilv_node_free(max); + lilv_node_free(def); + + lilv_node_free(homepage_p); + lilv_nodes_free(homepages); + + lilv_scale_points_free(points); + lilv_node_free(control_class); + lilv_node_free(audio_class); + lilv_node_free(out_class); + lilv_node_free(in_class); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_preset.c b/test/test_preset.c new file mode 100644 index 0000000..d26d844 --- /dev/null +++ b/test/test_preset.c @@ -0,0 +1,93 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" +#include "lv2/presets/presets.h" + +#include <assert.h> + +static const char* const plugin_ttl = "\ +:plug\n\ + a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin with project\" ;\n\ + lv2:project [\n\ + doap:name \"Fake project\" ;\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ + ] .\n\ +\n\ +<http://example.org/preset>\n\ + a pset:Preset ;\n\ + lv2:appliesTo :plug ;\n\ + rdfs:label \"some preset\" .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvNode* pset_Preset = lilv_new_uri(world, LV2_PRESETS__Preset); + LilvNodes* related = lilv_plugin_get_related(plug, pset_Preset); + + assert(lilv_nodes_size(related) == 1); + + lilv_node_free(pset_Preset); + lilv_nodes_free(related); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_project.c b/test/test_project.c new file mode 100644 index 0000000..bc2e2c3 --- /dev/null +++ b/test/test_project.c @@ -0,0 +1,97 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +:plug\n\ + a lv2:Plugin;\n\ + a lv2:CompressorPlugin;\n\ + doap:name \"Test plugin with project\" ;\n\ + lv2:project [\n\ + doap:maintainer [\n\ + foaf:name \"David Robillard\" ;\n\ + foaf:homepage <http://drobilla.net> ;\n\ + foaf:mbox <mailto:d@drobilla.net>\n\ + ] ;\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ + ] .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvNode* author_name = lilv_plugin_get_author_name(plug); + assert(!strcmp(lilv_node_as_string(author_name), "David Robillard")); + lilv_node_free(author_name); + + LilvNode* author_email = lilv_plugin_get_author_email(plug); + assert(!strcmp(lilv_node_as_string(author_email), "mailto:d@drobilla.net")); + lilv_node_free(author_email); + + LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); + assert( + !strcmp(lilv_node_as_string(author_homepage), "http://drobilla.net")); + lilv_node_free(author_homepage); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_project_no_author.c b/test/test_project_no_author.c new file mode 100644 index 0000000..017d359 --- /dev/null +++ b/test/test_project_no_author.c @@ -0,0 +1,87 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin with project\" ;\n\ + lv2:project [\n\ + doap:name \"Fake project\" ;\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ + ] .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvNode* author_name = lilv_plugin_get_author_name(plug); + assert(!author_name); + + LilvNode* author_email = lilv_plugin_get_author_email(plug); + assert(!author_email); + + LilvNode* author_homepage = lilv_plugin_get_author_homepage(plug); + assert(!author_homepage); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_prototype.c b/test/test_prototype.c new file mode 100644 index 0000000..4ad516e --- /dev/null +++ b/test/test_prototype.c @@ -0,0 +1,100 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +static const char* const manifest_ttl = "\ +:prot\n\ + a lv2:PluginBase ;\n\ + rdfs:seeAlso <plugin.ttl> .\n\ +\n\ +:plug\n\ + a lv2:Plugin ;\n\ + lv2:binary <inst" SHLIB_EXT "> ;\n\ + lv2:prototype :prot .\n"; + +static const char* const plugin_ttl = "\ +:prot\n\ + a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + lv2:project [\n\ + doap:name \"Fake project\" ;\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency ;\n\ + lv2:designation lv2:latency\n\ + ] .\n\ +\n\ +:plug doap:name \"Instance\" .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, manifest_ttl, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + // Test non-inherited property + LilvNode* name = lilv_plugin_get_name(plug); + assert(!strcmp(lilv_node_as_string(name), "Instance")); + lilv_node_free(name); + + // Test inherited property + const LilvNode* binary = lilv_plugin_get_library_uri(plug); + assert(strstr(lilv_node_as_string(binary), "inst" SHLIB_EXT)); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_reload_bundle.c b/test/test_reload_bundle.c new file mode 100644 index 0000000..19644ff --- /dev/null +++ b/test/test_reload_bundle.c @@ -0,0 +1,92 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <string.h> + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + // Create a simple plugin bundle + create_bundle(env, + ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT + "> ; rdfs:seeAlso <plugin.ttl> .\n", + ":plug a lv2:Plugin ; " + "doap:name \"First name\" ."); + + lilv_world_load_specifications(world); + + // Load bundle + LilvNode* bundle_uri = lilv_new_uri(world, env->test_bundle_uri); + lilv_world_load_bundle(world, bundle_uri); + + // Check that plugin is present + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + // Check that plugin name is correct + LilvNode* name = lilv_plugin_get_name(plug); + assert(!strcmp(lilv_node_as_string(name), "First name")); + lilv_node_free(name); + + // Unload bundle from world and delete it + lilv_world_unload_bundle(world, bundle_uri); + delete_bundle(env); + + // Create a new version of the same bundle, but with a different name + create_bundle(env, + ":plug a lv2:Plugin ; lv2:binary <foo" SHLIB_EXT + "> ; rdfs:seeAlso <plugin.ttl> .\n", + ":plug a lv2:Plugin ; " + "doap:name \"Second name\" ."); + + // Check that plugin is no longer in the world's plugin list + assert(lilv_plugins_size(plugins) == 0); + + // Load new bundle + lilv_world_load_bundle(world, bundle_uri); + + // Check that plugin is present again and is the same LilvPlugin + const LilvPlugin* plug2 = + lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug2); + assert(plug2 == plug); + + // Check that plugin now has new name + LilvNode* name2 = lilv_plugin_get_name(plug2); + assert(name2); + assert(!strcmp(lilv_node_as_string(name2), "Second name")); + lilv_node_free(name2); + + // Load new bundle again (noop) + lilv_world_load_bundle(world, bundle_uri); + + lilv_node_free(bundle_uri); + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_replace_version.c b/test/test_replace_version.c new file mode 100644 index 0000000..a686572 --- /dev/null +++ b/test/test_replace_version.c @@ -0,0 +1,105 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "../src/lilv_internal.h" + +#include "lilv/lilv.h" +#include "lv2/core/lv2.h" + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + LilvNode* plug_uri = lilv_new_uri(world, "http://example.org/versioned"); + LilvNode* lv2_minorVersion = lilv_new_uri(world, LV2_CORE__minorVersion); + LilvNode* lv2_microVersion = lilv_new_uri(world, LV2_CORE__microVersion); + LilvNode* minor = NULL; + LilvNode* micro = NULL; + + char* old_bundle_path = lilv_strjoin(LILV_TEST_DIR, "old_version.lv2/", 0); + + // Load plugin from old bundle + LilvNode* old_bundle = lilv_new_file_uri(world, NULL, old_bundle_path); + lilv_world_load_bundle(world, old_bundle); + lilv_world_load_resource(world, plug_uri); + + // Check version + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* old_plug = lilv_plugins_get_by_uri(plugins, plug_uri); + assert(old_plug); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + assert(!strcmp(lilv_node_as_string(minor), "1")); + assert(!strcmp(lilv_node_as_string(micro), "0")); + lilv_node_free(micro); + lilv_node_free(minor); + + char* new_bundle_path = lilv_strjoin(LILV_TEST_DIR, "new_version.lv2/", 0); + + // Load plugin from new bundle + LilvNode* new_bundle = lilv_new_file_uri(world, NULL, new_bundle_path); + lilv_world_load_bundle(world, new_bundle); + lilv_world_load_resource(world, plug_uri); + + // Check that version in the world model has changed + plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); + assert(new_plug); + assert(lilv_node_equals(lilv_plugin_get_bundle_uri(new_plug), new_bundle)); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + assert(!strcmp(lilv_node_as_string(minor), "2")); + assert(!strcmp(lilv_node_as_string(micro), "1")); + lilv_node_free(micro); + lilv_node_free(minor); + + // Try to load the old version again + lilv_world_load_bundle(world, old_bundle); + lilv_world_load_resource(world, plug_uri); + + // Check that version in the world model has not changed + plugins = lilv_world_get_all_plugins(world); + new_plug = lilv_plugins_get_by_uri(plugins, plug_uri); + assert(new_plug); + minor = lilv_world_get(world, plug_uri, lv2_minorVersion, 0); + micro = lilv_world_get(world, plug_uri, lv2_microVersion, 0); + assert(!strcmp(lilv_node_as_string(minor), "2")); + assert(!strcmp(lilv_node_as_string(micro), "1")); + lilv_node_free(micro); + lilv_node_free(minor); + + lilv_node_free(new_bundle); + lilv_node_free(old_bundle); + free(new_bundle_path); + free(old_bundle_path); + lilv_node_free(plug_uri); + lilv_node_free(lv2_minorVersion); + lilv_node_free(lv2_microVersion); + + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_state.c b/test/test_state.c new file mode 100644 index 0000000..6eb7793 --- /dev/null +++ b/test/test_state.c @@ -0,0 +1,581 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "../src/lilv_internal.h" + +#include "lilv/lilv.h" +#include "lv2/core/lv2.h" +#include "lv2/state/state.h" +#include "lv2/urid/urid.h" +#include "serd/serd.h" + +#ifdef _WIN32 +# include <direct.h> +# define mkdir(path, flags) _mkdir(path) +#else +# include <sys/stat.h> +# include <unistd.h> +#endif + +#include <assert.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +uint32_t atom_Float = 0; +float in = 1.0; +float out = 42.0; +float control = 1234.0; + +static const void* +get_port_value(const char* port_symbol, + void* user_data, + uint32_t* size, + uint32_t* type) +{ + if (!strcmp(port_symbol, "input")) { + *size = sizeof(float); + *type = atom_Float; + return ∈ + } else if (!strcmp(port_symbol, "output")) { + *size = sizeof(float); + *type = atom_Float; + return &out; + } else if (!strcmp(port_symbol, "control")) { + *size = sizeof(float); + *type = atom_Float; + return &control; + } else { + fprintf(stderr, + "error: get_port_value for nonexistent port `%s'\n", + port_symbol); + *size = *type = 0; + return NULL; + } +} + +static void +set_port_value(const char* port_symbol, + void* user_data, + const void* value, + uint32_t size, + uint32_t type) +{ + if (!strcmp(port_symbol, "input")) { + in = *(const float*)value; + } else if (!strcmp(port_symbol, "output")) { + out = *(const float*)value; + } else if (!strcmp(port_symbol, "control")) { + control = *(const float*)value; + } else { + fprintf(stderr, + "error: set_port_value for nonexistent port `%s'\n", + port_symbol); + } +} + +char** uris = NULL; +size_t n_uris = 0; + +static LV2_URID +map_uri(LV2_URID_Map_Handle handle, const char* uri) +{ + for (size_t i = 0; i < n_uris; ++i) { + if (!strcmp(uris[i], uri)) { + return i + 1; + } + } + + assert(serd_uri_string_has_scheme((const uint8_t*)uri)); + uris = (char**)realloc(uris, ++n_uris * sizeof(char*)); + uris[n_uris - 1] = lilv_strdup(uri); + return n_uris; +} + +static const char* +unmap_uri(LV2_URID_Map_Handle handle, LV2_URID urid) +{ + if (urid > 0 && urid <= n_uris) { + return uris[urid - 1]; + } + return NULL; +} + +static char* temp_dir = NULL; + +static char* +lilv_make_path(LV2_State_Make_Path_Handle handle, const char* path) +{ + return lilv_path_join(temp_dir, path); +} + +static void +lilv_free_path(LV2_State_Free_Path_Handle handle, char* path) +{ + lilv_free(path); +} + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + uint8_t* abs_bundle = (uint8_t*)lilv_path_absolute(LILV_TEST_BUNDLE); + SerdNode bundle = serd_node_new_file_uri(abs_bundle, 0, 0, true); + LilvNode* bundle_uri = lilv_new_uri(world, (const char*)bundle.buf); + LilvNode* plugin_uri = + lilv_new_uri(world, "http://example.org/lilv-test-plugin"); + lilv_world_load_bundle(world, bundle_uri); + free(abs_bundle); + serd_node_free(&bundle); + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri); + assert(plugin); + + LV2_URID_Map map = {NULL, map_uri}; + LV2_Feature map_feature = {LV2_URID_MAP_URI, &map}; + LV2_URID_Unmap unmap = {NULL, unmap_uri}; + LV2_Feature unmap_feature = {LV2_URID_UNMAP_URI, &unmap}; + const LV2_Feature* features[] = {&map_feature, &unmap_feature, NULL}; + + atom_Float = map.map(map.handle, "http://lv2plug.in/ns/ext/atom#Float"); + + LilvNode* num = lilv_new_int(world, 5); + LilvState* nostate = lilv_state_new_from_file(world, &map, num, "/junk"); + assert(!nostate); + + LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, features); + assert(instance); + lilv_instance_activate(instance); + lilv_instance_connect_port(instance, 0, &in); + lilv_instance_connect_port(instance, 1, &out); + lilv_instance_run(instance, 1); + assert(in == 1.0); + assert(out == 1.0); + + temp_dir = lilv_realpath("temp"); + + const char* scratch_dir = NULL; + char* copy_dir = NULL; + char* link_dir = NULL; + char* save_dir = NULL; + + // Get instance state state + LilvState* state = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + save_dir, + get_port_value, + world, + 0, + NULL); + + // Get another instance state + LilvState* state2 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + save_dir, + get_port_value, + world, + 0, + NULL); + + // Ensure they are equal + assert(lilv_state_equals(state, state2)); + + // Check that we can't delete unsaved state + assert(lilv_state_delete(world, state)); + + // Check that state has no URI + assert(!lilv_state_get_uri(state)); + + // Check that we can't save a state with no URI + char* bad_state_str = + lilv_state_to_string(world, &map, &unmap, state, NULL, NULL); + assert(!bad_state_str); + + // Check that we can't restore the NULL string (and it doesn't crash) + LilvState* bad_state = lilv_state_new_from_string(world, &map, NULL); + assert(!bad_state); + + // Save state to a string + char* state1_str = lilv_state_to_string( + world, &map, &unmap, state, "http://example.org/state1", NULL); + + // Restore from string + LilvState* from_str = lilv_state_new_from_string(world, &map, state1_str); + + // Ensure they are equal + assert(lilv_state_equals(state, from_str)); + lilv_free(state1_str); + + const LilvNode* state_plugin_uri = lilv_state_get_plugin_uri(state); + assert(lilv_node_equals(state_plugin_uri, plugin_uri)); + + // Tinker with the label of the first state + assert(lilv_state_get_label(state) == NULL); + lilv_state_set_label(state, "Test State Old Label"); + assert(!strcmp(lilv_state_get_label(state), "Test State Old Label")); + lilv_state_set_label(state, "Test State"); + assert(!strcmp(lilv_state_get_label(state), "Test State")); + + assert(!lilv_state_equals(state, state2)); // Label changed + + // Run and get a new instance state (which should now differ) + lilv_instance_run(instance, 1); + LilvState* state3 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + save_dir, + get_port_value, + world, + 0, + NULL); + assert(!lilv_state_equals(state2, state3)); // num_runs changed + + // Restore instance state to original state + lilv_state_restore(state2, instance, set_port_value, NULL, 0, NULL); + + // Take a new snapshot and ensure it matches the set state + LilvState* state4 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + save_dir, + get_port_value, + world, + 0, + NULL); + assert(lilv_state_equals(state2, state4)); + + // Set some metadata properties + lilv_state_set_metadata(state, + map.map(map.handle, LILV_NS_RDFS "comment"), + "This is a comment", + strlen("This is a comment") + 1, + map.map(map.handle, + "http://lv2plug.in/ns/ext/atom#Literal"), + LV2_STATE_IS_POD); + lilv_state_set_metadata(state, + map.map(map.handle, "http://example.org/metablob"), + "LIVEBEEF", + strlen("LIVEBEEF") + 1, + map.map(map.handle, "http://example.org/MetaBlob"), + 0); + + // Save state to a directory + int ret = lilv_state_save( + world, &map, &unmap, state, NULL, "state/state.lv2", "state.ttl"); + assert(!ret); + + // Load state from directory + LilvState* state5 = lilv_state_new_from_file(world, + &map, + NULL, + "state/state.lv2/state.ttl"); + + assert(lilv_state_equals(state, state5)); // Round trip accuracy + assert(lilv_state_get_num_properties(state) == 8); + + // Attempt to save state to nowhere (error) + ret = lilv_state_save(world, &map, &unmap, state, NULL, NULL, NULL); + assert(ret); + + // Save another state to the same directory (update manifest) + ret = lilv_state_save( + world, &map, &unmap, state, NULL, "state/state.lv2", "state2.ttl"); + assert(!ret); + + // Save state with URI to a directory + const char* state_uri = "http://example.org/state"; + ret = lilv_state_save(world, + &map, + &unmap, + state, + state_uri, + "state/state6.lv2", + "state6.ttl"); + assert(!ret); + + // Load state bundle into world and verify it matches + { + uint8_t* state6_path = + (uint8_t*)lilv_path_absolute("state/state6.lv2/"); + SerdNode state6_uri = serd_node_new_file_uri(state6_path, 0, 0, true); + LilvNode* state6_bundle = + lilv_new_uri(world, (const char*)state6_uri.buf); + LilvNode* state6_node = lilv_new_uri(world, state_uri); + lilv_world_load_bundle(world, state6_bundle); + lilv_world_load_resource(world, state6_node); + serd_node_free(&state6_uri); + lilv_free(state6_path); + + LilvState* state6 = lilv_state_new_from_world(world, &map, state6_node); + assert(lilv_state_equals(state, state6)); // Round trip accuracy + + // Check that loaded state has correct URI + assert(lilv_state_get_uri(state6)); + assert(!strcmp(lilv_node_as_string(lilv_state_get_uri(state6)), + state_uri)); + + // Unload state from world + lilv_world_unload_resource(world, state6_node); + lilv_world_unload_bundle(world, state6_bundle); + + // Ensure that it is no longer present + assert(!lilv_state_new_from_world(world, &map, state6_node)); + lilv_node_free(state6_bundle); + lilv_node_free(state6_node); + + // Delete state + lilv_state_delete(world, state6); + lilv_state_free(state6); + } + + // Make directories and test files support + mkdir("temp", 0700); + scratch_dir = temp_dir; + mkdir("files", 0700); + copy_dir = lilv_realpath("files"); + mkdir("links", 0700); + link_dir = lilv_realpath("links"); + + LV2_State_Make_Path make_path = {NULL, lilv_make_path}; + LV2_Feature make_path_feature = {LV2_STATE__makePath, &make_path}; + LV2_State_Free_Path free_path = {NULL, lilv_free_path}; + LV2_Feature free_path_feature = {LV2_STATE__freePath, &free_path}; + const LV2_Feature* ffeatures[] = {&make_path_feature, + &map_feature, + &free_path_feature, + NULL}; + + lilv_instance_deactivate(instance); + lilv_instance_free(instance); + instance = lilv_plugin_instantiate(plugin, 48000.0, ffeatures); + lilv_instance_activate(instance); + lilv_instance_connect_port(instance, 0, &in); + lilv_instance_connect_port(instance, 1, &out); + lilv_instance_run(instance, 1); + + // Test instantiating twice + LilvInstance* instance2 = + lilv_plugin_instantiate(plugin, 48000.0, ffeatures); + if (!instance2) { + fprintf(stderr, + "Failed to create multiple instances of <%s>\n", + lilv_node_as_uri(state_plugin_uri)); + return 1; + } + lilv_instance_free(instance2); + + // Get instance state state + LilvState* fstate = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + "state/fstate.lv2", + get_port_value, + world, + 0, + ffeatures); + + { + // Get another instance state + LilvState* fstate2 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + "state/fstate2.lv2", + get_port_value, + world, + 0, + ffeatures); + + // Check that it is identical + assert(lilv_state_equals(fstate, fstate2)); + + lilv_state_delete(world, fstate2); + lilv_state_free(fstate2); + } + + // Run, writing more to rec file + lilv_instance_run(instance, 2); + + // Get yet another instance state + LilvState* fstate3 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + "state/fstate3.lv2", + get_port_value, + world, + 0, + ffeatures); + + // Should be different + assert(!lilv_state_equals(fstate, fstate3)); + + // Save state to a directory + ret = lilv_state_save( + world, &map, &unmap, fstate, NULL, "state/fstate.lv2", "fstate.ttl"); + assert(!ret); + + // Load state from directory + LilvState* fstate4 = lilv_state_new_from_file( + world, &map, NULL, "state/fstate.lv2/fstate.ttl"); + assert(lilv_state_equals(fstate, fstate4)); // Round trip accuracy + + // Restore instance state to loaded state + lilv_state_restore(fstate4, instance, set_port_value, NULL, 0, ffeatures); + + // Take a new snapshot and ensure it matches + LilvState* fstate5 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + "state/fstate5.lv2", + get_port_value, + world, + 0, + ffeatures); + assert(lilv_state_equals(fstate3, fstate5)); + + // Save state to a (different) directory again + ret = lilv_state_save( + world, &map, &unmap, fstate, NULL, "state/fstate6.lv2", "fstate6.ttl"); + assert(!ret); + + // Reload it and ensure it's identical to the other loaded version + LilvState* fstate6 = lilv_state_new_from_file( + world, &map, NULL, "state/fstate6.lv2/fstate6.ttl"); + assert(lilv_state_equals(fstate4, fstate6)); + + // Run, changing rec file (without changing size) + lilv_instance_run(instance, 3); + + // Take a new snapshot + LilvState* fstate7 = lilv_state_new_from_instance(plugin, + instance, + &map, + scratch_dir, + copy_dir, + link_dir, + "state/fstate7.lv2", + get_port_value, + world, + 0, + ffeatures); + assert(!lilv_state_equals(fstate6, fstate7)); + + // Save the changed state to a (different) directory again + ret = lilv_state_save( + world, &map, &unmap, fstate7, NULL, "state/fstate7.lv2", "fstate7.ttl"); + assert(!ret); + + // Reload it and ensure it's changed + LilvState* fstate72 = lilv_state_new_from_file( + world, &map, NULL, "state/fstate7.lv2/fstate7.ttl"); + assert(lilv_state_equals(fstate72, fstate7)); + assert(!lilv_state_equals(fstate6, fstate72)); + + // Delete saved state we still have a state in memory that points to + lilv_state_delete(world, fstate7); + lilv_state_delete(world, fstate6); + lilv_state_delete(world, fstate5); + lilv_state_delete(world, fstate3); + lilv_state_delete(world, fstate); + lilv_state_delete(world, state2); + lilv_state_delete(world, state); + + // Delete remaining states on disk we've lost a reference to + const char* const old_state_paths[] = {"state/state.lv2/state.ttl", + "state/state.lv2/state2.ttl", + "state/fstate.lv2/fstate.ttl", + NULL}; + + for (const char* const* p = old_state_paths; *p; ++p) { + const char* path = *p; + LilvState* old_state = + lilv_state_new_from_file(world, &map, NULL, path); + lilv_state_delete(world, old_state); + lilv_state_free(old_state); + } + + lilv_instance_deactivate(instance); + lilv_instance_free(instance); + + lilv_node_free(num); + + lilv_state_free(state); + lilv_state_free(from_str); + lilv_state_free(state2); + lilv_state_free(state3); + lilv_state_free(state4); + lilv_state_free(state5); + lilv_state_free(fstate); + lilv_state_free(fstate3); + lilv_state_free(fstate4); + lilv_state_free(fstate5); + lilv_state_free(fstate6); + lilv_state_free(fstate7); + lilv_state_free(fstate72); + + rmdir("state"); + + // Free URI map + for (size_t i = 0; i < n_uris; ++i) { + free(uris[i]); + } + free(uris); + n_uris = 0; + + lilv_node_free(plugin_uri); + lilv_node_free(bundle_uri); + free(link_dir); + free(copy_dir); + free(temp_dir); + + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_string.c b/test/test_string.c new file mode 100644 index 0000000..8d79327 --- /dev/null +++ b/test/test_string.c @@ -0,0 +1,94 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#define _POSIX_C_SOURCE 200809L /* for setenv */ + +#undef NDEBUG + +#include "../src/lilv_internal.h" + +#ifdef _WIN32 +# include <windows.h> +# define setenv(n, v, r) SetEnvironmentVariable((n), (v)) +# define unsetenv(n) SetEnvironmentVariable((n), NULL) +#endif + +#include <assert.h> +#include <stdlib.h> +#include <string.h> + +int +main(void) +{ + char* s = NULL; + + assert(!strcmp((s = lilv_dirname("/foo/bar")), "/foo")); + free(s); + assert(!strcmp((s = lilv_dirname("/foo/bar/")), "/foo")); + free(s); + assert(!strcmp((s = lilv_dirname("/foo///bar/")), "/foo")); + free(s); + assert(!strcmp((s = lilv_dirname("/foo///bar//")), "/foo")); + free(s); + assert(!strcmp((s = lilv_dirname("foo")), ".")); + free(s); + assert(!strcmp((s = lilv_dirname("/foo")), "/")); + free(s); + assert(!strcmp((s = lilv_dirname("/")), "/")); + free(s); + assert(!strcmp((s = lilv_dirname("//")), "/")); + free(s); + assert(!strcmp((s = lilv_path_relative_to("/a/b", "/a/")), "b")); + free(s); + assert(!strcmp((s = lilv_path_relative_to("/a", "/b/c/")), "/a")); + free(s); + assert(!strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/")), "../c")); + free(s); + assert( + !strcmp((s = lilv_path_relative_to("/a/b/c", "/a/b/d/e/")), "../../c")); + free(s); + assert(!strcmp((s = lilv_path_join("/a", "b")), "/a/b")); + free(s); + assert(!strcmp((s = lilv_path_join("/a", "/b")), "/a/b")); + free(s); + assert(!strcmp((s = lilv_path_join("/a/", "/b")), "/a/b")); + free(s); + assert(!strcmp((s = lilv_path_join("/a/", "b")), "/a/b")); + free(s); + assert(!strcmp((s = lilv_path_join("/a", NULL)), "/a/")); + free(s); + assert(!strcmp((s = lilv_path_join(NULL, "/b")), "/b")); + free(s); + +#ifndef _WIN32 + setenv("LILV_TEST_1", "test", 1); + char* home_foo = lilv_strjoin(getenv("HOME"), "/foo", NULL); + assert(!strcmp((s = lilv_expand("$LILV_TEST_1")), "test")); + free(s); + assert(!strcmp((s = lilv_expand("~")), getenv("HOME"))); + free(s); + assert(!strcmp((s = lilv_expand("~foo")), "~foo")); + free(s); + assert(!strcmp((s = lilv_expand("~/foo")), home_foo)); + free(s); + assert(!strcmp((s = lilv_expand("$NOT_A_VAR")), "$NOT_A_VAR")); + free(s); + free(home_foo); + unsetenv("LILV_TEST_1"); +#endif + + return 0; +} diff --git a/test/test_ui.c b/test/test_ui.c new file mode 100644 index 0000000..6230318 --- /dev/null +++ b/test/test_ui.c @@ -0,0 +1,180 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +@prefix lv2ui: <http://lv2plug.in/ns/extensions/ui#> .\n\ +:plug a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:optionalFeature lv2:hardRTCapable ;\n\ + lv2:requiredFeature <http://lv2plug.in/ns/ext/event> ;\n\ + lv2ui:ui :ui , :ui2 , :ui3 , :ui4 ;\n\ + doap:maintainer [\n\ + foaf:name \"David Robillard\" ;\n\ + foaf:homepage <http://drobilla.net> ;\n\ + foaf:mbox <mailto:d@drobilla.net>\n\ + ] ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\" ;\n\ + lv2:minimum -1.0 ;\n\ + lv2:maximum 1.0 ;\n\ + lv2:default 0.5\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 1 ;\n\ + lv2:symbol \"bar\" ;\n\ + lv2:name \"Baz\" ;\n\ + lv2:minimum -2.0 ;\n\ + lv2:maximum 2.0 ;\n\ + lv2:default 1.0\n\ + ] , [\n\ + a lv2:ControlPort ;\n\ + a lv2:OutputPort ;\n\ + lv2:index 2 ;\n\ + lv2:symbol \"latency\" ;\n\ + lv2:name \"Latency\" ;\n\ + lv2:portProperty lv2:reportsLatency\n\ + ] .\n\ +\n\ + :ui\n\ + a lv2ui:GtkUI ;\n\ + lv2ui:requiredFeature lv2ui:makeResident ;\n\ + lv2ui:binary <ui" SHLIB_EXT "> ;\n\ + lv2ui:optionalFeature lv2ui:ext_presets .\n\ +\n\ + :ui2\n\ + a lv2ui:GtkUI ;\n\ + lv2ui:binary <ui2" SHLIB_EXT "> .\n\ +\n\ + :ui3\n\ + a lv2ui:GtkUI ;\n\ + lv2ui:binary <ui3" SHLIB_EXT "> .\n\ +\n\ + :ui4\n\ + a lv2ui:GtkUI ;\n\ + lv2ui:binary <ui4" SHLIB_EXT "> .\n"; + +static unsigned +ui_supported(const char* container_type_uri, const char* ui_type_uri) +{ + return !strcmp(container_type_uri, ui_type_uri); +} + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* plug = lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + assert(plug); + + LilvUIs* uis = lilv_plugin_get_uis(plug); + assert(lilv_uis_size(uis) == 4); + + const LilvUI* ui0 = lilv_uis_get(uis, lilv_uis_begin(uis)); + assert(ui0); + + LilvNode* ui_uri = lilv_new_uri(world, "http://example.org/ui"); + LilvNode* ui2_uri = lilv_new_uri(world, "http://example.org/ui3"); + LilvNode* ui3_uri = lilv_new_uri(world, "http://example.org/ui4"); + LilvNode* noui_uri = lilv_new_uri(world, "http://example.org/notaui"); + + const LilvUI* ui0_2 = lilv_uis_get_by_uri(uis, ui_uri); + assert(ui0 == ui0_2); + assert(lilv_node_equals(lilv_ui_get_uri(ui0_2), ui_uri)); + + const LilvUI* ui2 = lilv_uis_get_by_uri(uis, ui2_uri); + assert(ui2 != ui0); + + const LilvUI* ui3 = lilv_uis_get_by_uri(uis, ui3_uri); + assert(ui3 != ui0); + + const LilvUI* noui = lilv_uis_get_by_uri(uis, noui_uri); + assert(noui == NULL); + + const LilvNodes* classes = lilv_ui_get_classes(ui0); + assert(lilv_nodes_size(classes) == 1); + + LilvNode* ui_class_uri = + lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#GtkUI"); + + LilvNode* unknown_ui_class_uri = + lilv_new_uri(world, "http://example.org/mysteryUI"); + + assert(lilv_node_equals(lilv_nodes_get_first(classes), ui_class_uri)); + assert(lilv_ui_is_a(ui0, ui_class_uri)); + + const LilvNode* ui_type = NULL; + assert(lilv_ui_is_supported(ui0, ui_supported, ui_class_uri, &ui_type)); + assert(!lilv_ui_is_supported( + ui0, ui_supported, unknown_ui_class_uri, &ui_type)); + assert(lilv_node_equals(ui_type, ui_class_uri)); + + const LilvNode* plug_bundle_uri = lilv_plugin_get_bundle_uri(plug); + const LilvNode* ui_bundle_uri = lilv_ui_get_bundle_uri(ui0); + assert(lilv_node_equals(plug_bundle_uri, ui_bundle_uri)); + + const size_t ui_binary_uri_str_len = + strlen(lilv_node_as_string(plug_bundle_uri)) + strlen("ui" SHLIB_EXT); + + char* ui_binary_uri_str = (char*)calloc(1, ui_binary_uri_str_len + 1); + snprintf(ui_binary_uri_str, + ui_binary_uri_str_len + 1, + "%s%s", + lilv_node_as_string(plug_bundle_uri), + "ui" SHLIB_EXT); + + const LilvNode* ui_binary_uri = lilv_ui_get_binary_uri(ui0); + + LilvNode* expected_uri = lilv_new_uri(world, ui_binary_uri_str); + assert(lilv_node_equals(expected_uri, ui_binary_uri)); + + free(ui_binary_uri_str); + lilv_node_free(unknown_ui_class_uri); + lilv_node_free(ui_class_uri); + lilv_node_free(ui_uri); + lilv_node_free(ui2_uri); + lilv_node_free(ui3_uri); + lilv_node_free(noui_uri); + lilv_node_free(expected_uri); + lilv_uis_free(uis); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_util.c b/test/test_util.c new file mode 100644 index 0000000..982df3e --- /dev/null +++ b/test/test_util.c @@ -0,0 +1,63 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#define _XOPEN_SOURCE 600 /* for mkstemp */ + +#undef NDEBUG + +#include "../src/lilv_internal.h" + +#ifdef _WIN32 +# include <io.h> +# define mkstemp(pat) _mktemp(pat) +#endif + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +int +main(void) +{ + assert(!lilv_realpath(NULL)); + + char a_path[16]; + char b_path[16]; + strncpy(a_path, "copy_a_XXXXXX", sizeof(a_path)); + strncpy(b_path, "copy_b_XXXXXX", sizeof(b_path)); + mkstemp(a_path); + mkstemp(b_path); + + FILE* fa = fopen(a_path, "w"); + FILE* fb = fopen(b_path, "w"); + fprintf(fa, "AA\n"); + fprintf(fb, "AB\n"); + fclose(fa); + fclose(fb); + + assert(lilv_copy_file("does/not/exist", "copy")); + assert(lilv_copy_file(a_path, "not/a/dir/copy")); + assert(!lilv_copy_file(a_path, "copy_c")); + assert(!lilv_file_equals(a_path, b_path)); + assert(lilv_file_equals(a_path, a_path)); + assert(lilv_file_equals(a_path, "copy_c")); + assert(!lilv_file_equals("does/not/exist", b_path)); + assert(!lilv_file_equals(a_path, "does/not/exist")); + assert(!lilv_file_equals("does/not/exist", "/does/not/either")); + + return 0; +} diff --git a/test/test_value.c b/test/test_value.c new file mode 100644 index 0000000..ce95166 --- /dev/null +++ b/test/test_value.c @@ -0,0 +1,173 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <float.h> +#include <math.h> +#include <string.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + a lv2:CompressorPlugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:port [\n\ + a lv2:ControlPort ; a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"Foo\" ;\n\ + ] ."; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + LilvNode* uval = lilv_new_uri(world, "http://example.org"); + LilvNode* sval = lilv_new_string(world, "Foo"); + LilvNode* ival = lilv_new_int(world, 42); + LilvNode* fval = lilv_new_float(world, 1.6180); + + assert(lilv_node_is_uri(uval)); + assert(lilv_node_is_string(sval)); + assert(lilv_node_is_int(ival)); + assert(lilv_node_is_float(fval)); + + assert(!lilv_node_is_literal(NULL)); + assert(!lilv_node_is_literal(uval)); + assert(lilv_node_is_literal(sval)); + assert(lilv_node_is_literal(ival)); + assert(lilv_node_is_literal(fval)); + assert(!lilv_node_get_path(fval, NULL)); + + assert(!strcmp(lilv_node_as_uri(uval), "http://example.org")); + assert(!strcmp(lilv_node_as_string(sval), "Foo")); + assert(lilv_node_as_int(ival) == 42); + assert(fabs(lilv_node_as_float(fval) - 1.6180) < FLT_EPSILON); + assert(isnan(lilv_node_as_float(sval))); + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + + assert(!strcmp(lilv_uri_to_path("file:///foo"), "/foo")); + +#if defined(__clang__) +# pragma clang diagnostic pop +#elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) +# pragma GCC diagnostic pop +#endif + + LilvNode* loc_abs = lilv_new_file_uri(world, NULL, "/foo/bar"); + LilvNode* loc_rel = lilv_new_file_uri(world, NULL, "foo"); + LilvNode* host_abs = lilv_new_file_uri(world, "host", "/foo/bar"); + LilvNode* host_rel = lilv_new_file_uri(world, "host", "foo"); + + assert(!strcmp(lilv_node_as_uri(loc_abs), "file:///foo/bar")); + assert(!strncmp(lilv_node_as_uri(loc_rel), "file:///", 8)); + assert(!strcmp(lilv_node_as_uri(host_abs), "file://host/foo/bar")); + assert(!strncmp(lilv_node_as_uri(host_rel), "file://host/", 12)); + + lilv_node_free(host_rel); + lilv_node_free(host_abs); + lilv_node_free(loc_rel); + lilv_node_free(loc_abs); + + char* tok = lilv_node_get_turtle_token(uval); + assert(!strcmp(tok, "<http://example.org>")); + lilv_free(tok); + tok = lilv_node_get_turtle_token(sval); + assert(!strcmp(tok, "Foo")); + lilv_free(tok); + tok = lilv_node_get_turtle_token(ival); + assert(!strcmp(tok, "42")); + lilv_free(tok); + tok = lilv_node_get_turtle_token(fval); + assert(!strncmp(tok, "1.6180", 6)); + lilv_free(tok); + + LilvNode* uval_e = lilv_new_uri(world, "http://example.org"); + LilvNode* sval_e = lilv_new_string(world, "Foo"); + LilvNode* ival_e = lilv_new_int(world, 42); + LilvNode* fval_e = lilv_new_float(world, 1.6180); + LilvNode* uval_ne = lilv_new_uri(world, "http://no-example.org"); + LilvNode* sval_ne = lilv_new_string(world, "Bar"); + LilvNode* ival_ne = lilv_new_int(world, 24); + LilvNode* fval_ne = lilv_new_float(world, 3.14159); + + assert(lilv_node_equals(uval, uval_e)); + assert(lilv_node_equals(sval, sval_e)); + assert(lilv_node_equals(ival, ival_e)); + assert(lilv_node_equals(fval, fval_e)); + + assert(!lilv_node_equals(uval, uval_ne)); + assert(!lilv_node_equals(sval, sval_ne)); + assert(!lilv_node_equals(ival, ival_ne)); + assert(!lilv_node_equals(fval, fval_ne)); + + assert(!lilv_node_equals(uval, sval)); + assert(!lilv_node_equals(sval, ival)); + assert(!lilv_node_equals(ival, fval)); + + LilvNode* uval_dup = lilv_node_duplicate(uval); + assert(lilv_node_equals(uval, uval_dup)); + + LilvNode* ifval = lilv_new_float(world, 42.0); + assert(!lilv_node_equals(ival, ifval)); + lilv_node_free(ifval); + + LilvNode* nil = NULL; + assert(!lilv_node_equals(uval, nil)); + assert(!lilv_node_equals(nil, uval)); + assert(lilv_node_equals(nil, nil)); + + LilvNode* nil2 = lilv_node_duplicate(nil); + assert(lilv_node_equals(nil, nil2)); + + lilv_node_free(uval); + lilv_node_free(sval); + lilv_node_free(ival); + lilv_node_free(fval); + lilv_node_free(uval_e); + lilv_node_free(sval_e); + lilv_node_free(ival_e); + lilv_node_free(fval_e); + lilv_node_free(uval_ne); + lilv_node_free(sval_ne); + lilv_node_free(ival_ne); + lilv_node_free(fval_ne); + lilv_node_free(uval_dup); + lilv_node_free(nil2); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_verify.c b/test/test_verify.c new file mode 100644 index 0000000..dd88ba5 --- /dev/null +++ b/test/test_verify.c @@ -0,0 +1,57 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> + +static const char* const plugin_ttl = "\ +:plug a lv2:Plugin ;\n\ + doap:name \"Test plugin\" ;\n\ + lv2:port [\n\ + a lv2:ControlPort ;\n\ + a lv2:InputPort ;\n\ + lv2:index 0 ;\n\ + lv2:symbol \"foo\" ;\n\ + lv2:name \"bar\"\n\ + ] .\n"; + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + if (start_bundle(env, SIMPLE_MANIFEST_TTL, plugin_ttl)) { + return 1; + } + + const LilvPlugins* plugins = lilv_world_get_all_plugins(world); + const LilvPlugin* explug = + lilv_plugins_get_by_uri(plugins, env->plugin1_uri); + + assert(explug); + assert(lilv_plugin_verify(explug)); + + delete_bundle(env); + lilv_test_env_free(env); + + return 0; +} diff --git a/test/test_world.c b/test/test_world.c new file mode 100644 index 0000000..b8572d2 --- /dev/null +++ b/test/test_world.c @@ -0,0 +1,51 @@ +/* + Copyright 2007-2020 David Robillard <http://drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#undef NDEBUG + +#include "lilv_test_utils.h" + +#include "lilv/lilv.h" + +#include <assert.h> +#include <stddef.h> + +int +main(void) +{ + LilvTestEnv* const env = lilv_test_env_new(); + LilvWorld* const world = env->world; + + LilvNode* num = lilv_new_int(env->world, 4); + LilvNode* uri = lilv_new_uri(env->world, "http://example.org/object"); + + LilvNodes* matches = lilv_world_find_nodes(world, num, NULL, NULL); + assert(!matches); + + matches = lilv_world_find_nodes(world, NULL, num, NULL); + assert(!matches); + + matches = lilv_world_find_nodes(world, NULL, uri, NULL); + assert(!matches); + + lilv_node_free(uri); + lilv_node_free(num); + + lilv_world_unload_bundle(world, NULL); + lilv_test_env_free(env); + + return 0; +} @@ -26,6 +26,31 @@ uri = 'http://drobilla.net/sw/lilv' dist_pattern = 'http://download.drobilla.net/lilv-%d.%d.%d.tar.bz2' post_tags = ['Hacking', 'LAD', 'LV2', 'Lilv'] +tests = [ + 'test_bad_port_index', + 'test_bad_port_symbol', + 'test_classes', + 'test_discovery', + 'test_get_symbol', + 'test_no_author', + 'test_no_verify', + 'test_plugin', + 'test_port', + 'test_preset', + 'test_project', + 'test_project_no_author', + 'test_prototype', + 'test_reload_bundle', + 'test_replace_version', + 'test_state', + 'test_string', + 'test_ui', + 'test_util', + 'test_value', + 'test_verify', + 'test_world', +] + test_plugins = [ 'bad_syntax', 'failed_instantiation', @@ -367,18 +392,21 @@ def build(bld): bpath = os.path.join(testdir, 'test.lv2') bpath = bpath.replace('\\', '/') testdir = testdir.replace('\\', '/') - obj = bld(features = 'c cprogram', - source = ['test/lilv_test_utils.c', 'test/lilv_test.c'], - includes = ['.', './src'], - use = 'liblilv_profiled', - lib = test_libs, - uselib = 'SERD SORD SRATOM LV2', - target = 'test/lilv_test', - install_path = None, - defines = (defines + ['LILV_TEST_BUNDLE=\"%s/\"' % bpath] + - ['LILV_TEST_DIR=\"%s/\"' % testdir]), - cflags = test_cflags, - linkflags = test_linkflags) + for test in tests: + obj = bld(features = 'c cprogram', + source = ['test/lilv_test_utils.c', + 'test/%s.c' % test], + includes = ['.', './src'], + use = 'liblilv_profiled', + lib = test_libs, + uselib = 'SERD SORD SRATOM LV2', + target = 'test/' + test, + install_path = None, + defines = (defines + + ['LILV_TEST_BUNDLE=\"%s/\"' % bpath] + + ['LILV_TEST_DIR=\"%s/\"' % testdir]), + cflags = test_cflags, + linkflags = test_linkflags) # C++ API test if 'COMPILER_CXX' in bld.env: @@ -460,7 +488,10 @@ def build(bld): def test(tst): with tst.group('unit') as check: - check(['./test/lilv_test']) + for test in tests: + if not (sys.platform == 'win32' and test == 'test_state'): + check(['./test/' + test]) + if tst.is_defined('LILV_CXX'): check(['./test/lilv_cxx_test']) |