ChimeraTK-DeviceAccess  03.18.00
testTransferGroup.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 #define BOOST_TEST_DYN_LINK
5 #define BOOST_TEST_MODULE TransferGroupTest
6 #include <boost/test/unit_test.hpp>
7 using namespace boost::unit_test_framework;
8 
10 #include "Device.h"
11 #include "ExceptionDummyBackend.h"
15 #include "TransferGroup.h"
16 
17 using namespace boost::unit_test_framework;
18 using namespace ChimeraTK;
19 
20 boost::shared_ptr<TransferElementTestAccessor<int32_t>> makeTETA(AccessModeFlags flags = {}) {
21  return boost::make_shared<TransferElementTestAccessor<int32_t>>(flags);
22 }
23 
24 /**********************************************************************************************************************/
25 /**********************************************************************************************************************/
27 /**********************************************************************************************************************/
28 /**********************************************************************************************************************/
29 
34 BOOST_AUTO_TEST_CASE(test_B_12_1_3) {
35  std::cout << "test_B_12_1_3" << std::endl;
36  std::map<TransferElementID, bool> foundIds;
37 
38  auto A = makeTETA();
39  auto B = makeTETA();
40 
41  for(size_t i = 0; i < 3; ++i) A->_internalElements.push_back(makeTETA());
42  for(size_t i = 0; i < 4; ++i) B->_internalElements.push_back(makeTETA());
43 
44  TransferGroup group;
45 
46  A->resetCounters();
47  group.addAccessor(A);
48  foundIds.clear();
49  for(auto& id : A->_listReplacementElements) foundIds[id] = true;
50  for(auto& e : A->_internalElements) BOOST_CHECK(foundIds[e->getId()] == true);
51 
52  A->resetCounters();
53  B->resetCounters();
54  group.addAccessor(B);
55  foundIds.clear();
56  for(auto& id : A->_listReplacementElements) foundIds[id] = true;
57  for(auto& e : A->_internalElements) BOOST_CHECK(foundIds[e->getId()] == true);
58  for(auto& e : B->_internalElements) BOOST_CHECK(foundIds[e->getId()] == true);
59  foundIds.clear();
60  for(auto& id : B->_listReplacementElements) foundIds[id] = true;
61  for(auto& e : A->_internalElements) BOOST_CHECK(foundIds[e->getId()] == true);
62  for(auto& e : B->_internalElements) BOOST_CHECK(foundIds[e->getId()] == true);
63 }
64 
65 /**********************************************************************************************************************/
66 
71 BOOST_AUTO_TEST_CASE(test_B_12_3) {
72  std::cout << "test_B_12_3" << std::endl;
73  auto A = makeTETA();
74  TransferGroup group;
75  group.addAccessor(A);
76  BOOST_CHECK_THROW(A->read(), ChimeraTK::logic_error);
77  BOOST_CHECK_THROW(A->readNonBlocking(), ChimeraTK::logic_error);
78  BOOST_CHECK_THROW(A->readLatest(), ChimeraTK::logic_error);
79  BOOST_CHECK_THROW(A->write(), ChimeraTK::logic_error);
80  BOOST_CHECK_THROW(A->writeDestructively(), ChimeraTK::logic_error);
81 }
82 
83 /**********************************************************************************************************************/
84 
89 BOOST_AUTO_TEST_CASE(test_B_12_4) {
90  std::cout << "test_B_12_4" << std::endl;
91 
92  // situation: all accessors are read-write
93  {
94  auto A = makeTETA();
95  auto B = makeTETA();
96  TransferGroup group;
97  group.addAccessor(A);
98  group.addAccessor(B);
99  BOOST_CHECK(group.isReadOnly() == false);
100  }
101 
102  // situation: accessor read-only while adding
103  {
104  auto A = makeTETA();
105  auto B = makeTETA();
106  B->_writeable = false;
107  TransferGroup group;
108  group.addAccessor(A);
109  BOOST_CHECK(group.isReadOnly() == false);
110  group.addAccessor(B);
111  BOOST_CHECK(group.isReadOnly() == true);
112  }
113 
114  // situation: accessor becomes read-only only later (at runtime error)
115  {
116  auto A = makeTETA();
117  auto B = makeTETA();
118  TransferGroup group;
119  group.addAccessor(A);
120  group.addAccessor(B);
121  B->_throwRuntimeErrInTransfer = true;
122  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error); // no check intended, just catch
123  B->_writeable = false;
124  B->_throwRuntimeErrInTransfer = false;
125  BOOST_CHECK(group.isReadOnly() == true);
126  }
127 }
128 
129 /**********************************************************************************************************************/
130 
135 BOOST_AUTO_TEST_CASE(test_B_12_5) {
136  std::cout << "test_B_12_5" << std::endl;
137  auto A = makeTETA();
138  TransferGroup group;
139  group.addAccessor(A);
140  BOOST_CHECK_THROW(group.addAccessor(A), ChimeraTK::logic_error);
141 }
142 
143 /**********************************************************************************************************************/
144 
149 BOOST_AUTO_TEST_CASE(test_B_12_6) {
150  std::cout << "test_B_12_6" << std::endl;
151  auto A = makeTETA();
152  TransferGroup group1;
153  TransferGroup group2;
154  group1.addAccessor(A);
155  BOOST_CHECK_THROW(group2.addAccessor(A), ChimeraTK::logic_error);
156 }
157 
158 /**********************************************************************************************************************/
159 
164 BOOST_AUTO_TEST_CASE(test_B_12_7) {
165  std::cout << "test_B_12_7" << std::endl;
166  auto A = makeTETA({AccessMode::wait_for_new_data});
167  TransferGroup group;
168  BOOST_CHECK_THROW(group.addAccessor(A), ChimeraTK::logic_error);
169 }
170 
171 /**********************************************************************************************************************/
172 
177 BOOST_AUTO_TEST_CASE(test_B_12_8) {
178  std::cout << "test_B_12_8" << std::endl;
179  auto A = makeTETA();
180  auto B = makeTETA();
181  A->_listMayReplaceElements.insert(B->getId());
184 
185  TransferGroup group;
186  group.addAccessor(a);
187  group.addAccessor(b);
188 
189  BOOST_CHECK(b.getHighLevelImplElement() != B);
190 
191  A->_setPostReadData = 42;
192  group.read();
193  BOOST_CHECK_EQUAL(a[0][0], 42);
194  BOOST_CHECK_EQUAL(b[0][0], 42);
195 }
196 
197 /**********************************************************************************************************************/
198 
199 // helper macros for next test
200 // we use macros so line numbers make more sens if checks fail
201 #define CHECK_COUNTERS_HIGH_LEVEL(te, isWrite, expectedOrderPreMax, expectedOrderPostMin, expectTransfer) \
202  if(!isWrite) { \
203  BOOST_CHECK_EQUAL(te->_preRead_counter, 1); \
204  BOOST_CHECK_EQUAL(te->_preWrite_counter, 0); \
205  BOOST_CHECK_EQUAL(te->_postRead_counter, 1); \
206  BOOST_CHECK_EQUAL(te->_postWrite_counter, 0); \
207  if(expectTransfer) { \
208  BOOST_CHECK_EQUAL(te->_readTransfer_counter, 1); \
209  } \
210  } \
211  else { \
212  BOOST_CHECK_EQUAL(te->_preRead_counter, 0); \
213  BOOST_CHECK_EQUAL(te->_preWrite_counter, 1); \
214  BOOST_CHECK_EQUAL(te->_postRead_counter, 0); \
215  BOOST_CHECK_EQUAL(te->_postWrite_counter, 1); \
216  if(expectTransfer) { \
217  BOOST_CHECK_EQUAL(te->_writeTransfer_counter, 1); \
218  } \
219  } \
220  if(!expectTransfer) { \
221  BOOST_CHECK_EQUAL(te->_readTransfer_counter, 0); \
222  BOOST_CHECK_EQUAL(te->_writeTransfer_counter, 0); \
223  } \
224  \
225  BOOST_CHECK(te->_preIndex <= expectedOrderPreMax); \
226  BOOST_CHECK(te->_postIndex >= expectedOrderPostMin)
227 
228 #define CHECK_COUNTERS_MID_LEVEL(te) \
229  BOOST_CHECK_EQUAL(te->_preRead_counter, 0); /* our test accessor does not delegate this...*/ \
230  BOOST_CHECK_EQUAL(te->_preWrite_counter, 0); \
231  BOOST_CHECK_EQUAL(te->_readTransfer_counter, 0); \
232  BOOST_CHECK_EQUAL(te->_writeTransfer_counter, 0); \
233  BOOST_CHECK_EQUAL(te->_postRead_counter, 0); /* our test accessor does not delegate this... */ \
234  BOOST_CHECK_EQUAL(te->_postWrite_counter, 0)
235 
236 #define CHECK_COUNTERS_LOW_LEVEL(te, isWrite, expectedOrderMin, expectedOrderMax) \
237  BOOST_CHECK_EQUAL(te->_preRead_counter, 0); /* our test accessor does not delegate this... */ \
238  BOOST_CHECK_EQUAL(te->_preWrite_counter, 0); \
239  if(!isWrite) { \
240  BOOST_CHECK_EQUAL(te->_readTransfer_counter, 1); \
241  BOOST_CHECK_EQUAL(te->_writeTransfer_counter, 0); \
242  } \
243  else { \
244  BOOST_CHECK_EQUAL(te->_readTransfer_counter, 0); \
245  BOOST_CHECK_EQUAL(te->_writeTransfer_counter, 1); \
246  } \
247  BOOST_CHECK_EQUAL(te->_postRead_counter, 0); /* our test accessor does not delegate this... */ \
248  BOOST_CHECK_EQUAL(te->_postWrite_counter, 0); \
249  \
250  BOOST_CHECK(te->_transferIndex >= expectedOrderMin); \
251  BOOST_CHECK(te->_transferIndex <= expectedOrderMax)
252 
253 /**********************************************************************************************************************/
254 
259 BOOST_AUTO_TEST_CASE(test_B_12_9) {
260  std::cout << "test_B_12_9" << std::endl;
261  auto A = makeTETA();
262  auto B = makeTETA();
263 
264  // A has just one low-level transfer element
265  for(size_t i = 0; i < 1; ++i) {
266  A->_internalElements.push_back(makeTETA());
267  A->_hardwareAccessingElements.push_back(A->_internalElements[i]);
268  }
269  // B has two low-level transfer elements and one additional internal
270  for(size_t i = 0; i < 2; ++i) {
271  B->_internalElements.push_back(makeTETA());
272  B->_hardwareAccessingElements.push_back(B->_internalElements[i]);
273  }
274  B->_internalElements.push_back(makeTETA());
275 
276  TransferGroup group;
277 
278  group.addAccessor(A);
279  group.addAccessor(B);
280 
281  A->resetCounters();
282  B->resetCounters();
283  for(auto& e : A->_internalElements) e->resetCounters();
284  for(auto& e : B->_internalElements) e->resetCounters();
285  group.read();
286  CHECK_COUNTERS_HIGH_LEVEL(A, false, 1, 5, false);
287  CHECK_COUNTERS_HIGH_LEVEL(B, false, 1, 5, false);
288  CHECK_COUNTERS_MID_LEVEL(B->_internalElements[2]);
289  CHECK_COUNTERS_LOW_LEVEL(A->_internalElements[0], false, 2, 4);
290  CHECK_COUNTERS_LOW_LEVEL(B->_internalElements[0], false, 2, 4);
291  CHECK_COUNTERS_LOW_LEVEL(B->_internalElements[1], false, 2, 4);
292 }
293 /**********************************************************************************************************************/
294 
299 BOOST_AUTO_TEST_CASE(test_B_12_10_1_1) {
300  std::cout << "test_B_12_10_1_1" << std::endl;
301  auto A = makeTETA();
302  A->_throwRuntimeErrInPreconditions = true;
303  TransferGroup group;
304  group.addAccessor(A);
305  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error);
306  BOOST_CHECK_THROW(group.write(), ChimeraTK::runtime_error);
307  BOOST_CHECK_EQUAL(A->_preRead_counter, 0);
308  BOOST_CHECK_EQUAL(A->_preWrite_counter, 0);
309  BOOST_CHECK_EQUAL(A->_readTransfer_counter, 0);
310  BOOST_CHECK_EQUAL(A->_writeTransfer_counter, 0);
311  BOOST_CHECK_EQUAL(A->_writeTransferDestructively_counter, 0);
312  BOOST_CHECK_EQUAL(A->_postRead_counter, 0);
313  BOOST_CHECK_EQUAL(A->_postWrite_counter, 0);
314 }
315 
316 /**********************************************************************************************************************/
317 
322 BOOST_AUTO_TEST_CASE(test_B_12_10_1_2) {
323  std::cout << "test_B_12_10_1_2" << std::endl;
324  {
325  auto A = makeTETA();
326  A->_readable = false;
327  TransferGroup group;
328  group.addAccessor(A);
329  BOOST_CHECK_THROW(group.read(), ChimeraTK::logic_error);
330  BOOST_CHECK_EQUAL(A->_preRead_counter, 0);
331  BOOST_CHECK_EQUAL(A->_preWrite_counter, 0);
332  BOOST_CHECK_EQUAL(A->_readTransfer_counter, 0);
333  BOOST_CHECK_EQUAL(A->_writeTransfer_counter, 0);
334  BOOST_CHECK_EQUAL(A->_writeTransferDestructively_counter, 0);
335  BOOST_CHECK_EQUAL(A->_postRead_counter, 0);
336  BOOST_CHECK_EQUAL(A->_postWrite_counter, 0);
337  BOOST_CHECK_NO_THROW(group.write());
338  }
339  {
340  auto A = makeTETA();
341  A->_writeable = false;
342  TransferGroup group;
343  group.addAccessor(A);
344  BOOST_CHECK_THROW(group.write(), ChimeraTK::logic_error);
345  BOOST_CHECK_EQUAL(A->_preRead_counter, 0);
346  BOOST_CHECK_EQUAL(A->_preWrite_counter, 0);
347  BOOST_CHECK_EQUAL(A->_readTransfer_counter, 0);
348  BOOST_CHECK_EQUAL(A->_writeTransfer_counter, 0);
349  BOOST_CHECK_EQUAL(A->_writeTransferDestructively_counter, 0);
350  BOOST_CHECK_EQUAL(A->_postRead_counter, 0);
351  BOOST_CHECK_EQUAL(A->_postWrite_counter, 0);
352  BOOST_CHECK_NO_THROW(group.read());
353  }
354 }
355 
356 /**********************************************************************************************************************/
357 
364 BOOST_AUTO_TEST_CASE(test_B_12_10_3) {
365  std::cout << "test_B_12_10_3" << std::endl;
366  auto A = makeTETA();
367  auto B = makeTETA();
368 
369  // A has just one low-level transfer element
370  for(size_t i = 0; i < 1; ++i) {
371  A->_internalElements.push_back(makeTETA());
372  A->_hardwareAccessingElements.push_back(A->_internalElements[i]);
373  }
374 
375  TransferGroup group;
376 
377  group.addAccessor(A);
378  group.addAccessor(B);
379 
380  A->resetCounters();
381  B->resetCounters();
382  for(auto& e : A->_internalElements) e->resetCounters();
383  A->_internalElements[0]->_throwRuntimeErrInTransfer = true;
384  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error); // (no test intended, just catch)
385  BOOST_CHECK(A->_seenActiveException == A->_internalElements[0]->_thrownException);
386  BOOST_CHECK(A->_internalElements[0]->_seenActiveException == nullptr); // the test TE does not delegate the exception
387 }
388 
389 /**********************************************************************************************************************/
390 
395 BOOST_AUTO_TEST_CASE(test_B_12_10_4) {
396  std::cout << "test_B_12_10_4" << std::endl;
397  auto A = makeTETA();
398  auto B = makeTETA();
399 
400  TransferGroup group;
401 
402  group.addAccessor(A);
403  group.addAccessor(B);
404 
405  // A throws in read
406  A->resetCounters();
407  B->resetCounters();
408  A->_throwRuntimeErrInTransfer = true;
409  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error);
410  CHECK_COUNTERS_HIGH_LEVEL(A, false, 1, 4, true);
411  CHECK_COUNTERS_HIGH_LEVEL(B, false, 1, 4, true);
412 
413  // B throws in read
414  A->resetCounters();
415  B->resetCounters();
416  B->_throwRuntimeErrInTransfer = true;
417  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error);
418  CHECK_COUNTERS_HIGH_LEVEL(A, false, 1, 4, true);
419  CHECK_COUNTERS_HIGH_LEVEL(B, false, 1, 4, true);
420 
421  // both throw in read
422  A->resetCounters();
423  B->resetCounters();
424  A->_throwRuntimeErrInTransfer = true;
425  B->_throwRuntimeErrInTransfer = true;
426  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error);
427  CHECK_COUNTERS_HIGH_LEVEL(A, false, 1, 4, true);
428  CHECK_COUNTERS_HIGH_LEVEL(B, false, 1, 4, true);
429 
430  // A throws in write
431  A->resetCounters();
432  B->resetCounters();
433  A->_throwRuntimeErrInTransfer = true;
434  BOOST_CHECK_THROW(group.write(), ChimeraTK::runtime_error);
435  CHECK_COUNTERS_HIGH_LEVEL(A, true, 1, 4, true);
436  CHECK_COUNTERS_HIGH_LEVEL(B, true, 1, 4, true);
437 
438  // B throws in write
439  A->resetCounters();
440  B->resetCounters();
441  B->_throwRuntimeErrInTransfer = true;
442  BOOST_CHECK_THROW(group.write(), ChimeraTK::runtime_error);
443  CHECK_COUNTERS_HIGH_LEVEL(A, true, 1, 4, true);
444  CHECK_COUNTERS_HIGH_LEVEL(B, true, 1, 4, true);
445 
446  // both throw in write
447  A->resetCounters();
448  B->resetCounters();
449  A->_throwRuntimeErrInTransfer = true;
450  B->_throwRuntimeErrInTransfer = true;
451  BOOST_CHECK_THROW(group.write(), ChimeraTK::runtime_error);
452  CHECK_COUNTERS_HIGH_LEVEL(A, true, 1, 4, true);
453  CHECK_COUNTERS_HIGH_LEVEL(B, true, 1, 4, true);
454 }
455 
456 /**********************************************************************************************************************/
457 
464 BOOST_AUTO_TEST_CASE(test_B_12_10_5) {
465  std::cout << "test_B_12_10_5" << std::endl;
466  auto A = makeTETA();
467  auto B = makeTETA();
468 
469  TransferGroup group;
470 
471  group.addAccessor(A);
472  group.addAccessor(B);
473 
474  // both throw in read
475  A->resetCounters();
476  B->resetCounters();
477  A->_throwRuntimeErrInTransfer = true;
478  B->_throwRuntimeErrInTransfer = true;
479  std::exception_ptr e;
480  try {
481  group.read();
482  }
483  catch(...) {
484  e = std::current_exception();
485  }
486  assert(A->_thrownException != B->_thrownException); // make sure our test is sensitive
487  if(A->_transferIndex < B->_transferIndex) {
488  // A has thrown first
489  BOOST_CHECK(e == A->_thrownException);
490  }
491  else {
492  // B has thrown first
493  BOOST_CHECK(e == B->_thrownException);
494  }
495 
496  // both throw in write
497  A->resetCounters();
498  B->resetCounters();
499  A->_throwRuntimeErrInTransfer = true;
500  B->_throwRuntimeErrInTransfer = true;
501  try {
502  group.write();
503  }
504  catch(...) {
505  e = std::current_exception();
506  }
507  assert(A->_thrownException != B->_thrownException); // make sure our test is sensitive
508  if(A->_transferIndex < B->_transferIndex) {
509  // A has thrown first
510  BOOST_CHECK(e == A->_thrownException);
511  }
512  else {
513  // B has thrown first
514  BOOST_CHECK(e == B->_thrownException);
515  }
516 }
517 
518 /**********************************************************************************************************************/
519 
524 BOOST_AUTO_TEST_CASE(test_B_12_11_1) {
525  std::cout << "test_B_12_11_1" << std::endl;
526  auto A = makeTETA();
527  auto B = makeTETA();
528 
529  TransferGroup group;
530 
531  group.addAccessor(A);
532  group.addAccessor(B);
533 
534  // A throws in read
535  A->resetCounters();
536  B->resetCounters();
537  A->_throwRuntimeErrInTransfer = true;
538  BOOST_CHECK_THROW(group.read(), ChimeraTK::runtime_error); // (no check intended, just catch)
539  BOOST_CHECK(A->_updateDataBuffer == false);
540  BOOST_CHECK(B->_updateDataBuffer == false);
541 
542  // A throws in write
543  A->resetCounters();
544  B->resetCounters();
545  A->_throwRuntimeErrInTransfer = true;
546  BOOST_CHECK_THROW(group.write(), ChimeraTK::runtime_error); // (no check intended, just catch)
547  BOOST_CHECK(A->_updateDataBuffer == false);
548  BOOST_CHECK(B->_updateDataBuffer == false);
549 
550  // Nothing throws in read
551  A->resetCounters();
552  B->resetCounters();
553  group.read();
554  BOOST_CHECK(A->_updateDataBuffer == true);
555  BOOST_CHECK(B->_updateDataBuffer == true);
556 
557  // Nothing throws in write
558  A->resetCounters();
559  B->resetCounters();
560  group.write();
561  BOOST_CHECK(A->_updateDataBuffer == true);
562  BOOST_CHECK(B->_updateDataBuffer == true);
563 }
564 
565 /**********************************************************************************************************************/
566 /**********************************************************************************************************************/
568 /**********************************************************************************************************************/
569 /**********************************************************************************************************************/
570 
571 BOOST_AUTO_TEST_CASE(testExceptionHandling) {
572  const std::string EXCEPTION_DUMMY_CDD = "(ExceptionDummy:1?map=test3.map)";
573  BackendFactory::getInstance().setDMapFilePath("dummies.dmap");
574  ChimeraTK::Device device1;
575  ChimeraTK::Device device2;
576  ChimeraTK::Device device3;
577 
578  device1.open("DUMMYD1");
579  auto exceptionDummy = boost::dynamic_pointer_cast<ChimeraTK::ExceptionDummy>(
580  ChimeraTK::BackendFactory::getInstance().createBackend(EXCEPTION_DUMMY_CDD));
581  device2.open(EXCEPTION_DUMMY_CDD);
582  device3.open("DUMMYD2");
583 
584  auto accessor1 = device1.getScalarRegisterAccessor<int>("/BOARD/WORD_FIRMWARE");
585  auto accessor1w = device1.getScalarRegisterAccessor<int>("/BOARD/WORD_FIRMWARE");
586  // accessors 2 and 3 will be merged to a single low level transfer element
587  auto accessor2 = device2.getScalarRegisterAccessor<int>("/Integers/signed32");
588  auto accessor2w = device2.getScalarRegisterAccessor<int>("/Integers/signed32");
589  auto accessor3 = device2.getScalarRegisterAccessor<uint32_t>("/Integers/unsigned32");
590  auto accessor3w = device2.getScalarRegisterAccessor<uint32_t>("/Integers/unsigned32");
591  auto accessor4 = device2.getScalarRegisterAccessor<float>("/FixedPoint/value");
592  auto accessor4w = device2.getScalarRegisterAccessor<float>("/FixedPoint/value");
593  auto accessor5 = device3.getScalarRegisterAccessor<int>("/BOARD/WORD_FIRMWARE");
594  auto accessor5w = device3.getScalarRegisterAccessor<int>("/BOARD/WORD_FIRMWARE");
595 
596  TransferGroup tg;
597  tg.addAccessor(accessor2);
598  tg.addAccessor(accessor3);
599  tg.addAccessor(accessor1);
600  tg.addAccessor(accessor4);
601  tg.addAccessor(accessor5);
602 
603  accessor1 = 1;
604  accessor2 = 2;
605  accessor3 = 3;
606  accessor4 = 4;
607  accessor5 = 5;
608 
609  accessor1w = int(0xdeadcafe);
610  accessor2w = 815;
611  accessor3w = 4711;
612  accessor4w = 10101010;
613  accessor5w = int(0xc01dcafe);
614  accessor1w.write();
615  accessor2w.write();
616  accessor3w.write();
617  accessor4w.write();
618  accessor5w.write();
619 
620  exceptionDummy->throwExceptionRead = true;
621  BOOST_CHECK_THROW(tg.read(), ChimeraTK::runtime_error);
622 
623  BOOST_CHECK_EQUAL(static_cast<int>(accessor1), 1);
624  BOOST_CHECK_EQUAL(static_cast<int>(accessor2), 2);
625  BOOST_CHECK_EQUAL(static_cast<int>(accessor3), 3);
626  BOOST_CHECK_EQUAL(static_cast<int>(accessor4), 4);
627  BOOST_CHECK_EQUAL(static_cast<int>(accessor5), 5);
628 }
629 
630 /**********************************************************************************************************************/
631 
632 BOOST_AUTO_TEST_CASE(testAdding) {
633  BackendFactory::getInstance().setDMapFilePath("dummies.dmap");
635 
636  device.open("DUMMYD3");
637 
638  auto a1 = device.getOneDRegisterAccessor<int>("ADC/AREA_DMAABLE");
639  auto a2 = device.getOneDRegisterAccessor<int>("ADC/AREA_DMAABLE");
640  auto a3 = device.getOneDRegisterAccessor<int>("BOARD/WORD_STATUS");
641  auto a4 = device.getOneDRegisterAccessor<unsigned int>("ADC/AREA_DMAABLE");
642 
643  // slightly redundant to do this test here, this is just a control test still
644  // independent of the TransferGroup
645  a1[0] = 42;
646  a2[0] = 120;
647  a3[0] = 123;
648  a4[0] = 456;
649  BOOST_CHECK(a1[0] == 42);
650  a1.write();
651  a3.write();
652  a3[0] = 654;
653  BOOST_CHECK(a2[0] == 120);
654  BOOST_CHECK(a3[0] == 654);
655  BOOST_CHECK(a4[0] == 456);
656  a2.read();
657  BOOST_CHECK(a1[0] == 42);
658  BOOST_CHECK(a2[0] == 42);
659  BOOST_CHECK(a3[0] == 654);
660  BOOST_CHECK(a4[0] == 456);
661  a3.read();
662  BOOST_CHECK(a1[0] == 42);
663  BOOST_CHECK(a2[0] == 42);
664  BOOST_CHECK(a3[0] == 123);
665  BOOST_CHECK(a4[0] == 456);
666  a4.read();
667  BOOST_CHECK(a1[0] == 42);
668  BOOST_CHECK(a2[0] == 42);
669  BOOST_CHECK(a3[0] == 123);
670  BOOST_CHECK(a4[0] == 42);
671 
672  // add accessors to the transfer group
673  TransferGroup group;
674  group.addAccessor(a1);
675  BOOST_CHECK(!group.isReadOnly());
676  group.addAccessor(a2);
677  BOOST_CHECK(group.isReadOnly());
678  group.addAccessor(a3);
679  group.addAccessor(a4);
680  BOOST_CHECK(group.isReadOnly());
681 
682  // check if adding an accessor to another group throws an exception
683  TransferGroup group2;
684  BOOST_CHECK_THROW(group2.addAccessor(a1), ChimeraTK::logic_error);
685 
686  // check that reading and writing the accessors which are part of the group
687  // throws
688  BOOST_CHECK_THROW(a1.read(), ChimeraTK::logic_error);
689  BOOST_CHECK_THROW(a1.write(), ChimeraTK::logic_error);
690  BOOST_CHECK_THROW(a3.read(), ChimeraTK::logic_error);
691  BOOST_CHECK_THROW(a4.write(), ChimeraTK::logic_error);
692 
693  // during the replace operation, user buffers will be reset, if a replacement
694  BOOST_CHECK(a1[0] == 42);
695  BOOST_CHECK(a2[0] == 0); // this one was replaced
696  BOOST_CHECK(a3[0] == 123);
697  BOOST_CHECK(a4[0] == 42);
698 
699  // Writing to the register accessor (cooked) buffers should not influence the
700  // other accessors in the group.
701  a1[0] = 333;
702  BOOST_CHECK(a1[0] == 333);
703  BOOST_CHECK(a2[0] == 0);
704  BOOST_CHECK(a3[0] == 123);
705  BOOST_CHECK(a4[0] == 42);
706  a2[0] = 666;
707  BOOST_CHECK(a1[0] == 333);
708  BOOST_CHECK(a2[0] == 666);
709  BOOST_CHECK(a3[0] == 123);
710  BOOST_CHECK(a4[0] == 42);
711  a3[0] = 999;
712  BOOST_CHECK(a1[0] == 333);
713  BOOST_CHECK(a2[0] == 666);
714  BOOST_CHECK(a3[0] == 999);
715  BOOST_CHECK(a4[0] == 42);
716  a4[0] = 111;
717  BOOST_CHECK(a1[0] == 333);
718  BOOST_CHECK(a2[0] == 666);
719  BOOST_CHECK(a3[0] == 999);
720  BOOST_CHECK(a4[0] == 111);
721 
722  device.close();
723 }
724 
725 /**********************************************************************************************************************/
726 
727 template<typename T>
729  // if fakeLowLevel is set to true, the decorator will pretend to be the
730  // low-level TransferElement.
731  CountingDecorator(const boost::shared_ptr<ChimeraTK::TransferElement>& target, bool _fakeLowLevel = false)
732  : NDRegisterAccessorDecorator<T>(boost::dynamic_pointer_cast<NDRegisterAccessor<T>>(target)),
733  fakeLowLevel(_fakeLowLevel) {
734  assert(boost::dynamic_pointer_cast<NDRegisterAccessor<T>>(target) != nullptr); // a bit late but better than
735  // nothing...
736  this->_name = "CD:" + this->_name;
737  }
738 
739  void doPreRead(TransferType type) override {
740  nPreRead++;
742  }
743 
744  void doPostRead(TransferType type, bool hasNewData) override {
745  nPostRead++;
747  }
748 
749  void doPreWrite(TransferType type, VersionNumber versionNumber) override {
750  nPreWrite++;
751  NDRegisterAccessorDecorator<T>::doPreWrite(type, versionNumber);
752  }
753 
754  void doPostWrite(TransferType type, VersionNumber versionNumber) override {
755  nPostWrite++;
756  NDRegisterAccessorDecorator<T>::doPostWrite(type, versionNumber);
757  }
758 
759  void doReadTransferSynchronously() override {
760  nRead++;
762  }
763 
764  bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override {
765  nWrite++;
767  }
768 
769  std::vector<boost::shared_ptr<ChimeraTK::TransferElement>> getHardwareAccessingElements() override {
770  if(fakeLowLevel) {
771  return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
772  }
773  else {
775  }
776  }
777 
778  void replaceTransferElement(boost::shared_ptr<TransferElement> newElement) override {
779  if(fakeLowLevel) return;
780  if(_target->mayReplaceOther(newElement)) {
781  _target = boost::static_pointer_cast<NDRegisterAccessor<T>>(newElement);
782  }
783  else {
784  _target->replaceTransferElement(newElement);
785  }
786  }
787 
788  std::list<boost::shared_ptr<TransferElement>> getInternalElements() override {
789  if(fakeLowLevel) {
790  return {};
791  }
792  else {
794  }
795  }
796 
797  bool mayReplaceOther(const boost::shared_ptr<TransferElement const>& other) const override {
798  auto casted = boost::dynamic_pointer_cast<CountingDecorator<T> const>(other);
799  if(!casted) return false;
800  if(_target == casted->_target) return true;
801  if(_target->mayReplaceOther(casted->_target)) return true;
802  return false;
803  }
804 
805  void resetCounters() {
806  nPreRead = 0;
807  nPostRead = 0;
808  nPreWrite = 0;
809  nPostWrite = 0;
810  nRead = 0;
811  nReadNonBlocking = 0;
812  nReadLatest = 0;
813  nWrite = 0;
814  }
815 
817  size_t nPreRead{0};
818  size_t nPostRead{0};
819  size_t nPreWrite{0};
820  size_t nPostWrite{0};
821  size_t nRead{0};
822  size_t nReadNonBlocking{0};
823  size_t nReadLatest{0};
824  size_t nWrite{0};
825 
827 };
828 
829 /**********************************************************************************************************************/
830 
831 BOOST_AUTO_TEST_CASE(testCallsToPrePostFunctionsInDecorator) {
832  BackendFactory::getInstance().setDMapFilePath("dummies.dmap");
834 
835  device.open("DUMMYD3");
836 
837  // create register accessors of four registers with adjecent addresses, one of
838  // the registers is in the group two times
839  auto mux0 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
840  auto mux0_2 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
841  auto mux2 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
842  auto mux3 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
843 
844  // decorate the accessors which we will put into the transfer group, so we can
845  // count how often the functions are called
846  auto mux0d = boost::make_shared<CountingDecorator<int>>(mux0.getHighLevelImplElement());
847  auto mux0_2d = boost::make_shared<CountingDecorator<int>>(mux0_2.getHighLevelImplElement());
848  auto mux2d = boost::make_shared<CountingDecorator<int>>(mux2.getHighLevelImplElement());
849  auto mux3d = boost::make_shared<CountingDecorator<int>>(mux3.getHighLevelImplElement());
850 
851  // place the decorated registers inside the abstractors
852  mux0.replace(mux0d);
853  mux0_2.replace(mux0_2d);
854  mux2.replace(mux2d);
855  mux3.replace(mux3d);
856 
857  // create the same register accessors again, so we have a second set not part
858  // of the transfer group
859  auto mux0b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
860  auto mux2b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
861  auto mux3b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
862 
863  BOOST_CHECK(mux0d->_target != mux0_2d->_target);
864  BOOST_CHECK(mux0.getHighLevelImplElement() == mux0d);
865  BOOST_CHECK(mux0_2.getHighLevelImplElement() == mux0_2d);
866 
867  // add accessors to the transfer group
868  TransferGroup group;
869  group.addAccessor(mux0);
870  group.addAccessor(mux0_2);
871  group.addAccessor(mux2);
872  group.addAccessor(mux3);
873 
874  BOOST_CHECK(mux0.getHighLevelImplElement() == mux0d);
875  BOOST_CHECK(mux0_2.getHighLevelImplElement() != mux0_2d);
876  BOOST_CHECK(
877  boost::dynamic_pointer_cast<ChimeraTK::CopyRegisterDecoratorTrait>(mux0_2.getHighLevelImplElement()) != nullptr);
878 
879  // write some data to the registers (without the TransferGroup)
880  mux0b = 18;
881  mux0b.write();
882  mux2b = 22;
883  mux2b.write();
884  mux3b = 23;
885  mux3b.write();
886 
887  // read through transfer group
888  group.read();
889 
890  BOOST_CHECK_EQUAL(int(mux0), 18);
891  BOOST_CHECK_EQUAL(int(mux0_2), 18);
892 
893  // we don't know which of the accessors has been eliminated (and this is
894  // actually a random choice at runtime)
895  BOOST_CHECK((mux0d->nPreRead == 1 && mux0_2d->nPreRead == 0) || (mux0d->nPreRead == 0 && mux0_2d->nPreRead == 1));
896  if(mux0d->nPreRead == 1) {
897  BOOST_CHECK_EQUAL(mux0d->nPostRead, 1);
898  BOOST_CHECK_EQUAL(mux0_2d->nPreRead, 0);
899  BOOST_CHECK_EQUAL(mux0_2d->nPostRead, 0);
900  }
901  else {
902  BOOST_CHECK_EQUAL(mux0_2d->nPostRead, 1);
903  BOOST_CHECK_EQUAL(mux0d->nPreRead, 0);
904  BOOST_CHECK_EQUAL(mux0d->nPostRead, 0);
905  }
906  BOOST_CHECK_EQUAL(mux0d->nRead, 0);
907  BOOST_CHECK_EQUAL(mux0_2d->nRead, 0);
908  BOOST_CHECK_EQUAL(mux0d->nPreWrite, 0);
909  BOOST_CHECK_EQUAL(mux0d->nPostWrite, 0);
910  BOOST_CHECK_EQUAL(mux0d->nReadNonBlocking, 0);
911  BOOST_CHECK_EQUAL(mux0d->nReadLatest, 0);
912  BOOST_CHECK_EQUAL(mux0d->nWrite, 0);
913  BOOST_CHECK_EQUAL(mux0_2d->nPreWrite, 0);
914  BOOST_CHECK_EQUAL(mux0_2d->nPostWrite, 0);
915  BOOST_CHECK_EQUAL(mux0_2d->nReadNonBlocking, 0);
916  BOOST_CHECK_EQUAL(mux0_2d->nReadLatest, 0);
917  BOOST_CHECK_EQUAL(mux0_2d->nWrite, 0);
918 
919  BOOST_CHECK_EQUAL(int(mux2), 22);
920  BOOST_CHECK_EQUAL(mux2d->nPreRead, 1);
921  BOOST_CHECK_EQUAL(mux2d->nPostRead, 1);
922  BOOST_CHECK_EQUAL(mux2d->nPreWrite, 0);
923  BOOST_CHECK_EQUAL(mux2d->nPostWrite, 0);
924  BOOST_CHECK_EQUAL(mux2d->nRead, 0);
925  BOOST_CHECK_EQUAL(mux2d->nReadNonBlocking, 0);
926  BOOST_CHECK_EQUAL(mux2d->nReadLatest, 0);
927  BOOST_CHECK_EQUAL(mux2d->nWrite, 0);
928 
929  BOOST_CHECK_EQUAL(int(mux3), 23);
930  BOOST_CHECK_EQUAL(mux3d->nPreRead, 1);
931  BOOST_CHECK_EQUAL(mux3d->nPostRead, 1);
932  BOOST_CHECK_EQUAL(mux3d->nPreWrite, 0);
933  BOOST_CHECK_EQUAL(mux3d->nPostWrite, 0);
934  BOOST_CHECK_EQUAL(mux3d->nRead, 0);
935  BOOST_CHECK_EQUAL(mux3d->nReadNonBlocking, 0);
936  BOOST_CHECK_EQUAL(mux3d->nReadLatest, 0);
937  BOOST_CHECK_EQUAL(mux3d->nWrite, 0);
938 
939  mux0d->resetCounters();
940  mux0_2d->resetCounters();
941  mux2d->resetCounters();
942  mux3d->resetCounters();
943 
944  // write through transfer group is not possible, since it is read-only
945  mux0 = 24;
946  mux0_2 = 24;
947  mux2 = 30;
948  mux3 = 33;
949  BOOST_CHECK_THROW(group.write(), ChimeraTK::logic_error);
950 }
951 
952 /**********************************************************************************************************************/
953 
954 BOOST_AUTO_TEST_CASE(testCallsToPrePostFunctionsInLowLevel) {
955  BackendFactory::getInstance().setDMapFilePath("dummies.dmap");
957 
958  device.open("DUMMYD3");
959 
960  // create register accessors of four registers with adjacent addresses
961  auto mux0 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
962  auto mux0_2 = mux0; // make duplicate of one accessor
963  auto mux2 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
964  auto mux3 = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
965 
966  // decorate the accessors which we will put into the transfer group, so we can
967  // count how often the functions are called
968  auto mux0d = boost::make_shared<CountingDecorator<int>>(mux0.getHighLevelImplElement(), true);
969  auto mux0_2d = boost::make_shared<CountingDecorator<int>>(mux0_2.getHighLevelImplElement(), true);
970  auto mux2d = boost::make_shared<CountingDecorator<int>>(mux2.getHighLevelImplElement(), true);
971  auto mux3d = boost::make_shared<CountingDecorator<int>>(mux3.getHighLevelImplElement(), true);
972 
973  // decorate another time
974  auto mux0d2 = boost::make_shared<CountingDecorator<int>>(mux0d);
975  auto mux0_2d2 = boost::make_shared<CountingDecorator<int>>(mux0_2d);
976  auto mux2d2 = boost::make_shared<CountingDecorator<int>>(mux2d);
977  auto mux3d2 = boost::make_shared<CountingDecorator<int>>(mux3d);
978 
979  // place the decorated registers inside the abstractors
980  mux0.replace(mux0d2);
981  mux0_2.replace(mux0_2d2);
982  mux2.replace(mux2d2);
983  mux3.replace(mux3d2);
984 
985  // create the same register accessors again, so we have a second set not part
986  // of the transfer group
987  auto mux0b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_0");
988  auto mux2b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_2");
989  auto mux3b = device.getScalarRegisterAccessor<int>("/ADC/WORD_CLK_MUX_3");
990 
991  BOOST_CHECK(mux0d->_target == mux0_2d->_target);
992  BOOST_CHECK(mux0d2->_target == mux0d);
993  BOOST_CHECK(mux0_2d2->_target == mux0_2d);
994  BOOST_CHECK(mux2d2->_target == mux2d);
995  BOOST_CHECK(mux3d2->_target == mux3d);
996 
997  // add accessors to the transfer group
998  TransferGroup group;
999  group.addAccessor(mux0);
1000  group.addAccessor(mux0_2);
1001  group.addAccessor(mux2);
1002  group.addAccessor(mux3);
1003 
1004  BOOST_CHECK(mux0d->_target == mux0_2d->_target);
1005  BOOST_CHECK(
1006  boost::dynamic_pointer_cast<ChimeraTK::CopyRegisterDecoratorTrait>(mux0_2.getHighLevelImplElement()) != nullptr);
1007  BOOST_CHECK(mux2d2->_target == mux2d);
1008  BOOST_CHECK(mux3d2->_target == mux3d);
1009 
1010  // write some data to the registers (without the TransferGroup)
1011  mux0b = 18;
1012  mux0b.write();
1013  mux2b = 22;
1014  mux2b.write();
1015  mux3b = 23;
1016  mux3b.write();
1017 
1018  // read through transfer group
1019  group.read();
1020 
1021  BOOST_CHECK_EQUAL(int(mux0), 18);
1022  BOOST_CHECK_EQUAL(int(mux0_2), 18);
1023 
1024  // we don't know which of the accessors has been eliminated (and this is
1025  // actually a random choice at runtime)
1026  BOOST_CHECK((mux0d->nRead == 1 && mux0_2d->nRead == 0) || (mux0d->nRead == 0 && mux0_2d->nRead == 1));
1027  if(mux0d->nRead == 1) {
1028  BOOST_CHECK_EQUAL(mux0d->nPreRead, 1);
1029  BOOST_CHECK_EQUAL(mux0d->nPostRead, 1);
1030  BOOST_CHECK_EQUAL(mux0_2d->nPreRead, 0);
1031  BOOST_CHECK_EQUAL(mux0_2d->nPostRead, 0);
1032  }
1033  else {
1034  BOOST_CHECK_EQUAL(mux0_2d->nPreRead, 1);
1035  BOOST_CHECK_EQUAL(mux0_2d->nPostRead, 1);
1036  BOOST_CHECK_EQUAL(mux0d->nPreRead, 0);
1037  BOOST_CHECK_EQUAL(mux0d->nPostRead, 0);
1038  }
1039  BOOST_CHECK_EQUAL(mux0d->nPreWrite, 0);
1040  BOOST_CHECK_EQUAL(mux0d->nPostWrite, 0);
1041  BOOST_CHECK_EQUAL(mux0d->nReadNonBlocking, 0);
1042  BOOST_CHECK_EQUAL(mux0d->nReadLatest, 0);
1043  BOOST_CHECK_EQUAL(mux0d->nWrite, 0);
1044  BOOST_CHECK_EQUAL(mux0_2d->nPreWrite, 0);
1045  BOOST_CHECK_EQUAL(mux0_2d->nPostWrite, 0);
1046  BOOST_CHECK_EQUAL(mux0_2d->nReadNonBlocking, 0);
1047  BOOST_CHECK_EQUAL(mux0_2d->nReadLatest, 0);
1048  BOOST_CHECK_EQUAL(mux0_2d->nWrite, 0);
1049 
1050  BOOST_CHECK_EQUAL(int(mux2), 22);
1051  BOOST_CHECK_EQUAL(mux2d->nPreRead, 1);
1052  BOOST_CHECK_EQUAL(mux2d->nPostRead, 1);
1053  BOOST_CHECK_EQUAL(mux2d->nPreWrite, 0);
1054  BOOST_CHECK_EQUAL(mux2d->nPostWrite, 0);
1055  BOOST_CHECK_EQUAL(mux2d->nRead, 1);
1056  BOOST_CHECK_EQUAL(mux2d->nReadNonBlocking, 0);
1057  BOOST_CHECK_EQUAL(mux2d->nReadLatest, 0);
1058  BOOST_CHECK_EQUAL(mux2d->nWrite, 0);
1059 
1060  BOOST_CHECK_EQUAL(int(mux3), 23);
1061  BOOST_CHECK_EQUAL(mux3d->nPreRead, 1);
1062  BOOST_CHECK_EQUAL(mux3d->nPostRead, 1);
1063  BOOST_CHECK_EQUAL(mux3d->nPreWrite, 0);
1064  BOOST_CHECK_EQUAL(mux3d->nPostWrite, 0);
1065  BOOST_CHECK_EQUAL(mux3d->nRead, 1);
1066  BOOST_CHECK_EQUAL(mux3d->nReadNonBlocking, 0);
1067  BOOST_CHECK_EQUAL(mux3d->nReadLatest, 0);
1068  BOOST_CHECK_EQUAL(mux3d->nWrite, 0);
1069 
1070  mux0d->resetCounters();
1071  mux0_2d->resetCounters();
1072  mux2d->resetCounters();
1073  mux3d->resetCounters();
1074 
1075  // write through transfer group
1077  mux0 = 24;
1078  mux0_2 = 24;
1079  mux2 = 30;
1080  mux3 = 33;
1081  BOOST_CHECK_THROW(group.write(), ChimeraTK::logic_error);
1082 }
1083 
1084 BOOST_AUTO_TEST_CASE(testTemporaryAbstractorWorks) {
1085  // Testing that adding a plain transfer element to the TransferGroup still works as expected.
1086  BackendFactory::getInstance().setDMapFilePath("dummies.dmap");
1088 
1089  device.open("(dummy?map=mtcadummy.map)");
1090 
1091  TransferGroup group;
1092  auto a = device.getScalarRegisterAccessor<int32_t>("BOARD.WORD_FIRMWARE");
1093  auto b = device.getBackend()->getRegisterAccessor<int32_t>("BOARD.WORD_FIRMWARE", 1, 0, {});
1094 
1095  auto c = device.getScalarRegisterAccessor<int32_t>("BOARD.WORD_FIRMWARE");
1096 
1097  group.addAccessor(a);
1098  c = 12;
1099  c.write();
1100 
1101  group.read();
1102  BOOST_CHECK_EQUAL(a, 12);
1103  group.addAccessor(b);
1104 
1105  c = 13;
1106  c.write();
1107 
1108  group.read();
1109  BOOST_CHECK_EQUAL(a, 13);
1110  BOOST_CHECK_EQUAL(b->accessChannel(0)[0], 13);
1111 }
1112 
1113 /**********************************************************************************************************************/
ExceptionDummyBackend.h
CountingDecorator::getInternalElements
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Definition: testTransferGroup.cpp:788
ChimeraTK::TwoDRegisterAccessor
Accessor class to read and write 2D registers.
Definition: ForwardDeclarations.h:20
TransferGroup.h
device
ctk::Device device
Definition: testExceptionDummyDevice.cc:18
CountingDecorator
Definition: testTransferGroup.cpp:728
ChimeraTK::TransferGroup::write
void write(VersionNumber versionNumber={})
Trigger write transfer for all accessors in the group.
Definition: TransferGroup.cc:123
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
ChimeraTK::Device::getBackend
boost::shared_ptr< DeviceBackend > getBackend()
Obtain the backend.
Definition: Device.cc:111
ChimeraTK::BackendFactory::getInstance
static BackendFactory & getInstance()
Static function to get an instance of factory.
Definition: BackendFactory.cc:191
CountingDecorator::doReadTransferSynchronously
void doReadTransferSynchronously() override
Definition: testTransferGroup.cpp:759
CountingDecorator::getHardwareAccessingElements
std::vector< boost::shared_ptr< ChimeraTK::TransferElement > > getHardwareAccessingElements() override
Definition: testTransferGroup.cpp:769
ChimeraTK::TransferGroup::addAccessor
void addAccessor(TransferElementAbstractor &accessor)
Add a register accessor to the group.
Definition: TransferGroup.cc:305
CHECK_COUNTERS_MID_LEVEL
#define CHECK_COUNTERS_MID_LEVEL(te)
Definition: testTransferGroup.cpp:228
CountingDecorator::fakeLowLevel
bool fakeLowLevel
Definition: testTransferGroup.cpp:816
CountingDecorator::doPreRead
void doPreRead(TransferType type) override
Definition: testTransferGroup.cpp:739
ChimeraTK::TransferGroup::isReadOnly
bool isReadOnly()
Check if transfer group is read-only.
Definition: TransferGroup.cc:186
CountingDecorator::doPreWrite
void doPreWrite(TransferType type, VersionNumber versionNumber) override
Definition: testTransferGroup.cpp:749
ChimeraTK::runtime_error
Exception thrown when a runtime error has occured.
Definition: Exception.h:18
CountingDecorator::resetCounters
void resetCounters()
Definition: testTransferGroup.cpp:805
NDRegisterAccessorDecorator.h
ChimeraTK::TransferGroup
Group multiple data accessors to efficiently trigger data transfers on the whole group.
Definition: TransferGroup.h:26
ChimeraTK::TransferGroup::read
void read()
Trigger read transfer for all accessors in the group.
Definition: TransferGroup.cc:44
CHECK_COUNTERS_LOW_LEVEL
#define CHECK_COUNTERS_LOW_LEVEL(te, isWrite, expectedOrderMin, expectedOrderMax)
Definition: testTransferGroup.cpp:236
NumericAddressedLowLevelTransferElement.h
CountingDecorator::doPostRead
void doPostRead(TransferType type, bool hasNewData) override
Definition: testTransferGroup.cpp:744
CountingDecorator::mayReplaceOther
bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &other) const override
Definition: testTransferGroup.cpp:797
Device.h
CountingDecorator::doPostWrite
void doPostWrite(TransferType type, VersionNumber versionNumber) override
Definition: testTransferGroup.cpp:754
CountingDecorator::CountingDecorator
CountingDecorator(const boost::shared_ptr< ChimeraTK::TransferElement > &target, bool _fakeLowLevel=false)
Definition: testTransferGroup.cpp:731
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(test_B_12_1_3)
Tests for single specification points.
Definition: testTransferGroup.cpp:34
ChimeraTK::Device
Class allows to read/write registers from device.
Definition: Device.h:39
ChimeraTK::NDRegisterAccessorDecorator
Base class for decorators of the NDRegisterAccessor.
Definition: NDRegisterAccessorDecorator.h:120
CountingDecorator::replaceTransferElement
void replaceTransferElement(boost::shared_ptr< TransferElement > newElement) override
Definition: testTransferGroup.cpp:778
CopyRegisterDecorator.h
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
makeTETA
boost::shared_ptr< TransferElementTestAccessor< int32_t > > makeTETA(AccessModeFlags flags={})
Definition: testTransferGroup.cpp:20
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::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
ChimeraTK::AccessModeFlags
Set of AccessMode flags with additional functionality for an easier handling.
Definition: AccessMode.h:48
CountingDecorator::doWriteTransfer
bool doWriteTransfer(ChimeraTK::VersionNumber versionNumber) override
Definition: testTransferGroup.cpp:764
ChimeraTK
Definition: DummyBackend.h:16
CHECK_COUNTERS_HIGH_LEVEL
#define CHECK_COUNTERS_HIGH_LEVEL(te, isWrite, expectedOrderPreMax, expectedOrderPostMin, expectTransfer)
Definition: testTransferGroup.cpp:201
exceptionDummy
auto exceptionDummy
Definition: testExceptionDummyDevice.cc:16
TransferElementTestAccessor.h
ChimeraTK::NDRegisterAccessor
N-dimensional register accessor.
Definition: ForwardDeclarations.h:17
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51