ChimeraTK-ApplicationCore 04.06.00
Loading...
Searching...
No Matches
testModules.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#include <chrono>
4#include <future>
5
6#define BOOST_TEST_MODULE testModules
7
8#include <boost/test/included/unit_test.hpp>
9using namespace boost::unit_test_framework;
10
11#include "Application.h"
12#include "ApplicationModule.h"
13#include "ArrayAccessor.h"
14#include "ModuleGroup.h"
15#include "ScalarAccessor.h"
16#include "TestFacility.h"
17#include "VariableGroup.h"
18
19#include <boost/mpl/list.hpp>
20
22
23 namespace ctk = ChimeraTK;
24
25 /********************************************************************************************************************/
26 /* Variable group used in the modules */
27
29 using ctk::VariableGroup::VariableGroup;
30 ctk::ScalarPushInput<std::string> inGroup{this, "inGroup", "", "This is a string", {"C", "A"}};
32 this, "alsoInGroup", "justANumber", 16, "A 64 bit number array", {"A", "D"}};
33 };
34
35 /********************************************************************************************************************/
36 /* A plain application module for testing */
37
39 using ctk::ApplicationModule::ApplicationModule;
40
42 this, "nameOfSomeInput", "cm", "This is just some input for testing", {"A", "B"}};
43 ctk::ScalarOutput<double> someOutput{this, "someOutput", "V", "Description", {"A", "C"}};
44
45 SomeGroup someGroup{this, "someGroup", "Description of my test group"};
46
48 using ctk::VariableGroup::VariableGroup;
49 ctk::ScalarPushInput<uint8_t> foo{this, "foo", "counts", "Some counter", {"D"}};
50 } anotherGroup{this, "anotherName", "Description of my other group"};
51
52 void mainLoop() override {
53 while(true) {
54 someInput.read();
55 int val = someInput;
56 someOutput = val;
58 }
59 }
60 };
61
62 /********************************************************************************************************************/
63 /* Simple application with just one module */
64
66 OneModuleApp() : Application("myApp") {}
67 ~OneModuleApp() override { shutdown(); }
68
69 TestModule testModule{this, "testModule", "Module to test"};
70 };
71
72 /********************************************************************************************************************/
73 /* Application with a vector of modules */
74
76 explicit VectorOfModulesApp(size_t numberOfInstances) : Application("myApp"), nInstances(numberOfInstances) {
77 for(size_t i = 0; i < numberOfInstances; ++i) {
78 std::string moduleName = "testModule_" + std::to_string(i) + "_instance";
79 vectorOfTestModule.emplace_back(this, moduleName, "Description");
80 }
81 }
82 ~VectorOfModulesApp() override { shutdown(); }
83
84 size_t nInstances;
85 std::vector<TestModule> vectorOfTestModule;
86 };
87
88 /********************************************************************************************************************/
89 /* An application module with a vector of a variable group*/
90
92 VectorModule(ctk::ModuleGroup* owner, const std::string& name, const std::string& description, size_t nInstances,
93 const std::unordered_set<std::string>& tags = {})
94 : ctk::ApplicationModule(owner, name, description, tags) {
95 for(size_t i = 0; i < nInstances; ++i) {
96 std::string groupName = "testGroup_" + std::to_string(i);
97 vectorOfSomeGroup.emplace_back(this, groupName, "Description 2");
98 BOOST_CHECK(vectorOfSomeGroup.back().getModel().isValid());
99 }
100 for(size_t i = 0; i < nInstances; ++i) {
101 BOOST_CHECK(vectorOfSomeGroup[i].getModel().isValid());
102 }
103 }
104 VectorModule() = default;
105
107 this, "nameOfSomeInput", "cm", "This is just some input for testing", {"A", "B"}};
108 ctk::ArrayOutput<double> someOutput{this, "someOutput", "V", 1, "Description", {"A", "C"}};
109
110 std::vector<SomeGroup> vectorOfSomeGroup;
111
113 using ctk::VariableGroup::VariableGroup;
114 ctk::ScalarPushInput<uint8_t> foo{this, "foo", "counts", "Some counter", {"D"}};
115 } anotherGroup{this, "anotherName", "Description of my other group"};
116
117 void mainLoop() override {
118 while(true) {
119 someInput.read();
120 int val = someInput;
121 someOutput[0] = val;
123 }
124 }
125 };
126
127 /********************************************************************************************************************/
128 /* An module group with a vector of a application modules */
129
131 VectorModuleGroup(ModuleGroup* owner, const std::string& name, const std::string& description, size_t nInstances,
132 const std::unordered_set<std::string>& tags = {})
133 : ctk::ModuleGroup(owner, name, description, tags) {
134 for(size_t i = 0; i < nInstances; ++i) {
135 std::string vovModuleName = "test_" + std::to_string(i);
136 vectorOfVectorModule.emplace_back(this, vovModuleName, "Description 3", nInstances);
137 BOOST_CHECK(vectorOfVectorModule.back().getModel().isValid());
138 }
139 for(size_t i = 0; i < nInstances; ++i) {
140 BOOST_CHECK(vectorOfVectorModule[i].getModel().isValid());
141 }
142 }
143
144 VectorModuleGroup() = default;
145
146 std::vector<VectorModule> vectorOfVectorModule;
147 };
148
149 /********************************************************************************************************************/
150 /* Application with a vector of module groups containing a vector of modules
151 * containing a vector of variable groups */
152
154 explicit VectorOfEverythingApp(size_t numberOfInstances) : Application("myApp"), nInstances(numberOfInstances) {
155 for(size_t i = 0; i < nInstances; ++i) {
156 std::string name = "testModule_" + std::to_string(i) + "_instance";
157 vectorOfVectorModuleGroup.emplace_back(this, name, "Description", nInstances);
158 BOOST_CHECK(vectorOfVectorModuleGroup.back().getModel().isValid());
159 }
160 for(size_t i = 0; i < nInstances; ++i) {
161 BOOST_CHECK(vectorOfVectorModuleGroup[i].getModel().isValid());
162 }
163 }
165
167 std::vector<VectorModuleGroup> vectorOfVectorModuleGroup;
168 };
169
170 /********************************************************************************************************************/
171 /* Application with various modules that get initialised late in the constructor. */
172
179
180 VectorModuleGroup modGroupInstanceSource{this, "modGroupInstanceToAssignLater",
181 "This instance of VectorModuleGroup was assigned using the operator=()", 42};
183 this, "modInstanceToAssignLater", "This instance of VectorModule was assigned using the operator=()", 13};
184
187 };
188
189 /********************************************************************************************************************/
190 /* test module and variable ownerships */
191
192 BOOST_AUTO_TEST_CASE(test_ownership) {
193 std::cout << "***************************************************************"
194 "******************************************************"
195 << std::endl;
196 std::cout << "==> test_ownership" << std::endl;
197
198 OneModuleApp app;
199
200 BOOST_CHECK(app.testModule.getOwner() == &app);
201 BOOST_CHECK(app.testModule.someGroup.getOwner() == &(app.testModule));
202 BOOST_CHECK(app.testModule.anotherGroup.getOwner() == &(app.testModule));
203
204 BOOST_CHECK(app.testModule.someInput.getOwner() == &(app.testModule));
205 BOOST_CHECK(app.testModule.someOutput.getOwner() == &(app.testModule));
206
207 BOOST_CHECK(app.testModule.someGroup.inGroup.getOwner() == &(app.testModule.someGroup));
208 BOOST_CHECK(app.testModule.someGroup.alsoInGroup.getOwner() == &(app.testModule.someGroup));
209
210 BOOST_CHECK(app.testModule.anotherGroup.foo.getOwner() == &(app.testModule.anotherGroup));
211 }
212
213 /********************************************************************************************************************/
214 /* test that modules cannot be owned by the wrong types */
215
216 BOOST_AUTO_TEST_CASE(test_badHierarchies) {
217 std::cout << "***************************************************************"
218 "******************************************************"
219 << std::endl;
220 std::cout << "==> test_badHierarchies" << std::endl;
221
222 // ******************************************
223 // *** Tests for ApplicationModule
224
225 // check app ApplicationModules cannot be owned by nothing
226 {
227 OneModuleApp app;
228 try {
229 TestModule willFail(static_cast<ChimeraTK::ModuleGroup*>(nullptr), "willFail", "");
230 BOOST_FAIL("Exception expected");
231 }
232 catch(ChimeraTK::logic_error&) {
233 }
234 }
235
236 // ******************************************
237 // *** Tests for VariableGroup
238
239 // check app VariableGroup cannot be owned by nothing
240 {
241 OneModuleApp app;
242 try {
243 SomeGroup willFail(static_cast<ChimeraTK::VariableGroup*>(nullptr), "willFail", "");
244 BOOST_FAIL("Exception expected");
245 }
246 catch(ChimeraTK::logic_error&) {
247 }
248 }
249
250 // ******************************************
251 // *** Tests for ModuleGroup
252
253 // check app ModuleGroups cannot be owned by nothing
254 {
255 OneModuleApp app;
256 try {
257 VectorModuleGroup willFail(nullptr, "willFail", "", 1);
258 BOOST_FAIL("Exception expected");
259 }
260 catch(ChimeraTK::logic_error&) {
261 }
262 }
263 }
264
265 /********************************************************************************************************************/
266 /* test that modules can be owned by the right types */
267
268 BOOST_AUTO_TEST_CASE(test_allowedHierarchies) {
269 std::cout << "***************************************************************"
270 "******************************************************"
271 << std::endl;
272 std::cout << "==> test_allowedHierarchies" << std::endl;
273
274 // ******************************************
275 // *** Tests for ApplicationModule
276 // check ApplicationModules can be owned by Applications
277 try {
278 OneModuleApp app;
279 TestModule shouldNotFail(&(app), "shouldNotFail", "");
280 }
281 catch(ChimeraTK::logic_error&) {
282 BOOST_CHECK(false);
283 }
284
285 // check ApplicationModules can be owned by ModuleGroups
286 try {
288 auto* v = &(app.vectorOfVectorModuleGroup[0]);
289 BOOST_CHECK(v != nullptr);
290 TestModule shouldNotFail(v, "shouldNotFail", "");
291 }
292 catch(ChimeraTK::logic_error&) {
293 BOOST_FAIL("Exception not expected!");
294 }
295
296 // ******************************************
297 // *** Tests for VariableGroup
298
299 // check VariableGroup can be owned by ApplicationModules
300 try {
301 OneModuleApp app;
302 SomeGroup shouldNotFail(&(app.testModule), "shouldNotFail", "");
303 }
304 catch(ChimeraTK::logic_error&) {
305 BOOST_CHECK(false);
306 }
307
308 // check VariableGroup can be owned by VariableGroup
309 try {
310 OneModuleApp app;
311 SomeGroup shouldNotFail(&(app.testModule.someGroup), "shouldNotFail", "");
312 }
313 catch(ChimeraTK::logic_error&) {
314 BOOST_CHECK(false);
315 }
316
317 // ******************************************
318 // *** Tests for ModuleGroup
319
320 // check ModuleGroup can be owned by Applications
321 try {
322 OneModuleApp app;
323 VectorModuleGroup shouldNotFail(&(app), "shouldNotFail", "", 1);
324 }
325 catch(ChimeraTK::logic_error&) {
326 BOOST_CHECK(false);
327 }
328
329 // check ModuleGroup can be owned by ModuleGroups
330 try {
332 VectorModuleGroup shouldNotFail(&(app.vectorOfVectorModuleGroup[0]), "shouldNotFail", "", 1);
333 }
334 catch(ChimeraTK::logic_error&) {
335 BOOST_CHECK(false);
336 }
337 }
338
339 /********************************************************************************************************************/
340 /* test getSubmoduleList() and getSubmoduleListRecursive() */
341
342 BOOST_AUTO_TEST_CASE(test_getSubmoduleList) {
343 std::cout << "***************************************************************"
344 "******************************************************"
345 << std::endl;
346 std::cout << "==> test_getSubmoduleList" << std::endl;
347
348 OneModuleApp app;
349
350 {
351 std::list<ctk::Module*> list = app.getSubmoduleList();
352 BOOST_CHECK(list.size() == 1);
353 BOOST_CHECK(list.front() == &(app.testModule));
354 }
355
356 {
357 std::list<ctk::Module*> list = app.testModule.getSubmoduleList();
358 BOOST_CHECK(list.size() == 2);
359 size_t foundSomeGroup = 0;
360 size_t foundAnotherGroup = 0;
361 for(const auto* mod : list) {
362 if(mod == &(app.testModule.someGroup)) {
363 foundSomeGroup++;
364 }
365 if(mod == &(app.testModule.anotherGroup)) {
366 foundAnotherGroup++;
367 }
368 }
369 BOOST_CHECK(foundSomeGroup == 1);
370 BOOST_CHECK(foundAnotherGroup == 1);
371 }
372
373 {
374 std::list<ctk::Module*> list = app.getSubmoduleListRecursive();
375 BOOST_CHECK(list.size() == 3);
376 size_t foundTestModule = 0;
377 size_t foundSomeGroup = 0;
378 size_t foundAnotherGroup = 0;
379 for(const auto* mod : list) {
380 if(mod == &(app.testModule)) {
381 foundTestModule++;
382 }
383 if(mod == &(app.testModule.someGroup)) {
384 foundSomeGroup++;
385 }
386 if(mod == &(app.testModule.anotherGroup)) {
387 foundAnotherGroup++;
388 }
389 }
390 BOOST_CHECK(foundTestModule == 1);
391 BOOST_CHECK(foundSomeGroup == 1);
392 BOOST_CHECK(foundAnotherGroup == 1);
393 }
394
395 {
396 std::list<ctk::Module*> list = app.testModule.getSubmoduleListRecursive(); // identical to getSubmoduleList(),
397 // since no deeper hierarchies
398 BOOST_CHECK(list.size() == 2);
399 size_t foundSomeGroup = 0;
400 size_t foundAnotherGroup = 0;
401 for(const auto* mod : list) {
402 if(mod == &(app.testModule.someGroup)) {
403 foundSomeGroup++;
404 }
405 if(mod == &(app.testModule.anotherGroup)) {
406 foundAnotherGroup++;
407 }
408 }
409 BOOST_CHECK(foundSomeGroup == 1);
410 BOOST_CHECK(foundAnotherGroup == 1);
411 }
412 }
413
414 /********************************************************************************************************************/
415 /* test getAccessorList() and getAccessorListRecursive() */
416
417 BOOST_AUTO_TEST_CASE(test_getAccessorList) {
418 std::cout << "***************************************************************"
419 "******************************************************"
420 << std::endl;
421 std::cout << "==> test_getAccessorList" << std::endl;
422
423 OneModuleApp app;
424
425 {
426 std::list<ctk::VariableNetworkNode> list = app.testModule.getAccessorList();
427 BOOST_CHECK(list.size() == 2);
428 size_t foundSomeInput = 0;
429 size_t foundSomeOutput = 0;
430 for(const auto& var : list) {
432 foundSomeInput++;
433 }
435 foundSomeOutput++;
436 }
437 }
438 BOOST_CHECK(foundSomeInput == 1);
439 BOOST_CHECK(foundSomeOutput == 1);
440 }
441
442 {
443 const SomeGroup& someGroup(app.testModule.someGroup);
444 const std::list<ctk::VariableNetworkNode> list = someGroup.getAccessorList();
445 BOOST_CHECK(list.size() == 2);
446 size_t foundInGroup = 0;
447 size_t foundAlsoInGroup = 0;
448 for(const auto& var : list) {
450 foundInGroup++;
451 }
453 foundAlsoInGroup++;
454 }
455 }
456 BOOST_CHECK(foundInGroup == 1);
457 BOOST_CHECK(foundAlsoInGroup == 1);
458 }
459
460 {
461 std::list<ctk::VariableNetworkNode> list = app.getAccessorListRecursive();
462 BOOST_CHECK(list.size() == 5);
463 size_t foundSomeInput = 0;
464 size_t foundSomeOutput = 0;
465 size_t foundInGroup = 0;
466 size_t foundAlsoInGroup = 0;
467 size_t foundFoo = 0;
468 for(const auto& var : list) {
470 foundSomeInput++;
471 }
473 foundSomeOutput++;
474 }
476 foundInGroup++;
477 }
479 foundAlsoInGroup++;
480 }
481 if(var == ctk::VariableNetworkNode(app.testModule.anotherGroup.foo)) {
482 foundFoo++;
483 }
484 }
485 BOOST_CHECK(foundSomeInput == 1);
486 BOOST_CHECK(foundSomeOutput == 1);
487 BOOST_CHECK(foundInGroup == 1);
488 BOOST_CHECK(foundAlsoInGroup == 1);
489 BOOST_CHECK(foundFoo == 1);
490 }
491
492 {
493 std::list<ctk::VariableNetworkNode> list = app.testModule.getAccessorListRecursive();
494 BOOST_CHECK(list.size() == 5);
495 size_t foundSomeInput = 0;
496 size_t foundSomeOutput = 0;
497 size_t foundInGroup = 0;
498 size_t foundAlsoInGroup = 0;
499 size_t foundFoo = 0;
500 for(const auto& var : list) {
502 foundSomeInput++;
503 }
505 foundSomeOutput++;
506 }
508 foundInGroup++;
509 }
511 foundAlsoInGroup++;
512 }
513 if(var == ctk::VariableNetworkNode(app.testModule.anotherGroup.foo)) {
514 foundFoo++;
515 }
516 }
517 BOOST_CHECK(foundSomeInput == 1);
518 BOOST_CHECK(foundSomeOutput == 1);
519 BOOST_CHECK(foundInGroup == 1);
520 BOOST_CHECK(foundAlsoInGroup == 1);
521 BOOST_CHECK(foundFoo == 1);
522 }
523
524 {
525 std::list<ctk::VariableNetworkNode> list = app.testModule.anotherGroup.getAccessorListRecursive();
526 BOOST_CHECK(list.size() == 1);
527 size_t foundFoo = 0;
528 for(const auto& var : list) {
529 if(var == ctk::VariableNetworkNode(app.testModule.anotherGroup.foo)) {
530 foundFoo++;
531 }
532 }
533 BOOST_CHECK(foundFoo == 1);
534 }
535 }
536
537 /********************************************************************************************************************/
538 /* test addTag() */
539
541 std::cout << "***************************************************************"
542 "******************************************************"
543 << std::endl;
544 std::cout << "==> testAddTag" << std::endl;
545
546 OneModuleApp app;
547 app.testModule.addTag("newTag");
548
549 size_t nFound = 0;
550 auto checker = [&](auto proxy) {
551 ++nFound;
552 auto name = proxy.getFullyQualifiedPath();
553 BOOST_CHECK(name == "/testModule/nameOfSomeInput" || name == "/testModule/someOutput" ||
554 name == "/testModule/anotherName/foo" || name == "/testModule/someGroup/inGroup" ||
555 name == "/testModule/someGroup/alsoInGroup");
556 };
557
559 checker, ctk::Model::keepProcessVariables && ctk::Model::keepTag("newTag"), ChimeraTK::Model::depthFirstSearch);
560
561 BOOST_TEST(nFound == 5);
562 }
563
564 /********************************************************************************************************************/
565 /* test addTag() with negated tags, in order to remove tags */
566
567 BOOST_AUTO_TEST_CASE(testAddTagNegated) {
568 std::cout << "***************************************************************"
569 "******************************************************"
570 << std::endl;
571 std::cout << "==> testAddTagNegated" << std::endl;
572
573 BOOST_TEST(ChimeraTK::negateTag("newTag") == "!newTag");
574 BOOST_TEST(ChimeraTK::negateTag("!newTag") == "newTag");
575
576 {
577 // negated tags on module level
578 OneModuleApp app;
579 BOOST_TEST(ChimeraTK::negateTag("newTag") == "!newTag");
580 BOOST_TEST(ChimeraTK::negateTag("!newTag") == "newTag");
581 app.testModule.addTag("!newTag");
582 app.testModule.addTag("newTag");
583
584 const auto& tags = app.testModule.someOutput.getTags();
585 BOOST_CHECK(tags.find("newTag") == tags.end());
586 }
587 {
588 // negated tags on variable level
589 OneModuleApp app;
590 app.testModule.someOutput.addTag("newTag");
591 app.testModule.someOutput.addTag("!newTag");
592
593 const auto& tags = app.testModule.someOutput.getTags();
594 BOOST_CHECK(tags.find("newTag") == tags.end());
595 }
596 {
597 // negated tags on variable and module level, mixed
598 OneModuleApp app;
599 app.testModule.addTag("newTag");
600 app.testModule.someOutput.addTag("!newTag");
601
602 const auto& tags = app.testModule.someOutput.getTags();
603 BOOST_CHECK(tags.find("newTag") == tags.end());
604 }
605 // note, we currently do not test the tag set of the model associated with the accessors.
606 // the tags on the model level are not clear since a vertex in the model represents an output pv and its input
607 // in some other module at the same time
608 }
609
610 /********************************************************************************************************************/
611 /* test correct behaviour when using a std::vector of ApplicationModules */
612
613 BOOST_AUTO_TEST_CASE(testVectorOfApplicationModule) {
614 std::cout << "***************************************************************"
615 "******************************************************"
616 << std::endl;
617 std::cout << "==> testVectorOfApplicationModule" << std::endl;
618
619 // create app with a vector containing 10 modules
620 size_t nInstances = 10;
621 VectorOfModulesApp app(nInstances);
622
623 // the app creates the 10 module instances, check if this is done proplery (a quite redundant test...)
624 BOOST_TEST(app.vectorOfTestModule.size() == nInstances);
625
626 // some direct checks on the created instances
627 for(size_t i = 0; i < nInstances; ++i) {
628 std::string name = "testModule_" + std::to_string(i) + "_instance";
629 BOOST_TEST(app.vectorOfTestModule[i].getName() == name);
630 auto node = static_cast<ctk::VariableNetworkNode>(app.vectorOfTestModule[i].someInput);
631 BOOST_TEST(node.getQualifiedName() == "/myApp/" + name + "/nameOfSomeInput");
632
633 // check accessor list
634 std::list<ctk::VariableNetworkNode> accList = app.vectorOfTestModule[i].getAccessorList();
635 BOOST_TEST(accList.size() == 2);
636 size_t foundSomeInput = 0;
637 size_t foundSomeOutput = 0;
638 for(auto& acc : accList) {
639 if(acc == ctk::VariableNetworkNode(app.vectorOfTestModule[i].someInput)) {
640 foundSomeInput++;
641 }
642 if(acc == ctk::VariableNetworkNode(app.vectorOfTestModule[i].someOutput)) {
643 foundSomeOutput++;
644 }
645 }
646 BOOST_TEST(foundSomeInput == 1);
647 BOOST_TEST(foundSomeOutput == 1);
648
649 // check submodule list
650 std::list<ctk::Module*> modList = app.vectorOfTestModule[i].getSubmoduleList();
651 BOOST_TEST(modList.size() == 2);
652 size_t foundSomeGroup = 0;
653 size_t foundAnotherGroup = 0;
654 for(const auto* mod : modList) {
655 if(mod == &(app.vectorOfTestModule[i].someGroup)) {
656 foundSomeGroup++;
657 }
658 if(mod == &(app.vectorOfTestModule[i].anotherGroup)) {
659 foundAnotherGroup++;
660 }
661 }
662 BOOST_TEST(foundSomeGroup == 1);
663 BOOST_TEST(foundAnotherGroup == 1);
664 }
665
666 // check if instances appear properly in getSubmoduleList()
667 {
668 std::list<ctk::Module*> list = app.getSubmoduleList();
669 BOOST_TEST(list.size() == nInstances);
670 std::map<size_t, size_t> instancesFound;
671 for(size_t i = 0; i < nInstances; ++i) {
672 instancesFound[i] = 0;
673 }
674 for(const auto* mod : list) {
675 for(size_t i = 0; i < nInstances; ++i) {
676 if(mod == &(app.vectorOfTestModule[i])) {
677 instancesFound[i]++;
678 }
679 }
680 }
681 for(size_t i = 0; i < nInstances; ++i) {
682 BOOST_TEST(instancesFound[i] == 1);
683 }
684 }
685
686 // check if instances appear properly in getSubmoduleListRecursive() as well
687 {
688 std::list<ctk::Module*> list = app.getSubmoduleListRecursive();
689 BOOST_TEST(list.size() == 3 * nInstances);
690 std::map<size_t, size_t> instancesFound, instancesSomeGroupFound, instancesAnotherGroupFound;
691 for(size_t i = 0; i < nInstances; ++i) {
692 instancesFound[i] = 0;
693 instancesSomeGroupFound[i] = 0;
694 instancesAnotherGroupFound[i] = 0;
695 }
696 for(const auto* mod : list) {
697 for(size_t i = 0; i < nInstances; ++i) {
698 if(mod == &(app.vectorOfTestModule[i])) {
699 instancesFound[i]++;
700 }
701 if(mod == &(app.vectorOfTestModule[i].someGroup)) {
702 instancesSomeGroupFound[i]++;
703 }
704 if(mod == &(app.vectorOfTestModule[i].anotherGroup)) {
705 instancesAnotherGroupFound[i]++;
706 }
707 }
708 }
709 for(size_t i = 0; i < nInstances; ++i) {
710 BOOST_TEST(instancesFound[i] == 1);
711 BOOST_TEST(instancesSomeGroupFound[i] == 1);
712 BOOST_TEST(instancesAnotherGroupFound[i] == 1);
713 }
714 }
715
716 // check ownerships
717 for(size_t i = 0; i < nInstances; ++i) {
718 BOOST_CHECK(app.vectorOfTestModule[i].getOwner() == &app);
719 BOOST_CHECK(app.vectorOfTestModule[i].someInput.getOwner() == &(app.vectorOfTestModule[i]));
720 BOOST_CHECK(app.vectorOfTestModule[i].someOutput.getOwner() == &(app.vectorOfTestModule[i]));
721 BOOST_CHECK(app.vectorOfTestModule[i].someGroup.getOwner() == &(app.vectorOfTestModule[i]));
722 BOOST_CHECK(app.vectorOfTestModule[i].someGroup.inGroup.getOwner() == &(app.vectorOfTestModule[i].someGroup));
723 BOOST_CHECK(app.vectorOfTestModule[i].someGroup.alsoInGroup.getOwner() == &(app.vectorOfTestModule[i].someGroup));
724 BOOST_CHECK(app.vectorOfTestModule[i].anotherGroup.getOwner() == &(app.vectorOfTestModule[i]));
725 BOOST_CHECK(app.vectorOfTestModule[i].anotherGroup.foo.getOwner() == &(app.vectorOfTestModule[i].anotherGroup));
726 }
727 }
728
729 /********************************************************************************************************************/
730 /* test correct behaviour when using a std::vector of ModuleGroup, ApplicationModule and VariableGroup at the same
731 * time */
732
733 BOOST_AUTO_TEST_CASE(testVectorsOfAllModules) {
734 std::cout << "***************************************************************"
735 "******************************************************"
736 << std::endl;
737 std::cout << "==> testVectorsOfAllModules" << std::endl;
738
739 // create app with a vector containing 10 modules
740 size_t nInstances = 10;
741 VectorOfEverythingApp app(nInstances);
742
743 /*----------------------------------------------------------------------------------------------------------------*/
744 // the app creates the 10 module instances, check if this is done proplery (a quite redundant test...)
745 BOOST_CHECK(app.vectorOfVectorModuleGroup.size() == nInstances);
746 for(size_t i = 0; i < nInstances; ++i) {
747 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule.size() == nInstances);
748 for(size_t k = 0; k < nInstances; ++k) {
749 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup.size() == nInstances);
750 }
751 }
752
753 /*----------------------------------------------------------------------------------------------------------------*/
754 // check presence in lists (getSubmoduleList() and getAccessorList())
755
756 { // checks on first hierarchy level (application has the list of module groups)
757 std::list<ctk::Module*> list = app.getSubmoduleList();
758 BOOST_CHECK(list.size() == nInstances);
759 std::map<size_t, size_t> found;
760 for(size_t i = 0; i < nInstances; ++i) {
761 found[i] = 0;
762 }
763 for(const auto* mod : list) {
764 for(size_t i = 0; i < nInstances; ++i) {
765 if(mod == &(app.vectorOfVectorModuleGroup[i])) {
766 found[i]++;
767 }
768 }
769 }
770 for(size_t i = 0; i < nInstances; ++i) {
771 BOOST_CHECK(found[i] == 1);
772 }
773 }
774
775 { // checks on second hierarchy level (each module group has the list of modules)
776 for(size_t i = 0; i < nInstances; ++i) {
777 std::list<ctk::Module*> list = app.vectorOfVectorModuleGroup[i].getSubmoduleList();
778 BOOST_CHECK(list.size() == nInstances);
779
780 std::map<size_t, size_t> found;
781 for(size_t k = 0; k < nInstances; ++k) {
782 found[k] = 0;
783 }
784 for(const auto* mod : list) {
785 for(size_t k = 0; k < nInstances; ++k) {
786 if(mod == &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k])) {
787 found[k]++;
788 }
789 }
790 }
791 for(size_t k = 0; k < nInstances; ++k) {
792 BOOST_CHECK(found[k] == 1);
793 }
794 }
795 }
796
797 { // checks on third hierarchy level (each module has accessors and variable groups)
798 for(size_t i = 0; i < nInstances; ++i) {
799 for(size_t k = 0; k < nInstances; ++k) {
800 // search for accessors
801 std::list<ctk::VariableNetworkNode> accList =
802 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].getAccessorList();
803 BOOST_CHECK_EQUAL(accList.size(), 2);
804 size_t someInputFound = 0;
805 size_t someOutputFound = 0;
806 for(const auto& acc : accList) {
807 if(acc == ctk::VariableNetworkNode(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someInput)) {
808 someInputFound++;
809 }
810 if(acc == ctk::VariableNetworkNode(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someOutput)) {
811 someOutputFound++;
812 }
813 }
814 BOOST_CHECK_EQUAL(someInputFound, 1);
815 BOOST_CHECK_EQUAL(someOutputFound, 1);
816
817 // search for variable groups
818 std::list<ctk::Module*> modList = app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].getSubmoduleList();
819 BOOST_CHECK_EQUAL(modList.size(), nInstances + 1);
820
821 std::map<size_t, size_t> someGroupFound;
822 for(size_t m = 0; m < nInstances; ++m) {
823 someGroupFound[m] = 0;
824 }
825 size_t anotherGroupFound = 0;
826 for(const auto* mod : modList) {
827 for(size_t m = 0; m < nInstances; ++m) {
828 if(mod == &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m])) {
829 someGroupFound[m]++;
830 }
831 }
832 if(mod == &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].anotherGroup)) {
833 anotherGroupFound++;
834 }
835 }
836 for(size_t m = 0; m < nInstances; ++m) {
837 BOOST_CHECK_EQUAL(someGroupFound[m], 1);
838 }
839 BOOST_CHECK_EQUAL(anotherGroupFound, 1);
840 }
841 }
842 }
843
844 { // checks on fourth hierarchy level (each variable group has accessors)
845 for(size_t i = 0; i < nInstances; ++i) {
846 for(size_t k = 0; k < nInstances; ++k) {
847 for(size_t m = 0; m < nInstances; ++m) {
848 // search for accessors
849 std::list<ctk::VariableNetworkNode> accList =
850 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].getAccessorList();
851 BOOST_CHECK_EQUAL(accList.size(), 2);
852 size_t inGroupFound = 0;
853 size_t alsoInGroupFound = 0;
854 for(const auto& acc : accList) {
855 if(acc ==
857 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].inGroup)) {
858 inGroupFound++;
859 }
860 if(acc ==
862 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].alsoInGroup)) {
863 alsoInGroupFound++;
864 }
865 }
866 BOOST_CHECK_EQUAL(inGroupFound, 1);
867 BOOST_CHECK_EQUAL(alsoInGroupFound, 1);
868
869 // make sure no further subgroups exist
870 BOOST_CHECK_EQUAL(
871 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].getSubmoduleList().size(),
872 0);
873 }
874 }
875 }
876 }
877
878 /*----------------------------------------------------------------------------------------------------------------*/
879 // check ownerships
880 for(size_t i = 0; i < nInstances; ++i) {
881 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].getOwner() == &app);
882 for(size_t k = 0; k < nInstances; ++k) {
883 BOOST_CHECK(
884 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].getOwner() == &(app.vectorOfVectorModuleGroup[i]));
885 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someInput.getOwner() ==
886 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k]));
887 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someOutput.getOwner() ==
888 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k]));
889 for(size_t m = 0; m < nInstances; ++m) {
890 BOOST_CHECK(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].getOwner() ==
891 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k]));
892 BOOST_CHECK(
893 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].inGroup.getOwner() ==
894 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m]));
895 BOOST_CHECK(
896 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].alsoInGroup.getOwner() ==
897 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m]));
898 }
899 }
900 }
901
902 /*----------------------------------------------------------------------------------------------------------------*/
903 // check pointers to accessors in VariableNetworkNode
904 for(size_t i = 0; i < nInstances; ++i) {
905 for(size_t k = 0; k < nInstances; ++k) {
906 {
907 const auto* a = &(
908 static_cast<ctk::VariableNetworkNode>(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someInput)
909 .getAppAccessorNoType());
910 const auto* b = &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someInput);
911 BOOST_CHECK(a == b);
912 }
913 {
914 const auto* a = &(
915 static_cast<ctk::VariableNetworkNode>(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someOutput)
916 .getAppAccessorNoType());
917 const auto* b = &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].someOutput);
918 BOOST_CHECK(a == b);
919 }
920 for(size_t m = 0; m < nInstances; ++m) {
921 {
922 const auto* a = &(static_cast<ctk::VariableNetworkNode>(
923 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].inGroup)
924 .getAppAccessorNoType());
925 const auto* b = &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].inGroup);
926 BOOST_CHECK(a == b);
927 }
928 {
929 const auto* a = &(static_cast<ctk::VariableNetworkNode>(
930 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].alsoInGroup)
931 .getAppAccessorNoType());
932 const auto* b =
933 &(app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].vectorOfSomeGroup[m].alsoInGroup);
934 BOOST_CHECK(a == b);
935 }
936 }
937 }
938 }
939
940 /*----------------------------------------------------------------------------------------------------------------*/
941 // check model
942 { // check presence of all PVs (and indirectly the directories)
943 size_t nFound = 0;
944 std::set<std::string> pvNames;
945
946 auto checker = [&](auto proxy) {
947 pvNames.emplace(proxy.getFullyQualifiedPath());
948 ++nFound;
949 };
950
951 app.getModel().visit(
952 checker, ctk::Model::depthFirstSearch, ctk::Model::keepProcessVariables, ctk::Model::keepParenthood);
953
954 size_t nExpected = 0;
955 for(size_t i = 0; i < nInstances; ++i) {
956 std::string mgName = "/testModule_" + std::to_string(i) + "_instance";
957 for(size_t k = 0; k < nInstances; ++k) {
958 std::string amName = mgName + "/test_" + std::to_string(k);
959 for(size_t l = 0; l < nInstances; ++l) {
960 std::string vgName = amName + "/testGroup_" + std::to_string(l);
961 BOOST_CHECK(pvNames.count(vgName + "/inGroup"));
962 BOOST_CHECK(pvNames.count(vgName + "/alsoInGroup"));
963 nExpected += 2;
964 }
965
966 BOOST_CHECK(pvNames.count(amName + "/nameOfSomeInput"));
967 BOOST_CHECK(pvNames.count(amName + "/someOutput"));
968 BOOST_CHECK(pvNames.count(amName + "/anotherName/foo"));
969 nExpected += 3;
970 }
971 }
972
973 assert(nExpected == 2 * pow(nInstances, 3) + 3 * pow(nInstances, 2)); // = 2300 with nInstances = 10
974 BOOST_TEST(nFound == nExpected);
975 }
976
977 { // check presence of all module groups
978 size_t nFound = 0;
979 std::set<std::string> mgNames;
980
981 auto checker = [&](auto proxy) {
982 mgNames.emplace(proxy.getName());
983 ++nFound;
984 };
985
986 app.getModel().visit(
987 checker, ctk::Model::adjacentOutSearch, ctk::Model::keepOwnership, ctk::Model::keepModuleGroups);
988
989 for(size_t i = 0; i < nInstances; ++i) {
990 std::string mgName = "testModule_" + std::to_string(i) + "_instance";
991 BOOST_CHECK(mgNames.count(mgName));
992 }
993
994 BOOST_TEST(nFound == nInstances);
995 }
996
997 { // check presence of all application modules
998 for(size_t i = 0; i < nInstances; ++i) {
999 size_t nFound = 0;
1000 std::set<std::string> amNames;
1001
1002 auto checker = [&](auto proxy) {
1003 amNames.emplace(proxy.getName());
1004 ++nFound;
1005 };
1006
1007 app.vectorOfVectorModuleGroup[i].getModel().visit(
1008 checker, ctk::Model::adjacentOutSearch, ctk::Model::keepOwnership, ctk::Model::keepApplicationModules);
1009
1010 for(size_t k = 0; k < nInstances; ++k) {
1011 std::string amName = "test_" + std::to_string(k);
1012 BOOST_CHECK(amNames.count(amName));
1013 }
1014
1015 BOOST_TEST(nFound == nInstances);
1016 }
1017 }
1018
1019 { // check presence of all variable groups
1020 for(size_t i = 0; i < nInstances; ++i) {
1021 for(size_t k = 0; k < nInstances; ++k) {
1022 size_t nFound = 0;
1023 std::set<std::string> vgNames;
1024
1025 auto checker = [&](auto proxy) {
1026 vgNames.emplace(proxy.getName());
1027 ++nFound;
1028 };
1029
1030 app.vectorOfVectorModuleGroup[i].vectorOfVectorModule[k].getModel().visit(
1031 checker, ctk::Model::adjacentOutSearch, ctk::Model::keepOwnership, ctk::Model::keepVariableGroups);
1032
1033 BOOST_CHECK(vgNames.count("anotherName"));
1034 for(size_t l = 0; l < nInstances; ++l) {
1035 std::string vgName = "testGroup_" + std::to_string(l);
1036 BOOST_CHECK(vgNames.count(vgName));
1037 }
1038
1039 BOOST_TEST(nFound == nInstances + 1);
1040 }
1041 }
1042 }
1043 }
1044
1045 /********************************************************************************************************************/
1046 /* test late initialisation of modules using the assignment operator */
1047
1048 BOOST_AUTO_TEST_CASE(test_moveAssignmentOperator) {
1049 std::cout << "***************************************************************"
1050 "******************************************************"
1051 << std::endl;
1052 std::cout << "==> test_moveAssignmentOperator" << std::endl;
1053 std::cout << std::endl;
1054 {
1056
1057 BOOST_CHECK(app.modGroupInstanceToAssignLater.getName() == "modGroupInstanceToAssignLater");
1059 "This instance of VectorModuleGroup was assigned using the operator=()");
1060
1061 BOOST_CHECK(app.modInstanceToAssignLater.getName() == "modInstanceToAssignLater");
1062 BOOST_CHECK(app.modInstanceToAssignLater.getDescription() ==
1063 "This instance of VectorModule was assigned using the operator=()");
1064
1065 auto list = app.getSubmoduleList();
1066 BOOST_CHECK(list.size() == 2);
1067
1068 bool modGroupInstanceToAssignLater_found = false;
1069 bool modInstanceToAssignLater_found = false;
1070 for(const auto* mod : list) {
1071 if(mod == &(app.modGroupInstanceToAssignLater)) {
1072 modGroupInstanceToAssignLater_found = true;
1073 }
1074 if(mod == &(app.modInstanceToAssignLater)) {
1075 modInstanceToAssignLater_found = true;
1076 }
1077 }
1078
1079 BOOST_CHECK(modGroupInstanceToAssignLater_found);
1080 BOOST_CHECK(modInstanceToAssignLater_found);
1081 BOOST_CHECK_EQUAL(app.modGroupInstanceToAssignLater.getSubmoduleList().size(), 42);
1082 BOOST_CHECK_EQUAL(app.modInstanceToAssignLater.getSubmoduleList().size(), 14);
1083 BOOST_CHECK(app.modGroupInstanceSource.getName() == "**INVALID**");
1084 BOOST_CHECK(app.modGroupInstanceSource.getSubmoduleList().size() == 0);
1085 BOOST_CHECK(app.modGroupInstanceSource.vectorOfVectorModule.size() == 0);
1086
1087 BOOST_CHECK(app.modInstanceSource.getName() == "**INVALID**");
1088 BOOST_CHECK(app.modInstanceSource.getSubmoduleList().size() == 0);
1089 }
1090 {
1091 struct MovedTwiceAssignModuleLaterApp : public ctk::Application {
1092 MovedTwiceAssignModuleLaterApp() : Application("myApp") {
1093 modGroupInstanceToAssignLater = std::move(modGroupInstanceSource);
1094 modInstanceToAssignLater = std::move(modInstanceSource);
1095 modGroupInstanceToAssignedAfterMove = std::move(modGroupInstanceSource);
1096 modInstanceToAssignedAfterMove = std::move(modInstanceSource);
1097 }
1098 ~MovedTwiceAssignModuleLaterApp() override { shutdown(); }
1099
1100 VectorModuleGroup modGroupInstanceSource{this, "modGroupInstanceToAssignLater",
1101 "This instance of VectorModuleGroup was assigned using the operator=()", 42};
1102 VectorModule modInstanceSource{
1103 this, "modInstanceToAssignLater", "This instance of VectorModule was assigned using the operator=()", 13};
1104
1105 VectorModuleGroup modGroupInstanceToAssignLater;
1106 VectorModule modInstanceToAssignLater;
1107 VectorModuleGroup modGroupInstanceToAssignedAfterMove;
1108 VectorModule modInstanceToAssignedAfterMove;
1109 };
1110
1111 {
1112 auto appAgain = std::make_unique<MovedTwiceAssignModuleLaterApp>();
1113 VectorModuleGroup externalModGroup{appAgain.get(), "externalModGroup",
1114 "This instance of VectorModuleGroup was created to be destroyed after the correspondig app to check for "
1115 "errors and leaks",
1116 42};
1117 BOOST_CHECK(appAgain->modInstanceToAssignedAfterMove.getName() == "**INVALID**");
1118 BOOST_CHECK(appAgain->modGroupInstanceToAssignedAfterMove.vectorOfVectorModule.size() == 0);
1119 appAgain->modGroupInstanceToAssignLater = std::move(externalModGroup);
1120 // destroy app before externalModGroup
1121 appAgain.reset();
1122 BOOST_CHECK(externalModGroup.getName() == "**INVALID**");
1123 }
1124 }
1125 }
1126
1127 /********************************************************************************************************************/
1128 /* test tailing slashes in module names and group names will throw error*/
1129
1131 using ctk::ApplicationModule::ApplicationModule;
1132
1134 using ctk::VariableGroup::VariableGroup;
1135 ctk::ScalarPushInput<uint8_t> foo{this, "foo", "", "", {}};
1136
1137 } anotherGroup{this, "anotherGroupName", ""};
1138
1139 void mainLoop() override {}
1140 };
1141
1142 // module group
1143
1144 struct SlashApp : public ctk::Application {
1145 SlashApp() : Application("myApp") {}
1146 ~SlashApp() override { shutdown(); }
1147
1148 SlashModule slashModule{this, "slashModule/", ""};
1149 };
1150
1151 BOOST_AUTO_TEST_CASE(test_trailingSlashes) {
1152 std::cout << "***************************************************************"
1153 "******************************************************"
1154 << std::endl;
1155 std::cout << "==> test_trailingSlashes" << std::endl;
1156 std::cout << std::endl;
1157
1158 BOOST_CHECK_THROW(SlashApp app, ctk::logic_error);
1159 }
1160
1161 /********************************************************************************************************************/
1162 /* test tailing slashes in scalar variable name */
1163
1167
1169 using ctk::ApplicationModule::ApplicationModule;
1170
1171 ctk::ScalarPushInput<std::string> scalar{this, "scalar/", "", "", {}};
1172
1173 void mainLoop() override {}
1174 } someModule{this, "someModule", ""};
1175 };
1176
1177 BOOST_AUTO_TEST_CASE(test_trailingSlashesInScalarVariableNames) {
1178 std::cout << "***************************************************************"
1179 "******************************************************"
1180 << std::endl;
1181 std::cout << "==> test_trailingSlashesInScalarVariableNames" << std::endl;
1182 std::cout << std::endl;
1183 BOOST_CHECK_THROW(VariableSlashScalarApp app, ctk::logic_error);
1184 }
1185
1186 /********************************************************************************************************************/
1187 /* test tailing slashes in variable names */
1188
1192
1194 using ctk::ApplicationModule::ApplicationModule;
1195
1196 ctk::ArrayPushInput<int64_t> array{this, "array/", "", 16, "", {}};
1197
1198 void mainLoop() override {}
1199 } someModule{this, "someModule", ""};
1200 };
1201
1202 BOOST_AUTO_TEST_CASE(test_trailingSlashesInArrayVariableNames) {
1203 std::cout << "***************************************************************"
1204 "******************************************************"
1205 << std::endl;
1206 std::cout << "==> test_trailingSlashesInArrayVariableNames" << std::endl;
1207 std::cout << std::endl;
1208 BOOST_CHECK_THROW(VariableSlashArrayApp app, ctk::logic_error);
1209 }
1210
1211 /********************************************************************************************************************/
1212 /* test slash as variable name */
1213
1217
1219 using ctk::ApplicationModule::ApplicationModule;
1220
1221 ctk::ArrayPushInput<int64_t> array{this, "/", "", 16, "", {}};
1222
1223 void mainLoop() override {}
1224 } someModule{this, "someModule", ""};
1225 };
1226
1227 BOOST_AUTO_TEST_CASE(test_onlySlashAsVariableName) {
1228 std::cout << "***************************************************************"
1229 "******************************************************"
1230 << std::endl;
1231 std::cout << "==> test_trailingSlashesInArrayVariableNames" << std::endl;
1232 std::cout << std::endl;
1233 BOOST_CHECK_THROW(OnlySlashNameArrayApp app, ctk::logic_error);
1234 }
1235
1236 /********************************************************************************************************************/
1237 /* test tailing slash as module name */
1238
1242
1244 using ctk::ApplicationModule::ApplicationModule;
1245
1246 ctk::ArrayPushInput<int64_t> array{this, "someArray", "", 16, "", {}};
1247
1248 void mainLoop() override {}
1249 } someModule{this, "/", ""};
1250 };
1251
1252 BOOST_AUTO_TEST_CASE(test_onlySlashasModuleName) {
1253 std::cout << "***************************************************************"
1254 "******************************************************"
1255 << std::endl;
1256 std::cout << "==> test_trailingSlashesInArrayVariableNames" << std::endl;
1257 std::cout << std::endl;
1258
1260 ctk::TestFacility tf{app};
1261 tf.runApplication();
1262 BOOST_CHECK(app.someModule.getName() == "/");
1263 BOOST_CHECK(app.someModule.array.getName() == "/someArray");
1264 }
1265
1266 /********************************************************************************************************************/
1267 /* test multiple slashes in module name */
1268
1271 ~MultiSlashModule() override { shutdown(); }
1272
1274 using ctk::ApplicationModule::ApplicationModule;
1275
1276 ctk::ArrayPushInput<int64_t> array{this, "someArray", "", 16, "", {}};
1277
1278 void mainLoop() override {}
1279 } someModule{this, "aModule//withSlahsesInTheName/", ""};
1280 };
1281
1282 BOOST_AUTO_TEST_CASE(test_multipleSlashesInModuleName) {
1283 std::cout << "***************************************************************"
1284 "******************************************************"
1285 << std::endl;
1286 std::cout << "==> test_trailingSlashesInArrayVariableNames" << std::endl;
1287 std::cout << std::endl;
1288
1289 BOOST_CHECK_THROW(MultiSlashModule app, ctk::logic_error);
1290 ;
1291 }
1292
1293 /********************************************************************************************************************/
1294 /* test multiple slashes in variable name */
1295
1299
1301 using ctk::ApplicationModule::ApplicationModule;
1302
1303 ctk::ArrayPushInput<int64_t> array{this, "someArray/with//multiple///slashes", "", 16, "", {}};
1304
1305 void mainLoop() override {}
1306 } someModule{this, "someModule", ""};
1307 };
1308
1309 BOOST_AUTO_TEST_CASE(test_multipleSlashesInVariableName) {
1310 std::cout << "***************************************************************"
1311 "******************************************************"
1312 << std::endl;
1313 std::cout << "==> test_trailingSlashesInArrayVariableNames" << std::endl;
1314 std::cout << std::endl;
1315
1316 BOOST_CHECK_THROW(MultiSlashVarModule app, ctk::logic_error);
1317 ;
1318 }
1319
1320} // namespace Tests::testModules
Model::RootProxy getModel()
Return the root of the application model.
Definition Application.h:75
void shutdown() override
This will remove the global pointer to the instance and allows creating another instance afterwards.
ApplicationModule()=default
Default constructor: Allows late initialisation of modules (e.g.
ChimeraTK::Model::ApplicationModuleProxy getModel()
Return the application model proxy representing this module.
bool write(ChimeraTK::VersionNumber versionNumber)=delete
Convenience class for input array accessors with UpdateMode::push.
std::list< Module * > getSubmoduleListRecursive() const
Obtain the list of submodules associated with this instance and any submodules.
const std::string & getName() const
Get the name of the module instance.
Definition EntityOwner.h:59
std::list< VariableNetworkNode > getAccessorList() const
Obtain the list of accessors/variables directly associated with this instance.
Definition EntityOwner.h:77
std::list< Module * > getSubmoduleList() const
Obtain the list of submodules associated with this instance.
Definition EntityOwner.h:80
const std::string & getDescription() const
Get the description of the module instance.
Definition EntityOwner.h:69
void addTag(const std::string &tag)
Add a tag to all Application-type nodes inside this group.
std::list< VariableNetworkNode > getAccessorListRecursive() const
Obtain the list of accessors/variables associated with this instance and any submodules.
EntityOwner * getOwner() const
Return the owning module.
const std::unordered_set< std::string > & getTags()
Return set of tags.
void addTag(const std::string &tag)
Add a tag.
auto visit(VISITOR visitor, Args... args) const
Traverse the model using the specified filter and call the visitor functor for each ModuleGroup,...
Definition Model.h:1451
friend class Application
Definition ModuleGroup.h:47
ChimeraTK::Model::ModuleGroupProxy getModel()
Return the application model proxy representing this module.
Definition ModuleGroup.h:40
ModuleGroup()=default
Default constructor to allow late initialisation of module groups.
EntityOwner * getOwner() const
Definition Module.h:102
bool write(ChimeraTK::VersionNumber versionNumber)=delete
Convenience class for input scalar accessors with UpdateMode::push.
Helper class to facilitate tests of applications based on ApplicationCore.
Class describing a node of a variable network.
InvalidityTracer application module.
std::string negateTag(const std::string &tag)
negate tag using prefix '!'
BOOST_AUTO_TEST_CASE(test_ownership)
Convenience class for output array accessors (always UpdateMode::push)
Convenience class for output scalar accessors (always UpdateMode::push)
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
Tests::testModules::MultiSlashVarModule::SomeModule someModule
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
Tests::testModules::OnlySlashNameArrayApp::SomeModule someModule
ctk::ScalarPushInput< uint8_t > foo
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
ctk::ArrayPushInput< int64_t > alsoInGroup
ctk::ScalarPushInput< std::string > inGroup
ctk::ScalarPushInput< uint8_t > foo
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
ctk::ScalarOutput< double > someOutput
ctk::ScalarPushInput< int > someInput
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
Tests::testModules::VariableSlashArrayApp::SomeModule someModule
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
Tests::testModules::VariableSlashScalarApp::SomeModule someModule
ctk::ScalarPushInput< uint8_t > foo
std::vector< VectorModule > vectorOfVectorModule
VectorModuleGroup(ModuleGroup *owner, const std::string &name, const std::string &description, size_t nInstances, const std::unordered_set< std::string > &tags={})
VectorModule(ctk::ModuleGroup *owner, const std::string &name, const std::string &description, size_t nInstances, const std::unordered_set< std::string > &tags={})
ctk::ArrayOutput< double > someOutput
std::vector< SomeGroup > vectorOfSomeGroup
ctk::ScalarPushInput< int > someInput
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
std::vector< VectorModuleGroup > vectorOfVectorModuleGroup
VectorOfEverythingApp(size_t numberOfInstances)
VectorOfModulesApp(size_t numberOfInstances)
std::vector< TestModule > vectorOfTestModule