ChimeraTK-ApplicationCore 04.07.01
Loading...
Searching...
No Matches
testVariableGroup.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#include "TestFacility.h"
4
5#include <chrono>
6#include <future>
7
8#define BOOST_TEST_MODULE testVariableGroup
9
10#include "Application.h"
11#include "ApplicationModule.h"
12#include "ScalarAccessor.h"
13#include "VariableGroup.h"
14
15#include <boost/mpl/list.hpp>
16#include <boost/test/included/unit_test.hpp>
17#include <boost/thread.hpp>
18
20
21 using namespace boost::unit_test_framework;
22 namespace ctk = ChimeraTK;
23
24 /********************************************************************************************************************/
25 /* the ApplicationModule for the test is a template of the user type */
26
28 using ctk::ApplicationModule::ApplicationModule;
29
31 using ctk::VariableGroup::VariableGroup;
32 ctk::ScalarPushInput<int> consumingPush{this, "feedingPush", "MV/m", "Description"};
33 ctk::ScalarPushInput<int> consumingPush2{this, "feedingPush2", "MV/m", "Description"};
34 ctk::ScalarPushInput<int> consumingPush3{this, "feedingPush3", "MV/m", "Description"};
35 ctk::ScalarPollInput<int> consumingPoll{this, "feedingPoll", "MV/m", "Description"};
36 ctk::ScalarPollInput<int> consumingPoll2{this, "feedingPoll2", "MV/m", "Description"};
37 ctk::ScalarPollInput<int> consumingPoll3{this, "feedingPoll3", "MV/m", "Description"};
38 } mixedGroup{this, ".", "A group with both push and poll inputs"};
39
40 void prepare() override {
41 incrementDataFaultCounter(); // force all outputs to invalid
42 writeAll();
43 decrementDataFaultCounter(); // validity according to input validity
44 }
45
46 void mainLoop() override {}
47 };
48
50 using ctk::ApplicationModule::ApplicationModule;
51
52 ctk::ScalarOutput<int> feedingPush{this, "feedingPush", "MV/m", "Description"};
53 ctk::ScalarOutput<int> feedingPush2{this, "feedingPush2", "MV/m", "Description"};
54 ctk::ScalarOutput<int> feedingPush3{this, "feedingPush3", "MV/m", "Description"};
55 ctk::ScalarOutput<int> feedingPoll{this, "feedingPoll", "MV/m", "Description"};
56 ctk::ScalarOutput<int> feedingPoll2{this, "feedingPoll2", "MV/m", "Description"};
57 ctk::ScalarOutput<int> feedingPoll3{this, "feedingPoll3", "MV/m", "Description"};
58
59 void prepare() override {
60 incrementDataFaultCounter(); // force all outputs to invalid
61 writeAll();
62 decrementDataFaultCounter(); // validity according to input validity
63 }
64
65 void mainLoop() override {}
66 };
67
68 /********************************************************************************************************************/
69 /* dummy application */
70
72 TestApplication() : Application("testSuite") {}
73 ~TestApplication() override { shutdown(); }
74
75 InputModule in{this, "out", "The test module"};
76 OutputModule out{this, "out", "The other test module"};
77 };
78
79 /********************************************************************************************************************/
80 /* test module-wide read/write operations */
81
82 BOOST_AUTO_TEST_CASE(testModuleReadWrite) {
83 std::cout << "**************************************************************************************************\n";
84 std::cout << "*** testModuleReadWrite" << std::endl;
85
87 ctk::TestFacility test(app);
88
89 test.runApplication();
90
91 // single threaded test
92 app.in.mixedGroup.consumingPush = 666;
93 app.in.mixedGroup.consumingPush2 = 666;
94 app.in.mixedGroup.consumingPush3 = 666;
95 app.in.mixedGroup.consumingPoll = 666;
96 app.in.mixedGroup.consumingPoll2 = 666;
97 app.in.mixedGroup.consumingPoll3 = 666;
98 app.out.feedingPush = 18;
99 app.out.feedingPush2 = 20;
100 app.out.feedingPush3 = 22;
101 app.out.feedingPoll = 23;
102 app.out.feedingPoll2 = 24;
103 app.out.feedingPoll3 = 27;
104 BOOST_CHECK(app.in.mixedGroup.consumingPush == 666);
105 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 666);
106 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 666);
107 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 666);
108 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 666);
109 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 666);
110 app.out.writeAll();
111 BOOST_CHECK(app.in.mixedGroup.consumingPush == 666);
112 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 666);
113 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 666);
114 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 666);
115 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 666);
116 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 666);
117 app.in.readAll();
118 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
119 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 20);
120 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
121 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
122 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 24);
123 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
124
126 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
127 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 20);
128 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
129 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
130 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 24);
131 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
132
133 app.out.feedingPush2 = 30;
134 app.out.feedingPoll2 = 33;
135 app.out.writeAll();
136 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
137 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 20);
138 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
139 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
140 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 24);
141 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
143 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
144 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
145 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
146 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
147 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
148 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
150 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
151 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
152 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
153 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
154 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
155 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
156
157 app.out.feedingPush = 35;
158 app.out.feedingPoll3 = 40;
159 app.out.writeAll();
160 app.out.feedingPush = 36;
161 app.out.feedingPoll3 = 44;
162 app.out.writeAll();
163 BOOST_CHECK(app.in.mixedGroup.consumingPush == 18);
164 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
165 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
166 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
167 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
168 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 27);
170 BOOST_CHECK(app.in.mixedGroup.consumingPush == 35);
171 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
172 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
173 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
174 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
175 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
177 BOOST_CHECK(app.in.mixedGroup.consumingPush == 36);
178 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
179 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
180 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
181 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
182 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
184 BOOST_CHECK(app.in.mixedGroup.consumingPush == 36);
185 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
186 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
187 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
188 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
189 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
190
191 app.out.feedingPush = 45;
192 app.out.writeAll();
193 app.out.feedingPush = 46;
194 app.out.writeAll();
195 BOOST_CHECK(app.in.mixedGroup.consumingPush == 36);
196 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
197 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
198 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
199 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
200 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
201 app.in.readAllLatest();
202 BOOST_CHECK(app.in.mixedGroup.consumingPush == 46);
203 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
204 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
205 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
206 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
207 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
208 app.in.readAllLatest();
209 BOOST_CHECK(app.in.mixedGroup.consumingPush == 46);
210 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 30);
211 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 22);
212 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 23);
213 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 33);
214 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 44);
215 }
216
217 /********************************************************************************************************************/
218 /* test trigger by app variable when connecting a polled device register to an app variable */
219
220 BOOST_AUTO_TEST_CASE(testReadAny) {
221 std::cout << "**************************************************************************************************\n";
222 std::cout << "==> testReadAny" << std::endl;
223
224 TestApplication app;
225 ctk::TestFacility test(app);
226
227 test.runApplication();
228
229 auto group = app.in.mixedGroup.readAnyGroup();
230
231 // single threaded test
232 app.out.feedingPush = 0;
233 app.out.feedingPush2 = 42;
234 app.out.feedingPush3 = 120;
235 app.out.feedingPoll = 10;
236 app.out.feedingPoll2 = 11;
237 app.out.feedingPoll3 = 12;
238 app.out.feedingPoll.write();
239 app.out.feedingPoll2.write();
240 app.out.feedingPoll3.write();
241
242 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
243 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 0);
244 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 0);
245 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 0);
246 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 0);
247 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 0);
248
249 // test a single write
250 app.out.feedingPush2.write();
251 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
252 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 0);
253 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 0);
254 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 0);
255 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 0);
256 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 0);
257 auto id = group.readAny();
258 BOOST_CHECK(id == app.in.mixedGroup.consumingPush2.getId());
259 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
260 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 42);
261 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 0);
262 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 10);
263 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 11);
264 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 12);
265
266 // two more writes
267 app.out.feedingPush2 = 666;
268 app.out.feedingPush2.write();
269 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
270 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 42);
271 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 0);
272 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 10);
273 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 11);
274 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 12);
275 id = group.readAny();
276 BOOST_CHECK(id == app.in.mixedGroup.consumingPush2.getId());
277 app.out.feedingPush3.write();
278 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
279 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 666);
280 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 0);
281 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 10);
282 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 11);
283 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 12);
284 id = group.readAny();
285 BOOST_CHECK(id == app.in.mixedGroup.consumingPush3.getId());
286 BOOST_CHECK(app.in.mixedGroup.consumingPush == 0);
287 BOOST_CHECK(app.in.mixedGroup.consumingPush2 == 666);
288 BOOST_CHECK(app.in.mixedGroup.consumingPush3 == 120);
289 BOOST_CHECK(app.in.mixedGroup.consumingPoll == 10);
290 BOOST_CHECK(app.in.mixedGroup.consumingPoll2 == 11);
291 BOOST_CHECK(app.in.mixedGroup.consumingPoll3 == 12);
292 }
293
294} // namespace Tests::testVariableGroup
void shutdown() override
This will remove the global pointer to the instance and allows creating another instance afterwards.
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.
friend class Application
Definition ModuleGroup.h:47
void readAllLatest(bool includeReturnChannels=false)
Just call readLatest() on all readable variables in the group.
Definition Module.cc:138
void readAll(bool includeReturnChannels=false)
Read all readable variables in the group.
Definition Module.cc:72
void readAllNonBlocking(bool includeReturnChannels=false)
Just call readNonBlocking() on all readable variables in the group.
Definition Module.cc:106
ChimeraTK::ReadAnyGroup readAnyGroup()
Create a ChimeraTK::ReadAnyGroup for all readable variables in this Module.
Definition Module.cc:54
void writeAll(bool includeReturnChannels=false)
Just call write() on all writable variables in the group.
Definition Module.cc:157
bool write(ChimeraTK::VersionNumber versionNumber)=delete
Convenience class for output scalar accessors (always UpdateMode::push)
Convenience class for input scalar accessors with UpdateMode::poll.
Convenience class for input scalar accessors with UpdateMode::push.
Helper class to facilitate tests of applications based on ApplicationCore.
void runApplication() const
Start the application in testable mode.
InvalidityTracer application module.
BOOST_AUTO_TEST_CASE(testModuleReadWrite)
void prepare() override
Prepare the execution of the module.
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...
void prepare() override
Prepare the execution of the module.
void mainLoop() override
To be implemented by the user: function called in a separate thread executing the main loop of the mo...