summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/lilv_test.c154
-rw-r--r--test/manifest.ttl7
-rw-r--r--test/test_plugin.c235
-rw-r--r--test/test_plugin.ttl40
4 files changed, 436 insertions, 0 deletions
diff --git a/test/lilv_test.c b/test/lilv_test.c
index b5c5302..1994832 100644
--- a/test/lilv_test.c
+++ b/test/lilv_test.c
@@ -28,6 +28,9 @@
#include <math.h>
#include "lilv/lilv.h"
+#include "../src/lilv_internal.h"
+
+#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
#define TEST_PATH_MAX 1024
@@ -972,6 +975,156 @@ test_ui(void)
/*****************************************************************************/
+float in = 1.0;
+float out = 42.0;
+
+LilvNode*
+get_port_value(const char* port_symbol, void* user_data)
+{
+ if (!strcmp(port_symbol, "input")) {
+ return lilv_new_float((LilvWorld*)user_data, in);
+ } else if (!strcmp(port_symbol, "output")) {
+ return lilv_new_float((LilvWorld*)user_data, out);
+ } else {
+ fprintf(stderr, "error: get_port_value for nonexistent port `%s'\n",
+ port_symbol);
+ return NULL;
+ }
+}
+
+void
+set_port_value(const char* port_symbol,
+ const LilvNode* value,
+ void* user_data)
+{
+ if (!strcmp(port_symbol, "input")) {
+ in = lilv_node_as_float(value);
+ } else if (!strcmp(port_symbol, "output")) {
+ out = lilv_node_as_float(value);
+ } else {
+ fprintf(stderr, "error: set_port_value for nonexistent port `%s'\n",
+ port_symbol);
+ }
+}
+
+char** uris = NULL;
+size_t n_uris = 0;
+
+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;
+ }
+ }
+
+ uris = realloc(uris, ++n_uris * sizeof(char*));
+ uris[n_uris - 1] = lilv_strdup(uri);
+ return n_uris;
+}
+
+const char*
+unmap_uri(LV2_URID_Map_Handle handle,
+ LV2_URID urid)
+{
+ if (urid > 0 && urid <= n_uris) {
+ return uris[urid - 1];
+ }
+ return NULL;
+}
+
+int
+test_state(void)
+{
+ LilvWorld* world = lilv_world_new();
+ LilvNode* bundle_uri = lilv_new_uri(world, LILV_TEST_BUNDLE);
+ LilvNode* plugin_uri = lilv_new_uri(world,
+ "http://example.org/lilv-test-plugin");
+ lilv_world_load_bundle(world, bundle_uri);
+
+ const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
+ const LilvPlugin* plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
+ TEST_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 };
+
+ LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, features);
+ TEST_ASSERT(instance);
+
+ lilv_instance_connect_port(instance, 0, &in);
+ lilv_instance_connect_port(instance, 1, &out);
+
+ lilv_instance_run(instance, 1);
+ TEST_ASSERT(in == 1.0);
+ TEST_ASSERT(out == 1.0);
+
+ // Get instance state state
+ LilvState* state = lilv_state_new_from_instance(
+ plugin, instance, get_port_value, world, 0, NULL);
+
+ // Get another instance state
+ LilvState* state2 = lilv_state_new_from_instance(
+ plugin, instance, get_port_value, world, 0, NULL);
+
+ // Ensure they are equal
+ TEST_ASSERT(lilv_state_equals(state, state2));
+
+ const LilvNode* state_plugin_uri = lilv_state_get_plugin_uri(state);
+ TEST_ASSERT(lilv_node_equals(state_plugin_uri, plugin_uri));
+
+ // Tinker with the label of the first state
+ TEST_ASSERT(lilv_state_get_label(state) == NULL);
+ lilv_state_set_label(state, "Test State Old Label");
+ TEST_ASSERT(!strcmp(lilv_state_get_label(state), "Test State Old Label"));
+ lilv_state_set_label(state, "Test State");
+ TEST_ASSERT(!strcmp(lilv_state_get_label(state), "Test State"));
+
+ TEST_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, get_port_value, world, 0, NULL);
+ TEST_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, get_port_value, world, 0, NULL);
+ TEST_ASSERT(lilv_state_equals(state2, state4));
+
+ // Save state to a file
+ int ret = lilv_state_save(world, &unmap, state, NULL,
+ "state.ttl", "manifest.ttl");
+ TEST_ASSERT(!ret);
+
+ // Load state from file
+ LilvState* state5 = lilv_state_new_from_file(world, &map, NULL, "state.ttl");
+ TEST_ASSERT(lilv_state_equals(state, state5)); // Round trip accuracy
+
+ lilv_state_free(state);
+ lilv_state_free(state2);
+ lilv_state_free(state3);
+ lilv_state_free(state4);
+ lilv_state_free(state5);
+
+ lilv_instance_free(instance);
+
+ lilv_node_free(bundle_uri);
+ lilv_world_free(world);
+ return 1;
+}
+
+/*****************************************************************************/
+
/* add tests here */
static struct TestCase tests[] = {
TEST_CASE(utils),
@@ -983,6 +1136,7 @@ static struct TestCase tests[] = {
TEST_CASE(plugin),
TEST_CASE(port),
TEST_CASE(ui),
+ TEST_CASE(state),
{ NULL, NULL }
};
diff --git a/test/manifest.ttl b/test/manifest.ttl
new file mode 100644
index 0000000..5af7e88
--- /dev/null
+++ b/test/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://example.org/lilv-test-plugin>
+ a lv2:Plugin ;
+ lv2:binary <test_plugin.so> ;
+ rdfs:seeAlso <test_plugin.ttl> .
diff --git a/test/test_plugin.c b/test/test_plugin.c
new file mode 100644
index 0000000..0ef76f2
--- /dev/null
+++ b/test/test_plugin.c
@@ -0,0 +1,235 @@
+/*
+ Lilv Test Plugin
+ Copyright 2011 David Robillard <d@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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lv2/lv2plug.in/ns/ext/state/state.h"
+#include "lv2/lv2plug.in/ns/ext/urid/urid.h"
+#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
+
+#define TEST_URI "http://example.org/lilv-test-plugin"
+
+#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
+
+enum {
+ TEST_INPUT = 0,
+ TEST_OUTPUT = 1
+};
+
+typedef struct {
+ LV2_URID_Map* map;
+
+ struct {
+ LV2_URID atom_Float;
+ } uris;
+
+ float* input;
+ float* output;
+ unsigned num_runs;
+} Test;
+
+static void
+cleanup(LV2_Handle instance)
+{
+ free(instance);
+}
+
+static void
+connect_port(LV2_Handle instance,
+ uint32_t port,
+ void* data)
+{
+ Test* test = (Test*)instance;
+ switch (port) {
+ case TEST_INPUT:
+ test->input = (float*)data;
+ break;
+ case TEST_OUTPUT:
+ test->output = (float*)data;
+ break;
+ default:
+ break;
+ }
+}
+
+static LV2_Handle
+instantiate(const LV2_Descriptor* descriptor,
+ double rate,
+ const char* path,
+ const LV2_Feature* const* features)
+{
+ Test* test = (Test*)malloc(sizeof(Test));
+ if (!test) {
+ return NULL;
+ }
+
+ test->map = NULL;
+ test->input = NULL;
+ test->output = NULL;
+ test->num_runs = 0;
+
+ /* Scan host features for URID map */
+ for (int i = 0; features[i]; ++i) {
+ if (!strcmp(features[i]->URI, LV2_URID_URI "#map")) {
+ test->map = (LV2_URID_Map*)features[i]->data;
+ test->uris.atom_Float = test->map->map(
+ test->map->handle, NS_ATOM "Float");
+ }
+ }
+
+ if (!test->map) {
+ fprintf(stderr, "Host does not support urid:map.\n");
+ free(test);
+ return NULL;
+ }
+
+ return (LV2_Handle)test;
+}
+
+static void
+run(LV2_Handle instance,
+ uint32_t sample_count)
+{
+ Test* test = (Test*)instance;
+ *test->output = *test->input;
+ ++test->num_runs;
+}
+
+static uint32_t
+map_uri(Test* plugin, const char* uri)
+{
+ return plugin->map->map(plugin->map->handle, uri);
+}
+
+static void
+save(LV2_Handle instance,
+ LV2_State_Store_Function store,
+ void* callback_data,
+ uint32_t flags,
+ const LV2_Feature* const* features)
+{
+ Test* plugin = (Test*)instance;
+
+ store(callback_data,
+ map_uri(plugin, "http://example.org/greeting"),
+ "hello",
+ strlen("hello") + 1,
+ map_uri(plugin, NS_ATOM "String"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ const uint32_t urid = map_uri(plugin, "http://example.org/urivalue");
+ store(callback_data,
+ map_uri(plugin, "http://example.org/uri"),
+ &urid,
+ sizeof(uint32_t),
+ map_uri(plugin, NS_ATOM "URID"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ store(callback_data,
+ map_uri(plugin, "http://example.org/num-runs"),
+ &plugin->num_runs,
+ sizeof(plugin->num_runs),
+ map_uri(plugin, NS_ATOM "Int32"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ const float two = 2.0f;
+ store(callback_data,
+ map_uri(plugin, "http://example.org/two"),
+ &two,
+ sizeof(two),
+ map_uri(plugin, NS_ATOM "Float"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ const uint32_t affirmative = 1;
+ store(callback_data,
+ map_uri(plugin, "http://example.org/true"),
+ &affirmative,
+ sizeof(affirmative),
+ map_uri(plugin, NS_ATOM "Bool"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ const uint32_t negative = 0;
+ store(callback_data,
+ map_uri(plugin, "http://example.org/false"),
+ &negative,
+ sizeof(negative),
+ map_uri(plugin, NS_ATOM "Bool"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+
+ const uint8_t blob[] = "This is a bunch of data that happens to be text"
+ " but could really be anything at all, lest you feel like cramming"
+ " all sorts of ridiculous binary stuff in Turtle";
+ store(callback_data,
+ map_uri(plugin, "http://example.org/blob"),
+ blob,
+ sizeof(blob),
+ map_uri(plugin, "http://example.org/SomeUnknownType"),
+ LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+}
+
+static void
+restore(LV2_Handle instance,
+ LV2_State_Retrieve_Function retrieve,
+ void* callback_data,
+ uint32_t flags,
+ const LV2_Feature* const* features)
+{
+ Test* plugin = (Test*)instance;
+
+ size_t size;
+ uint32_t type;
+ uint32_t valflags;
+
+ plugin->num_runs = *(int32_t*)retrieve(
+ callback_data,
+ map_uri(plugin, "http://example.org/num-runs"),
+ &size, &type, &valflags);
+}
+
+const void*
+extension_data(const char* uri)
+{
+ static const LV2_State_Interface state = { save, restore };
+ if (!strcmp(uri, LV2_STATE_INTERFACE_URI)) {
+ return &state;
+ }
+ return NULL;
+}
+
+static const LV2_Descriptor descriptor = {
+ TEST_URI,
+ instantiate,
+ connect_port,
+ NULL, // activate,
+ run,
+ NULL, // deactivate,
+ cleanup,
+ extension_data
+};
+
+LV2_SYMBOL_EXPORT
+const LV2_Descriptor* lv2_descriptor(uint32_t index)
+{
+ switch (index) {
+ case 0:
+ return &descriptor;
+ default:
+ return NULL;
+ }
+}
diff --git a/test/test_plugin.ttl b/test/test_plugin.ttl
new file mode 100644
index 0000000..ec16d00
--- /dev/null
+++ b/test/test_plugin.ttl
@@ -0,0 +1,40 @@
+# Lilv Test Plugin
+# Copyright 2011 David Robillard <d@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.
+
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
+
+<http://example.org/lilv-test-plugin>
+ a lv2:Plugin ;
+ doap:name "Lilv Test" ;
+ doap:license <http://opensource.org/licenses/isc> ;
+ lv2:requiredFeature <http://lv2plug.in/ns/ext/urid#Mapper> ;
+ lv2:optionalFeature lv2:hardRtCapable ;
+ lv2:extensionData <http://lv2plug.in/ns/ext/state#Interface> ;
+ lv2:port [
+ a lv2:InputPort ,
+ lv2:ControlPort ;
+ lv2:index 0 ;
+ lv2:symbol "input" ;
+ lv2:name "Input"
+ ] , [
+ a lv2:OutputPort ,
+ lv2:ControlPort ;
+ lv2:index 1 ;
+ lv2:symbol "output" ;
+ lv2:name "Output"
+ ] .