From 55dc97a32eeeb42012ce1e7d28ed99ea537f4d2f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 14 Jul 2022 11:50:43 -0400 Subject: Switch to meson build system --- test/bad_syntax.lv2/meson.build | 25 ++ test/core.lv2/lv2core.ttl | 30 -- test/core.lv2/manifest.ttl | 9 - test/failed_instantiation.lv2/meson.build | 25 ++ test/failed_lib_descriptor.lv2/meson.build | 25 ++ test/lib_descriptor.lv2/meson.build | 25 ++ test/lilv_test_uri_map.h | 9 +- test/lilv_test_utils.c | 4 +- test/lv2/core.lv2/lv2core.ttl | 30 ++ test/lv2/core.lv2/manifest.ttl | 9 + test/lv2/core.lv2/meson.build | 8 + test/meson.build | 80 +++++ test/missing_descriptor.lv2/meson.build | 25 ++ test/missing_name.lv2/meson.build | 25 ++ test/missing_plugin.lv2/meson.build | 25 ++ test/missing_port.lv2/meson.build | 25 ++ test/missing_port_name.lv2/meson.build | 25 ++ test/new_version.lv2/meson.build | 17 + test/old_version.lv2/meson.build | 17 + test/test.lv2/manifest.ttl.in | 7 - test/test.lv2/test.c | 483 ----------------------------- test/test.lv2/test.ttl.in | 46 --- test/test_plugin.lv2/manifest.ttl.in | 7 + test/test_plugin.lv2/meson.build | 17 + test/test_plugin.lv2/test_plugin.c | 481 ++++++++++++++++++++++++++++ test/test_plugin.lv2/test_plugin.ttl.in | 46 +++ test/test_string.c | 2 - 27 files changed, 942 insertions(+), 585 deletions(-) create mode 100644 test/bad_syntax.lv2/meson.build delete mode 100644 test/core.lv2/lv2core.ttl delete mode 100644 test/core.lv2/manifest.ttl create mode 100644 test/failed_instantiation.lv2/meson.build create mode 100644 test/failed_lib_descriptor.lv2/meson.build create mode 100644 test/lib_descriptor.lv2/meson.build create mode 100644 test/lv2/core.lv2/lv2core.ttl create mode 100644 test/lv2/core.lv2/manifest.ttl create mode 100644 test/lv2/core.lv2/meson.build create mode 100644 test/meson.build create mode 100644 test/missing_descriptor.lv2/meson.build create mode 100644 test/missing_name.lv2/meson.build create mode 100644 test/missing_plugin.lv2/meson.build create mode 100644 test/missing_port.lv2/meson.build create mode 100644 test/missing_port_name.lv2/meson.build create mode 100644 test/new_version.lv2/meson.build create mode 100644 test/old_version.lv2/meson.build delete mode 100644 test/test.lv2/manifest.ttl.in delete mode 100644 test/test.lv2/test.c delete mode 100644 test/test.lv2/test.ttl.in create mode 100644 test/test_plugin.lv2/manifest.ttl.in create mode 100644 test/test_plugin.lv2/meson.build create mode 100644 test/test_plugin.lv2/test_plugin.c create mode 100644 test/test_plugin.lv2/test_plugin.ttl.in (limited to 'test') diff --git a/test/bad_syntax.lv2/meson.build b/test/bad_syntax.lv2/meson.build new file mode 100644 index 0000000..f50b43d --- /dev/null +++ b/test/bad_syntax.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('bad_syntax', + files('bad_syntax.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'bad_syntax.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('bad_syntax', + executable('test_bad_syntax', + files('test_bad_syntax.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/core.lv2/lv2core.ttl b/test/core.lv2/lv2core.ttl deleted file mode 100644 index 5659487..0000000 --- a/test/core.lv2/lv2core.ttl +++ /dev/null @@ -1,30 +0,0 @@ -@prefix lv2: . -@prefix owl: . -@prefix rdfs: . - - - a owl:Ontology . - -lv2:PluginBase - a rdfs:Class , - owl:Class ; - rdfs:label "Plugin Base" . - -lv2:Plugin - a rdfs:Class , - owl:Class ; - rdfs:subClassOf lv2:PluginBase ; - rdfs:label "Plugin" . - -lv2:DynamicsPlugin - a rdfs:Class , - owl:Class ; - rdfs:subClassOf lv2:Plugin ; - rdfs:label "Dynamics" . - -lv2:CompressorPlugin - a rdfs:Class , - owl:Class ; - rdfs:subClassOf lv2:DynamicsPlugin ; - rdfs:label "Compressor" . - diff --git a/test/core.lv2/manifest.ttl b/test/core.lv2/manifest.ttl deleted file mode 100644 index a77ad71..0000000 --- a/test/core.lv2/manifest.ttl +++ /dev/null @@ -1,9 +0,0 @@ -@prefix doap: . -@prefix lv2: . -@prefix rdfs: . - - - a lv2:Specification ; - lv2:minorVersion 16 ; - lv2:microVersion 0 ; - rdfs:seeAlso . diff --git a/test/failed_instantiation.lv2/meson.build b/test/failed_instantiation.lv2/meson.build new file mode 100644 index 0000000..8e95549 --- /dev/null +++ b/test/failed_instantiation.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('failed_instantiation', + files('failed_instantiation.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'failed_instantiation.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('failed_instantiation', + executable('test_failed_instantiation', + files('test_failed_instantiation.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/failed_lib_descriptor.lv2/meson.build b/test/failed_lib_descriptor.lv2/meson.build new file mode 100644 index 0000000..e4e9d76 --- /dev/null +++ b/test/failed_lib_descriptor.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('failed_lib_descriptor', + files('failed_lib_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'failed_lib_descriptor.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('failed_lib_descriptor', + executable('test_failed_lib_descriptor', + files('test_failed_lib_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/lib_descriptor.lv2/meson.build b/test/lib_descriptor.lv2/meson.build new file mode 100644 index 0000000..5a85fe5 --- /dev/null +++ b/test/lib_descriptor.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('lib_descriptor', + files('lib_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'lib_descriptor.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('lib_descriptor', + executable('test_lib_descriptor', + files('test_lib_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/lilv_test_uri_map.h b/test/lilv_test_uri_map.h index 5f85c86..88c9107 100644 --- a/test/lilv_test_uri_map.h +++ b/test/lilv_test_uri_map.h @@ -23,14 +23,13 @@ #include "serd/serd.h" #include -#include #include #include #include typedef struct { - char** uris; - size_t n_uris; + char** uris; + uint32_t n_uris; } LilvTestUriMap; static inline void @@ -43,7 +42,7 @@ lilv_test_uri_map_init(LilvTestUriMap* const map) static inline void lilv_test_uri_map_clear(LilvTestUriMap* const map) { - for (size_t i = 0; i < map->n_uris; ++i) { + for (uint32_t i = 0; i < map->n_uris; ++i) { free(map->uris[i]); } @@ -57,7 +56,7 @@ map_uri(LV2_URID_Map_Handle handle, const char* uri) { LilvTestUriMap* map = (LilvTestUriMap*)handle; - for (size_t i = 0; i < map->n_uris; ++i) { + for (uint32_t i = 0; i < map->n_uris; ++i) { if (!strcmp(map->uris[i], uri)) { return i + 1; } diff --git a/test/lilv_test_utils.c b/test/lilv_test_utils.c index f658f1b..941509a 100644 --- a/test/lilv_test_utils.c +++ b/test/lilv_test_utils.c @@ -14,8 +14,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _POSIX_C_SOURCE 200809L /* for setenv */ - #include "lilv_test_utils.h" #include "../src/filesystem.h" @@ -47,7 +45,7 @@ lilv_test_env_new(void) // Set custom LV2_PATH in build directory to only use test data char* test_path = lilv_path_canonical(LILV_TEST_DIR); - char* lv2_path = lilv_strjoin(test_path, "/test_lv2_path", NULL); + char* lv2_path = lilv_strjoin(test_path, "/lv2", NULL); LilvNode* path = lilv_new_string(world, lv2_path); lilv_world_set_option(world, LILV_OPTION_LV2_PATH, path); free(lv2_path); diff --git a/test/lv2/core.lv2/lv2core.ttl b/test/lv2/core.lv2/lv2core.ttl new file mode 100644 index 0000000..5659487 --- /dev/null +++ b/test/lv2/core.lv2/lv2core.ttl @@ -0,0 +1,30 @@ +@prefix lv2: . +@prefix owl: . +@prefix rdfs: . + + + a owl:Ontology . + +lv2:PluginBase + a rdfs:Class , + owl:Class ; + rdfs:label "Plugin Base" . + +lv2:Plugin + a rdfs:Class , + owl:Class ; + rdfs:subClassOf lv2:PluginBase ; + rdfs:label "Plugin" . + +lv2:DynamicsPlugin + a rdfs:Class , + owl:Class ; + rdfs:subClassOf lv2:Plugin ; + rdfs:label "Dynamics" . + +lv2:CompressorPlugin + a rdfs:Class , + owl:Class ; + rdfs:subClassOf lv2:DynamicsPlugin ; + rdfs:label "Compressor" . + diff --git a/test/lv2/core.lv2/manifest.ttl b/test/lv2/core.lv2/manifest.ttl new file mode 100644 index 0000000..a77ad71 --- /dev/null +++ b/test/lv2/core.lv2/manifest.ttl @@ -0,0 +1,9 @@ +@prefix doap: . +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 16 ; + lv2:microVersion 0 ; + rdfs:seeAlso . diff --git a/test/lv2/core.lv2/meson.build b/test/lv2/core.lv2/meson.build new file mode 100644 index 0000000..4ad7969 --- /dev/null +++ b/test/lv2/core.lv2/meson.build @@ -0,0 +1,8 @@ +ttl_files = files( + 'lv2core.ttl', + 'manifest.ttl', +) + +foreach file : ttl_files + configure_file(copy: true, input: file, output: '@PLAINNAME@') +endforeach diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000..22b316b --- /dev/null +++ b/test/meson.build @@ -0,0 +1,80 @@ +# Copyright 2020-2022 David Robillard +# SPDX-License-Identifier: CC0-1.0 OR ISC + +# Check release metadata +autoship = find_program('autoship', required: false) +if autoship.found() + test('autoship', autoship, args: ['test', lilv_src_root], suite: 'data') +endif + +test_args = ['-DLILV_STATIC'] +if cc.get_id() == 'msvc' + test_args += [ + '/wd4464', # relative include path contains '..' + ] +endif + +subdir('lv2/core.lv2') + +################ +# Bundle Tests # +################ + +subdir('bad_syntax.lv2') +subdir('failed_instantiation.lv2') +subdir('failed_lib_descriptor.lv2') +subdir('lib_descriptor.lv2') +subdir('missing_descriptor.lv2') +subdir('missing_name.lv2') +subdir('missing_plugin.lv2') +subdir('missing_port.lv2') +subdir('missing_port_name.lv2') +subdir('new_version.lv2') +subdir('old_version.lv2') +subdir('test_plugin.lv2') + +############## +# Unit Tests # +############## + +unit_tests = [ + 'bad_port_index', + 'bad_port_symbol', + 'classes', + 'discovery', + 'filesystem', + 'get_symbol', + 'no_author', + 'no_verify', + 'plugin', + 'port', + 'preset', + 'project', + 'project_no_author', + 'prototype', + 'reload_bundle', + 'replace_version', + 'state', + 'string', + 'ui', + 'util', + 'value', + 'verify', + 'world', +] + +define_args = [ + '-DLILV_TEST_BUNDLE="@0@/"'.format(meson.current_build_dir() / 'test_plugin.lv2'), + '-DLILV_TEST_DIR="@0@/"'.format(meson.current_build_dir()), +] + +foreach unit : unit_tests + test(unit, + executable('test_@0@'.format(unit), + files('lilv_test_utils.c', 'test_@0@.c'.format(unit)), + c_args: define_args + test_args + c_suppressions, + include_directories: include_directories('../src'), + dependencies: [lv2_dep, lilv_static_dep]), + suite: 'unit') +endforeach + diff --git a/test/missing_descriptor.lv2/meson.build b/test/missing_descriptor.lv2/meson.build new file mode 100644 index 0000000..cf1d45c --- /dev/null +++ b/test/missing_descriptor.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('missing_descriptor', + files('missing_descriptor.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_descriptor.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('missing_descriptor', + executable('test_missing_descriptor', + files('test_missing_descriptor.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/missing_name.lv2/meson.build b/test/missing_name.lv2/meson.build new file mode 100644 index 0000000..3fe6ce4 --- /dev/null +++ b/test/missing_name.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('missing_name', + files('missing_name.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_name.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('missing_name', + executable('test_missing_name', + files('test_missing_name.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/missing_plugin.lv2/meson.build b/test/missing_plugin.lv2/meson.build new file mode 100644 index 0000000..ca6a8fe --- /dev/null +++ b/test/missing_plugin.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('missing_plugin', + files('missing_plugin.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_plugin.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('missing_plugin', + executable('test_missing_plugin', + files('test_missing_plugin.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/missing_port.lv2/meson.build b/test/missing_port.lv2/meson.build new file mode 100644 index 0000000..f497b8c --- /dev/null +++ b/test/missing_port.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('missing_port', + files('missing_port.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_port.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('missing_port', + executable('test_missing_port', + files('test_missing_port.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/missing_port_name.lv2/meson.build b/test/missing_port_name.lv2/meson.build new file mode 100644 index 0000000..07e7811 --- /dev/null +++ b/test/missing_port_name.lv2/meson.build @@ -0,0 +1,25 @@ +module = shared_module('missing_port_name', + files('missing_port_name.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'missing_port_name.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + +test('missing_port_name', + executable('test_missing_port_name', + files('test_missing_port_name.c'), + c_args: c_suppressions + test_args, + dependencies: [lv2_dep, lilv_static_dep]), + args: [meson.current_build_dir() / ''], + suite: 'plugin') + diff --git a/test/new_version.lv2/meson.build b/test/new_version.lv2/meson.build new file mode 100644 index 0000000..b745415 --- /dev/null +++ b/test/new_version.lv2/meson.build @@ -0,0 +1,17 @@ +module = shared_module('new_version', + files('new_version.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'new_version.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + diff --git a/test/old_version.lv2/meson.build b/test/old_version.lv2/meson.build new file mode 100644 index 0000000..efec6e1 --- /dev/null +++ b/test/old_version.lv2/meson.build @@ -0,0 +1,17 @@ +module = shared_module('old_version', + files('old_version.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'old_version.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + diff --git a/test/test.lv2/manifest.ttl.in b/test/test.lv2/manifest.ttl.in deleted file mode 100644 index bc3952c..0000000 --- a/test/test.lv2/manifest.ttl.in +++ /dev/null @@ -1,7 +0,0 @@ -@prefix lv2: . -@prefix rdfs: . - - - a lv2:Plugin ; - lv2:binary ; - rdfs:seeAlso . diff --git a/test/test.lv2/test.c b/test/test.lv2/test.c deleted file mode 100644 index 1dc7076..0000000 --- a/test/test.lv2/test.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - Lilv Test Plugin - Copyright 2011-2022 David Robillard - - 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 - -#include "lv2/atom/atom.h" -#include "lv2/core/lv2.h" -#include "lv2/state/state.h" -#include "lv2/urid/urid.h" - -#ifdef _WIN32 -# define _WIN32_LEAN_AND_MEAN -# include -#endif - -#include -#include -#include -#include - -#define TEST_URI "http://example.org/lilv-test-plugin" - -enum { TEST_INPUT = 0, TEST_OUTPUT = 1, TEST_CONTROL = 2 }; - -typedef struct { - LV2_URID_Map* map; - LV2_State_Free_Path* free_path; - - struct { - LV2_URID atom_Float; - } uris; - - char* tmp_dir_path; - char* rec_file_path; - FILE* rec_file; - - float* input; - float* output; - unsigned num_runs; -} Test; - -static char* -temp_directory_path(void) -{ -#ifdef _WIN32 - const DWORD len = GetTempPath(0, NULL); - char* const buf = (char*)calloc(len, 1); - if (GetTempPath(len, buf) == 0) { - free(buf); - return NULL; - } - - return buf; -#else - const char* const tmpdir = getenv("TMPDIR"); - if (tmpdir) { - const size_t tmpdir_len = strlen(tmpdir); - char* const result = (char*)calloc(tmpdir_len + 1, 1); - - memcpy(result, tmpdir, tmpdir_len + 1); - return result; - } - - char* const result = (char*)calloc(6, 1); - - memcpy(result, "/tmp/", 6); - return result; -#endif -} - -static void -cleanup(LV2_Handle instance) -{ - Test* test = (Test*)instance; - if (test->rec_file) { - fclose(test->rec_file); - } - - if (test->free_path) { - test->free_path->free_path(test->free_path->handle, test->rec_file_path); - } - - free(test->tmp_dir_path); - 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; - case TEST_CONTROL: - 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) -{ - (void)descriptor; - (void)rate; - (void)path; - - Test* test = (Test*)calloc(1, sizeof(Test)); - if (!test) { - return NULL; - } - - test->tmp_dir_path = temp_directory_path(); - - LV2_State_Make_Path* make_path = NULL; - - 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, LV2_ATOM__Float); - } else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) { - make_path = (LV2_State_Make_Path*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { - test->free_path = (LV2_State_Free_Path*)features[i]->data; - } - } - - if (!test->map) { - fprintf(stderr, "Host does not support urid:map\n"); - free(test); - return NULL; - } - - if (make_path) { - if (!test->free_path) { - fprintf(stderr, "Host provided make_path without free_path\n"); - free(test); - return NULL; - } - - test->rec_file_path = make_path->path(make_path->handle, "recfile"); - if (!(test->rec_file = fopen(test->rec_file_path, "w"))) { - fprintf(stderr, "ERROR: Failed to open rec file\n"); - } - fprintf(test->rec_file, "instantiate\n"); - } - - return (LV2_Handle)test; -} - -static void -run(LV2_Handle instance, uint32_t sample_count) -{ - Test* test = (Test*)instance; - *test->output = *test->input; - if (sample_count == 1) { - ++test->num_runs; - } else if (sample_count == 2 && test->rec_file) { - // Append to rec file (changes size) - fprintf(test->rec_file, "run\n"); - } else if (sample_count == 3 && test->rec_file) { - // Change the first byte of rec file (doesn't change size) - fseek(test->rec_file, 0, SEEK_SET); - fprintf(test->rec_file, "X"); - fseek(test->rec_file, 0, SEEK_END); - } -} - -static uint32_t -map_uri(Test* plugin, const char* uri) -{ - return plugin->map->map(plugin->map->handle, uri); -} - -static LV2_State_Status -save(LV2_Handle instance, - LV2_State_Store_Function store, - void* callback_data, - uint32_t flags, - const LV2_Feature* const* features) -{ - (void)flags; - - Test* plugin = (Test*)instance; - - LV2_State_Map_Path* map_path = NULL; - LV2_State_Make_Path* make_path = NULL; - LV2_State_Free_Path* free_path = NULL; - for (int i = 0; features && features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { - map_path = (LV2_State_Map_Path*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) { - make_path = (LV2_State_Make_Path*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { - free_path = (LV2_State_Free_Path*)features[i]->data; - } - } - - if (!map_path || !free_path) { - return LV2_STATE_ERR_NO_FEATURE; - } - - store(callback_data, - map_uri(plugin, "http://example.org/greeting"), - "hello", - strlen("hello") + 1, - map_uri(plugin, LV2_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, LV2_ATOM__URID), - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - - // Try to store second value for the same property (should fail) - const uint32_t urid2 = map_uri(plugin, "http://example.org/urivalue2"); - if (!store(callback_data, - map_uri(plugin, "http://example.org/uri"), - &urid2, - sizeof(uint32_t), - map_uri(plugin, LV2_ATOM__URID), - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) { - return LV2_STATE_ERR_UNKNOWN; - } - - // Try to store with a null key (should fail) - if (!store(callback_data, - 0, - &urid2, - sizeof(uint32_t), - map_uri(plugin, LV2_ATOM__URID), - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) { - return LV2_STATE_ERR_UNKNOWN; - } - - store(callback_data, - map_uri(plugin, "http://example.org/num-runs"), - &plugin->num_runs, - sizeof(plugin->num_runs), - map_uri(plugin, LV2_ATOM__Int), - 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, LV2_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, LV2_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, LV2_ATOM__Bool), - LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); - - const uint8_t blob[] = "I am a blob of arbitrary data."; - 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); - - if (map_path) { - const char* const file_name = "temp_file.txt"; - const size_t file_name_len = strlen(file_name); - const size_t dir_path_len = strlen(plugin->tmp_dir_path); - char* const tmp_file_path = - (char*)calloc(dir_path_len + file_name_len + 1, 1); - - memcpy(tmp_file_path, plugin->tmp_dir_path, dir_path_len); - memcpy(tmp_file_path + dir_path_len, file_name, file_name_len + 1); - - FILE* file = fopen(tmp_file_path, "w"); - if (!file) { - fprintf(stderr, "error: Failed to open file %s\n", tmp_file_path); - free(tmp_file_path); - return LV2_STATE_ERR_UNKNOWN; - } - - fprintf(file, "Hello\n"); - fclose(file); - - char* apath = map_path->abstract_path(map_path->handle, tmp_file_path); - char* apath2 = map_path->abstract_path(map_path->handle, tmp_file_path); - free(tmp_file_path); - if (strcmp(apath, apath2)) { - fprintf(stderr, "error: Path %s != %s\n", apath, apath2); - } - - store(callback_data, - map_uri(plugin, "http://example.org/extfile"), - apath, - strlen(apath) + 1, - map_uri(plugin, LV2_ATOM__Path), - LV2_STATE_IS_POD); - - free_path->free_path(free_path->handle, apath); - free_path->free_path(free_path->handle, apath2); - - if (plugin->rec_file) { - fflush(plugin->rec_file); - apath = map_path->abstract_path(map_path->handle, plugin->rec_file_path); - - store(callback_data, - map_uri(plugin, "http://example.org/recfile"), - apath, - strlen(apath) + 1, - map_uri(plugin, LV2_ATOM__Path), - LV2_STATE_IS_POD); - - free_path->free_path(free_path->handle, apath); - } - - if (make_path) { - char* spath = make_path->path(make_path->handle, "save"); - FILE* sfile = fopen(spath, "w"); - fprintf(sfile, "save"); - fclose(sfile); - - apath = map_path->abstract_path(map_path->handle, spath); - store(callback_data, - map_uri(plugin, "http://example.org/save-file"), - apath, - strlen(apath) + 1, - map_uri(plugin, LV2_ATOM__Path), - LV2_STATE_IS_POD); - free_path->free_path(free_path->handle, apath); - free_path->free_path(free_path->handle, spath); - } - } - - return LV2_STATE_SUCCESS; -} - -static LV2_State_Status -restore(LV2_Handle instance, - LV2_State_Retrieve_Function retrieve, - void* callback_data, - uint32_t flags, - const LV2_Feature* const* features) -{ - (void)flags; - - Test* plugin = (Test*)instance; - - LV2_State_Map_Path* map_path = NULL; - LV2_State_Free_Path* free_path = NULL; - for (int i = 0; features && features[i]; ++i) { - if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { - map_path = (LV2_State_Map_Path*)features[i]->data; - } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { - free_path = (LV2_State_Free_Path*)features[i]->data; - } - } - - size_t size = 0; - uint32_t type = 0; - uint32_t valflags = 0; - - plugin->num_runs = - *(int32_t*)retrieve(callback_data, - map_uri(plugin, "http://example.org/num-runs"), - &size, - &type, - &valflags); - - if (!map_path || !free_path) { - return LV2_STATE_ERR_NO_FEATURE; - } - - char* apath = (char*)retrieve(callback_data, - map_uri(plugin, "http://example.org/extfile"), - &size, - &type, - &valflags); - - if (valflags != LV2_STATE_IS_POD) { - fprintf(stderr, "error: Restored bad file flags\n"); - return LV2_STATE_ERR_BAD_FLAGS; - } - - if (apath) { - char* path = map_path->absolute_path(map_path->handle, apath); - FILE* f = fopen(path, "r"); - char str[8]; - size_t n_read = fread(str, 1, sizeof(str), f); - fclose(f); - if (strncmp(str, "Hello\n", n_read)) { - fprintf( - stderr, "error: Restored bad file contents `%s' != `Hello'\n", str); - } - free_path->free_path(free_path->handle, path); - } - - apath = (char*)retrieve(callback_data, - map_uri(plugin, "http://example.org/save-file"), - &size, - &type, - &valflags); - if (apath) { - char* spath = map_path->absolute_path(map_path->handle, apath); - FILE* sfile = fopen(spath, "r"); - if (!sfile) { - fprintf(stderr, "error: Failed to open save file %s\n", spath); - } else { - fclose(sfile); - } - free_path->free_path(free_path->handle, spath); - } else { - fprintf(stderr, "error: Failed to restore save file.\n"); - } - - return LV2_STATE_SUCCESS; -} - -static const void* -extension_data(const char* uri) -{ - static const LV2_State_Interface state = {save, restore}; - if (!strcmp(uri, LV2_STATE__interface)) { - 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.lv2/test.ttl.in b/test/test.lv2/test.ttl.in deleted file mode 100644 index 1c16b4c..0000000 --- a/test/test.lv2/test.ttl.in +++ /dev/null @@ -1,46 +0,0 @@ -# Lilv Test Plugin -# Copyright 2011-2015 David Robillard -# -# 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: . -@prefix foaf: . -@prefix lv2: . -@prefix ui: . - - - a lv2:Plugin ; - doap:name "Lilv Test" ; - doap:license ; - lv2:requiredFeature ; - lv2:optionalFeature lv2:hardRTCapable ; - lv2:extensionData ; - 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" - ] , [ - a lv2:InputPort , - lv2:ControlPort ; - lv2:index 2 ; - lv2:symbol "control" ; - lv2:name "Control" - ] . diff --git a/test/test_plugin.lv2/manifest.ttl.in b/test/test_plugin.lv2/manifest.ttl.in new file mode 100644 index 0000000..48b009b --- /dev/null +++ b/test/test_plugin.lv2/manifest.ttl.in @@ -0,0 +1,7 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Plugin ; + lv2:binary ; + rdfs:seeAlso . diff --git a/test/test_plugin.lv2/meson.build b/test/test_plugin.lv2/meson.build new file mode 100644 index 0000000..2a4273d --- /dev/null +++ b/test/test_plugin.lv2/meson.build @@ -0,0 +1,17 @@ +module = shared_module('test_plugin', + files('test_plugin.c'), + c_args: c_suppressions, + dependencies: lv2_dep, + gnu_symbol_visibility: 'hidden', + name_prefix: '') + +extension = '.' + module.full_path().split('.')[-1] +config = configuration_data({'SHLIB_EXT': extension}) +ttl_files = ['manifest.ttl', 'test_plugin.ttl'] + +foreach f : ttl_files + configure_file(input: files(f + '.in'), + output: f, + configuration: config) +endforeach + diff --git a/test/test_plugin.lv2/test_plugin.c b/test/test_plugin.lv2/test_plugin.c new file mode 100644 index 0000000..9615fff --- /dev/null +++ b/test/test_plugin.lv2/test_plugin.c @@ -0,0 +1,481 @@ +/* + Lilv Test Plugin + Copyright 2011-2022 David Robillard + + 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 "lv2/atom/atom.h" +#include "lv2/core/lv2.h" +#include "lv2/state/state.h" +#include "lv2/urid/urid.h" + +#ifdef _WIN32 +# define _WIN32_LEAN_AND_MEAN +# include +#endif + +#include +#include +#include +#include + +#define TEST_URI "http://example.org/lilv-test-plugin" + +enum { TEST_INPUT = 0, TEST_OUTPUT = 1, TEST_CONTROL = 2 }; + +typedef struct { + LV2_URID_Map* map; + LV2_State_Free_Path* free_path; + + struct { + LV2_URID atom_Float; + } uris; + + char* tmp_dir_path; + char* rec_file_path; + FILE* rec_file; + + float* input; + float* output; + unsigned num_runs; +} Test; + +static char* +temp_directory_path(void) +{ +#ifdef _WIN32 + const DWORD len = GetTempPath(0, NULL); + char* const buf = (char*)calloc(len, 1); + if (GetTempPath(len, buf) == 0) { + free(buf); + return NULL; + } + + return buf; +#else + const char* const tmpdir = getenv("TMPDIR"); + if (tmpdir) { + const size_t tmpdir_len = strlen(tmpdir); + char* const result = (char*)calloc(tmpdir_len + 1, 1); + + memcpy(result, tmpdir, tmpdir_len + 1); + return result; + } + + char* const result = (char*)calloc(6, 1); + + memcpy(result, "/tmp/", 6); + return result; +#endif +} + +static void +cleanup(LV2_Handle instance) +{ + Test* test = (Test*)instance; + if (test->rec_file) { + fclose(test->rec_file); + } + + if (test->free_path) { + test->free_path->free_path(test->free_path->handle, test->rec_file_path); + } + + free(test->tmp_dir_path); + 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; + case TEST_CONTROL: + 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) +{ + (void)descriptor; + (void)rate; + (void)path; + + Test* test = (Test*)calloc(1, sizeof(Test)); + if (!test) { + return NULL; + } + + test->tmp_dir_path = temp_directory_path(); + + LV2_State_Make_Path* make_path = NULL; + + 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, LV2_ATOM__Float); + } else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) { + make_path = (LV2_State_Make_Path*)features[i]->data; + } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { + test->free_path = (LV2_State_Free_Path*)features[i]->data; + } + } + + if (!test->map) { + fprintf(stderr, "Host does not support urid:map\n"); + free(test); + return NULL; + } + + if (make_path) { + if (!test->free_path) { + fprintf(stderr, "Host provided make_path without free_path\n"); + free(test); + return NULL; + } + + test->rec_file_path = make_path->path(make_path->handle, "recfile"); + if (!(test->rec_file = fopen(test->rec_file_path, "w"))) { + fprintf(stderr, "ERROR: Failed to open rec file\n"); + } + fprintf(test->rec_file, "instantiate\n"); + } + + return (LV2_Handle)test; +} + +static void +run(LV2_Handle instance, uint32_t sample_count) +{ + Test* test = (Test*)instance; + *test->output = *test->input; + if (sample_count == 1) { + ++test->num_runs; + } else if (sample_count == 2 && test->rec_file) { + // Append to rec file (changes size) + fprintf(test->rec_file, "run\n"); + } else if (sample_count == 3 && test->rec_file) { + // Change the first byte of rec file (doesn't change size) + fseek(test->rec_file, 0, SEEK_SET); + fprintf(test->rec_file, "X"); + fseek(test->rec_file, 0, SEEK_END); + } +} + +static uint32_t +map_uri(Test* plugin, const char* uri) +{ + return plugin->map->map(plugin->map->handle, uri); +} + +static LV2_State_Status +save(LV2_Handle instance, + LV2_State_Store_Function store, + void* callback_data, + uint32_t flags, + const LV2_Feature* const* features) +{ + (void)flags; + + Test* plugin = (Test*)instance; + + LV2_State_Map_Path* map_path = NULL; + LV2_State_Make_Path* make_path = NULL; + LV2_State_Free_Path* free_path = NULL; + for (int i = 0; features && features[i]; ++i) { + if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { + map_path = (LV2_State_Map_Path*)features[i]->data; + } else if (!strcmp(features[i]->URI, LV2_STATE__makePath)) { + make_path = (LV2_State_Make_Path*)features[i]->data; + } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { + free_path = (LV2_State_Free_Path*)features[i]->data; + } + } + + if (!map_path || !free_path) { + return LV2_STATE_ERR_NO_FEATURE; + } + + store(callback_data, + map_uri(plugin, "http://example.org/greeting"), + "hello", + strlen("hello") + 1, + map_uri(plugin, LV2_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, LV2_ATOM__URID), + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); + + // Try to store second value for the same property (should fail) + const uint32_t urid2 = map_uri(plugin, "http://example.org/urivalue2"); + if (!store(callback_data, + map_uri(plugin, "http://example.org/uri"), + &urid2, + sizeof(uint32_t), + map_uri(plugin, LV2_ATOM__URID), + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) { + return LV2_STATE_ERR_UNKNOWN; + } + + // Try to store with a null key (should fail) + if (!store(callback_data, + 0, + &urid2, + sizeof(uint32_t), + map_uri(plugin, LV2_ATOM__URID), + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE)) { + return LV2_STATE_ERR_UNKNOWN; + } + + store(callback_data, + map_uri(plugin, "http://example.org/num-runs"), + &plugin->num_runs, + sizeof(plugin->num_runs), + map_uri(plugin, LV2_ATOM__Int), + 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, LV2_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, LV2_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, LV2_ATOM__Bool), + LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE); + + const uint8_t blob[] = "I am a blob of arbitrary data."; + 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); + + if (map_path) { + const char* const file_name = "temp_file.txt"; + const size_t file_name_len = strlen(file_name); + const size_t dir_path_len = strlen(plugin->tmp_dir_path); + char* const tmp_file_path = + (char*)calloc(dir_path_len + file_name_len + 1, 1); + + memcpy(tmp_file_path, plugin->tmp_dir_path, dir_path_len); + memcpy(tmp_file_path + dir_path_len, file_name, file_name_len + 1); + + FILE* file = fopen(tmp_file_path, "w"); + if (!file) { + fprintf(stderr, "error: Failed to open file %s\n", tmp_file_path); + free(tmp_file_path); + return LV2_STATE_ERR_UNKNOWN; + } + + fprintf(file, "Hello\n"); + fclose(file); + + char* apath = map_path->abstract_path(map_path->handle, tmp_file_path); + char* apath2 = map_path->abstract_path(map_path->handle, tmp_file_path); + free(tmp_file_path); + if (strcmp(apath, apath2)) { + fprintf(stderr, "error: Path %s != %s\n", apath, apath2); + } + + store(callback_data, + map_uri(plugin, "http://example.org/extfile"), + apath, + strlen(apath) + 1, + map_uri(plugin, LV2_ATOM__Path), + LV2_STATE_IS_POD); + + free_path->free_path(free_path->handle, apath); + free_path->free_path(free_path->handle, apath2); + + if (plugin->rec_file) { + fflush(plugin->rec_file); + apath = map_path->abstract_path(map_path->handle, plugin->rec_file_path); + + store(callback_data, + map_uri(plugin, "http://example.org/recfile"), + apath, + strlen(apath) + 1, + map_uri(plugin, LV2_ATOM__Path), + LV2_STATE_IS_POD); + + free_path->free_path(free_path->handle, apath); + } + + if (make_path) { + char* spath = make_path->path(make_path->handle, "save"); + FILE* sfile = fopen(spath, "w"); + fprintf(sfile, "save"); + fclose(sfile); + + apath = map_path->abstract_path(map_path->handle, spath); + store(callback_data, + map_uri(plugin, "http://example.org/save-file"), + apath, + strlen(apath) + 1, + map_uri(plugin, LV2_ATOM__Path), + LV2_STATE_IS_POD); + free_path->free_path(free_path->handle, apath); + free_path->free_path(free_path->handle, spath); + } + } + + return LV2_STATE_SUCCESS; +} + +static LV2_State_Status +restore(LV2_Handle instance, + LV2_State_Retrieve_Function retrieve, + void* callback_data, + uint32_t flags, + const LV2_Feature* const* features) +{ + (void)flags; + + Test* plugin = (Test*)instance; + + LV2_State_Map_Path* map_path = NULL; + LV2_State_Free_Path* free_path = NULL; + for (int i = 0; features && features[i]; ++i) { + if (!strcmp(features[i]->URI, LV2_STATE__mapPath)) { + map_path = (LV2_State_Map_Path*)features[i]->data; + } else if (!strcmp(features[i]->URI, LV2_STATE__freePath)) { + free_path = (LV2_State_Free_Path*)features[i]->data; + } + } + + size_t size = 0; + uint32_t type = 0; + uint32_t valflags = 0; + + plugin->num_runs = + *(int32_t*)retrieve(callback_data, + map_uri(plugin, "http://example.org/num-runs"), + &size, + &type, + &valflags); + + if (!map_path || !free_path) { + return LV2_STATE_ERR_NO_FEATURE; + } + + char* apath = (char*)retrieve(callback_data, + map_uri(plugin, "http://example.org/extfile"), + &size, + &type, + &valflags); + + if (valflags != LV2_STATE_IS_POD) { + fprintf(stderr, "error: Restored bad file flags\n"); + return LV2_STATE_ERR_BAD_FLAGS; + } + + if (apath) { + char* path = map_path->absolute_path(map_path->handle, apath); + FILE* f = fopen(path, "r"); + char str[8]; + size_t n_read = fread(str, 1, sizeof(str), f); + fclose(f); + if (strncmp(str, "Hello\n", n_read)) { + fprintf( + stderr, "error: Restored bad file contents `%s' != `Hello'\n", str); + } + free_path->free_path(free_path->handle, path); + } + + apath = (char*)retrieve(callback_data, + map_uri(plugin, "http://example.org/save-file"), + &size, + &type, + &valflags); + if (apath) { + char* spath = map_path->absolute_path(map_path->handle, apath); + FILE* sfile = fopen(spath, "r"); + if (!sfile) { + fprintf(stderr, "error: Failed to open save file %s\n", spath); + } else { + fclose(sfile); + } + free_path->free_path(free_path->handle, spath); + } else { + fprintf(stderr, "error: Failed to restore save file.\n"); + } + + return LV2_STATE_SUCCESS; +} + +static const void* +extension_data(const char* uri) +{ + static const LV2_State_Interface state = {save, restore}; + if (!strcmp(uri, LV2_STATE__interface)) { + 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.lv2/test_plugin.ttl.in b/test/test_plugin.lv2/test_plugin.ttl.in new file mode 100644 index 0000000..1c16b4c --- /dev/null +++ b/test/test_plugin.lv2/test_plugin.ttl.in @@ -0,0 +1,46 @@ +# Lilv Test Plugin +# Copyright 2011-2015 David Robillard +# +# 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: . +@prefix foaf: . +@prefix lv2: . +@prefix ui: . + + + a lv2:Plugin ; + doap:name "Lilv Test" ; + doap:license ; + lv2:requiredFeature ; + lv2:optionalFeature lv2:hardRTCapable ; + lv2:extensionData ; + 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" + ] , [ + a lv2:InputPort , + lv2:ControlPort ; + lv2:index 2 ; + lv2:symbol "control" ; + lv2:name "Control" + ] . diff --git a/test/test_string.c b/test/test_string.c index dcfd894..4b718b5 100644 --- a/test/test_string.c +++ b/test/test_string.c @@ -14,8 +14,6 @@ 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" -- cgit v1.2.1