Commit f0b4404b authored by Benjamin Heisch's avatar Benjamin Heisch
Browse files

Refractored tests, so every format dependent source fiels, are under subdir formats.

Also added regression tests
parent 14bb05c6
......@@ -36,6 +36,16 @@ set_version(1 0 0)
#####################BUILD######################
if(XPLUG_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif(XPLUG_BUILD_TESTS)
if(XPLUG_BUILD_EXAMPLES)
add_subdirectory(examples)
endif(XPLUG_BUILD_EXAMPLES)
add_subdirectory(formats)
add_subdirectory(include)
add_subdirectory(src)
......@@ -82,12 +92,3 @@ set(CPACK_PACKAGE_CONTACT "Benjamin Heisch")
include(CPack)
endif(XPLUG_INSTALL)
if(XPLUG_BUILD_TESTS)
enable_testing()
add_subdirectory(test)
endif(XPLUG_BUILD_TESTS)
if(XPLUG_BUILD_EXAMPLES)
add_subdirectory(examples)
endif(XPLUG_BUILD_EXAMPLES)
......@@ -21,7 +21,6 @@ public:
while (!in0->empty()) {
auto midiMsg = in0->get();
auto midiMsg2= midiMsg;
midiMsg[1]=midiMsg[1]*2;
out0->feed(std::move(midiMsg));
out1->feed(std::move(midiMsg2));
}
......
......@@ -24,7 +24,7 @@ public:
for (int i = 0; i < in0->size(); i++) {
for (int s = 0; s < in0->getSampleSize(); s++) {
if(in0->at(i)->getData() != nullptr && out0->at(i)->getData()!=nullptr )
out0->at(i)->getData()[s] = in0->at(i)->getData()[s] * 0.5f;
out0->at(i)->getData()[s] = in0->at(i)->getData()[s];
}
}
}
......
......@@ -4,7 +4,6 @@ option(XPLUG_LADSPA_SUPPORT "Support vor LADSPA" ON)
if(XPLUG_LADSPA_SUPPORT)
include(symbol_export)
add_library(ladspa "ladspa.h" "ladspa.cpp")
set_target_properties(ladspa PROPERTIES POSITION_INDEPENDENT_CODE True)
target_link_libraries(ladspa XPlug)
......@@ -12,4 +11,5 @@ if(XPLUG_LADSPA_SUPPORT)
target_include_directories(ladspa PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../../src)
EXPORT_SYMBOLS(ladspa FUNCTION_NAMES ladspa_descriptor)
install(TARGETS ladspa EXPORT XPlugExport DESTINATION lib)
add_subdirectory(tests)
endif(XPLUG_LADSPA_SUPPORT)
\ No newline at end of file
if(XPLUG_LADSPA_SUPPORT)
target_include_directories(XValidate PUBLIC ${CMAKE_SOURCE_DIR}/formats/ladspa)
if(XPLUG_BUILD_TESTS)
target_include_directories(XValidate PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..)
target_sources(XValidate PUBLIC ${CMAKE_CURRENT_LIST_DIR}/LADSPATestSuite.cpp)
endif(XPLUG_LADSPA_SUPPORT)
\ No newline at end of file
endif(XPLUG_BUILD_TESTS)
\ No newline at end of file
#include "../../IFormatTestSuite.hpp"
#include "IFormatTestSuite.hpp"
#include "tools/LibLoading.hpp"
#include "ladspa.h"
#include <vector>
......@@ -47,9 +47,6 @@ public:
return ret;
}
virtual SucceedState runPerformance() override
{
return TEST_SUCCEEDED;
}
};
REGISTER_TEST_SUITE(LADSPATestSuite);
\ No newline at end of file
......@@ -5,7 +5,6 @@ option(XPLUG_LV2_SUPPORT "Support vor LV2" ${LV2_FOUND})
if(XPLUG_LV2_SUPPORT)
include(symbol_export)
find_package(LV2 REQUIRED)
add_library(lv2 "lv2.cpp" "lv2_ttl_generation.cpp")
set_target_properties(lv2 PROPERTIES POSITION_INDEPENDENT_CODE True)
......@@ -16,5 +15,6 @@ if(XPLUG_LV2_SUPPORT)
add_executable(TTLGenerator "TtlGenerator.cpp")
target_link_libraries(TTLGenerator XPlug)
install(TARGETS lv2 EXPORT XPlugExport DESTINATION lib)
add_subdirectory(tests)
# add_executable(tt "turtle.cpp")
endif(XPLUG_LV2_SUPPORT)
\ No newline at end of file
......@@ -5,7 +5,7 @@
#include <tools/LibLoading.hpp>
#include <tools/StringTools.hpp>
#include "lv2_ttl_generation.hpp"
#include "turtle.hpp"
using namespace XPlug;
std::string(*getTTLFromPluginPtr)(IPlugin*) = nullptr;
......
......@@ -40,7 +40,8 @@ inline void handleInput(MidiHandle* in) {
// Struct for a 3 byte MIDI event, used for writing notes
typedef struct {
LV2_Atom_Event event;
MidiMessage msg;
//MidiMessage msg;
uint8_t msg[3];
} MIDINoteEvent;
/**
* @brief Treats the MidiHandle, at it would be an output. (fetches things from the Pipe to the output)
......@@ -51,14 +52,14 @@ inline void handleOutput(MidiHandle* out) {
const uint32_t out_capacity = out->midiDataLocation->atom.size;
// Write an empty Sequence header to the output
lv2_atom_sequence_clear(out->midiDataLocation);
out->midiDataLocation->atom.type = out->midi_MidiEventID;
//out->midiDataLocation->atom.type = out->midi_MidiEventID;
while (!out->connectedMidiPort->empty()) {
MIDINoteEvent ev;
// Could simply do fifth.event = *ev here instead...
ev.event.time.frames = 0; // Same time
ev.event.body.type = out->midi_MidiEventID; // Same type
ev.event.body.size = sizeof(MIDINoteEvent); // Same size
ev.msg = out->connectedMidiPort->get();
auto msg = out->connectedMidiPort->get();
MIDINoteEvent ev{
{0 , {sizeof(MIDINoteEvent) - sizeof(LV2_Atom),out->midi_MidiEventID } },//LV2_Atom_Event
{msg[0],msg[1],msg[2]} // new MidiMsg
};
lv2_atom_sequence_append_event(
out->midiDataLocation, out_capacity, &ev.event);
}
......
if(XPLUG_LV2_SUPPORT)
find_package(LV2 REQUIRED)
if(XPLUG_BUILD_TESTS)
target_include_directories(XValidate PUBLIC ${LV2_INCLUDE_DIRS})
target_sources(XValidate PUBLIC
${CMAKE_CURRENT_LIST_DIR}/LV2TestSuite.cpp
${CMAKE_CURRENT_LIST_DIR}/lilv.c
)
endif(XPLUG_LV2_SUPPORT)
\ No newline at end of file
target_include_directories(regression_tests PUBLIC ${LV2_INCLUDE_DIRS})
target_sources(regression_tests PUBLIC
${CMAKE_CURRENT_LIST_DIR}/LV2RegressionTest.cpp
${CMAKE_CURRENT_LIST_DIR}/lilv.c)
endif(XPLUG_BUILD_TESTS)
\ No newline at end of file
......@@ -10,8 +10,6 @@
#include <array>
#include <algorithm>
#include <map>
using namespace XPlug;
inline std::string replaceInString(std::string strToChange, const std::string itemToReplace, const std::string substitute)
......@@ -85,6 +83,7 @@ public:
this->lilvPort = lilvPort;
this->type = type;
this->features = features;
this->dir = dir;
}
Port(const Port& other) {
features = other.features;
......@@ -105,8 +104,9 @@ public:
this->data = new MidiEventBuffer;
memset(data, 0, sizeof(MidiEventBuffer));
((MidiEventBuffer*)this->data)->seq.atom.type = features->uridmap.map(features->uridmap.handle, LV2_ATOM__Sequence);
// lv2_atom_sequence_clear(&((MidiEventBuffer*)this->data)->seq);
((MidiEventBuffer*)this->data)->seq.atom.size = this->size_of_data -sizeof(LV2_Atom);
if(this->dir==Input)
lv2_atom_sequence_clear(&((MidiEventBuffer*)this->data)->seq);
return;
case Audio:
this->size_of_data =sizeof(float)*sample_count;
......@@ -117,11 +117,11 @@ public:
inline void addMidiMsg(uint8_t b1 , uint8_t b2, uint8_t b3) {
MIDINoteEvent ev{
{0 , {sizeof(MIDINoteEvent),features->uridmap.map(features->uridmap.handle, LV2_MIDI__MidiEvent) } },//LV2_Atom_Event
{0 , {sizeof(MIDINoteEvent)-sizeof(LV2_Atom),features->uridmap.map(features->uridmap.handle, LV2_MIDI__MidiEvent) } },//LV2_Atom_Event
{b1,b2,b3} // new MidiMsg
};
lv2_atom_sequence_append_event(&((MidiEventBuffer*)this->data)->seq,
sizeof(LV2_Atom_Sequence_Body) + sizeof(MIDINoteEvent[40]), (LV2_Atom_Event*)&ev);
sizeof(MIDINoteEvent[40]), (LV2_Atom_Event*)&ev);
}
......
#include "CatchTools.hpp"
#include "LV2Module.hpp"
#include "regression_data.hpp"
TEST_CASE("LV2 Midi Forwarding regression") {
LV2Module mod(MIDI_FORWARDER);
double sampleRate = 512;
size_t sampleCount = 512;
for (auto plug : mod.plugins) {
plug.instantiate(sampleRate);
plug.allocateAndConnectPorts(sampleCount);
plug.activate();
for (auto& p : plug.ports) {
if (p.type == PortType::Midi && p.dir == Direction::Input) {
// uint8_t* x= { 0x1,0x2,0x3 };
p.addMidiMsg(0x1, 0x2, 0x3);
p.addMidiMsg(0xFF, 0xFF, 0xFF);
}
}
plug.run(sampleRate);
for (auto& p : plug.ports) {
if (p.type == PortType::Midi && p.dir == Direction::Output) {
auto data = (MidiEventBuffer*)p.data;
INFO("Error, could not forward Midimessages.");
auto item1 = &data->midiEvents[0];
REQUIRE(item1->msg[0] == 0x1 );
REQUIRE(item1->msg[1] == 0x2);
REQUIRE(item1->msg[2] == 0x3 );
auto item2 = (MIDINoteEvent*)lv2_atom_sequence_next(&data->midiEvents->event);
REQUIRE(item2->msg[0] == 0xFF);
REQUIRE(item2->msg[1] == 0xFF);
REQUIRE(item2->msg[2] == 0xFF);
}
}
plug.deactivate();
}
//REQUIRE_MESSAGE(GlobalData().getNumberOfRegisteredPlugins() >= 1, "Static Initialisation Failed");
}
#include "../../IFormatTestSuite.hpp"
#include "IFormatTestSuite.hpp"
#include "tools/LibLoading.hpp"
#include "lv2/core/lv2.h"
#include "lv2/urid/urid.h"
......@@ -164,10 +164,7 @@ public:
}
return TEST_SUCCEEDED;
}
virtual SucceedState runPerformance() override
{
return TEST_SUCCEEDED;
}
virtual bool isSupported(std::string pluginPath) override
{
auto lib = LoadLib(pluginPath.c_str());
......
/*#include "turtle.hpp"
using namespace turtle;
int main(int argc, char* argv[]) {
//std::string ttlPath(argv[1]);
// turtle::read_from_file(ttlPath);
rdf rd{
{
{"rdf","http://www.w3.org/1999/02/22-rdf-syntax-ns#"},
{"rdfs","http://www.w3.org/2000/01/rdf-schema#"},
{"lv2","http://lv2plug.in/ns/lv2core#"},
{"owl","http://www.w3.org/2002/07/owl#"}
},{
{"<http://lv2plug.in/ns/lv2core>", "a", "owl:Ontology"},
{"<http://lv2plug.in/ns/lv2core>", "rdfs:label", "LV2"},
{"<http://lv2plug.in/ns/lv2core>", "rdfs:comment", "An extensible open standard for audio plugins."}
}
};
std::cout << get_as_ttl_string(beautify(rd));
}*/
\ No newline at end of file
#ifndef TURTLE_HPP
#define TURTLE_HPP
/*
#include <string>
#include <vector>
#include <map>
#include <regex>
#include <iostream>
#include <fstream>
#include <streambuf>
#define NEWLINE "\n"
namespace turtle {
class rdf;
inline void write_to_file(std::string path, rdf graph);
inline rdf read_from_file(std::string path);
struct triple {
std::string subject;
std::string predicat;
std::string object;
};
struct rdf {
/// friend void write_to_file(std::string path, rdf_graph graph);
/// friend rdf_graph read_from_file(std::string path);
std::map<std::string, std::string> prefixes;
std::vector<triple> triples;
inline void addPrefix(std::string prefixShortcut, std::string prefixURI) {
prefixes[prefixShortcut] = prefixURI;
}
};
inline rdf beautify(rdf r) {
auto replaceStr = [](std::string& strToMod, const std::string& val, const std::string& replacement) {
while (strToMod.find(val) != std::string::npos)
strToMod.replace(strToMod.find(val), val.size(), replacement);
};
for (auto triple : r.triples) {
for (auto prefix : r.prefixes) {
replaceStr(triple.subject, prefix.first, prefix.second);
replaceStr(triple.predicat, prefix.first+":" , prefix.second);
//replaceStr(triple.object, prefix.first+":", prefix.second);
}
}
return r;
}
class TurtleException :public std::exception {
std::string whatMsg;
public:
inline TurtleException(std::string what) {
this->whatMsg = what;
}
inline virtual char const* what() const override {
return whatMsg.c_str();
}
};
inline std::string get_as_ttl_string(rdf graph) {
std::string ttl_file_content;
for (auto prefix : graph.prefixes) {
ttl_file_content += "@prefix " + prefix.first + ": <" + prefix.second + "> ."+ NEWLINE;
}
std::string lastSubject = "";
std::string lastPredicate = "";
for (int i = 0; i < graph.triples.size(); i++) {
std::string next_seperator = std::string(" ") + (i + 1 == graph.triples.size() ? "." :
graph.triples[i].subject == graph.triples[i + 1].subject ?
";" : graph.triples[i].predicat == graph.triples[i + 1].predicat ? "," : ".");
std::string subject = graph.triples[i].subject==lastSubject?"\t": graph.triples[i].subject;
std::string predicate = graph.triples[i].predicat == lastPredicate ? "\t" : graph.triples[i].predicat;
ttl_file_content += graph.triples[i].subject +" "+ graph.triples[i].predicat +" "+ graph.triples[i].object + " ."+ NEWLINE;
lastPredicate = graph.triples[i].predicat;
lastSubject = graph.triples[i].subject;
}
return ttl_file_content;
}
enum class TokenType {
IRIREF,
PNAME_NS,
PNAME_LN,
BLANK_NODE_LABEL,
LANGTAG,
INTEGER,
DECIMAL,
DOUBLE,
EXPONENT,
STRING_LITERAL_QUOTE,
STRING_LITERAL_SINGLE_QUOTE,
STRING_LITERAL_LONG_SINGLE_QUOTE,
STRING_LITERAL_LONG_QUOTE,
UCHAR,
ECHAR,
WS,
ANON,
PN_CHARS_BASE,
PN_CHARS_U,
PN_CHARS,
PN_PREFIX,
PN_LOCAL,
PLX,
PERCENT,
HEX,
PN_LOCAL_ESC
};
struct TurtleToken {
TokenType tokentype;
std::string text;
};
#define TERMINAL(Name, regex) {#Name,regex}
class TurtleLexer {
protected:
std::string input;
int p ;// inedex of current input
char c;
std::vector<std::tuple<std::string, std::string>> terminals = {
TERMINAL(PERCENT,"%HEXHEX"),
TERMINAL(HEX,"([0-9]|[A-F]|[a-f])"),
TERMINAL(PN_LOCAL_ESC,"\\\\(_|~|.|-|!|$|&|'|(|)|\\*|\\+|,|;|=|\\/|\\?|#|@|%)")
};
public:
TurtleLexer(std::string content) {
p = 0;
this->input = content;
c = input[p];
for (auto& x : terminals) {
for (auto& y : terminals) {
//Wenn terminal x ein wort enthlt, welches identisch zu irgendeinem key aus terminals y ist, tausche es aus.
while (std::get<1>(x).find(std::get<0>(y)) != std::string::npos)
std::get<1>(x).replace(std::get<1>(x).find(std::get<0>(y)), std::get<0>(y).size(), std::get<1>(y));
}
}
}
TurtleToken nextToken() {
while (c != '\0') {
switch (c) {
case '\\':
return PN_LOCAL_ESC();
}
// 2 size Lexingrules
}
}
TurtleToken PN_LOCAL_ESC() {
regToken(std::regex("\\\\(_|~|.|-|!|$|&|'|(|)|\\*|\\+|,|;|=|\\/|\\?|#|@|%)"),2,TokenType::PN_LOCAL_ESC);
}
void consume() {
p++;
if (p >= input.size())c = '\0';
else c = input[p];
}
void match(char x) {
if (c == x)consume();
else throw TurtleException(std::string("expecting ") + x + "; found " + c);
}
TurtleToken regToken(std::regex regEx, size_t length, TokenType t) {
TurtleToken tk{t, "" };
std::smatch sm;
if (std::regex_match(this->input.cbegin() + p, this->input.cbegin()+p+length, sm, regEx)) {
tk.text = sm[0].str();
}
for (int i = 0; i < tk.text.size(); i++)
consume();
return tk;
}
};
/* class TurtleParser {
protected:
std::string content;
char c;
public:
TurtleToken nextToken() {
while (c != '\0') {
}
}
};*/
/*
inline std::vector<TurtleToken> lexing(std::string filecontent) {
std::vector<TurtleToken> tokens;
/* for (auto & x : terminals) {
for (auto & y : terminals) {
//Wenn terminal x ein wort enthlt, welches identisch zu irgendeinem key aus terminals y ist, tausche es aus.
while (std::get<1>(x).find(std::get<0>(y)) != std::string::npos)
std::get<1>(x).replace(std::get<1>(x).find(std::get<0>(y)), std::get<0>(y).size(), std::get<1>(y));
}
}
for (int i = 0; i < filecontent.size(); i=i) {
TurtleToken t;
for (auto x : terminals) {
std::smatch sm;
//resolve regex;
std::regex reg{ std::get<1>(x)};
if (std::regex_match(filecontent.cbegin() + i, filecontent.cend(), sm, reg,
match_not_bol|match_not_eol| match_continuous| format_first_only)) {
auto curT = TurtleToken{ std::get<0>(x) , sm[0].str() };
if (curT.text.size() >= t.text.size())
t = curT;
}
}
if (t.text.empty()) {
t= TurtleToken{ "UNKNOWN" , filecontent.substr(i,1) };
}
tokens.push_back(t);
i += t.text.size();
}*//*
return tokens;
}
inline rdf read_from_file(std::string path) {
std::ifstream t(path);
std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
// lexing(str);
for (auto tok : lexing("%99_")) {
// std::cout << "<" << tok.tokentype << ">" << " " << tok.text << std::endl;
}
rdf x;
return x;
}
}*/
#endif //! TURTLE_HPP
......@@ -14,4 +14,5 @@ if(XPLUG_VST2_SUPPORT)
target_link_libraries(vst2 XPlug)
EXPORT_SYMBOLS(vst2 FUNCTION_NAMES VSTPluginMain)
install(TARGETS vst2 EXPORT XPlugExport DESTINATION lib)
add_subdirectory(tests)
endif(XPLUG_VST2_SUPPORT)
\ No newline at end of file
if(XPLUG_VST2_SUPPORT)
if(XPLUG_BUILD_TESTS)
target_include_directories(XValidate PUBLIC ${CMAKE_SOURCE_DIR}/formats/vst2)
target_sources(XValidate PUBLIC ${CMAKE_CURRENT_LIST_DIR}/VST2TestSuite.cpp)
endif(XPLUG_VST2_SUPPORT)
\ No newline at end of file
target_include_directories(regression_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR}/..)
target_sources(regression_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR}/VST2RegressionTest.cpp)
endif(XPLUG_BUILD_TESTS)
\ No newline at end of file
#include "../../IFormatTestSuite.hpp"
#ifndef VST2_MODULE_HPP
#define VST2_MODULE_HPP
#include "tools/LibLoading.hpp"
#include "vst_def.hpp"
using namespace XPlug;
typedef AEffect* (*VSTPluginMain)(audioMasterCallback);
class VST2TestSuite :public FormatTestSuiteBase {
class VST2Module {
private:
size_t samplesize = 0;
VSTPluginMain VSTPluginMain_fnc = nullptr;
float** inData = nullptr;
float** outData = nullptr;
audioMasterCallback aMasterCallback = nullptr;
public:
XPlug::library_t pluginLib = nullptr;
AEffect* effect;
virtual std::string getFormatName() override
{
return "VST2";
}
virtual SucceedState run() override
{
size_t sampleSize = 512;
audioMasterCallback aMasterCallback = [](AEffect* effect, int32_t opCode, int32_t, intptr_t, void*, float)->intptr_t {
switch (opCode) {
case audioMasterProcessEvents:
break;
case audioMasterVersion:
return 100;
}
return 0;
};
auto lib = LoadLib(data.pluginPath.c_str());
if (lib == nullptr) return false;
auto VSTPluginMain_fnc = LoadFunc<VSTPluginMain>(lib, "VSTPluginMain");
inline VST2Module(std::string pluginPath, audioMasterCallback cb =nullptr) {
if (cb == nullptr) {
cb = [](AEffect* effect, int32_t opCode, int32_t, intptr_t, void*, float)->intptr_t {
switch (opCode) {
case audioMasterProcessEvents:
break;
case audioMasterVersion:
return 100;
}
return 0;
};
}
auto effect = VSTPluginMain_fnc(aMasterCallback);
test(1, effect != nullptr, "Error, couldnt create VST2 effect.");
aMasterCallback = cb;
pluginLib= XPlug::LoadLib(pluginPath.c_str());
VSTPluginMain_fnc = XPlug::LoadFunc<VSTPluginMain>(pluginLib, "VSTPluginMain");
}
inline ~VST2Module() {
XPlug::UnloadLib(this->pluginLib);