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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#define BOOST_TEST_MODULE testExceptionHandling
#include <boost/test/included/unit_test.hpp>
#include "ScriptedInitialisationHandler.h"
#include "Application.h"
#include "DeviceModule.h"
#include "TestFacility.h"
#include "ControlSystemModule.h"
#include "check_timeout.h"
#include <filesystem>
#include <fstream>
using namespace ChimeraTK;
struct DMapSetter {
DMapSetter() { setDMapFilePath("test.dmap"); }
};
struct TestApp : public Application {
using Application::Application;
~TestApp() { shutdown(); }
ConnectingDeviceModule dev1{this, "Dummy0",
"/MyModule/actuator"}; // pick one of the writable variables to AC knows that data type for the trigger
// default name for the output variable (initScriptOutput)
ScriptedInitHandler initHandler1{
this, "InitHander1", "description", "./deviceInitScript1.bash", dev1.getDeviceModule()};
// change the name of the output variable in case a second script is needed. Shorten the error grace time to 1 second
ScriptedInitHandler initHandler2{this, "InitHander2", "description", "./deviceInitScript2.bash",
dev1.getDeviceModule(), "secondInitScriptOutput", 1};
};
struct Fixture {
DMapSetter dmapSetter;
TestApp testApp{"ScriptedInitApp"};
TestFacility testFacility{false};
};
BOOST_FIXTURE_TEST_CASE(testSuccess, Fixture) {
(void)std::filesystem::remove("device1Init.success");
(void)std::filesystem::remove("continueDevice1Init");
(void)std::filesystem::remove("produceDevice1InitError");
testFacility.runApplication();
//testApp.dumpConnections();
auto initMessage = testFacility.getScalar<std::string>("/Devices/Dummy0/initScriptOutput");
initMessage.read();
std::string referenceString; // currently emtpy
BOOST_CHECK_EQUAL(static_cast<std::string>(initMessage), referenceString);
initMessage.read();
referenceString += "starting device1 init\n";
BOOST_CHECK_EQUAL(static_cast<std::string>(initMessage), referenceString);
// no more messages, script waiting for continue file
BOOST_CHECK(initMessage.readLatest() == false);
// let the script finish
std::ofstream continueFile;
continueFile.open("continueDevice1Init", std::ios::out);
initMessage.read();
referenceString += "device1 init successful\n";
BOOST_CHECK_EQUAL(static_cast<std::string>(initMessage), referenceString);
initMessage.read();
referenceString += "Dummy0 initialisation SUCCESS!";
BOOST_CHECK_EQUAL(static_cast<std::string>(initMessage), referenceString);
BOOST_CHECK(std::filesystem::exists("device1Init.success"));
auto secondInitMessage = testFacility.getScalar<std::string>("/Devices/Dummy0/secondInitScriptOutput");
secondInitMessage.read(); // empty
secondInitMessage.read(); // script message
secondInitMessage.read(); // success message
BOOST_CHECK_EQUAL(
static_cast<std::string>(secondInitMessage), "just a second script\nDummy0 initialisation SUCCESS!");
// cleanup
(void)std::filesystem::remove("device1Init.success");
(void)std::filesystem::remove("continueDevice1Init");
}
BOOST_FIXTURE_TEST_CASE(testError, Fixture) {
std::ofstream produceErrorFile; // If the file exists, the script produces an error
produceErrorFile.open("produceDevice2InitError", std::ios::out);
// let script1 finish
std::ofstream continueFile;
continueFile.open("continueDevice1Init", std::ios::out);
testFacility.runApplication();
//testApp.dumpConnections();
auto secondInitMessage = testFacility.getScalar<std::string>("/Devices/Dummy0/secondInitScriptOutput");
// let the script run three times. Afterwards manually check that there is only one printout on the console
auto startTime = std::chrono::steady_clock::now();
for(int i = 0; i < 3; ++i) {
secondInitMessage.read();
std::string referenceString; // currently emtpy
BOOST_CHECK_EQUAL(static_cast<std::string>(secondInitMessage), referenceString);
secondInitMessage.read();
referenceString += "Simulating error in second script\n";
BOOST_CHECK_EQUAL(static_cast<std::string>(secondInitMessage), referenceString);
secondInitMessage.read();
referenceString += "!!! Dummy0 initialisation FAILED!";
BOOST_CHECK_EQUAL(static_cast<std::string>(secondInitMessage), referenceString);
}
(void)std::filesystem::remove("produceDevice2InitError");
// recovery
secondInitMessage.read(); // empty
secondInitMessage.read(); // script message
secondInitMessage.read(); // success message
BOOST_CHECK_EQUAL(
static_cast<std::string>(secondInitMessage), "just a second script\nDummy0 initialisation SUCCESS!");
// at least three failure grace periods
auto stopTime = std::chrono::steady_clock::now();
BOOST_CHECK(std::chrono::duration_cast<std::chrono::seconds>(stopTime - startTime).count() >= 3);
(void)std::filesystem::remove("device1Init.success");
(void)std::filesystem::remove("continueDevice1Init");
}
BOOST_AUTO_TEST_CASE(testBoostException) {
BOOST_CHECK(false);
std::filesystem::rename("deviceInitScript1.bash", "deviceInitScript1.bash.dontuse");
try {
DMapSetter dmapSetter;
TestApp testApp{"ScriptedInitApp"};
TestFacility testFacility{false};
testFacility.runApplication();
sleep(10);
}
catch(ChimeraTK::logic_error& e) {
std::cout << "I caught the exception!" << std::endl;
}
std::filesystem::rename("deviceInitScript1.bash.dontuse", "deviceInitScript1.bash");
}