ChimeraTK-DeviceAccess-DoocsBackend  01.09.02
testDoocsBackend.cpp
Go to the documentation of this file.
1 /*
2  * testDoocsBackend.cpp
3  *
4  * Created on: Apr 27, 2016
5  * Author: Martin Hierholzer
6  */
7 #define BOOST_TEST_MODULE testDoocsBackend
8 
9 #include "eq_dummy.h"
10 #include <doocs-server-test-helper/doocsServerTestHelper.h>
11 #include <doocs-server-test-helper/ThreadedDoocsServer.h>
12 #include <doocs/EqCall.h>
13 
14 #include <ChimeraTK/Device.h>
15 #include <ChimeraTK/MappedImage.h>
16 #include <ChimeraTK/TransferGroup.h>
17 
18 #include <boost/filesystem.hpp>
19 #include <boost/test/included/unit_test.hpp>
20 
21 #include <cstdlib>
22 #include <fstream>
23 #include <iostream>
24 #include <random>
25 #include <thread>
26 #include <unistd.h>
27 
28 using namespace boost::unit_test_framework;
29 using namespace ChimeraTK;
30 
31 /**********************************************************************************************************************/
32 
33 static bool file_exists(const std::string& name);
34 static void createCacheFileFromCdd(const std::string& cdd);
35 static void deleteFile(const std::string& filename);
36 
37 class DoocsLauncher : public ThreadedDoocsServer {
38  public:
40  : ThreadedDoocsServer("testDoocsBackend.conf", boost::unit_test::framework::master_test_suite().argc,
41  boost::unit_test::framework::master_test_suite().argv, eq_dummy::createServer()) {
42  rpc_no = rpcNo();
43 
44  // use different cache files for each run to avoid conflicts (RPC numbers are protected by lock)
45  cacheFile1 = "cache1_" + rpc_no + ".xml";
46  cacheFile2 = "cache2_" + rpc_no + ".xml";
47 
48  // set CDDs for the two doocs addresses used in the test
49  DoocsServer1 = "(doocs:doocs://localhost:" + rpcNo() + "/F/D)";
50  DoocsServer1_cached = "(doocs:doocs://localhost:" + rpcNo() + "/F/D?cacheFile=" + cacheFile1 + "&updateCache=1)";
51  DoocsServer2 = "(doocs:doocs://localhost:" + rpcNo() + "/F/D/MYDUMMY)";
52  DoocsServer2_cached =
53  "(doocs:doocs://localhost:" + rpcNo() + "/F/D/MYDUMMY?cacheFile=" + cacheFile2 + "&updateCache=1)";
54 
55  // wait until server has started (both the update thread and the rpc thread)
56  doocs::EqCall eq;
57  doocs::EqAdr ea;
58  doocs::EqData src, dst;
59  ea.adr("doocs://localhost:" + rpcNo() + "/F/D/MYDUMMY/SOME_ZMQINT");
60  while(eq.get(&ea, &src, &dst)) usleep(100000);
61  }
62 
63  ~DoocsLauncher() override {
64  boost::filesystem::remove(cacheFile1);
65  boost::filesystem::remove(cacheFile2);
66  }
67 
68  static std::string rpc_no;
69  static std::string DoocsServer1;
70  static std::string DoocsServer1_cached;
71  static std::string cacheFile1;
72 
73  static std::string DoocsServer2;
74  static std::string DoocsServer2_cached;
75  static std::string cacheFile2;
76 };
77 
78 std::string DoocsLauncher::rpc_no;
79 std::string DoocsLauncher::DoocsServer1;
81 std::string DoocsLauncher::DoocsServer2;
83 std::string DoocsLauncher::cacheFile1;
84 std::string DoocsLauncher::cacheFile2;
85 
87 
88 /**********************************************************************************************************************/
89 
90 BOOST_AUTO_TEST_CASE(testScalarInt) {
91  ChimeraTK::Device device;
92 
93  BOOST_TEST(device.isOpened() == false);
94  device.open(DoocsLauncher::DoocsServer1);
95  BOOST_TEST(device.isOpened() == true);
96 
97  TwoDRegisterAccessor<int32_t> acc_someInt_as_int(device.getTwoDRegisterAccessor<int32_t>("MYDUMMY/SOME_INT"));
98  BOOST_TEST(acc_someInt_as_int.getVersionNumber() == VersionNumber{nullptr});
99 
100  BOOST_TEST(acc_someInt_as_int.getNChannels() == 1);
101  BOOST_TEST(acc_someInt_as_int.getNElementsPerChannel() == 1);
102  acc_someInt_as_int.read();
103  BOOST_TEST(acc_someInt_as_int[0][0] == 42);
104 
105  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 120);
106 
107  BOOST_TEST(acc_someInt_as_int[0][0] == 42);
108  // auto oldVersion = acc_someInt_as_int.getVersionNumber();
109  acc_someInt_as_int.read();
110  BOOST_TEST(acc_someInt_as_int[0][0] == 120);
111  // BOOST_TEST(acc_someInt_as_int.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0 for
112  // properties set through RPC call
113 
114  acc_someInt_as_int[0][0] = 1234;
115  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 120);
116  VersionNumber nextVersion;
117  acc_someInt_as_int.write(nextVersion);
118  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 1234);
119  BOOST_TEST(acc_someInt_as_int.getVersionNumber() == nextVersion);
120 
121  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 42);
122 
123  TwoDRegisterAccessor<double> acc_someInt_as_double(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_INT"));
124  BOOST_TEST(acc_someInt_as_double.getNChannels() == 1);
125  BOOST_TEST(acc_someInt_as_double.getNElementsPerChannel() == 1);
126  acc_someInt_as_double.read();
127  BOOST_CHECK_CLOSE(acc_someInt_as_double[0][0], 42, 0.001);
128 
129  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 120);
130 
131  BOOST_CHECK_CLOSE(acc_someInt_as_double[0][0], 42, 0.001);
132  acc_someInt_as_double.read();
133  BOOST_CHECK_CLOSE(acc_someInt_as_double[0][0], 120, 0.001);
134 
135  acc_someInt_as_double[0][0] = 1234.3;
136  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 120);
137  acc_someInt_as_double.write();
138  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 1234);
139 
140  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 42);
141 
142  TwoDRegisterAccessor<float> acc_someInt_as_float(device.getTwoDRegisterAccessor<float>("MYDUMMY/SOME_INT"));
143  BOOST_TEST(acc_someInt_as_float.getNChannels() == 1);
144  BOOST_TEST(acc_someInt_as_float.getNElementsPerChannel() == 1);
145  acc_someInt_as_float.read();
146  BOOST_CHECK_CLOSE(acc_someInt_as_float[0][0], 42, 0.001);
147 
148  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 120);
149 
150  BOOST_CHECK_CLOSE(acc_someInt_as_float[0][0], 42, 0.001);
151  acc_someInt_as_float.read();
152  BOOST_CHECK_CLOSE(acc_someInt_as_float[0][0], 120, 0.001);
153 
154  acc_someInt_as_float[0][0] = 1233.9;
155  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 120);
156  acc_someInt_as_float.write();
157  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 1234);
158 
159  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 42);
160 
161  TwoDRegisterAccessor<std::string> acc_someInt_as_string(
162  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_INT"));
163  BOOST_TEST(acc_someInt_as_string.getNChannels() == 1);
164  BOOST_TEST(acc_someInt_as_string.getNElementsPerChannel() == 1);
165  acc_someInt_as_string.read();
166  BOOST_TEST(acc_someInt_as_string[0][0] == "42");
167 
168  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 120);
169 
170  BOOST_TEST(acc_someInt_as_string[0][0] == "42");
171  acc_someInt_as_string.read();
172  BOOST_TEST(acc_someInt_as_string[0][0] == "120");
173 
174  acc_someInt_as_string[0][0] = "1234";
175  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 120);
176  acc_someInt_as_string.write();
177  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 1234);
178 
179  device.close();
180  BOOST_TEST(device.isOpened() == false);
181 }
182 
183 /**********************************************************************************************************************/
184 
185 BOOST_AUTO_TEST_CASE(testScalarFloat) {
186  ChimeraTK::Device device;
187  device.open(DoocsLauncher::DoocsServer1);
188 
189  TwoDRegisterAccessor<float> acc_someFloat_as_float(device.getTwoDRegisterAccessor<float>("MYDUMMY/SOME_FLOAT"));
190  BOOST_TEST(acc_someFloat_as_float.getNChannels() == 1);
191  BOOST_TEST(acc_someFloat_as_float.getNElementsPerChannel() == 1);
192  acc_someFloat_as_float.read();
193  BOOST_CHECK_CLOSE(acc_someFloat_as_float[0][0], 3.1415, 0.00001);
194 
195  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 123.456);
196 
197  BOOST_CHECK_CLOSE(acc_someFloat_as_float[0][0], 3.1415, 0.00001);
198  // auto oldVersion = acc_someFloat_as_float.getVersionNumber();
199  acc_someFloat_as_float.read();
200  BOOST_CHECK_CLOSE(acc_someFloat_as_float[0][0], 123.456, 0.00001);
201  // BOOST_TEST(acc_someFloat_as_float.getVersionNumber() == oldVersion);// DOOCS behaves differently, eventId == 0 for
202  // properties set through RPC call
203 
204  acc_someFloat_as_float[0][0] = 666.333;
205  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 123.456, 0.00001);
206  VersionNumber nextVersion;
207  acc_someFloat_as_float.write(nextVersion);
208  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 666.333, 0.00001);
209  BOOST_TEST(acc_someFloat_as_float.getVersionNumber() == nextVersion);
210 
211  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 3.1415);
212 
213  TwoDRegisterAccessor<double> acc_someFloat_as_double(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_FLOAT"));
214  BOOST_TEST(acc_someFloat_as_double.getNChannels() == 1);
215  BOOST_TEST(acc_someFloat_as_double.getNElementsPerChannel() == 1);
216  acc_someFloat_as_double.read();
217  BOOST_CHECK_CLOSE(acc_someFloat_as_double[0][0], 3.1415, 0.00001);
218 
219  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 123.456);
220 
221  BOOST_CHECK_CLOSE(acc_someFloat_as_double[0][0], 3.1415, 0.00001);
222  acc_someFloat_as_double.read();
223  BOOST_CHECK_CLOSE(acc_someFloat_as_double[0][0], 123.456, 0.00001);
224 
225  acc_someFloat_as_double[0][0] = 1234.3;
226  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 123.456, 0.00001);
227  acc_someFloat_as_double.write();
228  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 1234.3, 0.00001);
229 
230  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 3.1415);
231 
232  TwoDRegisterAccessor<int> acc_someFloat_as_int(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_FLOAT"));
233  BOOST_TEST(acc_someFloat_as_int.getNChannels() == 1);
234  BOOST_TEST(acc_someFloat_as_int.getNElementsPerChannel() == 1);
235  acc_someFloat_as_int.read();
236  BOOST_TEST(acc_someFloat_as_int[0][0] == 3);
237 
238  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 119.9);
239 
240  BOOST_TEST(acc_someFloat_as_int[0][0] == 3);
241  acc_someFloat_as_int.read();
242  BOOST_TEST(acc_someFloat_as_int[0][0] == 120);
243 
244  acc_someFloat_as_int[0][0] = 1234;
245  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 119.9, 0.00001);
246  acc_someFloat_as_int.write();
247  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 1234.0, 0.00001);
248 
249  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 3.1415);
250 
251  TwoDRegisterAccessor<std::string> acc_someFloat_as_string(
252  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_FLOAT"));
253  BOOST_TEST(acc_someFloat_as_string.getNChannels() == 1);
254  BOOST_TEST(acc_someFloat_as_string.getNElementsPerChannel() == 1);
255  acc_someFloat_as_string.read();
256  BOOST_CHECK_CLOSE(std::stod(acc_someFloat_as_string[0][0]), 3.1415, 0.00001);
257 
258  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 120);
259 
260  BOOST_CHECK_CLOSE(std::stod(acc_someFloat_as_string[0][0]), 3.1415, 0.00001);
261  acc_someFloat_as_string.read();
262  BOOST_TEST(acc_someFloat_as_string[0][0] == "120.000000");
263 
264  acc_someFloat_as_string[0][0] = "1234.5678";
265  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 120, 0.00001);
266  acc_someFloat_as_string.write();
267  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 1234.5678, 0.00001);
268 
269  device.close();
270 }
271 
272 /**********************************************************************************************************************/
273 
274 BOOST_AUTO_TEST_CASE(testScalarDouble) {
275  ChimeraTK::Device device;
276  device.open(DoocsLauncher::DoocsServer1);
277 
278  TwoDRegisterAccessor<float> acc_someDouble_as_float(device.getTwoDRegisterAccessor<float>("MYDUMMY/SOME_DOUBLE"));
279  BOOST_TEST(acc_someDouble_as_float.getNChannels() == 1);
280  BOOST_TEST(acc_someDouble_as_float.getNElementsPerChannel() == 1);
281  acc_someDouble_as_float.read();
282  BOOST_CHECK_CLOSE(acc_someDouble_as_float[0][0], 2.8, 0.00001);
283 
284  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_DOUBLE", 123.456);
285 
286  BOOST_CHECK_CLOSE(acc_someDouble_as_float[0][0], 2.8, 0.00001);
287  // auto oldVersion = acc_someDouble_as_float.getVersionNumber();
288  acc_someDouble_as_float.read();
289  BOOST_CHECK_CLOSE(acc_someDouble_as_float[0][0], 123.456, 0.00001);
290  // BOOST_TEST(acc_someDouble_as_float.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0
291  // for properties set through RPC call
292 
293  acc_someDouble_as_float[0][0] = 666.333;
294  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_DOUBLE"), 123.456, 0.00001);
295  VersionNumber nextVersion;
296  acc_someDouble_as_float.write(nextVersion);
297  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_DOUBLE"), 666.333, 0.00001);
298  BOOST_TEST(acc_someDouble_as_float.getVersionNumber() == nextVersion);
299 
300  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_DOUBLE", 3.1415);
301 
302  TwoDRegisterAccessor<double> acc_someDouble_as_double(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_DOUBLE"));
303  BOOST_TEST(acc_someDouble_as_double.getNChannels() == 1);
304  BOOST_TEST(acc_someDouble_as_double.getNElementsPerChannel() == 1);
305  acc_someDouble_as_double.read();
306  BOOST_CHECK_CLOSE(acc_someDouble_as_double[0][0], 3.1415, 0.00001);
307 
308  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_DOUBLE", 123.456);
309 
310  BOOST_CHECK_CLOSE(acc_someDouble_as_double[0][0], 3.1415, 0.00001);
311  acc_someDouble_as_double.read();
312  BOOST_CHECK_CLOSE(acc_someDouble_as_double[0][0], 123.456, 0.00001);
313 
314  acc_someDouble_as_double[0][0] = 1234.3;
315  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_DOUBLE"), 123.456, 0.00001);
316  acc_someDouble_as_double.write();
317  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_DOUBLE"), 1234.3, 0.00001);
318 
319  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 3.1415);
320 
321  TwoDRegisterAccessor<int> acc_someDouble_as_int(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_FLOAT"));
322  BOOST_TEST(acc_someDouble_as_int.getNChannels() == 1);
323  BOOST_TEST(acc_someDouble_as_int.getNElementsPerChannel() == 1);
324  acc_someDouble_as_int.read();
325  BOOST_TEST(acc_someDouble_as_int[0][0] == 3);
326 
327  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 119.9);
328 
329  BOOST_TEST(acc_someDouble_as_int[0][0] == 3);
330  acc_someDouble_as_int.read();
331  BOOST_TEST(acc_someDouble_as_int[0][0] == 120);
332 
333  acc_someDouble_as_int[0][0] = 1234;
334  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 119.9, 0.00001);
335  acc_someDouble_as_int.write();
336  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 1234.0, 0.00001);
337 
338  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 3.1415);
339 
340  TwoDRegisterAccessor<std::string> acc_someDouble_as_string(
341  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_FLOAT"));
342  BOOST_TEST(acc_someDouble_as_string.getNChannels() == 1);
343  BOOST_TEST(acc_someDouble_as_string.getNElementsPerChannel() == 1);
344  acc_someDouble_as_string.read();
345  BOOST_CHECK_CLOSE(std::stod(acc_someDouble_as_string[0][0]), 3.1415, 0.00001);
346 
347  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT", 120);
348 
349  BOOST_CHECK_CLOSE(std::stod(acc_someDouble_as_string[0][0]), 3.1415, 0.00001);
350  acc_someDouble_as_string.read();
351  BOOST_TEST(acc_someDouble_as_string[0][0] == "120.000000");
352 
353  acc_someDouble_as_string[0][0] = "1234.5678";
354  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 120, 0.00001);
355  acc_someDouble_as_string.write();
356  BOOST_CHECK_CLOSE(DoocsServerTestHelper::doocsGet<float>("//MYDUMMY/SOME_FLOAT"), 1234.5678, 0.00001);
357 
358  device.close();
359 }
360 
361 /**********************************************************************************************************************/
362 
363 BOOST_AUTO_TEST_CASE(testString) {
364  ChimeraTK::Device device;
365  device.open(DoocsLauncher::DoocsServer1);
366 
367  TwoDRegisterAccessor<std::string> acc_someString(device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_STRING"));
368  BOOST_TEST(acc_someString.getNChannels() == 1);
369  BOOST_TEST(acc_someString.getNElementsPerChannel() == 1);
370  auto oldVersion = acc_someString.getVersionNumber();
371  acc_someString.read();
372  BOOST_TEST(acc_someString[0][0] == "The quick brown fox jumps over the lazy dog.");
373  BOOST_TEST(acc_someString.getVersionNumber() != oldVersion);
374 
375  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_STRING", "Something else.");
376 
377  BOOST_TEST(acc_someString[0][0] == "The quick brown fox jumps over the lazy dog.");
378  acc_someString.read();
379  BOOST_TEST(acc_someString[0][0] == "Something else.");
380 
381  acc_someString[0][0] = "Even different!";
382  BOOST_TEST(DoocsServerTestHelper::doocsGet<std::string>("//MYDUMMY/SOME_STRING") == "Something else.");
383  VersionNumber nextVersion;
384  acc_someString.write(nextVersion);
385  BOOST_TEST(DoocsServerTestHelper::doocsGet<std::string>("//MYDUMMY/SOME_STRING") == "Even different!");
386  BOOST_TEST(acc_someString.getVersionNumber() == nextVersion);
387 
388  device.close();
389 }
390 
391 /**********************************************************************************************************************/
392 
393 BOOST_AUTO_TEST_CASE(testArrayInt) {
394  ChimeraTK::Device device;
395  device.open(DoocsLauncher::DoocsServer1);
396 
397  TwoDRegisterAccessor<int> acc_someArray(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_INT_ARRAY"));
398  BOOST_TEST(acc_someArray.getNChannels() == 1);
399  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 42);
400  acc_someArray.read();
401  for(int i = 0; i < 42; i++) BOOST_TEST(acc_someArray[0][i] == 3 * i + 120);
402 
403  std::vector<int> vals(42);
404  for(int i = 0; i < 42; i++) vals[i] = -55 * i;
405  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT_ARRAY", vals);
406 
407  for(int i = 0; i < 42; i++) BOOST_TEST(acc_someArray[0][i] == 3 * i + 120);
408  // auto oldVersion = acc_someArray.getVersionNumber();
409  acc_someArray.read();
410  for(int i = 0; i < 42; i++) BOOST_TEST(acc_someArray[0][i] == -55 * i);
411  // BOOST_TEST(acc_someArray.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0 for
412  // properties set through RPC call
413 
414  for(int i = 0; i < 42; i++) acc_someArray[0][i] = i - 21;
415  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
416  for(int i = 0; i < 42; i++) BOOST_TEST(vals[i] == -55 * i);
417  VersionNumber nextVersion;
418  acc_someArray.write(nextVersion);
419  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
420  for(int i = 0; i < 42; i++) BOOST_TEST(vals[i] == i - 21);
421  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
422 
423  // access via double
424  TwoDRegisterAccessor<double> acc_someArrayAsDouble(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_INT_ARRAY"));
425  acc_someArrayAsDouble.read();
426  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArrayAsDouble[0][i], i - 21, 0.00001);
427  for(int i = 0; i < 5; i++) acc_someArrayAsDouble[0][i] = 2.4 * i;
428  acc_someArrayAsDouble.write();
429  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
430  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], round(2.4 * i), 0.00001);
431 
432  // access via string
433  TwoDRegisterAccessor<std::string> acc_someArrayAsString(
434  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_INT_ARRAY"));
435  acc_someArrayAsString.read();
436  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(std::stod(acc_someArrayAsString[0][i]), round(2.4 * i), 0.00001);
437  for(int i = 0; i < 5; i++) acc_someArrayAsString[0][i] = std::to_string(3 * i);
438  acc_someArrayAsString.write();
439  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
440  for(int i = 0; i < 5; i++) BOOST_TEST(vals[i] == 3 * i);
441 
442  device.close();
443 }
444 
445 /**********************************************************************************************************************/
446 
447 BOOST_AUTO_TEST_CASE(testArrayShort) {
448  ChimeraTK::Device device;
449  device.open(DoocsLauncher::DoocsServer1);
450 
451  TwoDRegisterAccessor<int> acc_someArray(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_SHORT_ARRAY"));
452  BOOST_TEST(acc_someArray.getNChannels() == 1);
453  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 5);
454  acc_someArray.read();
455  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
456 
457  std::vector<short> vals(5);
458  for(int i = 0; i < 5; i++) vals[i] = -55 * i;
459  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_SHORT_ARRAY", vals);
460 
461  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
462  // auto oldVersion = acc_someArray.getVersionNumber();
463  acc_someArray.read();
464  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == -55 * i);
465  // BOOST_TEST(acc_someArray.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0 for
466  // properties set through RPC call
467 
468  std::vector<int> vals2(5);
469  for(int i = 0; i < 5; i++) acc_someArray[0][i] = i - 21;
470  vals2 = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_SHORT_ARRAY");
471  for(int i = 0; i < 5; i++) BOOST_TEST(vals2[i] == -55 * i);
472  VersionNumber nextVersion;
473  acc_someArray.write(nextVersion);
474  vals2 = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_SHORT_ARRAY");
475  for(int i = 0; i < 5; i++) BOOST_TEST(vals2[i] == i - 21);
476  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
477 
478  device.close();
479 }
480 
481 /**********************************************************************************************************************/
482 
483 BOOST_AUTO_TEST_CASE(testArrayLong) {
484  ChimeraTK::Device device;
485  device.open(DoocsLauncher::DoocsServer1);
486 
487  TwoDRegisterAccessor<int> acc_someArray(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_LONG_ARRAY"));
488  BOOST_TEST(acc_someArray.getNChannels() == 1);
489  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 5);
490  acc_someArray.read();
491  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
492 
493  std::vector<int64_t> vals(5);
494  for(int i = 0; i < 5; i++) vals[i] = -55 * i;
495  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_LONG_ARRAY", vals);
496 
497  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
498  // auto oldVersion = acc_someArray.getVersionNumber();
499  acc_someArray.read();
500  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArray[0][i] == -55 * i);
501  // BOOST_TEST(acc_someArray.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0 for
502  // properties set through RPC call
503 
504  std::vector<int> vals2(5);
505  for(int i = 0; i < 5; i++) acc_someArray[0][i] = i - 21;
506  vals2 = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_LONG_ARRAY");
507  for(int i = 0; i < 5; i++) BOOST_TEST(vals2[i] == -55 * i);
508  VersionNumber nextVersion;
509  acc_someArray.write(nextVersion);
510  vals2 = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_LONG_ARRAY");
511  for(int i = 0; i < 5; i++) BOOST_TEST(vals2[i] == i - 21);
512  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
513 
514  device.close();
515 }
516 
517 /**********************************************************************************************************************/
518 
519 BOOST_AUTO_TEST_CASE(testArrayFloat) {
520  ChimeraTK::Device device;
521  device.open(DoocsLauncher::DoocsServer1);
522 
523  TwoDRegisterAccessor<float> acc_someArray(device.getTwoDRegisterAccessor<float>("MYDUMMY/SOME_FLOAT_ARRAY"));
524  BOOST_TEST(acc_someArray.getNChannels() == 1);
525  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 5);
526  auto oldVersion = acc_someArray.getVersionNumber();
527  acc_someArray.read();
528  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], i / 1000., 0.00001);
529  BOOST_TEST(acc_someArray.getVersionNumber() != oldVersion);
530 
531  std::vector<float> vals(5);
532  for(int i = 0; i < 5; i++) vals[i] = -3.14159265 * i;
533  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT_ARRAY", vals);
534 
535  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], i / 1000., 0.00001);
536  acc_someArray.read();
537  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], -3.14159265 * i, 0.00001);
538 
539  for(int i = 0; i < 5; i++) acc_someArray[0][i] = 2. / (i + 0.01);
540  vals = DoocsServerTestHelper::doocsGetArray<float>("//MYDUMMY/SOME_FLOAT_ARRAY");
541  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], -3.14159265 * i, 0.00001);
542  VersionNumber nextVersion;
543  acc_someArray.write(nextVersion);
544  vals = DoocsServerTestHelper::doocsGetArray<float>("//MYDUMMY/SOME_FLOAT_ARRAY");
545  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], 2. / (i + 0.01), 0.00001);
546  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
547 
548  device.close();
549 }
550 
551 /**********************************************************************************************************************/
552 
553 BOOST_AUTO_TEST_CASE(testArrayDouble) {
554  ChimeraTK::Device device;
555  device.open(DoocsLauncher::DoocsServer1);
556 
557  TwoDRegisterAccessor<double> acc_someArray(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_DOUBLE_ARRAY"));
558  BOOST_TEST(acc_someArray.getNChannels() == 1);
559  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 5);
560  auto oldVersion = acc_someArray.getVersionNumber();
561  acc_someArray.read();
562  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], i / 333., 0.00001);
563  BOOST_TEST(acc_someArray.getVersionNumber() != oldVersion);
564 
565  std::vector<double> vals(5);
566  for(int i = 0; i < 5; i++) vals[i] = -3.14159265 * i;
567  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_DOUBLE_ARRAY", vals);
568 
569  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], i / 333., 0.00001);
570  acc_someArray.read();
571  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], -3.14159265 * i, 0.00001);
572 
573  for(int i = 0; i < 5; i++) acc_someArray[0][i] = 2. / (i + 0.01);
574  vals = DoocsServerTestHelper::doocsGetArray<double>("//MYDUMMY/SOME_DOUBLE_ARRAY");
575  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], -3.14159265 * i, 0.00001);
576  VersionNumber nextVersion;
577  acc_someArray.write(nextVersion);
578  vals = DoocsServerTestHelper::doocsGetArray<double>("//MYDUMMY/SOME_DOUBLE_ARRAY");
579  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], 2. / (i + 0.01), 0.00001);
580  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
581 
582  // access via int
583  TwoDRegisterAccessor<int> acc_someArrayAsInt(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_DOUBLE_ARRAY"));
584  acc_someArrayAsInt.read();
585  for(int i = 0; i < 5; i++) BOOST_TEST(acc_someArrayAsInt[0][i] == round(2. / (i + 0.01)));
586  for(int i = 0; i < 5; i++) acc_someArrayAsInt[0][i] = 2 * i;
587  acc_someArrayAsInt.write();
588  vals = DoocsServerTestHelper::doocsGetArray<double>("//MYDUMMY/SOME_DOUBLE_ARRAY");
589  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], 2 * i, 0.00001);
590 
591  // access via string
592  TwoDRegisterAccessor<std::string> acc_someArrayAsString(
593  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_DOUBLE_ARRAY"));
594  acc_someArrayAsString.read();
595  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(std::stod(acc_someArrayAsString[0][i]), 2 * i, 0.00001);
596  for(int i = 0; i < 5; i++) acc_someArrayAsString[0][i] = std::to_string(2.1 * i);
597  acc_someArrayAsString.write();
598  vals = DoocsServerTestHelper::doocsGetArray<double>("//MYDUMMY/SOME_DOUBLE_ARRAY");
599  for(int i = 0; i < 5; i++) BOOST_CHECK_CLOSE(vals[i], 2.1 * i, 0.00001);
600 
601  device.close();
602 }
603 
604 /**********************************************************************************************************************/
605 
606 BOOST_AUTO_TEST_CASE(testSpectrum) {
607  ChimeraTK::Device device;
608  device.open(DoocsLauncher::DoocsServer1);
609 
610  TwoDRegisterAccessor<float> acc_someArray(device.getTwoDRegisterAccessor<float>("MYDUMMY/SOME_SPECTRUM"));
611  BOOST_TEST(acc_someArray.getNChannels() == 1);
612  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 100);
613  auto oldVersion = acc_someArray.getVersionNumber();
614  acc_someArray.read();
615  for(int i = 0; i < 100; i++) BOOST_CHECK_CLOSE(acc_someArray[0][i], i / 42., 0.00001);
616  BOOST_TEST(acc_someArray.getVersionNumber() != oldVersion);
617 
618  device.close();
619 }
620 
621 /**********************************************************************************************************************/
622 
624  ChimeraTK::Device device;
625  device.open(DoocsLauncher::DoocsServer1);
626 
627  TwoDRegisterAccessor<int> acc_someArray(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_IIII"));
628  BOOST_TEST(acc_someArray.getNChannels() == 1);
629  BOOST_TEST(acc_someArray.getNElementsPerChannel() == 4);
630  acc_someArray.read();
631  for(int i = 0; i < 4; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
632 
633  std::vector<int> vals(4);
634  for(int i = 0; i < 4; i++) vals[i] = -55 * i;
635  DoocsServerTestHelper::doocsSetIIII("//MYDUMMY/SOME_IIII", vals);
636 
637  for(int i = 0; i < 4; i++) BOOST_TEST(acc_someArray[0][i] == 10 + i);
638  // auto oldVersion = acc_someArray.getVersionNumber();
639  acc_someArray.read();
640  for(int i = 0; i < 4; i++) BOOST_TEST(acc_someArray[0][i] == -55 * i);
641  // BOOST_TEST(acc_someArray.getVersionNumber() == oldVersion); // DOOCS behaves differently, eventId == 0 for
642  // properties set through RPC call
643 
644  for(int i = 0; i < 4; i++) acc_someArray[0][i] = i - 21;
645  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_IIII");
646  for(int i = 0; i < 4; i++) BOOST_TEST(vals[i] == -55 * i);
647  VersionNumber nextVersion;
648  acc_someArray.write(nextVersion);
649  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_IIII");
650  for(int i = 0; i < 4; i++) BOOST_TEST(vals[i] == i - 21);
651  BOOST_TEST(acc_someArray.getVersionNumber() == nextVersion);
652 
653  // access via double
654  TwoDRegisterAccessor<double> acc_someArrayAsDouble(device.getTwoDRegisterAccessor<double>("MYDUMMY/SOME_IIII"));
655  acc_someArrayAsDouble.read();
656  for(int i = 0; i < 4; i++) BOOST_CHECK_CLOSE(acc_someArrayAsDouble[0][i], i - 21, 0.00001);
657  for(int i = 0; i < 4; i++) acc_someArrayAsDouble[0][i] = 2.4 * i;
658  acc_someArrayAsDouble.write();
659  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_IIII");
660  for(int i = 0; i < 4; i++) BOOST_CHECK_CLOSE(vals[i], round(2.4 * i), 0.00001);
661 
662  // access via string
663  TwoDRegisterAccessor<std::string> acc_someArrayAsString(
664  device.getTwoDRegisterAccessor<std::string>("MYDUMMY/SOME_IIII"));
665  acc_someArrayAsString.read();
666  for(int i = 0; i < 4; i++) BOOST_CHECK_CLOSE(std::stod(acc_someArrayAsString[0][i]), round(2.4 * i), 0.00001);
667  for(int i = 0; i < 4; i++) acc_someArrayAsString[0][i] = std::to_string(3 * i);
668  acc_someArrayAsString.write();
669  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_IIII");
670  for(int i = 0; i < 4; i++) BOOST_TEST(vals[i] == 3 * i);
671 
672  device.close();
673 }
674 
675 /**********************************************************************************************************************/
676 
678  ChimeraTK::Device device;
679  device.open(DoocsLauncher::DoocsServer1);
680 
681  // check catalogue
682  auto catalogue = device.getRegisterCatalogue();
683  auto regI = catalogue.getRegister("MYDUMMY/SOME_IFFF/I");
684  auto regF1 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F1");
685  auto regF2 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F2");
686  auto regF3 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F3");
687  BOOST_TEST(regI.getDataDescriptor().isIntegral());
688  BOOST_TEST(regI.getDataDescriptor().isSigned());
689  BOOST_TEST(regI.getDataDescriptor().nDigits() == 11);
690  BOOST_TEST(!regF1.getDataDescriptor().isIntegral());
691  BOOST_TEST(regF1.getDataDescriptor().isSigned());
692  BOOST_TEST(!regF2.getDataDescriptor().isIntegral());
693  BOOST_TEST(regF2.getDataDescriptor().isSigned());
694  BOOST_TEST(!regF3.getDataDescriptor().isIntegral());
695  BOOST_TEST(regF3.getDataDescriptor().isSigned());
696 
697  // read access via int/float
698  {
699  auto acc_I = device.getScalarRegisterAccessor<int>("MYDUMMY/SOME_IFFF/I");
700  auto acc_F1 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F1");
701  auto acc_F2 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F2");
702  auto acc_F3 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F3");
703 
704  acc_I.read();
705  BOOST_CHECK_EQUAL(int(acc_I), 10);
706  acc_F1.read();
707  BOOST_CHECK_CLOSE(float(acc_F1), 2.71828, 0.00001);
708  acc_F2.read();
709  BOOST_CHECK_CLOSE(float(acc_F2), 3.14159, 0.00001);
710  acc_F3.read();
711  BOOST_CHECK_CLOSE(float(acc_F3), 197.327, 0.00001);
712  }
713 
714  // read access via strings
715  {
716  auto acc_I = device.getScalarRegisterAccessor<std::string>("MYDUMMY/SOME_IFFF/I");
717  auto acc_F1 = device.getScalarRegisterAccessor<std::string>("MYDUMMY/SOME_IFFF/F1");
718  auto acc_F2 = device.getScalarRegisterAccessor<std::string>("MYDUMMY/SOME_IFFF/F2");
719  auto acc_F3 = device.getScalarRegisterAccessor<std::string>("MYDUMMY/SOME_IFFF/F3");
720 
721  acc_I.read();
722  BOOST_CHECK_EQUAL(std::string(acc_I), "10");
723  acc_F1.read();
724  BOOST_CHECK_CLOSE(std::stod(acc_F1), 2.71828, 0.00001);
725  acc_F2.read();
726  BOOST_CHECK_CLOSE(std::stod(acc_F2), 3.14159, 0.00001);
727  acc_F3.read();
728  BOOST_CHECK_CLOSE(std::stod(acc_F3), 197.327, 0.00001);
729  }
730 
731  // write access via int/float
732  {
733  auto acc_I = device.getScalarRegisterAccessor<int>("MYDUMMY/SOME_IFFF/I");
734  auto acc_F1 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F1");
735  auto acc_F2 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F2");
736  auto acc_F3 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_IFFF/F3");
737 
738  acc_I = 42;
739  acc_I.write();
740 
741  acc_I.read();
742  BOOST_CHECK_EQUAL(int(acc_I), 42);
743  acc_F1.read();
744  BOOST_CHECK_CLOSE(float(acc_F1), 2.71828, 0.00001);
745  acc_F2.read();
746  BOOST_CHECK_CLOSE(float(acc_F2), 3.14159, 0.00001);
747  acc_F3.read();
748  BOOST_CHECK_CLOSE(float(acc_F3), 197.327, 0.00001);
749 
750  acc_F2 = 123.456;
751  acc_F2.write();
752 
753  acc_F3 = -666.666;
754  acc_F3.write();
755 
756  acc_I.read();
757  BOOST_CHECK_EQUAL(int(acc_I), 42);
758  acc_F1.read();
759  BOOST_CHECK_CLOSE(float(acc_F1), 2.71828, 0.00001);
760  acc_F2.read();
761  BOOST_CHECK_CLOSE(float(acc_F2), 123.456, 0.00001);
762  acc_F3.read();
763  BOOST_CHECK_CLOSE(float(acc_F3), -666.666, 0.00001);
764  }
765 
766  device.close();
767 }
768 
769 /**********************************************************************************************************************/
770 
772  ChimeraTK::Device device;
773  device.open(DoocsLauncher::DoocsServer1);
774 
775  // obtain default array length, just fitting image on DOOCS server
776  OneDRegisterAccessor<std::uint8_t> acc_someImage(device.getOneDRegisterAccessor<std::uint8_t>("MYDUMMY/SOME_IMAGE"));
777  BOOST_TEST(acc_someImage.getNElements() == 640 * 460 + sizeof(ChimeraTK::ImgHeader));
778 
779  acc_someImage.read();
780  ChimeraTK::MappedImage im(acc_someImage);
781  BOOST_TEST(im.header()->width == 200);
782  BOOST_TEST(im.header()->height == 100);
783  BOOST_CHECK(im.header()->image_format == ChimeraTK::ImgFormat::Gray16);
784  auto imv = im.interpretedView<std::uint16_t>();
785  BOOST_TEST(imv(0, 0) == 0x101);
786 
787  // obtain accessor with larger than default array length
788  OneDRegisterAccessor<std::uint8_t> acc_someImage_padded(
789  device.getOneDRegisterAccessor<std::uint8_t>("MYDUMMY/SOME_IMAGE", 200 * 1000));
790  BOOST_TEST(acc_someImage_padded.getNElements() == 200 * 1000);
791  acc_someImage_padded.read();
792  // verify that image content is same
793  for(unsigned i = 0; i < im.header()->totalLength; i++) {
794  BOOST_TEST(acc_someImage[i] == acc_someImage_padded[i]);
795  }
796  // obtain accessor with smaller array length, so image must be truncated
797  OneDRegisterAccessor<std::uint8_t> acc_someImage_truncated(
798  device.getOneDRegisterAccessor<std::uint8_t>("MYDUMMY/SOME_IMAGE", 200 * 51 * 2));
799  acc_someImage_truncated.read();
800  ChimeraTK::MappedImage im1(acc_someImage_truncated);
801  BOOST_TEST(im1.header()->width == 200);
802  BOOST_TEST(im1.header()->height == 50); // one line less than 51 because of header
803  BOOST_CHECK(im1.header()->image_format == ChimeraTK::ImgFormat::Gray16);
804 
805  device.close();
806 }
807 
808 /**********************************************************************************************************************/
809 
810 BOOST_AUTO_TEST_CASE(testBitAndStatus) {
811  ChimeraTK::Device device;
812  device.open(DoocsLauncher::DoocsServer1);
813 
814  TwoDRegisterAccessor<int> acc_someBit(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_BIT"));
815  TwoDRegisterAccessor<int> acc_someStatus(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_STATUS"));
816  TwoDRegisterAccessor<uint16_t> acc_someStatusU16(device.getTwoDRegisterAccessor<uint16_t>("MYDUMMY/SOME_STATUS"));
817 
818  BOOST_TEST(acc_someBit.getNChannels() == 1);
819  BOOST_TEST(acc_someStatus.getNChannels() == 1);
820  BOOST_TEST(acc_someBit.getNElementsPerChannel() == 1);
821  BOOST_TEST(acc_someStatus.getNElementsPerChannel() == 1);
822 
823  auto oldVersion = acc_someBit.getVersionNumber();
824  acc_someBit.read();
825  BOOST_TEST(acc_someBit[0][0] == 1);
826  BOOST_TEST(acc_someBit.getVersionNumber() != oldVersion);
827  oldVersion = acc_someStatus.getVersionNumber();
828  acc_someStatus.read();
829  BOOST_TEST(acc_someStatus[0][0] == 3);
830  BOOST_TEST(acc_someStatus.getVersionNumber() != oldVersion);
831 
832  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_BIT", 0);
833 
834  BOOST_TEST(acc_someBit[0][0] == 1);
835  acc_someBit.read();
836  BOOST_TEST(acc_someBit[0][0] == 0);
837  BOOST_TEST(acc_someStatus[0][0] == 3);
838  acc_someStatus.read();
839  BOOST_TEST(acc_someStatus[0][0] == 2);
840 
841  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_STATUS", 0xFFFF);
842 
843  BOOST_TEST(acc_someBit[0][0] == 0);
844  acc_someBit.read();
845  BOOST_TEST(acc_someBit[0][0] == 1);
846  BOOST_TEST(acc_someStatus[0][0] == 2);
847  acc_someStatus.read();
848  BOOST_TEST(acc_someStatus[0][0] == 0xFFFF);
849 
850  acc_someStatusU16.read();
851  BOOST_TEST(acc_someStatusU16[0][0] == 0xFFFF);
852 
853  acc_someBit[0][0] = 0;
854  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_STATUS") == 0xFFFF);
855  VersionNumber nextVersion;
856  acc_someBit.write(nextVersion);
857  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_STATUS") == 0xFFFE);
858  BOOST_TEST(acc_someBit.getVersionNumber() == nextVersion);
859 
860  acc_someStatus[0][0] = 123;
861  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_STATUS") == 0xFFFE);
862  nextVersion = {};
863  acc_someStatus.write(nextVersion);
864  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_STATUS") == 123);
865  BOOST_TEST(acc_someStatus.getVersionNumber() == nextVersion);
866 
867  device.close();
868 }
869 /**********************************************************************************************************************/
870 
871 BOOST_AUTO_TEST_CASE(testPartialAccess) {
872  ChimeraTK::Device device;
873  device.open(DoocsLauncher::DoocsServer1);
874 
875  // int array, 20 elements, offset of 1
876  {
877  OneDRegisterAccessor<int> acc_someArray(device.getOneDRegisterAccessor<int>("MYDUMMY/SOME_INT_ARRAY", 20, 1));
878  BOOST_TEST(acc_someArray.getNElements() == 20);
879 
880  std::vector<int> vals(42);
881  for(int i = 0; i < 42; i++) vals[i] = -55 * i;
882  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT_ARRAY", vals);
883 
884  acc_someArray.read();
885  for(int i = 0; i < 20; i++) BOOST_TEST(acc_someArray[i] == -55 * (i + 1));
886 
887  for(int i = 0; i < 20; i++) acc_someArray[i] = i;
888  acc_someArray.write();
889  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
890  for(int i = 0; i < 42; i++) {
891  if(i == 0 || i > 20) {
892  BOOST_TEST(vals[i] == -55 * i);
893  }
894  else {
895  BOOST_TEST(vals[i] == i - 1);
896  }
897  }
898  }
899 
900  // int array, 1 elements, offset of 10
901  {
902  OneDRegisterAccessor<int> acc_someArray(device.getOneDRegisterAccessor<int>("MYDUMMY/SOME_INT_ARRAY", 1, 10));
903  BOOST_TEST(acc_someArray.getNElements() == 1);
904 
905  std::vector<int> vals(42);
906  for(int i = 0; i < 42; i++) vals[i] = 33 * i;
907  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT_ARRAY", vals);
908 
909  acc_someArray.read();
910  BOOST_TEST(acc_someArray[0] == 33 * 10);
911 
912  acc_someArray[0] = 42;
913  acc_someArray.write();
914  vals = DoocsServerTestHelper::doocsGetArray<int>("//MYDUMMY/SOME_INT_ARRAY");
915  for(int i = 0; i < 42; i++) {
916  if(i == 10) {
917  BOOST_TEST(vals[i] == 42);
918  }
919  else {
920  BOOST_TEST(vals[i] == 33 * i);
921  }
922  }
923  }
924 
925  // double array with float user type, 3 elements, offset of 2
926  {
927  OneDRegisterAccessor<float> acc_someArray(device.getOneDRegisterAccessor<float>("MYDUMMY/SOME_DOUBLE_ARRAY", 3, 2));
928  BOOST_TEST(acc_someArray.getNElements() == 3);
929 
930  std::vector<double> vals(5);
931  for(int i = 0; i < 5; i++) vals[i] = 3.14 * i;
932  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_DOUBLE_ARRAY", vals);
933 
934  acc_someArray.read();
935  for(int i = 0; i < 3; i++) BOOST_CHECK_CLOSE(acc_someArray[i], 3.14 * (i + 2), 0.00001);
936 
937  for(int i = 0; i < 3; i++) acc_someArray[i] = 1.2 - i;
938  acc_someArray.write();
939  vals = DoocsServerTestHelper::doocsGetArray<double>("//MYDUMMY/SOME_DOUBLE_ARRAY");
940  for(int i = 0; i < 5; i++) {
941  if(i > 1) {
942  BOOST_CHECK_CLOSE(vals[i], 1.2 - (i - 2), 0.00001);
943  }
944  else {
945  BOOST_CHECK_CLOSE(vals[i], 3.14 * i, 0.00001);
946  }
947  }
948  }
949 
950  // float array with string user type, 1 elements, offset of 0
951  {
952  ScalarRegisterAccessor<std::string> acc_someArray(
953  device.getScalarRegisterAccessor<std::string>("MYDUMMY/SOME_FLOAT_ARRAY", 0));
954 
955  std::vector<float> vals(5);
956  for(int i = 0; i < 5; i++) vals[i] = 2.82 * (i + 1);
957  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_FLOAT_ARRAY", vals);
958 
959  acc_someArray.read();
960  BOOST_CHECK_CLOSE(std::stod(acc_someArray), 2.82, 0.00001);
961 
962  acc_someArray = "-11.111";
963  acc_someArray.write();
964  vals = DoocsServerTestHelper::doocsGetArray<float>("//MYDUMMY/SOME_FLOAT_ARRAY");
965  for(int i = 0; i < 5; i++) {
966  if(i == 0) {
967  BOOST_CHECK_CLOSE(vals[i], -11.111, 0.00001);
968  }
969  else {
970  BOOST_CHECK_CLOSE(vals[i], 2.82 * (i + 1), 0.00001);
971  }
972  }
973  }
974 
975  device.close();
976 }
977 
978 /**********************************************************************************************************************/
979 
980 BOOST_AUTO_TEST_CASE(testExceptions) {
981  ChimeraTK::Device device;
982  device.open(DoocsLauncher::DoocsServer1);
983 
984  // unsupported data type
985  BOOST_CHECK_THROW(device.getTwoDRegisterAccessor<int>("MYDUMMY/UNSUPPORTED_DATA_TYPE"), // D_fiii
986  ChimeraTK::logic_error);
987 
988  // non-existing DOOCS property
989  BOOST_CHECK_THROW(device.getTwoDRegisterAccessor<int>("MYDUMMY/NOT_EXISTING"), ChimeraTK::logic_error);
990 
991  // read string with non-string user type
992  BOOST_CHECK_THROW(device.getTwoDRegisterAccessor<int>("MYDUMMY/SOME_STRING"), ChimeraTK::logic_error);
993 
994  // access too many elements (double register)
995  BOOST_CHECK_THROW(device.getOneDRegisterAccessor<float>("MYDUMMY/SOME_DOUBLE_ARRAY", 10, 1), ChimeraTK::logic_error);
996 
997  // access too many elements (int register)
998  BOOST_CHECK_THROW(device.getOneDRegisterAccessor<float>("MYDUMMY/SOME_INT_ARRAY", 100, 1), ChimeraTK::logic_error);
999 
1000  device.close();
1001 }
1002 
1003 /**********************************************************************************************************************/
1004 
1005 void createCacheFileFromCdd(const std::string& cdd) {
1006  namespace ctk = ChimeraTK;
1007  auto d = ctk::Device(cdd);
1008  d.open();
1009  auto discardedCatalogue = d.getRegisterCatalogue();
1010 }
1011 
1012 void deleteFile(const std::string& filename) {
1013  errno = 0;
1014  if(unlink(filename.c_str()) < 0) throw std::system_error(std::make_error_code(static_cast<std::errc>(errno)));
1015 }
1016 
1017 /**********************************************************************************************************************/
1018 
1019 BOOST_AUTO_TEST_CASE(testCatalogue) {
1020  {
1021  createCacheFileFromCdd(DoocsLauncher::DoocsServer1_cached);
1022  createCacheFileFromCdd(DoocsLauncher::DoocsServer2_cached);
1023 
1024  ChimeraTK::Device device;
1025  device.open(DoocsLauncher::DoocsServer2);
1026 
1027  ChimeraTK::Device device_cached;
1028  device_cached.open(DoocsLauncher::DoocsServer2_cached);
1029 
1030  std::vector<ChimeraTK::RegisterCatalogue> catalogueList2;
1031  catalogueList2.push_back(device.getRegisterCatalogue());
1032  catalogueList2.push_back(device_cached.getRegisterCatalogue());
1033 
1034  for(auto& catalogue : catalogueList2) {
1035  // check number of registers, but not with the exact number, since DOOCS adds some registers!
1036  BOOST_TEST(catalogue.getNumberOfRegisters() > 13);
1037 
1038  // check for the presence of known registers
1039  BOOST_TEST(catalogue.hasRegister("SOME_INT"));
1040  BOOST_TEST(catalogue.hasRegister("SOME_FLOAT"));
1041  BOOST_TEST(catalogue.hasRegister("SOME_DOUBLE"));
1042  BOOST_TEST(catalogue.hasRegister("SOME_STRING"));
1043  BOOST_TEST(catalogue.hasRegister("SOME_STATUS"));
1044  BOOST_TEST(catalogue.hasRegister("SOME_BIT"));
1045  BOOST_TEST(catalogue.hasRegister("SOME_INT_ARRAY"));
1046  BOOST_TEST(catalogue.hasRegister("SOME_SHORT_ARRAY"));
1047  BOOST_TEST(catalogue.hasRegister("SOME_LONG_ARRAY"));
1048  BOOST_TEST(catalogue.hasRegister("SOME_FLOAT_ARRAY"));
1049  BOOST_TEST(catalogue.hasRegister("SOME_DOUBLE_ARRAY"));
1050  BOOST_TEST(catalogue.hasRegister("SOME_SPECTRUM"));
1051  BOOST_TEST(catalogue.hasRegister("SOME_IFFF/I"));
1052  BOOST_TEST(catalogue.hasRegister("SOME_IFFF/F1"));
1053  BOOST_TEST(catalogue.hasRegister("SOME_IFFF/F2"));
1054  BOOST_TEST(catalogue.hasRegister("SOME_IFFF/F3"));
1055 
1056  // check the properties of some registers
1057  auto r1 = catalogue.getRegister("SOME_INT");
1058  BOOST_TEST(r1.getRegisterName() == "SOME_INT");
1059  BOOST_TEST(r1.getNumberOfElements() == 1);
1060  BOOST_TEST(r1.getNumberOfChannels() == 1);
1061  BOOST_TEST(r1.getNumberOfDimensions() == 0);
1062  BOOST_TEST(not r1.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1063 
1064  auto r2 = catalogue.getRegister("SOME_STRING");
1065  BOOST_TEST(r2.getRegisterName() == "SOME_STRING");
1066  BOOST_TEST(r2.getNumberOfElements() == 1);
1067  BOOST_TEST(r2.getNumberOfChannels() == 1);
1068  BOOST_TEST(r2.getNumberOfDimensions() == 0);
1069  BOOST_TEST(not r2.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1070 
1071  auto r3 = catalogue.getRegister("SOME_INT_ARRAY");
1072  BOOST_TEST(r3.getRegisterName() == "SOME_INT_ARRAY");
1073  BOOST_TEST(r3.getNumberOfElements() == 42);
1074  BOOST_TEST(r3.getNumberOfChannels() == 1);
1075  BOOST_TEST(r3.getNumberOfDimensions() == 1);
1076  BOOST_TEST(not r3.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1077 
1078  auto r4 = catalogue.getRegister("SOME_FLOAT_ARRAY");
1079  BOOST_TEST(r4.getRegisterName() == "SOME_FLOAT_ARRAY");
1080  BOOST_TEST(r4.getNumberOfElements() == 5);
1081  BOOST_TEST(r4.getNumberOfChannels() == 1);
1082  BOOST_TEST(r4.getNumberOfDimensions() == 1);
1083  BOOST_TEST(not r4.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1084 
1085  auto r5 = catalogue.getRegister("SOME_SPECTRUM");
1086  BOOST_TEST(r5.getRegisterName() == "SOME_SPECTRUM");
1087  BOOST_TEST(r5.getNumberOfElements() == 100);
1088  BOOST_TEST(r5.getNumberOfChannels() == 1);
1089  BOOST_TEST(r5.getNumberOfDimensions() == 1);
1090  BOOST_TEST(not r5.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1091 
1092  auto r6 = catalogue.getRegister("SOME_ZMQINT");
1093  BOOST_TEST(r6.getRegisterName() == "SOME_ZMQINT");
1094  BOOST_TEST(r6.getNumberOfElements() == 1);
1095  BOOST_TEST(r6.getNumberOfChannels() == 1);
1096  BOOST_TEST(r6.getNumberOfDimensions() == 0);
1097  BOOST_TEST(r6.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1098 
1099  auto r7 = catalogue.getRegister("SOME_IIII");
1100  BOOST_TEST(r7.getRegisterName() == "SOME_IIII");
1101  BOOST_TEST(r7.getNumberOfElements() == 4);
1102  BOOST_TEST(r7.getNumberOfChannels() == 1);
1103  BOOST_TEST(r7.getNumberOfDimensions() == 1);
1104  BOOST_TEST(not r7.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1105 
1106  auto regI = catalogue.getRegister("SOME_IFFF/I");
1107  auto regF1 = catalogue.getRegister("SOME_IFFF/F1");
1108  auto regF2 = catalogue.getRegister("SOME_IFFF/F2");
1109  auto regF3 = catalogue.getRegister("SOME_IFFF/F3");
1110  BOOST_TEST(regI.getDataDescriptor().isIntegral());
1111  BOOST_TEST(regI.getDataDescriptor().isSigned());
1112  BOOST_TEST(regI.getDataDescriptor().nDigits() == 11);
1113  BOOST_TEST(!regF1.getDataDescriptor().isIntegral());
1114  BOOST_TEST(regF1.getDataDescriptor().isSigned());
1115  BOOST_TEST(!regF2.getDataDescriptor().isIntegral());
1116  BOOST_TEST(regF2.getDataDescriptor().isSigned());
1117  BOOST_TEST(!regF3.getDataDescriptor().isIntegral());
1118  BOOST_TEST(regF3.getDataDescriptor().isSigned());
1119  }
1120  device.close();
1121  device_cached.close();
1122 
1123  // quick check with the other level (location is included in the register name)
1124  device.open(DoocsLauncher::DoocsServer1);
1125  device_cached.open(DoocsLauncher::DoocsServer1_cached);
1126 
1127  std::vector<ChimeraTK::RegisterCatalogue> catalogueList1;
1128  catalogueList1.push_back(device.getRegisterCatalogue());
1129  catalogueList1.push_back(device_cached.getRegisterCatalogue());
1130 
1131  for(auto& catalogue : catalogueList1) {
1132  // check number of registers, but not with the exact number, since DOOCS adds some registers!
1133  BOOST_TEST(catalogue.getNumberOfRegisters() > 13);
1134 
1135  // check for the presence of known registers
1136  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_INT"));
1137  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_ZMQINT"));
1138  BOOST_TEST(catalogue.hasRegister("DUMMY._SVR/SVR.BPN"));
1139  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_IFFF/I"));
1140  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_IFFF/F1"));
1141  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_IFFF/F2"));
1142  BOOST_TEST(catalogue.hasRegister("MYDUMMY/SOME_IFFF/F3"));
1143 
1144  // check the properties of some registers
1145  auto r8 = catalogue.getRegister("MYDUMMY/SOME_INT");
1146  BOOST_TEST(r8.getRegisterName() == "MYDUMMY/SOME_INT");
1147  BOOST_TEST(r8.getNumberOfElements() == 1);
1148  BOOST_TEST(r8.getNumberOfChannels() == 1);
1149  BOOST_TEST(r8.getNumberOfDimensions() == 0);
1150  BOOST_TEST(not r8.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1151 
1152  auto r9 = catalogue.getRegister("DUMMY._SVR/SVR.BPN");
1153  BOOST_TEST(r9.getRegisterName() == "DUMMY._SVR/SVR.BPN");
1154  BOOST_TEST(r9.getNumberOfElements() == 1);
1155  BOOST_TEST(r9.getNumberOfChannels() == 1);
1156  BOOST_TEST(r9.getNumberOfDimensions() == 0);
1157  BOOST_TEST(not r9.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1158 
1159  auto r10 = catalogue.getRegister("MYDUMMY/SOME_ZMQINT");
1160  BOOST_TEST(r10.getRegisterName() == "MYDUMMY/SOME_ZMQINT");
1161  BOOST_TEST(r10.getNumberOfElements() == 1);
1162  BOOST_TEST(r10.getNumberOfChannels() == 1);
1163  BOOST_TEST(r10.getNumberOfDimensions() == 0);
1164  BOOST_TEST(r10.getSupportedAccessModes().has(ChimeraTK::AccessMode::wait_for_new_data));
1165 
1166  auto regI = catalogue.getRegister("MYDUMMY/SOME_IFFF/I");
1167  auto regF1 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F1");
1168  auto regF2 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F2");
1169  auto regF3 = catalogue.getRegister("MYDUMMY/SOME_IFFF/F3");
1170  BOOST_TEST(regI.getDataDescriptor().isIntegral());
1171  BOOST_TEST(regI.getDataDescriptor().isSigned());
1172  BOOST_TEST(regI.getDataDescriptor().nDigits() == 11);
1173  BOOST_TEST(!regF1.getDataDescriptor().isIntegral());
1174  BOOST_TEST(regF1.getDataDescriptor().isSigned());
1175  BOOST_TEST(!regF2.getDataDescriptor().isIntegral());
1176  BOOST_TEST(regF2.getDataDescriptor().isSigned());
1177  BOOST_TEST(!regF3.getDataDescriptor().isIntegral());
1178  BOOST_TEST(regF3.getDataDescriptor().isSigned());
1179  }
1180  device.close();
1181  device_cached.close();
1182  } // ensure we delete the cache file written on destruction
1183 
1184  deleteFile(DoocsLauncher::cacheFile1);
1185  deleteFile(DoocsLauncher::cacheFile2);
1186 }
1187 
1188 /**********************************************************************************************************************/
1189 
1191  ChimeraTK::Device device;
1192  device.open(DoocsLauncher::DoocsServer1);
1193 
1194  // device info string
1195  BOOST_TEST(device.readDeviceInfo() == "DOOCS server address: doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D");
1196 
1197  // test in TransferGroup
1198  TwoDRegisterAccessor<int32_t> acc1(device.getTwoDRegisterAccessor<int32_t>("MYDUMMY/SOME_INT"));
1199  TwoDRegisterAccessor<int32_t> acc2(device.getTwoDRegisterAccessor<int32_t>("MYDUMMY/SOME_INT"));
1200  TransferGroup group;
1201  group.addAccessor(acc1);
1202  group.addAccessor(acc2);
1203 
1204  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 123);
1205  group.read();
1206  BOOST_CHECK_EQUAL(acc1[0][0], 123);
1207  BOOST_CHECK_EQUAL(acc2[0][0], 123);
1208  acc1[0][0] = 42;
1209 
1210  device.close();
1211 
1212  // compatibility with SDM syntax
1213  device.open("sdm://./doocs=TEST.DOOCS,NOT_EXISTING,SOME_LOCATION");
1214  BOOST_TEST(device.readDeviceInfo() == "DOOCS server address: TEST.DOOCS/NOT_EXISTING/SOME_LOCATION");
1215  device.close();
1216 }
1217 
1218 /**********************************************************************************************************************/
1219 
1220 BOOST_AUTO_TEST_CASE(testDestruction) {
1221  auto server = find_device("MYDUMMY");
1222  server->lock();
1223  {
1224  auto d = ChimeraTK::Device(DoocsLauncher::DoocsServer2_cached);
1225  d.open();
1226  usleep(10000); // give it a chance to start filling the catalogue
1227  // should not block here on instance destruction.
1228  }
1229  server->unlock();
1230 }
1231 
1232 /**********************************************************************************************************************/
1233 
1234 bool file_exists(const std::string& name) {
1235  std::ifstream f(name.c_str());
1236  return f.good();
1237 }
1238 
1239 BOOST_AUTO_TEST_CASE(testCacheFileCreation) {
1240  {
1241  BOOST_TEST(file_exists(DoocsLauncher::cacheFile1) == false);
1242  BOOST_TEST(file_exists(DoocsLauncher::cacheFile2) == false);
1243 
1244  auto d1 = ChimeraTK::Device(DoocsLauncher::DoocsServer1_cached);
1245  auto d2 = ChimeraTK::Device(DoocsLauncher::DoocsServer2_cached);
1246 
1247  auto discardedCatalogue = d1.getRegisterCatalogue();
1248  discardedCatalogue = d2.getRegisterCatalogue();
1249 
1250  BOOST_TEST(file_exists(DoocsLauncher::cacheFile1) == true);
1251  BOOST_TEST(file_exists(DoocsLauncher::cacheFile2) == true);
1252  }
1253  deleteFile(DoocsLauncher::cacheFile1);
1254  deleteFile(DoocsLauncher::cacheFile2);
1255 }
1256 
1257 /**********************************************************************************************************************/
1258 
1259 std::time_t createDummyXml(const std::string& filename) {
1260  std::string xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
1261  "<catalogue version=\"1.0\">"
1262  " <register>\n"
1263  " <name>/DUMMY</name>\n"
1264  " <length>1</length>\n"
1265  " <access_mode></access_mode>\n"
1266  " <doocs_type_id>1</doocs_type_id>\n" // DATA_TEXT
1267  " <!--doocs id: INT-->\n"
1268  " </register>\n"
1269  "</catalogue>\n";
1270  std::ofstream o(filename);
1271  o << xml;
1272  o.close();
1273 
1274  auto creation_time = boost::filesystem::last_write_time(DoocsLauncher::cacheFile2);
1275 
1276  // boost::filesystem::last_write_time timestamp resolution is not high
1277  // enough to pick modifications without this wait.
1278  std::this_thread::sleep_for(std::chrono::seconds(1));
1279  return creation_time;
1280 }
1281 
1282 /**********************************************************************************************************************/
1283 
1284 BOOST_AUTO_TEST_CASE(testCacheXmlReplacement) {
1285  // test local copy is replaced when catalogue fetching is complete.
1286  auto creation_time = createDummyXml(DoocsLauncher::cacheFile2);
1287  {
1288  auto d = ChimeraTK::Device(DoocsLauncher::DoocsServer2_cached);
1289  std::atomic<bool> cancelTimeOutTask{false};
1290 
1291  std::future<void> timeoutTask = std::async(std::launch::async, [&]() {
1292  unsigned int count = 60;
1293  while(count > 0 && not cancelTimeOutTask) {
1294  std::this_thread::sleep_for(std::chrono::seconds(1));
1295  count--;
1296  }
1297  });
1298 
1299  auto hasTimedOut = [&]() { return timeoutTask.wait_for(std::chrono::seconds(0)) == std::future_status::ready; };
1300 
1301  auto modification_time = creation_time;
1302  while((modification_time <= creation_time) && not hasTimedOut()) {
1303  modification_time = boost::filesystem::last_write_time(DoocsLauncher::cacheFile2);
1304  std::this_thread::sleep_for(std::chrono::seconds(2));
1305  }
1306  // cancel timeout task
1307  cancelTimeOutTask = true;
1308  BOOST_TEST(modification_time > creation_time); // given the percondition,
1309  // this should fail if loop
1310  // times out.
1311  deleteFile(DoocsLauncher::cacheFile2);
1312  }
1313 }
1314 
1315 /**********************************************************************************************************************/
1316 
1317 BOOST_AUTO_TEST_CASE(testCacheXmlReplacementBehaviorOnFailure) {
1318  // local copy unchanged if app exits before.
1319  auto creation_time = createDummyXml(DoocsLauncher::cacheFile2);
1320  auto server = find_device("MYDUMMY");
1321  server->lock();
1322  { auto d = ChimeraTK::Device(DoocsLauncher::DoocsServer2_cached); }
1323  server->unlock();
1324  auto modification_time = boost::filesystem::last_write_time(DoocsLauncher::cacheFile2);
1325  BOOST_TEST(creation_time == modification_time);
1326  deleteFile(DoocsLauncher::cacheFile2);
1327 }
1328 
1329 /**********************************************************************************************************************/
1330 
1331 BOOST_AUTO_TEST_CASE(testAccessorForCachedMode) {
1332  createCacheFileFromCdd(DoocsLauncher::DoocsServer1_cached);
1333  auto d = ChimeraTK::Device(DoocsLauncher::DoocsServer1_cached);
1334 
1335  DoocsServerTestHelper::doocsSet("//MYDUMMY/SOME_INT", 120);
1336  TwoDRegisterAccessor<int32_t> acc_someInt_as_int(d.getTwoDRegisterAccessor<int32_t>("MYDUMMY/SOME_INT"));
1337  BOOST_TEST(acc_someInt_as_int.getNChannels() == 1);
1338  BOOST_TEST(acc_someInt_as_int.getNElementsPerChannel() == 1);
1339 
1340  d.open();
1341 
1342  acc_someInt_as_int.read();
1343  BOOST_TEST(acc_someInt_as_int[0][0] == 120);
1344 
1345  acc_someInt_as_int[0][0] = 50;
1346  acc_someInt_as_int.write();
1347  BOOST_TEST(DoocsServerTestHelper::doocsGet<int>("//MYDUMMY/SOME_INT") == 50);
1348  deleteFile(DoocsLauncher::cacheFile1);
1349 }
1350 
1351 /**********************************************************************************************************************/
1352 
1353 BOOST_AUTO_TEST_CASE(testBlankXMLThrow) {
1354  std::string xml = "";
1355  std::ofstream o(DoocsLauncher::cacheFile2);
1356  o << xml;
1357  o.close();
1358 
1359  BOOST_CHECK_THROW(ChimeraTK::Device x(DoocsLauncher::DoocsServer2_cached), ChimeraTK::logic_error);
1360  deleteFile(DoocsLauncher::cacheFile2);
1361 }
1362 
1363 /**********************************************************************************************************************/
1364 
1365 BOOST_AUTO_TEST_CASE(testEventId) {
1366  ChimeraTK::Device device;
1367  device.open(DoocsLauncher::DoocsServer1);
1368  auto catalogue = device.getRegisterCatalogue();
1369 
1370  // Run update once to have the ZMQ variable's mp number updated
1371  DoocsServerTestHelper::runUpdate();
1372 
1373  // Get EqFct to access the mp counter for ZMQ
1374  auto eqfct = reinterpret_cast<eq_dummy*>(find_device("MYDUMMY"));
1375 
1376  // device info string
1377  BOOST_TEST(device.readDeviceInfo() == "DOOCS server address: doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D");
1378 
1379  for(std::string param : {"SOME_INT", "SOME_FLOAT", "SOME_BIT", "SOME_INT_ARRAY", "SOME_SHORT_ARRAY",
1380  "SOME_LONG_ARRAY", "SOME_FLOAT_ARRAY", "SOME_DOUBLE_ARRAY", "SOME_SPECTRUM", "SOME_IIII", "SOME_IFFF"}) {
1381  auto path = RegisterPath("MYDUMMY/" + param + "/eventId");
1382  BOOST_TEST(catalogue.hasRegister(path));
1383 
1384  auto regInfo = catalogue.getRegister(path);
1385  BOOST_TEST(regInfo.isReadable());
1386  BOOST_TEST(!regInfo.isWriteable());
1387  BOOST_CHECK_EQUAL(regInfo.getNumberOfElements(), 1);
1388  BOOST_CHECK_EQUAL(regInfo.getNumberOfChannels(), 1);
1389  BOOST_CHECK_EQUAL(regInfo.getNumberOfDimensions(), 0);
1390  auto descriptor = regInfo.getDataDescriptor();
1391  BOOST_TEST(descriptor.fundamentalType() == ChimeraTK::DataDescriptor::FundamentalType::numeric);
1392  BOOST_CHECK_EQUAL(descriptor.nDigits(), 20);
1393  BOOST_TEST(descriptor.isSigned());
1394  BOOST_TEST(descriptor.isIntegral());
1395 
1396  auto acc1 = device.getScalarRegisterAccessor<int64_t>(path);
1397  acc1.read();
1398  BOOST_CHECK_EQUAL(static_cast<int64_t>(acc1), eqfct->counter - 1);
1399  BOOST_CHECK_EQUAL(acc1.isReadOnly(), true);
1400  BOOST_CHECK_EQUAL(acc1.isWriteable(), false);
1401  BOOST_CHECK_EQUAL(acc1.isReadable(), true);
1402  BOOST_CHECK_THROW(acc1.write(), ChimeraTK::logic_error);
1403 
1404  auto acc2 = device.getScalarRegisterAccessor<std::string>(path);
1405  acc2.read();
1406  BOOST_CHECK_EQUAL(static_cast<std::string>(acc2), std::to_string(eqfct->counter - 1));
1407  BOOST_CHECK_EQUAL(acc2.isReadOnly(), true);
1408  BOOST_CHECK_EQUAL(acc2.isWriteable(), false);
1409  BOOST_CHECK_EQUAL(acc2.isReadable(), true);
1410  BOOST_CHECK_THROW(acc2.write(), ChimeraTK::logic_error);
1411 
1412  // auto acc3 = device.getScalarRegisterAccessor<uint8_t>(path);
1413  // BOOST_CHECK_THROW(acc3.read(), boost::numeric::positive_overflow);
1414  }
1415 
1416  // Check that we get the accessor for some unsupported type as well
1417  // Whether or not eventId retuns something usefull here is completely undefined
1418  auto acc1 = device.getScalarRegisterAccessor<int64_t>("MYDUMMY/UNSUPPORTED_DATA_TYPE/eventId");
1419  BOOST_TEST(acc1.isInitialised());
1420 
1421  // Run update once to have the ZMQ variable's mp number updated
1422  DoocsServerTestHelper::runUpdate();
1423 
1424  auto path = RegisterPath("MYDUMMY/SOME_ZMQINT/eventId");
1425  BOOST_TEST(catalogue.hasRegister(path));
1426  auto acc2 = device.getScalarRegisterAccessor<int64_t>(path);
1427  acc2.read();
1428  BOOST_CHECK_EQUAL(static_cast<int64_t>(acc2), eqfct->counter - 1);
1429  BOOST_CHECK_EQUAL(acc2.isReadOnly(), true);
1430  BOOST_CHECK_EQUAL(acc2.isWriteable(), false);
1431  BOOST_CHECK_EQUAL(acc2.isReadable(), true);
1432  BOOST_CHECK_THROW(acc2.write(), ChimeraTK::logic_error);
1433 
1434  device.close();
1435 }
1436 
1437 /**********************************************************************************************************************/
1438 
1439 BOOST_AUTO_TEST_CASE(testTimeStamp) {
1440  ChimeraTK::Device device;
1441  device.open(DoocsLauncher::DoocsServer1);
1442  auto catalogue = device.getRegisterCatalogue();
1443 
1444  // Run update once to have the ZMQ variable's mp number updated
1445  DoocsServerTestHelper::runUpdate();
1446 
1447  // Get EqFct to access the mp counter for ZMQ
1448  auto eqfct = reinterpret_cast<eq_dummy*>(find_device("MYDUMMY"));
1449 
1450  // device info string
1451  BOOST_TEST(device.readDeviceInfo() == "DOOCS server address: doocs://localhost:" + DoocsLauncher::rpc_no + "/F/D");
1452 
1453  for(std::string param : {"SOME_INT", "SOME_FLOAT", "SOME_BIT", "SOME_INT_ARRAY", "SOME_SHORT_ARRAY",
1454  "SOME_LONG_ARRAY", "SOME_FLOAT_ARRAY", "SOME_DOUBLE_ARRAY", "SOME_SPECTRUM", "SOME_IIII", "SOME_IFFF"}) {
1455  auto path = RegisterPath("MYDUMMY/" + param + "/timeStamp");
1456  BOOST_TEST(catalogue.hasRegister(path));
1457 
1458  auto regInfo = catalogue.getRegister(path);
1459  BOOST_TEST(regInfo.isReadable());
1460  BOOST_TEST(!regInfo.isWriteable());
1461  BOOST_CHECK_EQUAL(regInfo.getNumberOfElements(), 1);
1462  BOOST_CHECK_EQUAL(regInfo.getNumberOfChannels(), 1);
1463  BOOST_CHECK_EQUAL(regInfo.getNumberOfDimensions(), 0);
1464  auto descriptor = regInfo.getDataDescriptor();
1465  BOOST_TEST(descriptor.fundamentalType() == ChimeraTK::DataDescriptor::FundamentalType::numeric);
1466  BOOST_CHECK_EQUAL(descriptor.nDigits(), 20);
1467  BOOST_TEST(descriptor.isSigned());
1468  BOOST_TEST(descriptor.isIntegral());
1469 
1470  auto acc1 = device.getScalarRegisterAccessor<int64_t>(path);
1471  acc1.read();
1472  BOOST_CHECK_EQUAL(static_cast<int64_t>(acc1), eqfct->startTime - 1);
1473  BOOST_CHECK_EQUAL(acc1.isReadOnly(), true);
1474  BOOST_CHECK_EQUAL(acc1.isWriteable(), false);
1475  BOOST_CHECK_EQUAL(acc1.isReadable(), true);
1476  BOOST_CHECK_THROW(acc1.write(), ChimeraTK::logic_error);
1477 
1478  auto acc2 = device.getScalarRegisterAccessor<std::string>(path);
1479  acc2.read();
1480  BOOST_CHECK_EQUAL(static_cast<std::string>(acc2), std::to_string(eqfct->startTime - 1));
1481  BOOST_CHECK_EQUAL(acc2.isReadOnly(), true);
1482  BOOST_CHECK_EQUAL(acc2.isWriteable(), false);
1483  BOOST_CHECK_EQUAL(acc2.isReadable(), true);
1484  BOOST_CHECK_THROW(acc2.write(), ChimeraTK::logic_error);
1485 
1486  // auto acc3 = device.getScalarRegisterAccessor<uint8_t>(path);
1487  // BOOST_CHECK_THROW(acc3.read(), boost::numeric::positive_overflow);
1488  }
1489 
1490  // Check that we get the accessor for some unsupported type as well
1491  // Whether or not eventId retuns something usefull here is completely undefined
1492  auto acc1 = device.getScalarRegisterAccessor<int64_t>("MYDUMMY/UNSUPPORTED_DATA_TYPE/timeStamp");
1493  BOOST_TEST(acc1.isInitialised());
1494 
1495  // Run update once to have the ZMQ variable's mp number updated
1496  DoocsServerTestHelper::runUpdate();
1497 
1498  auto path = RegisterPath("MYDUMMY/SOME_ZMQINT/timeStamp");
1499  BOOST_TEST(catalogue.hasRegister(path));
1500  auto acc2 = device.getScalarRegisterAccessor<int64_t>(path);
1501  acc2.read();
1502  BOOST_CHECK_EQUAL(static_cast<int64_t>(acc2), eqfct->startTime - 1);
1503  BOOST_CHECK_EQUAL(acc2.isReadOnly(), true);
1504  BOOST_CHECK_EQUAL(acc2.isWriteable(), false);
1505  BOOST_CHECK_EQUAL(acc2.isReadable(), true);
1506  BOOST_CHECK_THROW(acc2.write(), ChimeraTK::logic_error);
1507 
1508  device.close();
1509 }
1510 
1511 /**********************************************************************************************************************/
1512 
1513 BOOST_AUTO_TEST_CASE(testEventIdMapping) {
1514  ChimeraTK::Device device;
1515  device.open(DoocsLauncher::DoocsServer1);
1516  auto catalogue = device.getRegisterCatalogue();
1517  auto eqfct = reinterpret_cast<eq_dummy*>(find_device("MYDUMMY"));
1518 
1519  auto acc1 = device.getScalarRegisterAccessor<int>("MYDUMMY/SOME_INT");
1520  auto acc2 = device.getScalarRegisterAccessor<float>("MYDUMMY/SOME_FLOAT");
1521  auto acc1_id = device.getScalarRegisterAccessor<int64_t>("MYDUMMY/SOME_INT/eventId");
1522  auto acc2_id = device.getScalarRegisterAccessor<int64_t>("MYDUMMY/SOME_FLOAT/eventId");
1523 
1524  // Start with eventID 0 - even with that, we should not get VersionNumber{nullptr}
1525  auto id = eqfct->counter;
1526  eqfct->counter = 0;
1527 
1528  // Run update once to have the ZMQ variable's mp number updated to 0 (before reading anything, i.e.
1529  // before having id in the EventID mapper
1530  DoocsServerTestHelper::runUpdate();
1531 
1532  acc1.read();
1533  acc1_id.read();
1534  acc2.read();
1535  acc2_id.read();
1536 
1537  BOOST_TEST(acc1.getVersionNumber() != ChimeraTK::VersionNumber{nullptr});
1538  BOOST_TEST(acc2.getVersionNumber() != ChimeraTK::VersionNumber{nullptr});
1539  // notice: The version numbers for acc1 and acc2 are not the same, and also
1540  // those of acc1_id and acc2_id do not match any of them. Data with eventId 0 cannot be correlated at all.
1541  BOOST_TEST(acc1_id == 0);
1542  BOOST_TEST(acc2_id == 0);
1543 
1544  eqfct->counter = id;
1545 
1546  // Run update once to have the ZMQ variable's mp number updated. As it was not in the mapper yet,
1547  // the according VersionNumber will be larger that the ones from the last reads with eventID 0, so the
1548  // correlation works. (see further test with eventID 0 at the end of the sequence).
1549  DoocsServerTestHelper::runUpdate();
1550 
1551  acc1.read();
1552  acc2.read();
1553  acc1_id.read();
1554  acc2_id.read();
1555 
1556  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc2.getVersionNumber(),
1557  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1558  static_cast<std::string>(acc2.getVersionNumber()));
1559  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc1_id.getVersionNumber(),
1560  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1561  static_cast<std::string>(acc1_id.getVersionNumber()));
1562  BOOST_CHECK_MESSAGE(acc2.getVersionNumber() == acc2_id.getVersionNumber(),
1563  static_cast<std::string>(acc2.getVersionNumber()) + " should be equal to " +
1564  static_cast<std::string>(acc2_id.getVersionNumber()));
1565  BOOST_CHECK_EQUAL(acc1_id, id);
1566  BOOST_CHECK_EQUAL(acc2_id, id);
1567 
1568  // update() will set a new eventId
1569  DoocsServerTestHelper::runUpdate();
1570 
1571  // After reading only one of the accessors, the version should now be different
1572  acc2.read();
1573  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() != acc2.getVersionNumber(),
1574  static_cast<std::string>(acc1.getVersionNumber()) + " should not be equal to " +
1575  static_cast<std::string>(acc2.getVersionNumber()));
1576 
1577  // After reading acc1 as well, they should match up now
1578  acc1.read();
1579  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc2.getVersionNumber(),
1580  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1581  static_cast<std::string>(acc2.getVersionNumber()));
1582 
1583  // Check consistency accros two different DOOCS backend instances. Right after opening, the spec B.1.2.1 kicks in and
1584  // prevents that the version numbers are consistent.
1585  VersionNumber someVersionBeforeOpeningSecondDevice;
1586  ChimeraTK::Device device2;
1587  device2.open(DoocsLauncher::DoocsServer2);
1588  auto acc3 = device2.getScalarRegisterAccessor<int>("SOME_INT");
1589  acc3.read();
1590  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() > someVersionBeforeOpeningSecondDevice,
1591  static_cast<std::string>(acc3.getVersionNumber()) + " should be greater than " +
1592  static_cast<std::string>(someVersionBeforeOpeningSecondDevice));
1593 
1594  // update() will set a new eventId, hence a new version number. Now that both backends are already open, numbers must
1595  // be consistent.
1596  VersionNumber lastVersion = acc3.getVersionNumber();
1597  for(size_t i = 0; i < 3; ++i) {
1598  DoocsServerTestHelper::runUpdate();
1599  acc2.read();
1600  acc3.read();
1601  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() > lastVersion,
1602  static_cast<std::string>(acc3.getVersionNumber()) + " should be greater than " +
1603  static_cast<std::string>(lastVersion));
1604  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() == acc2.getVersionNumber(),
1605  static_cast<std::string>(acc3.getVersionNumber()) + " should be equal to " +
1606  static_cast<std::string>(acc2.getVersionNumber()));
1607  lastVersion = acc3.getVersionNumber();
1608  }
1609 
1610  // Putting one device into an exception state and recovering it will break consistency for exactly one read again.
1611  device2.setException("Test Exception");
1612 
1613  // device being in exception state should not affect the first device
1614  DoocsServerTestHelper::runUpdate();
1615  acc2.read();
1616  BOOST_CHECK_MESSAGE(acc2.getVersionNumber() > lastVersion,
1617  static_cast<std::string>(acc2.getVersionNumber()) + " should be greater than " +
1618  static_cast<std::string>(lastVersion));
1619  lastVersion = acc2.getVersionNumber();
1620 
1621  // recover second device
1622  someVersionBeforeOpeningSecondDevice = {};
1623  device2.open();
1624  acc3.read();
1625  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() > someVersionBeforeOpeningSecondDevice,
1626  static_cast<std::string>(acc3.getVersionNumber()) + " should be greater than " +
1627  static_cast<std::string>(someVersionBeforeOpeningSecondDevice));
1628 
1629  // next update: numbers must be consistent again
1630  DoocsServerTestHelper::runUpdate();
1631  acc2.read();
1632  acc3.read();
1633  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() > lastVersion,
1634  static_cast<std::string>(acc3.getVersionNumber()) + " should be greater than " +
1635  static_cast<std::string>(lastVersion));
1636  BOOST_CHECK_MESSAGE(acc3.getVersionNumber() == acc2.getVersionNumber(),
1637  static_cast<std::string>(acc3.getVersionNumber()) + " should be equal to " +
1638  static_cast<std::string>(acc2.getVersionNumber()));
1639  lastVersion = acc3.getVersionNumber();
1640 
1641  //+++++++++++++++++++++++++++++++++
1642  // Check out-of-order updates
1643  //+++++++++++++++++++++++++++++++++
1644  // We use acc3 from device2 to fill two events in normal order, then read the two events in inverse order on acc1
1645  // and acc2 of device1.
1646  auto id1 = eqfct->counter; // eqfct->counter gets incremented at the end of update()...
1647  DoocsServerTestHelper::runUpdate();
1648  acc3.read();
1649  auto ver1 = acc3.getVersionNumber(); // this is the version number matching id1
1650  DoocsServerTestHelper::runUpdate();
1651  acc3.read();
1652  auto ver2 = acc3.getVersionNumber(); // this is the version number matching id2
1653 
1654  acc1.read();
1655  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == ver2,
1656  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " + static_cast<std::string>(ver2));
1657  BOOST_TEST(acc1.dataValidity() == DataValidity::ok);
1658 
1659  eqfct->counter = id1;
1660  DoocsServerTestHelper::runUpdate();
1661 
1662  acc2.read();
1663  BOOST_CHECK_MESSAGE(acc2.getVersionNumber() == ver1,
1664  static_cast<std::string>(acc2.getVersionNumber()) + " should be equal to " + static_cast<std::string>(ver1));
1665  BOOST_TEST(acc2.dataValidity() == DataValidity::ok);
1666 
1667  // backwards going eventId on same accessor does not change VersionNumber. Data validity stays ok
1668  acc1.read();
1669  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == ver2,
1670  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " + static_cast<std::string>(ver2));
1671  BOOST_TEST(acc1.dataValidity() == DataValidity::ok);
1672 
1673  //++++++++++++++++++++++++++++++++++++++++++++++
1674  // Check eventID 0 mixed with regular updates
1675  //++++++++++++++++++++++++++++++++++++++++++++++
1676  // first do two update so we get out of the out-of-order sequence
1677  DoocsServerTestHelper::
1678  runUpdate(); // after the first update we are back to ID 2 from above. Just get a new one again..
1679  DoocsServerTestHelper::runUpdate();
1680 
1681  acc1.read();
1682  auto lastRegularAcc1Version = acc1.getVersionNumber();
1683  acc1_id.read();
1684  int64_t lastRegularEventId = acc1_id;
1685  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc1_id.getVersionNumber(),
1686  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1687  static_cast<std::string>(acc1_id.getVersionNumber()));
1688 
1689  // now process some data with event ID 0
1690  auto idAfterZero = eqfct->counter; // the id that would have been given out
1691  eqfct->counter = 0;
1692  DoocsServerTestHelper::runUpdate();
1693 
1694  // the version number increases with event ID 0
1695  acc1.read();
1696  acc1_id.read();
1697  auto acc1VersionForId0 = acc1.getVersionNumber();
1698  auto acc1_idVersionForId0 = acc1_id.getVersionNumber();
1699  BOOST_TEST(acc1.getVersionNumber() > lastRegularAcc1Version);
1700  BOOST_TEST(acc1_id.getVersionNumber() > lastRegularAcc1Version);
1701  BOOST_CHECK_EQUAL(acc1_id, 0);
1702 
1703  // Now send the same eventID again as we had it before the 0 (a new version has already been tested in the start
1704  // sequence, where id 0 was the first one to be received)
1705  eqfct->counter = lastRegularEventId;
1706  DoocsServerTestHelper::runUpdate();
1707 
1708  acc1.read();
1709  acc1_id.read();
1710  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc1VersionForId0, // version has not changed
1711  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1712  static_cast<std::string>(acc1VersionForId0));
1713  BOOST_CHECK_MESSAGE(acc1_id.getVersionNumber() == acc1_idVersionForId0, // version has not changed
1714  static_cast<std::string>(acc1_id.getVersionNumber()) + " should be equal to " +
1715  static_cast<std::string>(acc1_idVersionForId0));
1716  BOOST_CHECK_EQUAL(acc1_id, lastRegularEventId); // the data content of acc1_id changed -> we lost the consistency
1717 
1718  // acc2 has not seen the id 0 and still is consistent
1719  acc2.read();
1720  acc2_id.read();
1721  BOOST_CHECK_MESSAGE(acc2.getVersionNumber() == lastRegularAcc1Version, // version has not changed
1722  static_cast<std::string>(acc2.getVersionNumber()) + " should be equal to " +
1723  static_cast<std::string>(lastRegularAcc1Version));
1724  BOOST_CHECK_MESSAGE(acc2_id.getVersionNumber() == lastRegularAcc1Version, // version has not changed
1725  static_cast<std::string>(acc2_id.getVersionNumber()) + " should be equal to " +
1726  static_cast<std::string>(lastRegularAcc1Version));
1727  BOOST_CHECK_EQUAL(acc2_id, lastRegularEventId);
1728 
1729  // after the next update, acc1 is back to consistent again
1730  DoocsServerTestHelper::runUpdate();
1731 
1732  acc1.read();
1733  acc1_id.read();
1734  BOOST_TEST(acc1.getVersionNumber() > acc1VersionForId0);
1735 
1736  BOOST_CHECK_MESSAGE(acc1.getVersionNumber() == acc1_id.getVersionNumber(),
1737  static_cast<std::string>(acc1.getVersionNumber()) + " should be equal to " +
1738  static_cast<std::string>(acc1_id.getVersionNumber()));
1739  BOOST_CHECK_EQUAL(acc1_id, idAfterZero);
1740 }
1741 
1742 /**********************************************************************************************************************/
createDummyXml
std::time_t createDummyXml(const std::string &filename)
Definition: testDoocsBackend.cpp:1259
DoocsLauncher::DoocsServer1
static std::string DoocsServer1
Definition: testDoocsBackend.cpp:69
DoocsLauncher::DoocsServer1_cached
static std::string DoocsServer1_cached
Definition: testDoocsBackend.cpp:70
BOOST_GLOBAL_FIXTURE
BOOST_GLOBAL_FIXTURE(DoocsLauncher)
DoocsLauncher::cacheFile1
static std::string cacheFile1
Definition: testDoocsBackend.cpp:71
eq_dummy
Definition: eq_dummy.h:7
DoocsLauncher::~DoocsLauncher
~DoocsLauncher() override
Definition: testDoocsBackend.cpp:63
DoocsLauncher
Definition: testDoocsBackend.cpp:37
DoocsLauncher::DoocsLauncher
DoocsLauncher()
Definition: testDoocsBackend.cpp:39
DoocsLauncher::rpc_no
static std::string rpc_no
Definition: testDoocsBackend.cpp:68
eq_dummy.h
DoocsLauncher::DoocsServer2_cached
static std::string DoocsServer2_cached
Definition: testDoocsBackend.cpp:74
eq_dummy::counter
int64_t counter
Definition: eq_dummy.h:34
DoocsLauncher::cacheFile2
static std::string cacheFile2
Definition: testDoocsBackend.cpp:75
DoocsLauncher::DoocsServer2
static std::string DoocsServer2
Definition: testDoocsBackend.cpp:73
ChimeraTK
Definition: spec_DoocsBackend.dox:2
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(testScalarInt)
Definition: testDoocsBackend.cpp:90