"git@gitlab.desy.de:detectorsoftware/libagipdctrl.git" did not exist on "bc3054cb7fb2bc22c371d4266e942a32d665499e"
-
Christoph Kampmeyer authoredChristoph Kampmeyer authored
testVirtualHierarchy.cc 11.98 KiB
#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);
}
//cs.dump();
}
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();
// 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);
}