Remove Cxxtest dependency
[zynaddsubfx-code.git] / src / Tests / MessageTest.cpp
blob779bdaff347af88d93c399cb58b02833aa32877e
1 /*
2 ZynAddSubFX - a software synthesizer
4 PluginTest.h - CxxTest for embedding zyn
5 Copyright (C) 2013-2013 Mark McCurry
6 Authors: Mark McCurry
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 #include "test-suite.h"
14 #include <cmath>
15 #include <cstdlib>
16 #include <iostream>
17 #include <fstream>
18 #include <string>
19 #include <thread>
20 #include <rtosc/thread-link.h>
21 #include <unistd.h>
22 #include "../Misc/MiddleWare.h"
23 #include "../Misc/Master.h"
24 #include "../Misc/Part.h"
25 #include "../Misc/PresetExtractor.h"
26 #include "../Misc/PresetExtractor.cpp"
27 #include "../Misc/Util.h"
28 #include "../globals.h"
29 #include "../UI/NSM.H"
30 using namespace std;
31 using namespace zyn;
33 class NSM_Client *nsm = 0;
34 MiddleWare *middleware = 0;
36 char *instance_name=(char*)"";
38 #define NUM_MIDDLEWARE 3
40 class MessageTest
42 public:
43 Config config;
44 void setUp() {
45 synth = new SYNTH_T;
46 mw = new MiddleWare(std::move(*synth), &config);
47 ms = mw->spawnMaster();
48 realtime = NULL;
51 void tearDown() {
52 delete mw;
53 delete synth;
56 void testKitEnable(void)
58 const char *msg = NULL;
59 mw->transmitMsg("/part0/kit0/Psubenabled", "T");
60 TS_ASSERT(ms->uToB->hasNext());
61 msg = ms->uToB->read();
62 TS_ASSERT_EQUAL_STR("/part0/kit0/subpars-data", msg);
63 TS_ASSERT(ms->uToB->hasNext());
64 msg = ms->uToB->read();
65 TS_ASSERT_EQUAL_STR("/part0/kit0/Psubenabled", msg);
68 void testBankCapture(void)
70 mw->transmitMsg("/bank/slot23", "");
71 TS_ASSERT(!ms->uToB->hasNext());
72 mw->transmitMsg("/bank/fake", "");
73 TS_ASSERT(ms->uToB->hasNext());
74 const char *msg = ms->uToB->read();
75 TS_ASSERT_EQUAL_STR("/bank/fake", msg);
78 void testOscCopyPaste(void)
80 //Enable pad synth
81 mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
83 TS_ASSERT(ms->uToB->hasNext());
84 ms->applyOscEvent(ms->uToB->read());
85 TS_ASSERT(ms->uToB->hasNext());
86 ms->applyOscEvent(ms->uToB->read());
87 TS_ASSERT(!ms->uToB->hasNext());
89 auto &osc_src = *ms->part[0]->kit[0].adpars->VoicePar[0].FmGn;
90 auto &osc_dst = *ms->part[0]->kit[0].padpars->oscilgen;
91 auto &osc_oth = *ms->part[0]->kit[0].adpars->VoicePar[1].OscilGn;
93 TS_ASSERT_EQUAL_INT(osc_src.Pbasefuncpar, 64);
94 osc_src.Pbasefuncpar = 32;
95 TS_ASSERT_EQUAL_INT(osc_src.Pbasefuncpar, 32);
97 //Copy From ADsynth modulator
98 printf("====Copy From ADsynth modulator\n");
99 start_realtime();
100 mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/VoicePar0/FMSmp/");
102 TS_ASSERT_EQUAL_STR("Poscilgen", mw->getPresetsStore().clipboard.type.c_str());
103 // a regex would be better here...
104 // hopefully, mxml will not change its whitespace behavior
105 assert_non_null(strstr(mw->getPresetsStore().clipboard.data.c_str(), "<par name=\"base_function_par\" value=\"32\" />"),
106 "base_function_par at right value", __LINE__);
108 /* // better test this without string comparison:
110 XMLwrapper xml;
111 bool couldPutXml = xml.putXMLdata(mw->getPresetsStore().clipboard.data.c_str());
112 TS_ASSERT(couldPutXml);
113 unsigned char copiedBasefuncPar = xml.getpar127("base_function_par", 0);
114 TS_ASSERT_EQUALS(copiedBasefuncPar, 32);
117 //printf("clipboard type: %s\n",mw->getPresetsStore().clipboard.type.c_str());
118 //printf("clipboard data:\n%s\n",mw->getPresetsStore().clipboard.data.c_str());
120 TS_ASSERT_EQUAL_INT(osc_dst.Pbasefuncpar, 64);
121 TS_ASSERT_EQUAL_INT(osc_oth.Pbasefuncpar, 64);
123 //Paste to PADsynth
124 printf("====Paste to PADsynth\n");
125 mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/oscilgen/");
127 printf("====Paste to ADsynth\n");
128 mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/VoicePar1/OscilSmp/");
130 stop_realtime();
131 TS_ASSERT_EQUAL_INT(osc_dst.Pbasefuncpar, 32);
132 TS_ASSERT_EQUAL_INT(osc_oth.Pbasefuncpar, 32);
136 void start_realtime(void)
138 do_exit = false;
139 realtime = new std::thread([this](){
140 int tries = 0;
141 while(tries < 10000) {
142 if(!ms->uToB->hasNext()) {
143 if(do_exit)
144 break;
146 usleep(500);
147 continue;
149 const char *msg = ms->uToB->read();
150 printf("RT: handling <%s>\n", msg);
151 ms->applyOscEvent(msg);
152 }});
155 void stop_realtime(void)
157 do_exit = true;
158 realtime->join();
159 delete realtime;
160 realtime = NULL;
163 void run_realtime(void)
165 start_realtime();
166 stop_realtime();
169 void testMidiLearn(void)
171 mw->transmitMsg("/learn", "s", "/Pkeyshift");
172 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
173 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 64);
175 //Perform a learning operation
177 run_realtime(); //1. runs learning and identifies a CC to bind
178 mw->tick(); //2. produces new binding table
179 run_realtime(); //3. applies new binding table
182 //Verify that the learning actually worked
183 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 13);
184 run_realtime();
185 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 13);
187 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 2);
188 run_realtime();
189 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 2);
191 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 0);
192 run_realtime();
193 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 0);
195 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 127);
196 run_realtime();
197 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 127);
200 void testMidiLearnSave(void)
202 mw->transmitMsg("/learn", "s", "/Pkeyshift");
203 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 108);
205 //param is at default until rt-thread is run
206 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 64);
209 //Perform a learning operation
210 run_realtime();
212 //Verify binding affects control
213 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 108);
216 printf("# Trying to save automations\n");
217 start_realtime();
218 mw->transmitMsg("/save_xlz", "s", "test-midi-learn.xlz");
219 stop_realtime();
221 //Verify that some file exists
222 printf("# Verifying file exists\n");
223 FILE *f = fopen("test-midi-learn.xlz", "r");
224 assert_non_null(f, "test file exists", __LINE__);
226 if(f)
227 fclose(f);
229 printf("# Clearing automation\n");
230 //Clear out state
231 mw->transmitMsg("/clear_xlz", "");
232 //Send dummy message
233 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 27);
234 run_realtime();
236 //Verify automation table is clear
237 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 108);
239 printf("# Loading automation\n");
240 mw->transmitMsg("/load_xlz", "s", "test-midi-learn.xlz");
241 //Send message
242 mw->transmitMsg("/virtual_midi_cc", "iii", 0, 23, 28);
243 run_realtime();
245 //Verify automation table is restored
246 TS_ASSERT_EQUAL_INT(ms->Pkeyshift, 28);
249 void testLfoPaste(void)
251 start_realtime();
252 ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 32;
253 TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
255 //Copy
256 mw->transmitMsg("/presets/copy", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
258 ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand = 99;
259 TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 99);
261 //Paste
262 mw->transmitMsg("/presets/paste", "s", "/part0/kit0/adpars/GlobalPar/FreqLfo/");
263 stop_realtime();
265 TS_ASSERT_EQUAL_INT(ms->part[0]->kit[0].adpars->GlobalPar.FreqLfo->Pfreqrand, 32);
268 void testPadPaste(void)
270 mw->transmitMsg("/part0/kit0/Ppadenabled", "T");
271 run_realtime();
273 start_realtime();
275 auto &field1 = ms->part[0]->kit[0].padpars->PVolume;
276 auto &field2 = ms->part[0]->kit[0].padpars->oscilgen->Pfilterpar1;
277 field1 = 32;
278 TS_ASSERT_EQUAL_INT(field1, 32);
279 field2 = 35;
280 TS_ASSERT_EQUAL_INT(field2, 35);
282 //Copy
283 mw->transmitMsg("/presets/copy", "s", "/part0/kit0/padpars/");
285 field1 = 99;
286 TS_ASSERT_EQUAL_INT(field1, 99);
287 field2 = 95;
288 TS_ASSERT_EQUAL_INT(field2, 95);
290 //Paste
291 mw->transmitMsg("/presets/paste", "s", "/part0/kit0/padpars/");
292 stop_realtime();
294 TS_ASSERT_EQUAL_INT(field1, 32);
295 TS_ASSERT_EQUAL_INT(field2, 35);
298 void testFilterDepricated(void)
300 vector<string> v = {"Pfreq", "Pfreqtrack", "Pgain", "Pq"};
301 for(size_t i=0; i<v.size(); ++i) {
302 string path = "/part0/kit0/adpars/GlobalPar/GlobalFilter/"+v[i];
303 for(int j=0; j<128; ++j) {
304 mw->transmitMsg(path.c_str(), "i", j); //Set
305 mw->transmitMsg(path.c_str(), ""); //Get
309 while(ms->uToB->hasNext()) {
310 const char *msg = ms->uToB->read();
311 //printf("RT: handling <%s>\n", msg);
312 ms->applyOscEvent(msg);
315 int id = 0;
316 int state = 0;
317 int value = 0;
318 // 0 - broadcast
319 // 1 - true value (set)
320 // 2 - expected value (get)
321 while(ms->bToU->hasNext()) {
322 const char *msg = ms->bToU->read();
323 if(state == 0) {
324 TS_ASSERT_EQUAL_INT(rtosc_narguments(msg), 0U);
325 state = 1;
326 } else if(state == 1) {
327 TS_ASSERT_EQUAL_INT(rtosc_narguments(msg), 1U);
328 value = rtosc_argument(msg, 0).i;
329 state = 2;
330 } else if(state == 2) {
331 int val = rtosc_argument(msg, 0).i;
332 if(value != val) {
333 printf("%s - %d should equal %d\n", msg, value, val);
334 TS_ASSERT(0);
336 state = 0;
339 (void) id;
340 //printf("Message #%d %s:%s\n", id++, msg, rtosc_argument_string(msg));
341 //if(rtosc_narguments(msg))
342 // printf(" %d\n", rtosc_argument(msg, 0).i);
347 private:
348 SYNTH_T *synth;
349 MiddleWare *mw;
350 Master *ms;
351 std::thread *realtime;
352 bool do_exit;
355 int main()
357 MessageTest test;
358 RUN_TEST(testKitEnable);
359 RUN_TEST(testBankCapture);
360 RUN_TEST(testOscCopyPaste);
361 RUN_TEST(testMidiLearn);
362 RUN_TEST(testMidiLearnSave);
363 RUN_TEST(testLfoPaste);
364 RUN_TEST(testPadPaste);
365 RUN_TEST(testFilterDepricated);
366 return test_summary();