-
Martin Christoph Hierholzer authored
- allow setting the "eliminateHierarchy" flag in the constructor of a module This is an interface change which was done in an incompatible way!
Martin Christoph Hierholzer authored- allow setting the "eliminateHierarchy" flag in the constructor of a module This is an interface change which was done in an incompatible way!
testVariableGroup.cc 11.17 KiB
/*
* testVariableGroup.cc
*
* Created on: Nov 8, 2016
* Author: Martin Hierholzer
*/
#include <future>
#include <chrono>
#define BOOST_TEST_MODULE testVariableGroup
#include <boost/test/included/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <boost/thread.hpp>
#include "Application.h"
#include "ScalarAccessor.h"
#include "ApplicationModule.h"
#include "VariableGroup.h"
using namespace boost::unit_test_framework;
namespace ctk = ChimeraTK;
/*********************************************************************************************************************/
/* the ApplicationModule for the test is a template of the user type */
struct TestModule : public ctk::ApplicationModule {
using ctk::ApplicationModule::ApplicationModule;
struct MixedGroup : public ctk::VariableGroup {
using ctk::VariableGroup::VariableGroup;
ctk::ScalarPushInput<int> consumingPush{this, "consumingPush", "MV/m", "Descrption"};
ctk::ScalarPushInput<int> consumingPush2{this, "consumingPush2", "MV/m", "Descrption"};
ctk::ScalarPushInput<int> consumingPush3{this, "consumingPush3", "MV/m", "Descrption"};
ctk::ScalarPollInput<int> consumingPoll{this, "consumingPoll", "MV/m", "Descrption"};
ctk::ScalarPollInput<int> consumingPoll2{this, "consumingPoll2", "MV/m", "Descrption"};
ctk::ScalarPollInput<int> consumingPoll3{this, "consumingPoll3", "MV/m", "Descrption"};
};
MixedGroup mixedGroup{this, "mixedGroup", "A group with both push and poll inputs"};
ctk::ScalarOutput<int> feedingPush{this, "feedingPush", "MV/m", "Descrption"};
ctk::ScalarOutput<int> feedingPush2{this, "feedingPush2", "MV/m", "Descrption"};
ctk::ScalarOutput<int> feedingPush3{this, "feedingPush3", "MV/m", "Descrption"};
ctk::ScalarOutput<int> feedingPoll{this, "feedingPoll", "MV/m", "Descrption"};
ctk::ScalarOutput<int> feedingPoll2{this, "feedingPoll2", "MV/m", "Descrption"};
ctk::ScalarOutput<int> feedingPoll3{this, "feedingPoll3", "MV/m", "Descrption"};
void mainLoop() {}
};
/*********************************************************************************************************************/
/* dummy application */
struct TestApplication : public ctk::Application {
TestApplication() : Application("test suite") { ChimeraTK::ExperimentalFeatures::enable(); }
~TestApplication() { shutdown(); }
using Application::makeConnections; // we call makeConnections() manually in the tests to catch exceptions etc.
void defineConnections() {} // the setup is done in the tests
TestModule testModule{this, "testModule", "The test module"};
};
/*********************************************************************************************************************/
/* test trigger by app variable when connecting a polled device register to an app variable */
BOOST_AUTO_TEST_CASE( testMixedGroup ) {
std::cout << "*********************************************************************************************************************" << std::endl;
std::cout << "==> testMixedGroup" << std::endl;
TestApplication app;
app.testModule.feedingPush >> app.testModule.mixedGroup.consumingPush;
app.testModule.feedingPush2 >> app.testModule.mixedGroup.consumingPush2;
app.testModule.feedingPush3 >> app.testModule.mixedGroup.consumingPush3;
app.testModule.feedingPoll >> app.testModule.mixedGroup.consumingPoll;
app.testModule.feedingPoll2 >> app.testModule.mixedGroup.consumingPoll2;
app.testModule.feedingPoll3 >> app.testModule.mixedGroup.consumingPoll3;
app.initialise();
app.run();
// single theaded test
app.testModule.feedingPush = 0;
app.testModule.feedingPush2 = 42;
app.testModule.feedingPush3 = 120;
app.testModule.feedingPoll = 10;
app.testModule.feedingPoll2 = 11;
app.testModule.feedingPoll3 = 12;
app.testModule.feedingPoll.write();
app.testModule.feedingPoll2.write();
app.testModule.feedingPoll3.write();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 0);
// test a single write
app.testModule.feedingPush2.write();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 0);
app.testModule.mixedGroup.readAny();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 42);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// two more writes
app.testModule.feedingPush2 = 666;
app.testModule.feedingPush2.write();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 42);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
app.testModule.mixedGroup.readAny();
app.testModule.feedingPush3.write();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
app.testModule.mixedGroup.readAny();
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// launch readAny() asynchronously and make sure it does not yet receive anything
auto futureRead = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
BOOST_CHECK(futureRead.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 0);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// write something
app.testModule.feedingPush = 3;
app.testModule.feedingPush.write();
// check that the group now receives the just written value
BOOST_CHECK(futureRead.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// launch another readAny() asynchronously and make sure it does not yet receive anything
auto futureRead2 = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
BOOST_CHECK(futureRead2.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// write to the poll-type variables
app.testModule.feedingPoll = 66;
app.testModule.feedingPoll.write();
app.testModule.feedingPoll2 = 77;
app.testModule.feedingPoll2.write();
app.testModule.feedingPoll3 = 88;
app.testModule.feedingPoll3.write();
// make sure readAny still does not receive anything
BOOST_CHECK(futureRead2.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 666);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 10);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 11);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 12);
// write something to the push-type variables
app.testModule.feedingPush2 = 123;
app.testModule.feedingPush2.write();
// check that the group now receives the just written values
BOOST_CHECK(futureRead2.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 123);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 66);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 77);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 88);
// two changes at a time
auto futureRead3 = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
BOOST_CHECK(futureRead3.wait_for(std::chrono::milliseconds(200)) == std::future_status::timeout);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 123);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 120);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 66);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 77);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 88);
app.testModule.feedingPush2 = 234;
app.testModule.feedingPush3 = 345;
app.testModule.feedingPush2.write();
app.testModule.feedingPush3.write();
BOOST_CHECK(futureRead3.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
auto futureRead4 = std::async(std::launch::async, [&app]{ app.testModule.mixedGroup.readAny(); });
BOOST_CHECK(futureRead4.wait_for(std::chrono::milliseconds(2000)) == std::future_status::ready);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush == 3);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush2 == 234);
BOOST_CHECK(app.testModule.mixedGroup.consumingPush3 == 345);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll == 66);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll2 == 77);
BOOST_CHECK(app.testModule.mixedGroup.consumingPoll3 == 88);
}