5#define BOOST_TEST_MODULE testTrigger
14#include <ChimeraTK/BackendFactory.h>
15#include <ChimeraTK/ControlSystemAdapter/ControlSystemPVManager.h>
16#include <ChimeraTK/ControlSystemAdapter/DevicePVManager.h>
17#include <ChimeraTK/ControlSystemAdapter/PVManager.h>
18#include <ChimeraTK/Device.h>
19#include <ChimeraTK/DeviceAccessVersion.h>
20#include <ChimeraTK/DummyBackend.h>
22#include <boost/mpl/list.hpp>
23#include <boost/test/included/unit_test.hpp>
29 using namespace boost::unit_test_framework;
42 using ctk::ApplicationModule::ApplicationModule;
57 } someModule{
this,
".",
""};
69 app.
dev = {&app,
"Dummy0"};
71 auto finger = tf.getVoid(
"/finger");
72 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
78 dev.write(
"MyModule/actuator", 1);
80 BOOST_TEST(rb.readNonBlocking() ==
false);
83 BOOST_TEST(rb.readNonBlocking() ==
true);
86 dev.write(
"MyModule/actuator", 10);
89 BOOST_TEST(rb.readNonBlocking() ==
true);
96 app.
dev = {&app,
"Dummy0",
"/cs/tick"};
98 auto tick = tf.getVoid(
"/cs/tick");
99 auto finger = tf.getVoid(
"/finger");
100 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
106 dev.write(
"MyModule/actuator", 2);
108 BOOST_TEST(rb.readNonBlocking() ==
false);
110 tf.stepApplication();
111 BOOST_TEST(rb.readNonBlocking() ==
true);
116 tf.stepApplication();
117 BOOST_TEST(rb.readNonBlocking() ==
false);
120 dev.write(
"MyModule/actuator", 20);
124 tf.stepApplication();
125 BOOST_TEST(rb.readNonBlocking() ==
true);
126 BOOST_TEST(rb == 20);
130 tf.stepApplication();
131 BOOST_TEST(rb.readNonBlocking() ==
false);
132 BOOST_TEST(rb == 20);
143 using ctk::ApplicationModule::ApplicationModule;
152 } someModule{
this,
".",
""};
165 app.
dev = {&app,
"Dummy0"};
171 ChimeraTK::logic_error);
177 app.
dev = {&app,
"Dummy0",
"/cs/trigger"};
180 auto tick = tf.getVoid(
"/cs/trigger");
181 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
187 dev.write(
"MyModule/actuator", 1);
190 tf.stepApplication();
192 BOOST_TEST(rb.readNonBlocking() ==
true);
195 dev.write(
"MyModule/actuator", 12);
196 BOOST_TEST(rb.readNonBlocking() ==
false);
200 tf.stepApplication();
201 BOOST_TEST(rb.readNonBlocking() ==
true);
202 BOOST_TEST(rb == 12);
214 using ctk::ApplicationModule::ApplicationModule;
230 using ctk::ApplicationModule::ApplicationModule;
240 } someModule{
this,
".",
""};
253 auto tick = tf.getVoid(
"/cs/trigger");
254 auto tock = tf.getScalar<
int>(
"/tock");
255 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
261 dev.write(
"MyModule/actuator", 1);
264 tf.stepApplication();
266 BOOST_TEST(tock.readNonBlocking() ==
true);
267 BOOST_TEST(tock == 1);
268 BOOST_TEST(rb.readNonBlocking() ==
true);
271 dev.write(
"MyModule/actuator", 12);
272 BOOST_TEST(tock.readNonBlocking() ==
false);
273 BOOST_TEST(tock == 1);
274 BOOST_TEST(rb.readNonBlocking() ==
false);
278 tf.stepApplication();
279 BOOST_TEST(tock.readNonBlocking() ==
true);
280 BOOST_TEST(tock == 2);
281 BOOST_TEST(rb.readNonBlocking() ==
true);
282 BOOST_TEST(rb == 12);
293 using ctk::ApplicationModule::ApplicationModule;
302 } someOtherModule{
this,
".",
""};
305 using ctk::ApplicationModule::ApplicationModule;
315 } someModule{
this,
".",
""};
329 auto tick = tf.getVoid(
"/cs/trigger");
330 auto f = tf.getScalar<
float>(
"/Device/signed32");
331 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
338 dev2.write(
"FixedPoint/value", 12.4);
342 dev.write(
"MyModule/actuator", 1);
344 BOOST_TEST(f.readNonBlocking() ==
false);
345 BOOST_TEST(rb.readNonBlocking() ==
false);
348 tf.stepApplication();
349 BOOST_TEST(f.readNonBlocking() ==
true);
350 BOOST_TEST(rb.readNonBlocking() ==
true);
352 BOOST_TEST((f - 12.4) < 0.01);
355 dev.write(
"MyModule/actuator", 2);
356 dev2.write(
"FixedPoint/value", 24.8);
358 BOOST_TEST(f.readNonBlocking() ==
false);
359 BOOST_TEST(rb.readNonBlocking() ==
false);
362 tf.stepApplication();
363 BOOST_TEST(f.readNonBlocking() ==
true);
364 BOOST_TEST(rb.readNonBlocking() ==
true);
366 BOOST_TEST((f - 24.8) < 0.001);
378 using ctk::ApplicationModule::ApplicationModule;
389 } someModule{
this,
".",
""};
399 app.
dev = {&app,
"Dummy0",
"/cs/trigger"};
402 auto tick = tf.getVoid(
"/cs/trigger");
403 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
409 dev.write(
"MyModule/actuator", 1);
412 tf.stepApplication();
414 BOOST_TEST(rb.readNonBlocking() ==
true);
417 dev.write(
"MyModule/actuator", 12);
418 BOOST_TEST(rb.readNonBlocking() ==
false);
422 tf.stepApplication();
423 BOOST_TEST(rb.readNonBlocking() ==
true);
424 BOOST_TEST(rb == 12);
431 app.
dev = {&app,
"Dummy0",
"/trigger"};
434 auto tick = tf.getVoid(
"/finger");
435 auto rb = tf.getScalar<
int>(
"/MyModule/readBack");
441 dev.write(
"MyModule/actuator", 1);
444 tf.stepApplication();
446 BOOST_TEST(rb.readNonBlocking() ==
true);
449 dev.write(
"MyModule/actuator", 12);
450 BOOST_TEST(rb.readNonBlocking() ==
false);
454 tf.stepApplication();
455 BOOST_TEST(rb.readNonBlocking() ==
true);
456 BOOST_TEST(rb == 12);
462 const std::string
dummySdm{
"(TestTransferGroupDummy?map=test_readonly.map)"};
465 using test_types = boost::mpl::list<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, float, double>;
475 static boost::shared_ptr<DeviceBackend>
createInstance(std::string, std::map<std::string, std::string> parameters) {
479 void read(uint64_t bar, uint64_t address, int32_t* data,
size_t sizeInBytes)
override {
484 DummyBackend::read(bar, address, data, sizeInBytes);
498 const std::unordered_set<std::string>& tags = {})
521 std::cout <<
"Start of main loop" << std::endl;
523 std::cout <<
"End of main loop" << std::endl;
532 ChimeraTK::BackendFactory::getInstance().registerBackendType(
547 std::cout <<
"***************************************************************"
548 "******************************************************"
550 std::cout <<
"==> testTriggerTransferGroup" << std::endl;
552 ChimeraTK::BackendFactory::getInstance().setDMapFilePath(
"test.dmap");
555 auto pvManagers = ctk::createPVManager();
556 app.setPVManager(pvManagers.second);
560 auto backend = boost::dynamic_pointer_cast<TestTransferGroupDummy>(
561 ChimeraTK::BackendFactory::getInstance().createBackend(
dummySdm));
562 BOOST_CHECK(backend !=
nullptr);
572 dev.write(
"/REG1.DUMMY_WRITEABLE", 11);
573 dev.write(
"/REG2.DUMMY_WRITEABLE", 22);
574 dev.write(
"/REG3.DUMMY_WRITEABLE", 33);
582 BOOST_TEST(backend->lastBar == 0);
583 BOOST_TEST(backend->lastAddress == 0);
587 BOOST_TEST(backend->lastSizeInBytes == 32);
598 dev.write(
"/REG1.DUMMY_WRITEABLE", 12);
599 dev.write(
"/REG2.DUMMY_WRITEABLE", 23);
600 dev.write(
"/REG3.DUMMY_WRITEABLE", 34);
605 BOOST_TEST(backend->lastBar == 0);
606 BOOST_TEST(backend->lastAddress == 0);
610 BOOST_TEST(backend->lastSizeInBytes == 32);
639 std::cout <<
"Init Handler blocked." << std::endl;
643 std::cout <<
"Init Handler completed." << std::endl;
657 std::cout <<
"***************************************************************"
658 "******************************************************"
660 std::cout <<
"==> TestTriggerTransferGroupInitHandler" << std::endl;
666 auto trigger = test.
getVoid(
"/testModule/theTrigger");
667 auto readBack = test.
getScalar<
int>(
"/MyModule/readBack");
668 auto devStatus = test.
getScalar<
int>(
"/Devices/Dummy0/status");
673 BOOST_REQUIRE(devStatus == 0);
675 BOOST_REQUIRE(devStatus == 1);
688 BOOST_REQUIRE(devStatus == 0);
701 BOOST_REQUIRE(devStatus == 1);
void run() override
Execute the module.
void initialise() override
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.
void decrementDataFaultCounter() override
Decrement the fault counter and set the data validity flag to ok if the counter has reached 0.
void incrementDataFaultCounter() override
Set the data validity flag to fault and increment the fault counter.
void reportException(std::string errMsg)
Use this function to report an exception.
void readAll(bool includeReturnChannels=false)
Read all readable variables in the group.
void writeAll(bool includeReturnChannels=false)
Just call write() on all writable variables in the group.
bool write(ChimeraTK::VersionNumber versionNumber)=delete
Helper class to set the DMAP file path.
Helper class to facilitate tests of applications based on ApplicationCore.
ChimeraTK::VoidRegisterAccessor getVoid(const ChimeraTK::RegisterPath &name) const
Obtain a void process variable from the application, which is published to the control system.
ChimeraTK::ScalarRegisterAccessor< T > getScalar(const ChimeraTK::RegisterPath &name) const
Obtain a scalar process variable from the application, which is published to the control system.
void runApplication() const
Start the application in testable mode.
bool write(ChimeraTK::VersionNumber versionNumber)=delete
std::atomic< uint64_t > lastBar
TestTransferGroupDummy(const std::string &mapFileName)
static boost::shared_ptr< DeviceBackend > createInstance(std::string, std::map< std::string, std::string > parameters)
std::atomic< size_t > lastSizeInBytes
void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes) override
std::atomic< size_t > numberOfTransfers
std::atomic< uint64_t > lastAddress
InvalidityTracer application module.
BOOST_AUTO_TEST_CASE(TestDev2AppWithPollTrigger)
boost::mpl::list< int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, float, double > test_types
const std::string dummySdm
Convenience class for output scalar accessors (always UpdateMode::push)
Convenience class for output void (always UpdateMode::push)
ctk::ScalarPollInput< int > readBack
ctk::SetDMapFilePath path
ctk::ScalarPollInput< int > tests
ctk::SetDMapFilePath path
ctk::ScalarPushInput< int > readBack
ctk::ScalarOutput< int > tock
ctk::ScalarPollInput< int > tests
ctk::ScalarPushInput< int > readBack
ctk::SetDMapFilePath path
ctk::ScalarPushInput< float > singed32
ctk::SetDMapFilePath path
ctk::ScalarPushInput< int > readBack
ctk::ScalarPollInput< int > tests
ctk::SetDMapFilePath path
ctk::SetDMapFilePath dmap
std::atomic< bool > block
~TestApplication2() override
~TestApplication() override
boost::barrier mainLoopStarted
ctk::ScalarPushInput< int > consumingPush3
void prepare() override
Prepare the execution of the module.
ctk::ScalarPushInput< int > consumingPush2
ctk::ScalarPushInput< int > consumingPush
ctk::ScalarOutput< int > theTrigger
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
TestModule(ctk::ModuleGroup *owner, const std::string &name, const std::string &description, const std::unordered_set< std::string > &tags={})
#define CHECK_TIMEOUT(condition, maxMilliseconds)
ctk::ScalarOutput< uint64_t > tick