Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#define BOOST_TEST_MODULE testVirtualHierarchy
#include <boost/test/included/unit_test.hpp>
#include "Application.h"
#include "ApplicationModule.h"
#include "ModuleGroup.h"
#include "TestFacility.h"
using namespace boost::unit_test_framework;
namespace ctk = ChimeraTK;
struct TestModule : public ctk::ApplicationModule {
using ctk::ApplicationModule::ApplicationModule;
ctk::ScalarPushInput<int> input{this, "input", "", {"CS"}};
ctk::ScalarOutput<int> output{this, "output", "", {"CS"}};
void mainLoop() override {}
};
struct TestModule2 : public ctk::ApplicationModule {
using ctk::ApplicationModule::ApplicationModule;
ctk::ScalarPushInput<int> input2{this, "input2", "", {"CS"}};
ctk::ScalarOutput<int> output2{this, "output2", "", {"CS"}};
void mainLoop() override {}
};
struct TestModule3 : public ctk::ApplicationModule {
using ctk::ApplicationModule::ApplicationModule;
ctk::ScalarPushInput<int> input3{this, "input3", "", {"CS"}};
ctk::ScalarOutput<int> output3{this, "output3", "", {"CS"}};
void mainLoop() override {}
};
struct TestModuleWithVariableGroups : public ctk::ApplicationModule {
using ctk::ApplicationModule::ApplicationModule;
struct GroupOneLevelUp : public ctk::VariableGroup {
using ctk::VariableGroup::VariableGroup;
ctk::ScalarOutput<int> outputInGroupOneLevelUp{this, "outputInGroupOneLevelUp", "", ""};
} groupOneLevelUp{this, "groupOneLevelUp", "", ctk::HierarchyModifier::oneLevelUp};
struct GroupOneUpAndHide : public ctk::VariableGroup {
using ctk::VariableGroup::VariableGroup;
ctk::ScalarOutput<int> outputInGroupOneUpAndHide{this, "outputInGroupOneUpAndHide", "", ""};
} groupOneUpAndHide{this, "groupOneUpAndHide", "", ctk::HierarchyModifier::oneUpAndHide};
void mainLoop() override {}
};
struct InnerGroup : public ctk::ModuleGroup {
using ctk::ModuleGroup::ModuleGroup;
TestModule innerModule{this, "innerModule", "", ctk::HierarchyModifier::none};
TestModule2 innerModuleOneUpAndHide{this, "innerModuleOneUpAndHide", "", ctk::HierarchyModifier::oneUpAndHide};
TestModule3 innerModuleMoveToRoot{this, "innerModuleMoveToRoot", "", ctk::HierarchyModifier::moveToRoot};
TestModule3 innerModuleSameNameAsGroup{this, "innerModuleGroup", "", ctk::HierarchyModifier::oneLevelUp};
TestModuleWithVariableGroups innerModuleWithVariableGroups{this, "innerModuleWithVariableGroups", ""};
};
struct OuterGroup : public ctk::ModuleGroup {
OuterGroup(EntityOwner* owner, const std::string& name, const std::string& description,
ctk::HierarchyModifier modifier, ctk::HierarchyModifier innerGroupModifier = ctk::HierarchyModifier::none)
: ModuleGroup{owner, name, description, modifier}, innerGroup{this, "innerModuleGroup", "", innerGroupModifier} {
// Here, findTag should give proper exceptions if HierarchyModifiers are used illegally
auto allAccessors = getOwner()->findTag(".*").getAccessorListRecursive();
// for(auto acc : allAccessors) {
// std::cout << " -- Accessor: " << acc.getName() << " of module: " << acc.getOwningModule()->getName()
// << std::endl;
// }
}
virtual ~OuterGroup() {}
TestModule outerModule{this, "outerModuleInGroup", "", ctk::HierarchyModifier::oneLevelUp};
InnerGroup innerGroup;
};
struct TestApplication : public ctk::Application {
TestApplication(ctk::HierarchyModifier outerModuleModifier,
ctk::HierarchyModifier innerGroupModifier = ctk::HierarchyModifier::none, bool skipConnection = false)
: Application("testApp"), outerModuleGroup1{this, "outerModuleGroup1", "", ctk::HierarchyModifier::none,
innerGroupModifier},
outerModule{this, "outerModule", "", outerModuleModifier}, _skipConnection{skipConnection} {}
~TestApplication() { shutdown(); }
OuterGroup outerModuleGroup1;
TestModule outerModule;
ctk::ControlSystemModule cs;
void defineConnections() {
// Tests for getVirtualQualifiedName require that findTag is not used globally,
// so it can be disabled
if(!_skipConnection) {
findTag(".*").connectTo(cs);
}
bool _skipConnection;
};
// Check if HierarchyModifiers are properly handled in the call to findTag
// in the constructor of TestApplication
BOOST_AUTO_TEST_CASE(testIllegalModifiers) {
std::cout << "testIllegalModifiers" << std::endl;
{
std::cout << " Creating TestApplication with outerModuleModifier = none " << std::endl;
// Should work
TestApplication app(ctk::HierarchyModifier::none);
ctk::TestFacility test;
std::cout << std::endl;
}
{
std::cout << " Creating TestApplication with outerModuleModifier = oneLevelUp " << std::endl;
TestApplication app(ctk::HierarchyModifier::oneLevelUp);
// Should detect illegal usage of oneLevelUp on first level below Application and throw
BOOST_CHECK_THROW(ctk::TestFacility test, ctk::logic_error);
std::cout << std::endl;
}
// Should detect illegal usage of oneUpAndHide on first level below Application and throw
// Currently leads to memory access violation, should also throw
// Bug is described by issue #166.
// {
// std::cout << "Creating TestApplication with outerModuleModifier = oneUpAndHide " << std::endl;
// TestApplication app(ctk::HierarchyModifier::oneUpAndHide);
// ctk::TestFacility test;
// std::cout << std::endl;
// }
{
std::cout << " Creating TestApplication with outerModuleModifier = moveToRoot " << std::endl;
// Should work
TestApplication app(ctk::HierarchyModifier::moveToRoot);
ctk::TestFacility test;
std::cout << std::endl;
}
}
BOOST_AUTO_TEST_CASE(testGetVirtualQualifiedName) {
std::cout << "testGetVirtualQualifiedName" << std::endl;
{
TestApplication app(ctk::HierarchyModifier::none);
ctk::TestFacility test;
//app.cs.dump();
BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp/outerModule");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.getVirtualQualifiedName(), "/testApp/outerModuleGroup1");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.outerModule.getVirtualQualifiedName(), "/testApp/outerModuleInGroup");
BOOST_CHECK_EQUAL(
app.outerModuleGroup1.innerGroup.getVirtualQualifiedName(), "/testApp/outerModuleGroup1/innerModuleGroup");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModule.getVirtualQualifiedName(),
"/testApp/outerModuleGroup1/innerModuleGroup/innerModule");
BOOST_CHECK_EQUAL(
app.outerModuleGroup1.innerGroup.innerModuleWithVariableGroups.groupOneLevelUp.getVirtualQualifiedName(),
"/testApp/outerModuleGroup1/innerModuleGroup/groupOneLevelUp");
BOOST_CHECK_EQUAL(
app.outerModuleGroup1.innerGroup.innerModuleWithVariableGroups.groupOneUpAndHide.getVirtualQualifiedName(),
"/testApp/outerModuleGroup1/innerModuleGroup");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleOneUpAndHide.getVirtualQualifiedName(),
"/testApp/outerModuleGroup1");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleMoveToRoot.getVirtualQualifiedName(),
"/testApp/innerModuleMoveToRoot");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModuleSameNameAsGroup.getVirtualQualifiedName(),
"/testApp/outerModuleGroup1/innerModuleGroup");
}
{
TestApplication app(ctk::HierarchyModifier::hideThis);
ctk::TestFacility test;
// app.cs.dump();
BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp");
}
// Modifiers oneLevelUp and oneUpAndHide need to be catched by getVirtualQualifiedName, if used on
// the top level og the application. Note: If defineConnections uses findTag on the entire app,
// the error is catched there, this is avoided by the boolean constructor arguments below
{
TestApplication app(ctk::HierarchyModifier::oneLevelUp, ctk::HierarchyModifier::none, true);
ctk::TestFacility test;
BOOST_CHECK_THROW(app.outerModule.getVirtualQualifiedName(), ctk::logic_error);
}
{
TestApplication app(ctk::HierarchyModifier::oneUpAndHide, ctk::HierarchyModifier::none, true);
ctk::TestFacility test;
BOOST_CHECK_THROW(app.outerModule.getVirtualQualifiedName(), ctk::logic_error);
}
{
TestApplication app(ctk::HierarchyModifier::moveToRoot, ctk::HierarchyModifier::moveToRoot);
ctk::TestFacility test;
// app.cs.dump();
BOOST_CHECK_EQUAL(app.outerModule.getVirtualQualifiedName(), "/testApp/outerModule");
auto virtualisedApp = app.findTag(".*");
BOOST_CHECK_NO_THROW(virtualisedApp["outerModule"]);
BOOST_CHECK_NO_THROW(virtualisedApp["innerModuleMoveToRoot"]);
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.getVirtualQualifiedName(), "/testApp/innerModuleGroup");
BOOST_CHECK_EQUAL(app.outerModuleGroup1.innerGroup.innerModule.getVirtualQualifiedName(),
"/testApp/innerModuleGroup/innerModule");
}
}
BOOST_AUTO_TEST_CASE(testGetNetworkNodesOnVirtualHierarchy) {
std::cout << "testGetNetworkNodesOnVirtualHierarchy" << std::endl;
TestApplication app(ctk::HierarchyModifier::none);
ctk::TestFacility test;
//app.cs.dump();
//app.outerModuleGroup1.virtualise().dump();
auto virtualisedApplication = app.findTag(".*");
virtualisedApplication.dump();
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
// Need to trip away "/appName/" in the submodule() calls
size_t firstModuleOffsetInPath = ("/" + app.getName() + "/").size();
auto pathToInnerModuleOneUpAndHide =
app.outerModuleGroup1.innerGroup.innerModuleOneUpAndHide.getVirtualQualifiedName();
// Get submodule by the virtual path
ctk::Module& module = virtualisedApplication.submodule(
{pathToInnerModuleOneUpAndHide.begin() + firstModuleOffsetInPath, pathToInnerModuleOneUpAndHide.end()});
auto node2 = module("input2");
BOOST_CHECK_EQUAL(node2.getName(), "input2");
// As a reference, navigate to the module using operator []
auto node2Ref = virtualisedApplication["outerModuleGroup1"]("input2");
BOOST_CHECK(node2 == node2Ref);
// Repeat test for other modules: Module moved to root
auto pathToInnerModuleMoveToRoot = app.outerModuleGroup1.innerGroup.innerModuleMoveToRoot.getVirtualQualifiedName();
ctk::Module& innerModuleMoveToRoot = virtualisedApplication.submodule(
{pathToInnerModuleMoveToRoot.begin() + firstModuleOffsetInPath, pathToInnerModuleMoveToRoot.end()});
auto node3 = innerModuleMoveToRoot("input3");
auto node3Ref = virtualisedApplication["innerModuleMoveToRoot"]("input3");
BOOST_CHECK(node3 == node3Ref);
// Repeat test for other modules: Module with same name as its group and modifier oneLevelUp
auto pathToInnerModuleSameNameAsGroup =
app.outerModuleGroup1.innerGroup.innerModuleSameNameAsGroup.getVirtualQualifiedName();
ctk::Module& innerModuleSameNameAsGroup = virtualisedApplication.submodule(
{pathToInnerModuleSameNameAsGroup.begin() + firstModuleOffsetInPath, pathToInnerModuleSameNameAsGroup.end()});
node3 = innerModuleSameNameAsGroup("input3");
node3Ref = virtualisedApplication["outerModuleGroup1"]["innerModuleGroup"]("input3");
BOOST_CHECK(node3 == node3Ref);
auto pathToGroupWithOneLevelUp =
app.outerModuleGroup1.innerGroup.innerModuleWithVariableGroups.groupOneLevelUp.getVirtualQualifiedName();
ctk::Module& groupWithOneLevelUp = virtualisedApplication.submodule(
{pathToGroupWithOneLevelUp.begin() + firstModuleOffsetInPath, pathToGroupWithOneLevelUp.end()});
auto node4 = groupWithOneLevelUp("outputInGroupOneLevelUp");
auto node4Ref =
virtualisedApplication["outerModuleGroup1"]["innerModuleGroup"]["groupOneLevelUp"]("outputInGroupOneLevelUp");
BOOST_CHECK(node4 == node4Ref);
auto pathToGroupWithOneUpAndHide =
app.outerModuleGroup1.innerGroup.innerModuleWithVariableGroups.groupOneUpAndHide.getVirtualQualifiedName();
ctk::Module& groupWithOneUpAndHide = virtualisedApplication.submodule(
{pathToGroupWithOneUpAndHide.begin() + firstModuleOffsetInPath, pathToGroupWithOneUpAndHide.end()});
auto node5 = groupWithOneUpAndHide("outputInGroupOneUpAndHide");
auto node5Ref = virtualisedApplication["outerModuleGroup1"]["innerModuleGroup"]("outputInGroupOneUpAndHide");
BOOST_CHECK(node5 == node5Ref);