ChimeraTK-DeviceAccess  03.18.00
testSubdeviceBackend.cpp
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 
4 #include "Device.h"
5 
6 #include <thread>
7 
8 #define BOOST_TEST_DYN_LINK
9 #define BOOST_TEST_MODULE SubdeviceBackendTest
10 #define BOOST_NO_EXCEPTIONS
11 #include <boost/test/unit_test.hpp>
12 using namespace boost::unit_test_framework;
13 #undef BOOST_NO_EXCEPTIONS
14 
15 using namespace ChimeraTK;
16 
17 #define CHECK_TIMEOUT(execPreCheck, condition, maxMilliseconds) \
18  { \
19  std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); \
20  execPreCheck while(!(condition)) { \
21  bool timeout_reached = (std::chrono::steady_clock::now() - t0) > std::chrono::milliseconds(maxMilliseconds); \
22  BOOST_CHECK(!timeout_reached); \
23  if(timeout_reached) break; \
24  usleep(1000); \
25  execPreCheck \
26  } \
27  }
28 
29 BOOST_AUTO_TEST_SUITE(SubdeviceBackendTestSuite)
30 
31 /**********************************************************************************************************************/
32 
33 BOOST_AUTO_TEST_CASE(testOpenClose) {
34  setDMapFilePath("subdeviceTest.dmap");
35 
36  Device dev;
37  BOOST_CHECK(!dev.isOpened());
38  dev.open("SUBDEV1");
39  BOOST_CHECK(dev.isOpened());
40  dev.close();
41  BOOST_CHECK(!dev.isOpened());
42  dev.open();
43  BOOST_CHECK(dev.isOpened());
44  // It must always be possible to re-open and re-close a backend
45  dev.open();
46  BOOST_CHECK(dev.isOpened());
47  dev.open("SUBDEV1");
48  BOOST_CHECK(dev.isOpened());
49  dev.close();
50  BOOST_CHECK(!dev.isOpened());
51  dev.close();
52  BOOST_CHECK(!dev.isOpened());
53 }
54 
56 
57 /**********************************************************************************************************************/
58 
59 BOOST_AUTO_TEST_CASE(testMayReplaceOther) {
60  setDMapFilePath("subdeviceTest.dmap");
61 
62  Device dev;
63  dev.open("SUBDEV1");
64  Device target;
65  target.open("TARGET1");
66 
67  {
68  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1", 0, {AccessMode::raw});
69  auto acc1_2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1", 0, {AccessMode::raw});
70  BOOST_CHECK(acc1.getHighLevelImplElement()->mayReplaceOther(acc1_2.getHighLevelImplElement()));
71  BOOST_CHECK(acc1_2.getHighLevelImplElement()->mayReplaceOther(acc1.getHighLevelImplElement()));
72  }
73 
74  {
75  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1", 0, {AccessMode::raw});
76  auto acc1_2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1");
77  BOOST_CHECK(!acc1.getHighLevelImplElement()->mayReplaceOther(acc1_2.getHighLevelImplElement()));
78  BOOST_CHECK(!acc1_2.getHighLevelImplElement()->mayReplaceOther(acc1.getHighLevelImplElement()));
79  }
80 
81  {
82  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2");
83  auto acc1_2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2");
84  BOOST_CHECK(acc1.getHighLevelImplElement()->mayReplaceOther(acc1_2.getHighLevelImplElement()));
85  BOOST_CHECK(acc1_2.getHighLevelImplElement()->mayReplaceOther(acc1.getHighLevelImplElement()));
86  }
87 
88  {
89  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1");
90  auto acc1_2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2");
91  BOOST_CHECK(!acc1.getHighLevelImplElement()->mayReplaceOther(acc1_2.getHighLevelImplElement()));
92  BOOST_CHECK(!acc1_2.getHighLevelImplElement()->mayReplaceOther(acc1.getHighLevelImplElement()));
93  }
94 
95  {
96  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2");
97  auto acc1_2 = dev.getScalarRegisterAccessor<int16_t>("APP.0.MY_REGISTER2");
98  BOOST_CHECK(!acc1.getHighLevelImplElement()->mayReplaceOther(acc1_2.getHighLevelImplElement()));
99  BOOST_CHECK(!acc1_2.getHighLevelImplElement()->mayReplaceOther(acc1.getHighLevelImplElement()));
100  }
101 }
102 
103 /**********************************************************************************************************************/
104 
105 BOOST_AUTO_TEST_CASE(testWriteScalarRaw) {
106  setDMapFilePath("subdeviceTest.dmap");
107 
108  Device dev;
109  dev.open("SUBDEV1");
110  Device target;
111  target.open("TARGET1");
112 
113  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1", 0, {AccessMode::raw});
114  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 0, {AccessMode::raw});
115 
116  acc1 = 42;
117  acc1.write();
118  acc1t.read();
119  BOOST_CHECK_EQUAL(int32_t(acc1t), 42);
120 
121  acc1 = -120;
122  acc1.write();
123  acc1t.read();
124  BOOST_CHECK_EQUAL(int32_t(acc1t), -120);
125 
126  auto acc2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2", 0, {AccessMode::raw});
127  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 1, {AccessMode::raw});
128 
129  acc2 = 666;
130  acc2.write();
131  acc2t.read();
132  BOOST_CHECK_EQUAL(int32_t(acc2t), 666);
133 
134  acc2 = -99999;
135  acc2.write();
136  acc2t.read();
137  BOOST_CHECK_EQUAL(int32_t(acc2t), -99999);
138 
139  acc2.setAsCooked<float>(42.5);
140  BOOST_CHECK_EQUAL(int32_t(acc2), 170); // 42.5*4, 2 fractional bits
141  acc2 = 666 * 4;
142  BOOST_CHECK_CLOSE(acc2.getAsCooked<float>(), 666, 0.01);
143 
144  dev.close();
145 }
146 
147 /**********************************************************************************************************************/
148 
149 BOOST_AUTO_TEST_CASE(testWriteScalarInAreaRaw) {
150  setDMapFilePath("subdeviceTest.dmap");
151 
152  Device dev;
153  dev.open("SUBDEV1");
154  Device target;
155  target.open("TARGET1");
156 
157  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_AREA1", 0, {AccessMode::raw});
158  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 2, {AccessMode::raw});
159 
160  acc1 = 42;
161  acc1.write();
162  acc1t.read();
163  BOOST_CHECK_EQUAL((int32_t)acc1t, 42);
164 
165  acc1 = -120;
166  acc1.write();
167  acc1t.read();
168  BOOST_CHECK_EQUAL((int32_t)acc1t, -120);
169 
170  auto acc2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_AREA1", 3, {AccessMode::raw});
171  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 5, {AccessMode::raw});
172 
173  acc2 = 666;
174  acc2.write();
175  acc2t.read();
176  BOOST_CHECK_EQUAL((int32_t)acc2t, 666);
177 
178  acc2 = -99999;
179  acc2.write();
180  acc2t.read();
181  BOOST_CHECK_EQUAL((int32_t)acc2t, -99999);
182 
183  dev.close();
184 }
185 
186 /**********************************************************************************************************************/
187 
188 BOOST_AUTO_TEST_CASE(testWriteArrayRaw) {
189  setDMapFilePath("subdeviceTest.dmap");
190 
191  Device dev;
192  dev.open("SUBDEV1");
193  Device target;
194  target.open("TARGET1");
195 
196  auto acc1 = dev.getOneDRegisterAccessor<int32_t>("APP.0.MY_AREA1", 0, 0, {AccessMode::raw});
197  auto acc1t = target.getOneDRegisterAccessor<int32_t>("APP.0.THE_AREA", 6, 2, {AccessMode::raw});
198 
199  acc1 = {10, 20, 30, 40, 50, 60};
200  acc1.write();
201  acc1t.read();
202  BOOST_CHECK((std::vector<int32_t>)acc1t == std::vector<int32_t>({10, 20, 30, 40, 50, 60}));
203 
204  acc1 = {15, 25, 35, 45, 55, 65};
205  acc1.write();
206  acc1t.read();
207  BOOST_CHECK((std::vector<int32_t>)acc1t == std::vector<int32_t>({15, 25, 35, 45, 55, 65}));
208 
209  dev.close();
210 }
211 
212 /**********************************************************************************************************************/
213 
214 BOOST_AUTO_TEST_CASE(testWriteScalarCooked) {
215  setDMapFilePath("subdeviceTest.dmap");
216 
217  Device dev;
218  dev.open("SUBDEV1");
219  Device target;
220  target.open("TARGET1");
221 
222  auto acc1 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER1"); // 0 fractional bits
223  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 0, {AccessMode::raw});
224 
225  acc1 = 42;
226  acc1.write();
227  acc1t.read();
228  BOOST_CHECK_EQUAL((int32_t)acc1t, 42);
229 
230  acc1 = -120;
231  acc1.write();
232  acc1t.read();
233  BOOST_CHECK_EQUAL((int32_t)acc1t, -120);
234 
235  auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2"); // 2 fractional bits
236  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 1, {AccessMode::raw});
237 
238  acc2 = 666;
239  acc2.write();
240  acc2t.read();
241  BOOST_CHECK_EQUAL((int32_t)acc2t, 666 * 4);
242 
243  acc2 = -333;
244  acc2.write();
245  acc2t.read();
246  BOOST_CHECK_EQUAL((int32_t)acc2t,
247  (-333 * 4) & 0x3FFFF); // the raw value does not get negative since
248  // we have 18 bits only
249 
250  acc2 = -99999;
251  acc2.write();
252  acc2t.read();
253  BOOST_CHECK_EQUAL((int32_t)acc2t, 131072); // negative overflow
254 
255  dev.close();
256 }
257 
258 /**********************************************************************************************************************/
259 
260 BOOST_AUTO_TEST_CASE(testWriteArrayCooked) {
261  setDMapFilePath("subdeviceTest.dmap");
262 
263  Device dev;
264  dev.open("SUBDEV1");
265  Device target;
266  target.open("TARGET1");
267 
268  auto acc1 = dev.getOneDRegisterAccessor<int32_t>("APP.0.MY_AREA1");
269  auto acc1t = target.getOneDRegisterAccessor<int32_t>("APP.0.THE_AREA", 6, 2, {AccessMode::raw});
270 
271  acc1 = {10, 20, 30, 40, 50, 60};
272  acc1.write();
273  acc1t.read();
274  BOOST_CHECK((std::vector<int32_t>)acc1t ==
275  std::vector<int32_t>({10 * 65536, 20 * 65536, 30 * 65536, 40 * 65536, 50 * 65536, 60 * 65536}));
276 
277  acc1 = {15, 25, 35, 45, 55, 65};
278  acc1.write();
279  acc1t.read();
280  BOOST_CHECK((std::vector<int32_t>)acc1t ==
281  std::vector<int32_t>({15 * 65536, 25 * 65536, 35 * 65536, 45 * 65536, 55 * 65536, 65 * 65536}));
282 
283  dev.close();
284 }
285 
286 /**********************************************************************************************************************/
287 /**********************************************************************************************************************/
288 
289 BOOST_AUTO_TEST_CASE(testReadScalarRaw) {
290  setDMapFilePath("subdeviceTest.dmap");
291 
292  Device dev;
293  dev.open("SUBDEV1");
294  Device target;
295  target.open("TARGET1");
296 
297  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER1", 0, {AccessMode::raw});
298  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 0, {AccessMode::raw});
299 
300  acc1t = 42;
301  acc1t.write();
302  acc1.read();
303  BOOST_CHECK_EQUAL((int32_t)acc1, 42);
304 
305  acc1t = -120;
306  acc1t.write();
307  acc1.read();
308  BOOST_CHECK_EQUAL((int32_t)acc1, -120);
309 
310  auto acc2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_REGISTER2", 0, {AccessMode::raw});
311  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 1, {AccessMode::raw});
312 
313  acc2t = 666;
314  acc2t.write();
315  acc2.read();
316  BOOST_CHECK_EQUAL((int32_t)acc2, 666);
317 
318  acc2t = -99999;
319  acc2t.write();
320  acc2.read();
321  BOOST_CHECK_EQUAL((int32_t)acc2, -99999);
322 
323  dev.close();
324 }
325 
326 /**********************************************************************************************************************/
327 
328 BOOST_AUTO_TEST_CASE(testReadScalarInAreaRaw) {
329  setDMapFilePath("subdeviceTest.dmap");
330 
331  Device dev;
332  dev.open("SUBDEV1");
333  Device target;
334  target.open("TARGET1");
335 
336  auto acc1 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_AREA1", 0, {AccessMode::raw});
337  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 2, {AccessMode::raw});
338 
339  acc1t = 42;
340  acc1t.write();
341  acc1.read();
342  BOOST_CHECK_EQUAL((int32_t)acc1, 42);
343 
344  acc1t = -120;
345  acc1t.write();
346  acc1.read();
347  BOOST_CHECK_EQUAL((int32_t)acc1, -120);
348 
349  auto acc2 = dev.getScalarRegisterAccessor<int32_t>("APP.0.MY_AREA1", 3, {AccessMode::raw});
350  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 5, {AccessMode::raw});
351 
352  acc2t = 666;
353  acc2t.write();
354  acc2.read();
355  BOOST_CHECK_EQUAL((int32_t)acc2, 666);
356 
357  acc2t = -99999;
358  acc2t.write();
359  acc2.read();
360  BOOST_CHECK_EQUAL((int32_t)acc2, -99999);
361 
362  dev.close();
363 }
364 
365 /**********************************************************************************************************************/
366 
367 BOOST_AUTO_TEST_CASE(testReadArrayRaw) {
368  setDMapFilePath("subdeviceTest.dmap");
369 
370  Device dev;
371  dev.open("SUBDEV1");
372  Device target;
373  target.open("TARGET1");
374 
375  auto acc1 = dev.getOneDRegisterAccessor<int32_t>("APP.0.MY_AREA1", 0, 0, {AccessMode::raw});
376  auto acc1t = target.getOneDRegisterAccessor<int32_t>("APP.0.THE_AREA", 6, 2, {AccessMode::raw});
377 
378  acc1t = {10, 20, 30, 40, 50, 60};
379  acc1t.write();
380  acc1.read();
381  BOOST_CHECK((std::vector<int32_t>)acc1 == std::vector<int32_t>({10, 20, 30, 40, 50, 60}));
382 
383  acc1t = {15, 25, 35, 45, 55, 65};
384  acc1t.write();
385  acc1.read();
386  BOOST_CHECK((std::vector<int32_t>)acc1 == std::vector<int32_t>({15, 25, 35, 45, 55, 65}));
387 
388  dev.close();
389 }
390 
391 /**********************************************************************************************************************/
392 
393 BOOST_AUTO_TEST_CASE(testReadScalarCooked) {
394  setDMapFilePath("subdeviceTest.dmap");
395 
396  Device dev;
397  dev.open("SUBDEV1");
398  Device target;
399  target.open("TARGET1");
400 
401  auto acc1 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER1"); // 0 fractional bits
402  auto acc1t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 0, {AccessMode::raw});
403 
404  acc1t = 42;
405  acc1t.write();
406  acc1.read();
407  BOOST_CHECK_EQUAL((int32_t)acc1, 42);
408 
409  acc1t = -120;
410  acc1t.write();
411  acc1.read();
412  BOOST_CHECK_EQUAL((int32_t)acc1, -120);
413 
414  auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2"); // 2 fractional bits
415  auto acc2t = target.getScalarRegisterAccessor<int32_t>("APP.0.THE_AREA", 1, {AccessMode::raw});
416 
417  acc2t = 666 * 4;
418  acc2t.write();
419  acc2.read();
420  BOOST_CHECK_EQUAL((int32_t)acc2, 666);
421 
422  acc2t = -333 * 4;
423  acc2t.write();
424  acc2.read();
425  BOOST_CHECK_EQUAL((int32_t)acc2,
426  -333); // the raw value does not get negative since we have 18 bits only
427 
428  acc2t = 131072;
429  acc2t.write();
430  acc2.read();
431  BOOST_CHECK_EQUAL((int32_t)acc2, -32768);
432 
433  dev.close();
434 }
435 
436 /**********************************************************************************************************************/
437 
438 BOOST_AUTO_TEST_CASE(testReadArrayCooked) {
439  setDMapFilePath("subdeviceTest.dmap");
440 
441  Device dev;
442  dev.open("SUBDEV1");
443  Device target;
444  target.open("TARGET1");
445 
446  auto acc1 = dev.getOneDRegisterAccessor<int32_t>("APP.0.MY_AREA1");
447  auto acc1t = target.getOneDRegisterAccessor<int32_t>("APP.0.THE_AREA", 6, 2, {AccessMode::raw});
448 
449  acc1t = {10 * 65536, 20 * 65536, 30 * 65536, 40 * 65536, 50 * 65536, 60 * 65536};
450  acc1t.write();
451  acc1.read();
452  BOOST_CHECK((std::vector<int32_t>)acc1 == std::vector<int32_t>({10, 20, 30, 40, 50, 60}));
453 
454  acc1t = {15 * 65536, 25 * 65536, 35 * 65536, 45 * 65536, 55 * 65536, 65 * 65536};
455  acc1t.write();
456  acc1.read();
457  BOOST_CHECK((std::vector<int32_t>)acc1 == std::vector<int32_t>({15, 25, 35, 45, 55, 65}));
458 
459  dev.close();
460 }
461 
462 /**********************************************************************************************************************/
463 
464 BOOST_AUTO_TEST_CASE(test3regsScalar) {
465  setDMapFilePath("subdeviceTest.dmap");
466 
467  Device dev;
468  dev.open("SUBDEV2");
469  Device target;
470  target.open("TARGET1");
471 
472  auto acc1 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER1");
473  auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2");
474  auto accA = target.getScalarRegisterAccessor<int32_t>("APP.1.ADDRESS");
475  auto accD = target.getScalarRegisterAccessor<int32_t>("APP.1.DATA");
476  auto accS = target.getScalarRegisterAccessor<int32_t>("APP.1.STATUS");
477  std::atomic<bool> done;
478  std::thread t;
479 
480  BOOST_CHECK_THROW(acc1.read(), ChimeraTK::logic_error);
481  BOOST_CHECK_THROW(acc2.read(), ChimeraTK::logic_error);
482 
483  accS = 1;
484  accS.write();
485  done = false;
486  t = std::thread([&] {
487  acc2 = 42;
488  acc2.write();
489  done = true;
490  });
491  usleep(10000);
492  BOOST_CHECK(done == false);
493  accS = 0;
494  accS.write();
495  CHECK_TIMEOUT(accA.read();, (accA == 4), 5000);
496  t.join();
497  accD.read();
498  BOOST_CHECK_EQUAL(static_cast<int32_t>(accD), 42 * 4);
499 
500  acc1 = 120;
501  acc1.write();
502  accA.read();
503  BOOST_CHECK_EQUAL(static_cast<int32_t>(accA), 0);
504  accD.read();
505  BOOST_CHECK_EQUAL(static_cast<int32_t>(accD), 120);
506 
507  dev.close();
508 }
509 
510 /**********************************************************************************************************************/
511 
512 BOOST_AUTO_TEST_CASE(test3regsArray) {
513  setDMapFilePath("subdeviceTest.dmap");
514 
515  Device dev;
516  dev.open("SUBDEV2");
517  Device target;
518  target.open("TARGET1");
519 
520  auto accArea = dev.getOneDRegisterAccessor<double>("APP.0.MY_AREA2");
521  auto accA = target.getScalarRegisterAccessor<int32_t>("APP.1.ADDRESS");
522  auto accD = target.getScalarRegisterAccessor<int32_t>("APP.1.DATA");
523  auto accS = target.getScalarRegisterAccessor<int32_t>("APP.1.STATUS");
524  std::atomic<bool> done;
525  std::thread t;
526 
527  accS = 1;
528  accS.write();
529  done = false;
530  t = std::thread([&] {
531  accArea[0] = 123;
532  accArea[1] = 456;
533  accArea.write();
534  done = true;
535  });
536  usleep(10000);
537  BOOST_CHECK(done == false);
538  accS = 0;
539  accS.write();
540  CHECK_TIMEOUT(accA.read();, (accA == 33), 5000);
541  t.join();
542  accD.read();
543  BOOST_CHECK_EQUAL(static_cast<int32_t>(accD), 456);
544 
547 
548  dev.close();
549 }
550 
551 /**********************************************************************************************************************/
552 
553 BOOST_AUTO_TEST_CASE(test3regsByteOffset1) {
554  setDMapFilePath("subdeviceTest.dmap");
555 
556  Device dev;
557  dev.open("SUBDEV2");
558  Device target;
559  target.open("TARGET1");
560 
561  auto acc = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER_AT_BYTE_1");
562  auto accA = target.getScalarRegisterAccessor<int32_t>("APP.1.ADDRESS");
563  auto accD = target.getScalarRegisterAccessor<int32_t>("APP.1.DATA");
564  auto accS = target.getScalarRegisterAccessor<int32_t>("APP.1.STATUS");
565  std::atomic<bool> done;
566  std::thread t;
567 
568  BOOST_CHECK_THROW(acc.read(), ChimeraTK::logic_error);
569 
570  accS = 1;
571  accS.write();
572  done = false;
573  t = std::thread([&] {
574  acc = 1897;
575  acc.write();
576  done = true;
577  });
578  usleep(10000);
579  BOOST_CHECK(done == false);
580  accS = 0;
581  accS.write();
582  t.join();
583  accA.read();
584  BOOST_CHECK(accA == 1);
585  accD.read();
586  BOOST_CHECK(accD == 1897);
587 
588  dev.close();
589 }
590 
591 /**********************************************************************************************************************/
592 
593 BOOST_AUTO_TEST_CASE(testAreaHandshake1) {
594  setDMapFilePath("subdeviceTestAreaHandshake.dmap");
595 
596  Device dev;
597  dev.open("SUBDEV4");
598  Device target;
599  target.open("TARGET1");
600 
601  auto acc1 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER1");
602  auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2");
603  auto acc3 = dev.getOneDRegisterAccessor<int>("APP.0.MY_AREA1", 6, 0);
604  auto accArea = target.getOneDRegisterAccessor<int32_t>("APP.0.THE_AREA", 10, 0, {AccessMode::raw});
605  auto accS = target.getScalarRegisterAccessor<int32_t>("APP.1.STATUS");
606  std::atomic<bool> done;
607  std::thread t;
608 
609  BOOST_CHECK_THROW(acc1.read(), ChimeraTK::logic_error);
610  std::vector<int> vec = {1, 2, 3, 4, 5, 6};
611 
612  accS = 1;
613  accS.write();
614  done = false;
615  t = std::thread([&] {
616  acc1 = 1897;
617  acc2 = 1897;
618  acc3 = vec;
619  acc1.write();
620  acc2.write();
621  acc3.write();
622  done = true;
623  });
624  usleep(10000);
625  BOOST_CHECK(done == false);
626  int countStatusResets = 0;
627  // the dummyForAreaHandshake backend which we use for this test does not set back the status register. we do it
628  // manually from the test, and count how often we need do so Like this we can check that the accessor waits on
629  // status==0 _each_ time before writing, in particular each array entry counts.
630  while(true) {
631  // wait for status=busy
632  do {
633  accS.read();
634  usleep(20000);
635  } while(accS == 0 && !done);
636  if(done) break;
637  countStatusResets++;
638  accS = 0;
639  accS.write();
640  }
641  BOOST_CHECK(countStatusResets == 8);
642  t.join();
643  accArea.read();
644  BOOST_CHECK(accArea[0] == 1897);
645  BOOST_CHECK(accArea[1] == 1897 * 4);
646  BOOST_CHECK(accArea[2] == 65536 * vec[0]);
647  BOOST_CHECK(accArea[3] == 65536 * vec[1]);
648  dev.close();
649 }
650 
651 /**********************************************************************************************************************/
652 
653 BOOST_AUTO_TEST_CASE(test2regsScalar) {
654  setDMapFilePath("subdeviceTest.dmap");
655 
656  Device dev;
657  dev.open("SUBDEV3");
658  Device target;
659  target.open("TARGET1");
660 
661  auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2");
662  auto accA = target.getScalarRegisterAccessor<int32_t>("APP.1.ADDRESS");
663  auto accD = target.getScalarRegisterAccessor<int32_t>("APP.1.DATA");
664 
665  BOOST_CHECK_THROW(acc2.read(), ChimeraTK::logic_error);
666  accA = 42;
667  accA.write();
668 
669  auto start = std::chrono::steady_clock::now();
670  acc2 = 666;
671  acc2.write();
673  std::chrono::duration<double> diff = stop - start;
674  BOOST_CHECK(diff.count() >= 1.0); // sleep time is set to 1 second
675 
676  accA.read();
677  BOOST_CHECK(accA == 4);
678  accD.read();
679  BOOST_CHECK_EQUAL(static_cast<int32_t>(accD), 666 * 4);
680 
681  dev.close();
682 }
683 
684 /**********************************************************************************************************************/
685 
686 BOOST_AUTO_TEST_CASE(testIsFunctional) {
687  setDMapFilePath("subdeviceTest.dmap");
688 
689  Device dev;
690  dev.open("SUBDEV1");
691  Device target;
692  target.open("TARGET1");
693  BOOST_CHECK(dev.isFunctional());
694  dev.setException("Test Exception");
695  // Device should not be functional anymore
696  BOOST_CHECK(!dev.isFunctional());
697  dev.open();
698  BOOST_CHECK(dev.isFunctional());
699  dev.close();
700  BOOST_CHECK(!dev.isFunctional());
701 }
702 
703 /**********************************************************************************************************************/
704 
705 BOOST_AUTO_TEST_SUITE_END()
ChimeraTK::Device::close
void close()
Close the device.
Definition: Device.cc:66
ChimeraTK::Device::getOneDRegisterAccessor
OneDRegisterAccessor< UserType > getOneDRegisterAccessor(const RegisterPath &registerPathName, size_t numberOfWords=0, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a OneDRegisterAccessor object for the given register.
Definition: Device.h:273
MirrorRequestType::stop
@ stop
ChimeraTK::testable_rebot_sleep::now
boost::chrono::steady_clock::time_point now()
Definition: testableRebotSleep.cc:7
Device.h
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(testOpenClose)
Definition: testSubdeviceBackend.cpp:33
CHECK_TIMEOUT
#define CHECK_TIMEOUT(execPreCheck, condition, maxMilliseconds)
Definition: testSubdeviceBackend.cpp:17
ChimeraTK::Device
Class allows to read/write registers from device.
Definition: Device.h:39
ChimeraTK::Device::open
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition: Device.cc:58
ChimeraTK::Device::getScalarRegisterAccessor
ScalarRegisterAccessor< UserType > getScalarRegisterAccessor(const RegisterPath &registerPathName, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a ScalarRegisterObject object for the given register.
Definition: Device.h:263
ChimeraTK::Device::isOpened
bool isOpened() const
Check if the device is currently opened.
Definition: Device.cc:73
ChimeraTK::setDMapFilePath
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
Definition: Utilities.cpp:327
ChimeraTK::Device::isFunctional
bool isFunctional() const
Return wether a device is working as intended, usually this means it is opened and does not have any ...
Definition: Device.cc:82
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51
ChimeraTK::Device::setException
void setException(const std::string &message)
Set the device into an exception state.
Definition: Device.cc:97