diff options
Diffstat (limited to 'tests')
34 files changed, 1268 insertions, 0 deletions
diff --git a/tests/TestClient.hpp b/tests/TestClient.hpp new file mode 100644 index 00000000..8d99db86 --- /dev/null +++ b/tests/TestClient.hpp @@ -0,0 +1,54 @@ +/* + This file is part of Ingen. + Copyright 2007-2017 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INGEN_TESTCLIENT_HPP +#define INGEN_TESTCLIENT_HPP + +#include <boost/variant/get.hpp> + +#include "ingen/Interface.hpp" +#include "ingen/Log.hpp" + +using namespace Ingen; + +class TestClient : public Ingen::Interface +{ +public: + explicit TestClient(Log& log) : _log(log) {} + ~TestClient() {} + + URI uri() const override { return URI("ingen:testClient"); } + + void message(const Message& msg) override { + if (const Response* const response = boost::get<Response>(&msg)) { + if (response->status != Status::SUCCESS) { + _log.error(fmt("error on message %1%: %2% (%3%)\n") + % response->id + % ingen_status_string(response->status) + % response->subject); + exit(EXIT_FAILURE); + } + } else if (const Error* const error = boost::get<Error>(&msg)) { + _log.error(fmt("error: %1%\n") % error->message); + exit(EXIT_FAILURE); + } + } + +private: + Log& _log; +}; + +#endif // INGEN_TESTCLIENT_HPP diff --git a/tests/connect_disconnect_node_node.ttl b/tests/connect_disconnect_node_node.ttl new file mode 100644 index 00000000..935de482 --- /dev/null +++ b/tests/connect_disconnect_node_node.ttl @@ -0,0 +1,36 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node1> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/node2> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/node1/left_out> ; + ingen:head <ingen:/main/node2/left_in> + ] . + +<msg3> + a patch:Delete ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/node1/left_out> ; + ingen:head <ingen:/main/node2/left_in> + ] . diff --git a/tests/connect_disconnect_node_patch.ttl b/tests/connect_disconnect_node_patch.ttl new file mode 100644 index 00000000..77ada2ad --- /dev/null +++ b/tests/connect_disconnect_node_patch.ttl @@ -0,0 +1,105 @@ +@prefix atom: <http://lv2plug.in/ns/ext/atom#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/amp> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://lv2plug.in/plugins/eg-amp> + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/sampler> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://lv2plug.in/plugins/eg-sampler> + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/out> ; + patch:body [ + a lv2:OutputPort , + lv2:AudioPort + ] . + +<msg3> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg4> + a patch:Put ; + patch:subject <ingen:/main/control> ; + patch:body [ + a lv2:InputPort , + atom:AtomPort ; + atom:bufferType atom:Sequence + ] . + +<msg5> + a patch:Put ; + patch:subject <ingen:/main/gain> ; + patch:body [ + a lv2:InputPort , + lv2:ControlPort + ] . + +<msg6> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/amp/out> ; + ingen:head <ingen:/main/out> + ] . + +<msg7> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/in> ; + ingen:head <ingen:/main/amp/in> + ] . + +<msg8> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/gain> ; + ingen:head <ingen:/main/amp/gain> + ] . + +<msg9> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/control> ; + ingen:head <ingen:/main/sampler/control> + ] . + +<msg10> + a patch:Delete ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/amp/out> ; + ingen:head <ingen:/main/out> + ] . + +<msg11> + a patch:Delete ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/in> ; + ingen:head <ingen:/main/amp/in> + ] . diff --git a/tests/connect_disconnect_patch_patch.ttl b/tests/connect_disconnect_patch_patch.ttl new file mode 100644 index 00000000..b35a4b55 --- /dev/null +++ b/tests/connect_disconnect_patch_patch.ttl @@ -0,0 +1,36 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/out> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/in> ; + ingen:head <ingen:/main/out> + ] . + +<msg3> + a patch:Delete ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/in> ; + ingen:head <ingen:/main/out> + ] . diff --git a/tests/copy_node.ttl b/tests/copy_node.ttl new file mode 100644 index 00000000..129ba758 --- /dev/null +++ b/tests/copy_node.ttl @@ -0,0 +1,16 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Copy ; + patch:subject <ingen:/main/node> ; + patch:destination <ingen:/main/copy> . diff --git a/tests/create_delete_node.ttl b/tests/create_delete_node.ttl new file mode 100644 index 00000000..81086e69 --- /dev/null +++ b/tests/create_delete_node.ttl @@ -0,0 +1,27 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Delete ; + patch:subject <ingen:/main/node> . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/deprecatednode> ; + patch:body [ + a ingen:Block ; + ingen:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg3> + a patch:Delete ; + patch:subject <ingen:/main/deprecatednode> . diff --git a/tests/create_delete_patch.ttl b/tests/create_delete_patch.ttl new file mode 100644 index 00000000..2fa72c42 --- /dev/null +++ b/tests/create_delete_patch.ttl @@ -0,0 +1,14 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/sub> ; + patch:body [ + a ingen:Graph ; + ] . + +<msg1> + a patch:Delete ; + patch:subject <ingen:/main/sub> . diff --git a/tests/create_delete_poly_patch.ttl b/tests/create_delete_poly_patch.ttl new file mode 100644 index 00000000..ea0228d4 --- /dev/null +++ b/tests/create_delete_poly_patch.ttl @@ -0,0 +1,15 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/sub> ; + patch:body [ + a ingen:Graph ; + ingen:polyphony 8 ; + ] . + +<msg1> + a patch:Delete ; + patch:subject <ingen:/main/sub> . diff --git a/tests/create_delete_port.ttl b/tests/create_delete_port.ttl new file mode 100644 index 00000000..ba26560d --- /dev/null +++ b/tests/create_delete_port.ttl @@ -0,0 +1,53 @@ +@prefix atom: <http://lv2plug.in/ns/ext/atom#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/audio_in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/float_in> ; + patch:body [ + a lv2:InputPort , + lv2:ControlPort + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/cv_in> ; + patch:body [ + a lv2:InputPort , + lv2:CVPort + ] . + +<msg3> + a patch:Put ; + patch:subject <ingen:/main/atom_in> ; + patch:body [ + a lv2:InputPort , + atom:AtomPort ; + atom:bufferType atom:Sequence + ] . + +<msg4> + a patch:Delete ; + patch:subject <ingen:/main/audio_in> . + +<msg5> + a patch:Delete ; + patch:subject <ingen:/main/float_in> . + +<msg6> + a patch:Delete ; + patch:subject <ingen:/main/cv_in> . + +<msg7> + a patch:Delete ; + patch:subject <ingen:/main/atom_in> . diff --git a/tests/disconnect_all_node.ttl b/tests/disconnect_all_node.ttl new file mode 100644 index 00000000..2b65f758 --- /dev/null +++ b/tests/disconnect_all_node.ttl @@ -0,0 +1,45 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node1> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/node2> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/node1/left_out> ; + ingen:head <ingen:/main/node2/left_in> + ] . + +<msg3> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/node1/right_out> ; + ingen:head <ingen:/main/node2/right_in> + ] . + +<msg4> + a patch:Delete ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:incidentTo <ingen:/main/node1> + ] . diff --git a/tests/disconnect_all_port.ttl b/tests/disconnect_all_port.ttl new file mode 100644 index 00000000..5c2d92f2 --- /dev/null +++ b/tests/disconnect_all_port.ttl @@ -0,0 +1,32 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/audio_in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/audio_in> ; + ingen:head <ingen:/main/node/left_in> + ] . + +<msg3> + a patch:Delete ; + patch:subject <ingen:/main/audio_in> . diff --git a/tests/duplicate_node.ttl b/tests/duplicate_node.ttl new file mode 100644 index 00000000..47d71dfc --- /dev/null +++ b/tests/duplicate_node.ttl @@ -0,0 +1,19 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/deprecatednode> ; + patch:body [ + a ingen:Block ; + lv2:prototype <ingen:/main/node> + ] . diff --git a/tests/empty.ingen/main.ttl b/tests/empty.ingen/main.ttl new file mode 100644 index 00000000..eee1ce4b --- /dev/null +++ b/tests/empty.ingen/main.ttl @@ -0,0 +1,52 @@ +@prefix atom: <http://lv2plug.in/ns/ext/atom#> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix midi: <http://lv2plug.in/ns/ext/midi#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +<control> + ingen:canvasX 32.0 ; + ingen:canvasY 32.0 ; + ingen:polyphonic false ; + atom:bufferType atom:Sequence ; + atom:supports patch:Message ; + <http://lv2plug.in/ns/ext/resize-port#minimumSize> 4096 ; + lv2:designation lv2:control ; + lv2:index 0 ; + lv2:name "Control" ; + lv2:portProperty lv2:connectionOptional ; + lv2:symbol "control" ; + a atom:AtomPort , + lv2:InputPort . + +<> + ingen:polyphony 1 ; + <http://lv2plug.in/ns/extensions/ui#ui> ingen:GraphUIGtk2 ; + lv2:extensionData <http://lv2plug.in/ns/ext/state#interface> ; + lv2:port <control> , + <notify> ; + lv2:symbol "empty" ; + doap:name "empty" ; + a ingen:Graph , + lv2:Plugin . + +<notify> + ingen:canvasX 128.0 ; + ingen:canvasY 32.0 ; + ingen:polyphonic false ; + atom:bufferType atom:Sequence ; + atom:supports patch:Message ; + <http://lv2plug.in/ns/ext/resize-port#minimumSize> 4096 ; + lv2:designation lv2:control ; + lv2:index 1 ; + lv2:name "Control" ; + lv2:portProperty lv2:connectionOptional ; + lv2:symbol "notify" ; + a atom:AtomPort , + lv2:OutputPort . + diff --git a/tests/empty.ingen/manifest.ttl b/tests/empty.ingen/manifest.ttl new file mode 100644 index 00000000..71f194a0 --- /dev/null +++ b/tests/empty.ingen/manifest.ttl @@ -0,0 +1,16 @@ +@prefix atom: <http://lv2plug.in/ns/ext/atom#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix doap: <http://usefulinc.com/ns/doap#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix midi: <http://lv2plug.in/ns/ext/midi#> . +@prefix owl: <http://www.w3.org/2002/07/owl#> . +@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . +@prefix xsd: <http://www.w3.org/2001/XMLSchema#> . + +<main.ttl> + lv2:prototype ingen:GraphPrototype ; + a ingen:Graph , + lv2:Plugin ; + rdfs:seeAlso <main.ttl> . diff --git a/tests/enable_graph.ttl b/tests/enable_graph.ttl new file mode 100644 index 00000000..f3fa786c --- /dev/null +++ b/tests/enable_graph.ttl @@ -0,0 +1,15 @@ +@prefix ingen: <http://drobilla.net/ns/ingen#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . + +<msg0> + a patch:Set ; + patch:subject <ingen:/main> ; + patch:property ingen:enabled ; + patch:value true . + +<msg1> + a patch:Set ; + patch:subject <ingen:/main> ; + patch:property ingen:enabled ; + patch:value false . diff --git a/tests/get_engine.ttl b/tests/get_engine.ttl new file mode 100644 index 00000000..adfa6a01 --- /dev/null +++ b/tests/get_engine.ttl @@ -0,0 +1,7 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Get ; + patch:subject <ingen:/engine> . diff --git a/tests/get_node.ttl b/tests/get_node.ttl new file mode 100644 index 00000000..12977092 --- /dev/null +++ b/tests/get_node.ttl @@ -0,0 +1,15 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Get ; + patch:subject <ingen:/main/node> . diff --git a/tests/get_patch.ttl b/tests/get_patch.ttl new file mode 100644 index 00000000..9ea9e036 --- /dev/null +++ b/tests/get_patch.ttl @@ -0,0 +1,39 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/sub> ; + patch:body [ + a ingen:Graph + ] . + +<msg1> + a patch:Put ; + patch:subject <ingen:/main/sub/node1> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg2> + a patch:Put ; + patch:subject <ingen:/main/sub/node2> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Combo> + ] . + +<msg3> + a patch:Put ; + patch:subject <ingen:/main/> ; + patch:body [ + a ingen:Arc ; + ingen:tail <ingen:/main/sub/node1/left_out> ; + ingen:head <ingen:/main/sub/node2/left_in> + ] . + +<msg4> + a patch:Get ; + patch:subject <ingen:/main/> . diff --git a/tests/get_plugin.ttl b/tests/get_plugin.ttl new file mode 100644 index 00000000..19a9c93c --- /dev/null +++ b/tests/get_plugin.ttl @@ -0,0 +1,7 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Get ; + patch:subject <http://lv2plug.in/plugins/eg-amp> . diff --git a/tests/get_plugins.ttl b/tests/get_plugins.ttl new file mode 100644 index 00000000..8dc91cdf --- /dev/null +++ b/tests/get_plugins.ttl @@ -0,0 +1,7 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Get ; + patch:subject <ingen:/plugins> . diff --git a/tests/get_port.ttl b/tests/get_port.ttl new file mode 100644 index 00000000..4f26e499 --- /dev/null +++ b/tests/get_port.ttl @@ -0,0 +1,15 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Get ; + patch:subject <ingen:/main/in> . diff --git a/tests/ingen_bench.cpp b/tests/ingen_bench.cpp new file mode 100644 index 00000000..e8cccf4c --- /dev/null +++ b/tests/ingen_bench.cpp @@ -0,0 +1,140 @@ +/* + This file is part of Ingen. + Copyright 2007-2017 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <cstdlib> +#include <iostream> +#include <string> +#include <thread> + +#include "ingen/Clock.hpp" +#include "ingen/Configuration.hpp" +#include "ingen/EngineBase.hpp" +#include "ingen/Forge.hpp" +#include "ingen/Interface.hpp" +#include "ingen/Parser.hpp" +#include "ingen/World.hpp" +#include "ingen/runtime_paths.hpp" +#include "ingen/types.hpp" + +#include "TestClient.hpp" +#include "ingen_config.h" + +using namespace std; +using namespace Ingen; + +World* world = nullptr; + +static void +ingen_try(bool cond, const char* msg) +{ + if (!cond) { + cerr << "ingen: Error: " << msg << endl; + delete world; + exit(EXIT_FAILURE); + } +} + +static std::string +real_path(const char* path) +{ + char* const c_real_path = realpath(path, nullptr); + const std::string result(c_real_path ? c_real_path : ""); + free(c_real_path); + return result; +} + +int +main(int argc, char** argv) +{ + set_bundle_path_from_code((void*)&ingen_try); + + // Create world + try { + world = new World(nullptr, nullptr, nullptr); + world->conf().add( + "output", "output", 'O', "File to write benchmark output", + Ingen::Configuration::SESSION, world->forge().String, Atom()); + world->load_configuration(argc, argv); + } catch (std::exception& e) { + cout << "ingen: " << e.what() << endl; + return EXIT_FAILURE; + } + + // Get mandatory command line arguments + const Atom& load = world->conf().option("load"); + const Atom& out = world->conf().option("output"); + if (!load.is_valid() || !out.is_valid()) { + cerr << "Usage: ingen_bench --load START_GRAPH --output OUT_FILE" << endl; + return EXIT_FAILURE; + } + + // Get start graph and output file options + const std::string start_graph = real_path((const char*)load.get_body()); + const std::string out_file = (const char*)out.get_body(); + if (start_graph.empty()) { + cerr << "error: initial graph '" + << ((const char*)load.get_body()) + << "' does not exist" << endl; + return EXIT_FAILURE; + } + + // Load modules + ingen_try(world->load_module("server"), + "Unable to load server module"); + + // Initialise engine + ingen_try(bool(world->engine()), + "Unable to create engine"); + world->engine()->init(48000.0, 4096, 4096); + world->engine()->activate(); + + // Load graph + if (!world->parser()->parse_file(world, world->interface().get(), start_graph)) { + cerr << "error: failed to load initial graph " << start_graph << endl; + return EXIT_FAILURE; + } + world->engine()->flush_events(std::chrono::milliseconds(20)); + + // Run benchmark + // TODO: Set up real-time scheduling for this and worker threads + Ingen::Clock clock; + const uint32_t n_test_frames = 1 << 20; + const uint32_t block_length = 4096; + const uint64_t t_start = clock.now_microseconds(); + for (uint32_t i = 0; i < n_test_frames; i += block_length) { + world->engine()->advance(block_length); + world->engine()->run(block_length); + //world->engine()->main_iteration(); + } + const uint64_t t_end = clock.now_microseconds(); + + // Write log output + FILE* log = fopen(out_file.c_str(), "a"); + if (ftell(log) == 0) { + fprintf(log, "# n_threads\trun_time\treal_time\n"); + } + fprintf(log, "%u\t%f\t%f\n", + world->conf().option("threads").get<int32_t>(), + (t_end - t_start) / 1000000.0, + (n_test_frames / 48000.0)); + fclose(log); + + // Shut down + world->engine()->deactivate(); + + delete world; + return EXIT_SUCCESS; +} diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp new file mode 100644 index 00000000..c0a7bd32 --- /dev/null +++ b/tests/ingen_test.cpp @@ -0,0 +1,223 @@ +/* + This file is part of Ingen. + Copyright 2007-2017 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <signal.h> + +#include <cstdlib> +#include <iostream> +#include <string> + +#include <boost/optional.hpp> + +#include "raul/Path.hpp" + +#include "serd/serd.h" +#include "sord/sordmm.hpp" +#include "sratom/sratom.h" + +#include "ingen_config.h" + +#include "ingen/AtomReader.hpp" +#include "ingen/AtomWriter.hpp" +#include "ingen/Configuration.hpp" +#include "ingen/Configuration.hpp" +#include "ingen/EngineBase.hpp" +#include "ingen/Interface.hpp" +#include "ingen/Parser.hpp" +#include "ingen/Properties.hpp" +#include "ingen/Serialiser.hpp" +#include "ingen/Store.hpp" +#include "ingen/URIMap.hpp" +#include "ingen/World.hpp" +#include "ingen/filesystem.hpp" +#include "ingen/runtime_paths.hpp" +#include "ingen/types.hpp" + +#include "TestClient.hpp" + +using namespace std; +using namespace Ingen; + +World* world = nullptr; + +static void +ingen_try(bool cond, const char* msg) +{ + if (!cond) { + cerr << "ingen: Error: " << msg << endl; + delete world; + exit(EXIT_FAILURE); + } +} + +int +main(int argc, char** argv) +{ + set_bundle_path_from_code((void*)&ingen_try); + + // Create world + try { + world = new World(nullptr, nullptr, nullptr); + world->load_configuration(argc, argv); + } catch (std::exception& e) { + cout << "ingen: " << e.what() << endl; + return EXIT_FAILURE; + } + + // Get mandatory command line arguments + const Atom& load = world->conf().option("load"); + const Atom& execute = world->conf().option("execute"); + if (!load.is_valid() || !execute.is_valid()) { + cerr << "Usage: ingen_test --load START_GRAPH --execute COMMANDS_FILE" << endl; + return EXIT_FAILURE; + } + + // Get start graph and commands file options + const char* load_path = (const char*)load.get_body(); + char* real_start_graph = realpath(load_path, nullptr); + if (!real_start_graph) { + cerr << "error: initial graph '" << load_path << "' does not exist" << endl; + return EXIT_FAILURE; + } + + const std::string start_graph = real_start_graph; + const FilePath cmds_file_path = (const char*)execute.get_body(); + free(real_start_graph); + + // Load modules + ingen_try(world->load_module("server"), + "Unable to load server module"); + + // Initialise engine + ingen_try(bool(world->engine()), + "Unable to create engine"); + world->engine()->init(48000.0, 4096, 4096); + world->engine()->activate(); + + // Load graph + if (!world->parser()->parse_file(world, world->interface().get(), start_graph)) { + cerr << "error: failed to load initial graph " << start_graph << endl; + return EXIT_FAILURE; + } + world->engine()->flush_events(std::chrono::milliseconds(20)); + + // Read commands + + LV2_URID_Map* map = &world->uri_map().urid_map_feature()->urid_map; + Sratom* sratom = sratom_new(map); + + sratom_set_object_mode(sratom, SRATOM_OBJECT_MODE_BLANK_SUBJECT); + + LV2_Atom_Forge forge; + lv2_atom_forge_init(&forge, map); + + AtomForgeSink out(&forge); + + // AtomReader to read commands from a file and send them to engine + AtomReader atom_reader(world->uri_map(), + world->uris(), + world->log(), + *world->interface().get()); + + // AtomWriter to serialise responses from the engine + SPtr<Interface> client(new TestClient(world->log())); + + world->interface()->set_respondee(client); + world->engine()->register_client(client); + + SerdURI cmds_base; + SerdNode cmds_file_uri = serd_node_new_file_uri( + (const uint8_t*)cmds_file_path.c_str(), + nullptr, &cmds_base, true); + Sord::Model* cmds = new Sord::Model(*world->rdf_world(), + (const char*)cmds_file_uri.buf); + SerdEnv* env = serd_env_new(&cmds_file_uri); + cmds->load_file(env, SERD_TURTLE, cmds_file_path); + Sord::Node nil; + int n_events = 0; + for (;; ++n_events) { + std::string subject_str = (fmt("msg%1%") % n_events).str(); + Sord::URI subject(*world->rdf_world(), subject_str, + (const char*)cmds_file_uri.buf); + Sord::Iter iter = cmds->find(subject, nil, nil); + if (iter.end()) { + break; + } + + out.clear(); + sratom_read(sratom, &forge, world->rdf_world()->c_obj(), + cmds->c_obj(), subject.c_obj()); + +#if 0 + const LV2_Atom* atom = out.atom(); + cerr << "READ " << atom->size << " BYTES" << endl; + cerr << sratom_to_turtle( + sratom, + &world->uri_map().urid_unmap_feature()->urid_unmap, + (const char*)cmds_file_uri.buf, + NULL, NULL, atom->type, atom->size, LV2_ATOM_BODY(atom)) << endl; +#endif + + if (!atom_reader.write(out.atom(), n_events + 1)) { + return EXIT_FAILURE; + } + + world->engine()->flush_events(std::chrono::milliseconds(20)); + } + + delete cmds; + + // Save resulting graph + auto r = world->store()->find(Raul::Path("/")); + const std::string base = cmds_file_path.stem(); + const std::string out_name = base.substr(0, base.find('.')) + ".out.ingen"; + const FilePath out_path = filesystem::current_path() / out_name; + world->serialiser()->write_bundle(r->second, URI(out_path)); + + // Undo every event (should result in a graph identical to the original) + for (int i = 0; i < n_events; ++i) { + world->interface()->undo(); + world->engine()->flush_events(std::chrono::milliseconds(20)); + } + + // Save completely undone graph + r = world->store()->find(Raul::Path("/")); + const std::string undo_name = base.substr(0, base.find('.')) + ".undo.ingen"; + const FilePath undo_path = filesystem::current_path() / undo_name; + world->serialiser()->write_bundle(r->second, URI(undo_path)); + + // Redo every event (should result in a graph identical to the pre-undo output) + for (int i = 0; i < n_events; ++i) { + world->interface()->redo(); + world->engine()->flush_events(std::chrono::milliseconds(20)); + } + + // Save completely redone graph + r = world->store()->find(Raul::Path("/")); + const std::string redo_name = base.substr(0, base.find('.')) + ".redo.ingen"; + const FilePath redo_path = filesystem::current_path() / redo_name; + world->serialiser()->write_bundle(r->second, URI(redo_path)); + + serd_env_free(env); + sratom_free(sratom); + serd_node_free(&cmds_file_uri); + + // Shut down + world->engine()->deactivate(); + + delete world; + return EXIT_SUCCESS; +} diff --git a/tests/load_graph.ttl b/tests/load_graph.ttl new file mode 100644 index 00000000..f1cd9dda --- /dev/null +++ b/tests/load_graph.ttl @@ -0,0 +1,8 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Copy ; + patch:subject <empty.ingen/> ; + patch:destination <ingen:/main/> . diff --git a/tests/move_node.ttl b/tests/move_node.ttl new file mode 100644 index 00000000..22f6cfb8 --- /dev/null +++ b/tests/move_node.ttl @@ -0,0 +1,16 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Move ; + patch:subject <ingen:/main/node> ; + patch:destination <ingen:/main/tone> . diff --git a/tests/move_port.ttl b/tests/move_port.ttl new file mode 100644 index 00000000..4b035037 --- /dev/null +++ b/tests/move_port.ttl @@ -0,0 +1,16 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Move ; + patch:subject <ingen:/main/in> ; + patch:destination <ingen:/main/input> . diff --git a/tests/move_root_port.ttl b/tests/move_root_port.ttl new file mode 100644 index 00000000..2c925767 --- /dev/null +++ b/tests/move_root_port.ttl @@ -0,0 +1,20 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . + +<msg1> + a patch:Move ; + patch:subject <ingen:/main/in> ; + patch:destination <ingen:/main/input> . + +<msg2> + a patch:Delete ; + patch:subject <ingen:/main/input> . diff --git a/tests/poly.ttl b/tests/poly.ttl new file mode 100644 index 00000000..a02ba96e --- /dev/null +++ b/tests/poly.ttl @@ -0,0 +1,25 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/node> ; + patch:body [ + a ingen:Block ; + lv2:prototype <http://drobilla.net/plugins/mda/Shepard> + ] . + +<msg1> + a patch:Set ; + patch:context ingen:internalContext ; + patch:subject <ingen:/main/> ; + patch:property ingen:polyphony ; + patch:value 4 . + +<msg2> + a patch:Set ; + patch:context ingen:externalContext ; + patch:subject <ingen:/main/node> ; + patch:property ingen:polyphonic ; + patch:value true . diff --git a/tests/put_audio_in.ttl b/tests/put_audio_in.ttl new file mode 100644 index 00000000..97468cff --- /dev/null +++ b/tests/put_audio_in.ttl @@ -0,0 +1,10 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:AudioPort + ] . diff --git a/tests/save_graph.ttl b/tests/save_graph.ttl new file mode 100644 index 00000000..5f472d80 --- /dev/null +++ b/tests/save_graph.ttl @@ -0,0 +1,8 @@ +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . +@prefix ingen: <http://drobilla.net/ns/ingen#> . + +<msg0> + a patch:Copy ; + patch:subject <ingen:/main/> ; + patch:destination <file:///tmp/savetest.ingen/> . diff --git a/tests/set_graph_poly.ttl b/tests/set_graph_poly.ttl new file mode 100644 index 00000000..0933c3a4 --- /dev/null +++ b/tests/set_graph_poly.ttl @@ -0,0 +1,17 @@ +@prefix ingen: <http://drobilla.net/ns/ingen#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . + +<msg0> + a patch:Set ; + patch:context ingen:internalContext ; + patch:subject <ingen:/main/> ; + patch:property ingen:polyphony ; + patch:value 4 . + +<msg1> + a patch:Set ; + patch:context ingen:internalContext ; + patch:subject <ingen:/main/> ; + patch:property ingen:polyphony ; + patch:value 1 . diff --git a/tests/set_patch_port_value.ttl b/tests/set_patch_port_value.ttl new file mode 100644 index 00000000..07b467b4 --- /dev/null +++ b/tests/set_patch_port_value.ttl @@ -0,0 +1,17 @@ +@prefix ingen: <http://drobilla.net/ns/ingen#> . +@prefix lv2: <http://lv2plug.in/ns/lv2core#> . +@prefix patch: <http://lv2plug.in/ns/ext/patch#> . + +<msg0> + a patch:Put ; + patch:subject <ingen:/main/in> ; + patch:body [ + a lv2:InputPort , + lv2:ControlPort + ] . + +<msg1> + a patch:Set ; + patch:subject <ingen:/main/in> ; + patch:property ingen:value ; + patch:value 0.5 .
\ No newline at end of file diff --git a/tests/test_utils.hpp b/tests/test_utils.hpp new file mode 100644 index 00000000..a0cc53ac --- /dev/null +++ b/tests/test_utils.hpp @@ -0,0 +1,40 @@ +/* + This file is part of Ingen. + Copyright 2018 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <iostream> + +#include <boost/format.hpp> + +typedef boost::basic_format<char> fmt; + +#define EXPECT_TRUE(value) \ + if (!(value)) { \ + std::cerr << (fmt("error: %1%:%2%: !%3%\n") % __FILE__ % \ + __LINE__ % (#value)); \ + } + +#define EXPECT_FALSE(value) \ + if ((value)) { \ + std::cerr << (fmt("error: %1%:%2%: !%3%\n") % __FILE__ % \ + __LINE__ % (#value)); \ + } + +#define EXPECT_EQ(value, expected) \ + if (!((value) == (expected))) { \ + std::cerr << (fmt("error: %1%:%2%: %3% != %4%\n") % __FILE__ % \ + __LINE__ % (#value) % (#expected)); \ + std::cerr << "note: actual value: " << value << std::endl; \ + } diff --git a/tests/tst_FilePath.cpp b/tests/tst_FilePath.cpp new file mode 100644 index 00000000..55d6f1c2 --- /dev/null +++ b/tests/tst_FilePath.cpp @@ -0,0 +1,103 @@ +/* + This file is part of Ingen. + Copyright 2018 David Robillard <http://drobilla.net/> + + Ingen is free software: you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free + Software Foundation, either version 3 of the License, or any later version. + + Ingen is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for details. + + You should have received a copy of the GNU Affero General Public License + along with Ingen. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <boost/utility/string_view.hpp> + +#include "ingen/FilePath.hpp" +#include "test_utils.hpp" + +using Ingen::FilePath; + +int +main(int, char**) +{ + EXPECT_EQ(FilePath("/").parent_path(), FilePath("/")); + + EXPECT_TRUE(FilePath("/abs").is_absolute()) + EXPECT_FALSE(FilePath("/abs").is_relative()) + EXPECT_EQ(FilePath("/abs").root_name(), FilePath()); + EXPECT_EQ(FilePath("/abs").root_directory(), FilePath("/")); + EXPECT_EQ(FilePath("/abs").root_path(), FilePath("/")); + EXPECT_EQ(FilePath("/abs").relative_path(), FilePath("abs")); + EXPECT_EQ(FilePath("/abs").parent_path(), FilePath("/")); + EXPECT_EQ(FilePath("/abs").filename(), FilePath("abs")); + EXPECT_EQ(FilePath("/abs").stem(), FilePath("abs")); + EXPECT_EQ(FilePath("/abs").extension(), FilePath()); + + EXPECT_FALSE(FilePath("rel").is_absolute()) + EXPECT_TRUE(FilePath("rel").is_relative()) + EXPECT_EQ(FilePath("rel").root_name(), FilePath()); + EXPECT_EQ(FilePath("rel").root_directory(), FilePath()); + EXPECT_EQ(FilePath("rel").root_path(), FilePath()); + EXPECT_EQ(FilePath("rel").relative_path(), FilePath()); + EXPECT_EQ(FilePath("rel").parent_path(), FilePath()); + EXPECT_EQ(FilePath("rel").filename(), "rel"); + EXPECT_EQ(FilePath("rel").stem(), "rel"); + EXPECT_EQ(FilePath("rel").extension(), FilePath()); + + EXPECT_FALSE(FilePath("file.txt").is_absolute()) + EXPECT_TRUE(FilePath("file.txt").is_relative()) + EXPECT_EQ(FilePath("file.txt").filename(), "file.txt"); + EXPECT_EQ(FilePath("file.txt").stem(), "file"); + EXPECT_EQ(FilePath("file.txt").extension(), ".txt"); + + EXPECT_TRUE(FilePath("/abs/file.txt").is_absolute()) + EXPECT_FALSE(FilePath("/abs/file.txt").is_relative()) + EXPECT_EQ(FilePath("/abs/file.txt").filename(), "file.txt"); + EXPECT_EQ(FilePath("/abs/file.txt").stem(), "file"); + EXPECT_EQ(FilePath("/abs/file.txt").extension(), ".txt"); + + EXPECT_FALSE(FilePath("rel/file.txt").is_absolute()) + EXPECT_TRUE(FilePath("rel/file.txt").is_relative()) + EXPECT_EQ(FilePath("rel/file.txt").filename(), "file.txt"); + EXPECT_EQ(FilePath("rel/file.txt").stem(), "file"); + EXPECT_EQ(FilePath("rel/file.txt").extension(), ".txt"); + + FilePath path("/x"); + EXPECT_EQ(path, "/x"); + path = std::string("/a"); + EXPECT_EQ(path, "/a"); + + path /= FilePath("b"); + EXPECT_EQ(path, "/a/b"); + + path += FilePath("ar"); + EXPECT_EQ(path, "/a/bar"); + + path += std::string("/c"); + EXPECT_EQ(path, "/a/bar/c"); + + path += "a"; + EXPECT_EQ(path, "/a/bar/ca"); + + path += 'r'; + EXPECT_EQ(path, "/a/bar/car"); + + path += boost::string_view("/d"); + EXPECT_EQ(path, "/a/bar/car/d"); + + const FilePath apple("apple"); + const FilePath zebra("zebra"); + EXPECT_TRUE(apple == apple); + EXPECT_TRUE(apple != zebra); + EXPECT_TRUE(apple < zebra); + EXPECT_TRUE(apple <= zebra); + EXPECT_TRUE(apple <= apple); + EXPECT_TRUE(zebra > apple); + EXPECT_TRUE(zebra >= apple); + EXPECT_TRUE(zebra >= zebra); + return 0; +} |