-
Martin Christoph Hierholzer authoredMartin Christoph Hierholzer authored
fixtures.h 4.66 KiB
#pragma once
#include <ChimeraTK/BackendFactory.h>
#include <ChimeraTK/Device.h>
#include <ChimeraTK/NDRegisterAccessor.h>
#include <ChimeraTK/ExceptionDummyBackend.h>
#include <ChimeraTK/DummyRegisterAccessor.h>
#include "Application.h"
#include "ApplicationModule.h"
#include "ControlSystemModule.h"
#include "DeviceModule.h"
#include "ScalarAccessor.h"
#include "TestFacility.h"
#include "check_timeout.h"
#include <future>
struct PollModule : ChimeraTK::ApplicationModule {
using ChimeraTK::ApplicationModule::ApplicationModule;
ChimeraTK::ScalarPollInput<int> pollInput{this, "REG1", "", "", {"DEVICE"}};
std::promise<void> p;
void mainLoop() override {
p.set_value();
}
};
struct PushModule : ChimeraTK::ApplicationModule {
using ChimeraTK::ApplicationModule::ApplicationModule;
struct : ChimeraTK::VariableGroup {
using ChimeraTK::VariableGroup::VariableGroup;
ChimeraTK::ScalarPushInput<int> pushInput{this, "PUSH_READ", "", ""};
} reg1{this, "REG1", ""};
std::promise<void> p;
void mainLoop() override {
p.set_value();
}
};
struct UpdateModule:ChimeraTK::ApplicationModule{
using ChimeraTK::ApplicationModule::ApplicationModule;
ChimeraTK::ScalarOutput<int> deviceRegister{this, "REG1", "", "", {"DEVICE"}};
std::promise<void> p;
void mainLoop() override {
p.set_value();
}
};
struct DummyApplication : ChimeraTK::Application {
constexpr static const char* ExceptionDummyCDD1 = "(ExceptionDummy:1?map=test.map)";
DummyApplication() : Application("DummyApplication") {}
~DummyApplication() { shutdown(); }
PushModule pushModule{this, "", ""};
PollModule pollModule{this, "", ""};
UpdateModule updateModule{this, "", ""};
ChimeraTK::ControlSystemModule cs;
ChimeraTK::DeviceModule device{this, ExceptionDummyCDD1};
void defineConnections() override {
findTag("CS").connectTo(cs);
findTag("DEVICE").connectTo(device);
auto push_input = device("REG1/PUSH_READ", typeid(int), 1, ChimeraTK::UpdateMode::push);
push_input >> pushModule.reg1.pushInput;
}
};
template<bool enableTestFacility>
struct fixture_with_poll_and_push_input {
fixture_with_poll_and_push_input()
: deviceBackend(boost::dynamic_pointer_cast<ChimeraTK::ExceptionDummy>(
ChimeraTK::BackendFactory::getInstance().createBackend(DummyApplication::ExceptionDummyCDD1))),
exceptionDummyRegister(deviceBackend->getRawAccessor("", "REG1")) {
deviceBackend->open();
testFacitiy.runApplication();
status.replace(testFacitiy.getScalar<int>(
ChimeraTK::RegisterPath("/Devices") / DummyApplication::ExceptionDummyCDD1 / "status"));
message.replace(testFacitiy.getScalar<std::string>(
ChimeraTK::RegisterPath("/Devices") / DummyApplication::ExceptionDummyCDD1 / "message"));
// wait until all modules have been properly started, to ensure the initial value propagation is complete
/************************************************************************************************/
application.pollModule.p.get_future().wait();
application.pushModule.p.get_future().wait();
application.updateModule.p.get_future().wait();
/************************************************************************************************/
}
~fixture_with_poll_and_push_input() {
deviceBackend->throwExceptionRead = false;
deviceBackend->throwExceptionWrite = false;
}
template<typename T>
auto read(ChimeraTK::DummyRegisterRawAccessor& accessor) {
auto lock = accessor.getBufferLock();
return static_cast<T>(accessor);
}
template<typename T>
auto read(ChimeraTK::DummyRegisterRawAccessor&& accessor) {
read<T>(accessor);
}
template<typename T>
void write(ChimeraTK::DummyRegisterRawAccessor& accessor, T value) {
auto lock = accessor.getBufferLock();
accessor = static_cast<int32_t>(value);
}
template<typename T>
void write(ChimeraTK::DummyRegisterRawAccessor&& accessor, T value) {
write(accessor, value);
}
bool isDeviceInError() {
// By definition, the DeviceModule has finished the recovery procedure when the status is 0 again.
status.readLatest();
return static_cast<int>(status);
}
boost::shared_ptr<ChimeraTK::ExceptionDummy> deviceBackend;
DummyApplication application;
ChimeraTK::TestFacility testFacitiy{enableTestFacility};
ChimeraTK::ScalarRegisterAccessor<int> status;
ChimeraTK::ScalarRegisterAccessor<std::string> message;
ChimeraTK::DummyRegisterRawAccessor exceptionDummyRegister;
ChimeraTK::ScalarPushInput<int>& pushVariable{application.pushModule.reg1.pushInput};
ChimeraTK::ScalarPollInput<int>& pollVariable{application.pollModule.pollInput};
ChimeraTK::ScalarOutput<int>& outputVariable{application.updateModule.deviceRegister};
};