ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
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>
12using namespace boost::unit_test_framework;
13#undef BOOST_NO_EXCEPTIONS
14
15using 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
29BOOST_AUTO_TEST_SUITE(SubdeviceBackendTestSuite)
30
31/**********************************************************************************************************************/
32
33BOOST_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
59BOOST_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
105BOOST_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
149BOOST_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
188BOOST_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
214BOOST_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
260BOOST_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
289BOOST_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
328BOOST_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
367BOOST_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
393BOOST_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
438BOOST_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
464BOOST_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
512BOOST_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
553BOOST_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
593BOOST_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 = 0;
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 BOOST_CHECK(done == false);
625 int countStatusResets = 0;
626 // the dummyForAreaHandshake backend which we use for this test does not set back the status register. we do it
627 // manually from the test, and count how often we need do so Like this we can check that the accessor waits on
628 // status==0 _each_ time before writing, in particular each array entry counts.
629 while(true) {
630 // wait for status=busy
631 do {
632 accS.read();
633 usleep(20000);
634 } while(accS == 0 && !done);
635 if(done) break;
636 countStatusResets++;
637 accS = 0;
638 accS.write();
639 }
640 BOOST_TEST(countStatusResets == 8);
641 t.join();
642 accArea.read();
643 BOOST_CHECK(accArea[0] == 1897);
644 BOOST_CHECK(accArea[1] == 1897 * 4);
645 BOOST_CHECK(accArea[2] == 65536 * vec[0]);
646 BOOST_CHECK(accArea[3] == 65536 * vec[1]);
647 dev.close();
648}
649
650/**********************************************************************************************************************/
651
652BOOST_AUTO_TEST_CASE(test2regsScalar) {
653 setDMapFilePath("subdeviceTest.dmap");
654
655 Device dev;
656 dev.open("SUBDEV3");
657 Device target;
658 target.open("TARGET1");
659
660 auto acc2 = dev.getScalarRegisterAccessor<double>("APP.0.MY_REGISTER2");
661 auto accA = target.getScalarRegisterAccessor<int32_t>("APP.1.ADDRESS");
662 auto accD = target.getScalarRegisterAccessor<int32_t>("APP.1.DATA");
663
664 BOOST_CHECK_THROW(acc2.read(), ChimeraTK::logic_error);
665 accA = 42;
666 accA.write();
667
668 auto start = std::chrono::steady_clock::now();
669 acc2 = 666;
670 acc2.write();
671 auto stop = std::chrono::steady_clock::now();
672 std::chrono::duration<double> diff = stop - start;
673 BOOST_CHECK(diff.count() >= 1.0); // sleep time is set to 1 second
674
675 accA.read();
676 BOOST_CHECK(accA == 4);
677 accD.read();
678 BOOST_CHECK_EQUAL(static_cast<int32_t>(accD), 666 * 4);
679
680 dev.close();
681}
682
683/**********************************************************************************************************************/
684
685BOOST_AUTO_TEST_CASE(testIsFunctional) {
686 setDMapFilePath("subdeviceTest.dmap");
687
688 Device dev;
689 dev.open("SUBDEV1");
690 Device target;
691 target.open("TARGET1");
692 BOOST_CHECK(dev.isFunctional());
693 dev.setException("Test Exception");
694 // Device should not be functional anymore
695 BOOST_CHECK(!dev.isFunctional());
696 dev.open();
697 BOOST_CHECK(dev.isFunctional());
698 dev.close();
699 BOOST_CHECK(!dev.isFunctional());
700}
701
702/**********************************************************************************************************************/
703
704BOOST_AUTO_TEST_CASE(TestInvolvedBackendIDs) {
705 setDMapFilePath("subdeviceTest.dmap");
706
707 ChimeraTK::Device device("SUBDEV1");
708 ChimeraTK::Device target1("TARGET1");
709
710 auto deviceIDs = device.getInvolvedBackendIDs();
711 BOOST_TEST(deviceIDs.size() == 2);
712 BOOST_TEST(deviceIDs.contains(target1.getBackend()->getBackendID()));
713 BOOST_TEST(deviceIDs.contains(device.getBackend()->getBackendID()));
714}
715
716/**********************************************************************************************************************/
717
718BOOST_AUTO_TEST_SUITE_END()
Class allows to read/write registers from device.
Definition Device.h:39
bool isOpened() const
Check if the device is currently opened.
Definition Device.cc:73
std::set< DeviceBackend::BackendID > getInvolvedBackendIDs()
Recursively obtain the set of all backend IDs that are used withing the device.
Definition Device.cc:117
void close()
Close the device.
Definition Device.cc:66
void setException(const std::string &message)
Set the device into an exception state.
Definition Device.cc:97
boost::shared_ptr< DeviceBackend > getBackend()
Obtain the backend.
Definition Device.cc:111
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:266
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:276
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
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
Exception thrown when a logic error has occured.
Definition Exception.h:51
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
ctk::Device device
#define CHECK_TIMEOUT(execPreCheck, condition, maxMilliseconds)
BOOST_AUTO_TEST_CASE(testOpenClose)