ChimeraTK-DeviceAccess  03.18.00
testDummyRegisterAccessor.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 
7 #include "DummyBackend.h"
9 
10 #include <boost/bind/bind.hpp>
11 #include <boost/date_time/posix_time/posix_time.hpp>
12 #include <boost/function.hpp>
13 #include <boost/lambda/lambda.hpp>
14 #include <boost/make_shared.hpp>
15 
16 #include <algorithm>
17 #include <math.h>
18 
19 using namespace boost::unit_test_framework;
20 using namespace ChimeraTK;
21 
22 #define TEST_MAPPING_FILE "testDummyRegisterAccessors.map"
23 #define INVALID_MAPPING_FILE "invalidSequences.map"
24 
25 // Test implementation of the dummy backend with two accessors
26 class DummyRegisterTest;
27 class TestableDummyBackend : public DummyBackend {
28  public:
29  explicit TestableDummyBackend(std::string mapFileName)
30  : DummyBackend(mapFileName), someRegister(this, "APP0", "SOME_REGISTER"),
31  someMuxedRegister(this, "APP0", "DAQ0_ADCA") {}
32 
35 
36  friend class DummyRegisterTest;
37 };
38 
39 // Test implementation of the dummy backend for the invalid map file
41  public:
42  explicit InvalidDummyBackend(std::string mapFileName)
43  : DummyBackend(mapFileName), invalidRegister(this, "INVALID", "NO_WORDS") {}
44 
46 
47  friend class DummyRegisterTest;
48 };
49 
50 /**********************************************************************************************************************/
52  public:
53  DummyRegisterTest() { device = boost::shared_ptr<TestableDummyBackend>(new TestableDummyBackend(TEST_MAPPING_FILE)); }
54 
56  void testExceptions();
57 
59  void testRegisterAccessor();
60 
62  void testMuxedRegisterAccessor();
63 
64  private:
65  boost::shared_ptr<TestableDummyBackend> device;
66  friend class DummyRegisterTestSuite;
67 };
68 
69 /**********************************************************************************************************************/
70 class DummyRegisterTestSuite : public test_suite {
71  public:
72  DummyRegisterTestSuite() : test_suite("DummyRegister test suite") {
73  boost::shared_ptr<DummyRegisterTest> dummyDeviceTest(new DummyRegisterTest);
74 
75  add(BOOST_CLASS_TEST_CASE(&DummyRegisterTest::testRegisterAccessor, dummyDeviceTest));
76  add(BOOST_CLASS_TEST_CASE(&DummyRegisterTest::testMuxedRegisterAccessor, dummyDeviceTest));
77  add(BOOST_CLASS_TEST_CASE(&DummyRegisterTest::testExceptions, dummyDeviceTest));
78  }
79 };
80 
81 /**********************************************************************************************************************/
83  framework::master_test_suite().p_name.value = "DummyRegister test suite";
84  framework::master_test_suite().add(new DummyRegisterTestSuite);
85 
86  return true;
87 }
88 
89 /**********************************************************************************************************************/
91  std::cout << "testExceptions" << std::endl;
92 
94 }
95 
96 /**********************************************************************************************************************/
98  std::cout << "testRegisterAccessor" << std::endl;
99 
100  // open the device
101  device->open();
102 
103  // check number of elements getter
104  BOOST_CHECK(device->someRegister.getNumberOfElements() == 10);
105 
106  // test operator=
107  device->someRegister = 3;
108  BOOST_CHECK(device->_barContents[1][0] == 3);
109 
110  // test operator[] on r.h.s.
111  device->_barContents[1][0] = 5;
112  device->_barContents[1][3] = 77;
113  BOOST_CHECK(device->someRegister[0] == 5);
114  BOOST_CHECK(device->someRegister[3] == 77);
115 
116  // test operator[] on l.h.s.
117  device->someRegister[0] = 666;
118  device->someRegister[9] = 999;
119  BOOST_CHECK(device->_barContents[1][0] == 666);
120  BOOST_CHECK(device->_barContents[1][9] == 999);
121  device->someRegister[1] = 111;
122  device->someRegister[2] = 222;
123  device->someRegister[3] = 333;
124  device->someRegister[4] = 444;
125  BOOST_CHECK(device->_barContents[1][1] == 111);
126  BOOST_CHECK(device->_barContents[1][2] == 222);
127  BOOST_CHECK(device->_barContents[1][3] == 333);
128  BOOST_CHECK(device->_barContents[1][4] == 444);
129 
130  // test increment and decrement operators
131  BOOST_CHECK(device->someRegister[1]++ == 111);
132  BOOST_CHECK(device->someRegister[2]-- == 222);
133  BOOST_CHECK(++device->someRegister[3] == 334);
134  BOOST_CHECK(--device->someRegister[4] == 443);
135  BOOST_CHECK(device->_barContents[1][1] == 112);
136  BOOST_CHECK(device->_barContents[1][2] == 221);
137  BOOST_CHECK(device->_barContents[1][3] == 334);
138  BOOST_CHECK(device->_barContents[1][4] == 443);
139 
140  // close the device
141  device->close();
142 }
143 
144 /**********************************************************************************************************************/
146  std::cout << "testMuxedRegisterAccessor" << std::endl;
147 
148  // open the device
149  device->open();
150 
151  // check number of elements getter
152  BOOST_CHECK(device->someMuxedRegister.getNumberOfElements() == 4096);
153  BOOST_CHECK(device->someMuxedRegister.getNumberOfSequences() == 16);
154 
155  // the area offset is 1000 bytes. When addressing the index of the 32 bit word
156  // in the bar, we have to divide by 4
157  static const int areaIndexOffset = 1000 / 4;
158 
159  // since our register does not have a fixed type, we use this union/struct to
160  // fill the bar content directly the packed attribute prevents the compiler
161  // from adding a padding between the struct fields
162  union _mixedReg {
163  struct _cooked {
164  int32_t r0;
165  int16_t r1;
166  int16_t r2;
167  int8_t r3;
168  int8_t r4;
169  int32_t r5;
170  int16_t r6;
171  int32_t r7;
172  int32_t r8;
173  int32_t r9;
174  int32_t r10;
175  int32_t r11;
176  int32_t r12;
177  int32_t r13;
178  int32_t r14;
179  uint32_t r15;
180  } __attribute__((packed)) cooked;
181  int32_t raw[13];
182  } mixedReg;
183 
184  int pitch = sizeof(mixedReg.raw);
185 
186  // fill the register
187  mixedReg.cooked.r0 = 42;
188  mixedReg.cooked.r1 = 120;
189  mixedReg.cooked.r2 = 222;
190  mixedReg.cooked.r3 = -110;
191  mixedReg.cooked.r4 = 1;
192  mixedReg.cooked.r5 = 33;
193  mixedReg.cooked.r6 = 6;
194  mixedReg.cooked.r7 = 7;
195  mixedReg.cooked.r8 = 8;
196  mixedReg.cooked.r9 = 9;
197  mixedReg.cooked.r10 = 10;
198  mixedReg.cooked.r11 = 11;
199  mixedReg.cooked.r12 = 12;
200  mixedReg.cooked.r13 = 13;
201  mixedReg.cooked.r14 = 14;
202  mixedReg.cooked.r15 = 15;
203  for(int i = 0; i < 13; i++) device->_barContents[0xD][areaIndexOffset + i] = mixedReg.raw[i];
204 
205  // test the test, to be sure the union is not going wrong
206  BOOST_CHECK((int)((char*)&(mixedReg.cooked.r5) - (char*)&(mixedReg.cooked.r0)) == 10);
207  BOOST_CHECK((int)((char*)&(mixedReg.cooked.r10) - (char*)&(mixedReg.cooked.r0)) == 28);
208  BOOST_CHECK((int)((char*)&(mixedReg.cooked.r15) - (char*)&(mixedReg.cooked.r0)) == pitch - 4);
209  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + 0] == 42);
210  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + 1] == 120 + 0x10000 * 222);
211  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + 9] == 12);
212  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + 12] == 15);
213 
214  mixedReg.cooked.r0 = 1;
215  mixedReg.cooked.r1 = 11;
216  mixedReg.cooked.r2 = 22;
217  mixedReg.cooked.r3 = 33;
218  mixedReg.cooked.r4 = 0;
219  mixedReg.cooked.r5 = 55;
220  mixedReg.cooked.r6 = 66;
221  mixedReg.cooked.r7 = 77;
222  mixedReg.cooked.r8 = 88;
223  mixedReg.cooked.r9 = 99;
224  mixedReg.cooked.r10 = 100;
225  mixedReg.cooked.r11 = 111;
226  mixedReg.cooked.r12 = 222;
227  mixedReg.cooked.r13 = 333;
228  mixedReg.cooked.r14 = 444;
229  mixedReg.cooked.r15 = 555;
230  for(int i = 0; i < 13; i++) device->_barContents[0xD][areaIndexOffset + pitch / 4 + i] = mixedReg.raw[i];
231 
232  // test the test, to be sure the union is not going wrong
233  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + pitch / 4 + 0] == 1);
234  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + pitch / 4 + 1] == 11 + 0x10000 * 22);
235  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + pitch / 4 + 9] == 222);
236  BOOST_CHECK(device->_barContents[0xD][areaIndexOffset + pitch / 4 + 12] == 555);
237 
238  // fill the rest of the register (has 4096 samples per channel)
239  for(int i = 2; i < 4096; i++) {
240  mixedReg.cooked.r0 = i + 0;
241  mixedReg.cooked.r1 = i + 1;
242  mixedReg.cooked.r2 = i + 2;
243  mixedReg.cooked.r3 = i + 3;
244  mixedReg.cooked.r4 = i + 4;
245  mixedReg.cooked.r5 = i + 5;
246  mixedReg.cooked.r6 = i + 6;
247  mixedReg.cooked.r7 = i + 7;
248  mixedReg.cooked.r8 = i + 8;
249  mixedReg.cooked.r9 = i + 9;
250  mixedReg.cooked.r10 = i + 10;
251  mixedReg.cooked.r11 = i + 11;
252  mixedReg.cooked.r12 = i + 12;
253  mixedReg.cooked.r13 = i + 13;
254  mixedReg.cooked.r14 = i + 14;
255  mixedReg.cooked.r15 = i + 15;
256  for(int k = 0; k < 13; k++) device->_barContents[0xD][areaIndexOffset + i * (pitch / 4) + k] = mixedReg.raw[k];
257  }
258 
259  // test reading by [][] operator
260  BOOST_CHECK(device->someMuxedRegister[0][0] == 42);
261  BOOST_CHECK(device->someMuxedRegister[1][0] == 120);
262  BOOST_CHECK(device->someMuxedRegister[2][0] == 222);
263  BOOST_CHECK(device->someMuxedRegister[3][0] == -110);
264  BOOST_CHECK(device->someMuxedRegister[4][0] == 1);
265  BOOST_CHECK(device->someMuxedRegister[5][0] == 33);
266  BOOST_CHECK(device->someMuxedRegister[6][0] == 6);
267  BOOST_CHECK(device->someMuxedRegister[7][0] == 7);
268  BOOST_CHECK(device->someMuxedRegister[8][0] == 8);
269  BOOST_CHECK(device->someMuxedRegister[9][0] == 9);
270  BOOST_CHECK(device->someMuxedRegister[10][0] == 10);
271  BOOST_CHECK(device->someMuxedRegister[11][0] == 11);
272  BOOST_CHECK(device->someMuxedRegister[12][0] == 12);
273  BOOST_CHECK(device->someMuxedRegister[13][0] == 13);
274  BOOST_CHECK(device->someMuxedRegister[14][0] == 14);
275  BOOST_CHECK(device->someMuxedRegister[15][0] == 15);
276 
277  BOOST_CHECK(device->someMuxedRegister[0][1] == 1);
278  BOOST_CHECK(device->someMuxedRegister[1][1] == 11);
279  BOOST_CHECK(device->someMuxedRegister[2][1] == 22);
280  BOOST_CHECK(device->someMuxedRegister[3][1] == 33);
281  BOOST_CHECK(device->someMuxedRegister[4][1] == 0);
282  BOOST_CHECK(device->someMuxedRegister[5][1] == 55);
283  BOOST_CHECK(device->someMuxedRegister[6][1] == 66);
284  BOOST_CHECK(device->someMuxedRegister[7][1] == 77);
285  BOOST_CHECK(device->someMuxedRegister[8][1] == 88);
286  BOOST_CHECK(device->someMuxedRegister[9][1] == 99);
287  BOOST_CHECK(device->someMuxedRegister[10][1] == 100);
288  BOOST_CHECK(device->someMuxedRegister[11][1] == 111);
289  BOOST_CHECK(device->someMuxedRegister[12][1] == 222);
290  BOOST_CHECK(device->someMuxedRegister[13][1] == 333);
291  BOOST_CHECK(device->someMuxedRegister[14][1] == 444);
292  BOOST_CHECK(device->someMuxedRegister[15][1] == 555);
293 
294  for(int i = 2; i < 65536 / 16; i++) {
295  for(int k = 0; k < 16; k++) {
296  int expectedValue = i + k;
297  void* ptr = (void*)&expectedValue;
298  if(k == 1 || k == 2 || k == 6) { // 16 bit
299  expectedValue = *(reinterpret_cast<int16_t*>(ptr));
300  }
301  else if(k == 3) { // 8 bit
302  expectedValue = *(reinterpret_cast<int8_t*>(ptr));
303  }
304  else if(k == 4) { // 1 bit
305  expectedValue = expectedValue & 0x1;
306  }
307  else if(k == 7) { // 24 bit
308  expectedValue = expectedValue & 0xFFFFFF;
309  }
310  std::stringstream message;
311  message << "someMuxedRegister[" << k << "][" << i << "] == " << device->someMuxedRegister[k][i] << " but "
312  << expectedValue << " expected.";
313  BOOST_CHECK_MESSAGE(device->someMuxedRegister[k][i] == expectedValue, message.str());
314  }
315  }
316 
317  // test writing by [][] operator
318  device->someMuxedRegister[0][0] = 666;
319  device->someMuxedRegister[1][0] = 999;
320  device->someMuxedRegister[2][0] = 222;
321  device->someMuxedRegister[3][0] = -111;
322  device->someMuxedRegister[4][0] = 0;
323  device->someMuxedRegister[5][0] = 555;
324  device->someMuxedRegister[6][0] = 666;
325  device->someMuxedRegister[7][0] = 777;
326  device->someMuxedRegister[8][0] = 888;
327  device->someMuxedRegister[9][0] = 999;
328  device->someMuxedRegister[10][0] = 1111;
329  device->someMuxedRegister[11][0] = 2222;
330  device->someMuxedRegister[12][0] = 3333;
331  device->someMuxedRegister[13][0] = 4444;
332  device->someMuxedRegister[14][0] = 5555;
333  device->someMuxedRegister[15][0] = 6666;
334 
335  for(int i = 1; i < 65536 / 16; i++) {
336  for(int k = 0; k < 16; k++) {
337  device->someMuxedRegister[k][i] = 10 * k + i;
338  }
339  }
340 
341  for(int k = 0; k < 13; k++) mixedReg.raw[k] = device->_barContents[0xD][areaIndexOffset + k];
342  BOOST_CHECK(mixedReg.cooked.r0 == 666);
343  BOOST_CHECK(mixedReg.cooked.r1 == 999);
344  BOOST_CHECK(mixedReg.cooked.r2 == 222);
345  BOOST_CHECK(mixedReg.cooked.r3 == -111);
346  BOOST_CHECK(mixedReg.cooked.r4 == 0);
347  BOOST_CHECK(mixedReg.cooked.r5 == 555);
348  BOOST_CHECK(mixedReg.cooked.r6 == 666);
349  BOOST_CHECK(mixedReg.cooked.r7 == 777);
350  BOOST_CHECK(mixedReg.cooked.r8 == 888);
351  BOOST_CHECK(mixedReg.cooked.r9 == 999);
352  BOOST_CHECK(mixedReg.cooked.r10 == 1111);
353  BOOST_CHECK(mixedReg.cooked.r11 == 2222);
354  BOOST_CHECK(mixedReg.cooked.r12 == 3333);
355  BOOST_CHECK(mixedReg.cooked.r13 == 4444);
356  BOOST_CHECK(mixedReg.cooked.r14 == 5555);
357  BOOST_CHECK(mixedReg.cooked.r15 == 6666);
358 
359  for(int i = 1; i < 65536 / 16; i++) {
360  for(int k = 0; k < 13; k++) mixedReg.raw[k] = device->_barContents[0xD][areaIndexOffset + i * (pitch / 4) + k];
361  BOOST_CHECK(mixedReg.cooked.r0 == 10 * 0 + i);
362  BOOST_CHECK(mixedReg.cooked.r1 == std::min(10 * 1 + i, 32767));
363  BOOST_CHECK(mixedReg.cooked.r2 == std::min(10 * 2 + i, 32767));
364  BOOST_CHECK(mixedReg.cooked.r3 == std::min(10 * 3 + i, 127));
365  BOOST_CHECK(mixedReg.cooked.r4 == std::min(10 * 4 + i, 1));
366  BOOST_CHECK(mixedReg.cooked.r5 == 10 * 5 + i);
367  BOOST_CHECK(mixedReg.cooked.r6 == std::min(10 * 6 + i, 32767));
368  BOOST_CHECK(mixedReg.cooked.r7 == 10 * 7 + i);
369  BOOST_CHECK(mixedReg.cooked.r8 == 10 * 8 + i);
370  BOOST_CHECK(mixedReg.cooked.r9 == 10 * 9 + i);
371  BOOST_CHECK(mixedReg.cooked.r10 == 10 * 10 + i);
372  BOOST_CHECK(mixedReg.cooked.r11 == 10 * 11 + i);
373  BOOST_CHECK(mixedReg.cooked.r12 == 10 * 12 + i);
374  BOOST_CHECK(mixedReg.cooked.r13 == 10 * 13 + i);
375  BOOST_CHECK(mixedReg.cooked.r14 == 10 * 14 + i);
376  BOOST_CHECK(mixedReg.cooked.r15 == (unsigned int)(10 * 15 + i));
377  }
378 
379  // close the device
380  device->close();
381 }
ChimeraTK::AccessMode::raw
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
TestableDummyBackend
The TestableDummybackend is derived from DummyBackend to get access to the protected members.
Definition: testDummyBackend.cpp:50
device
ctk::Device device
Definition: testExceptionDummyDevice.cc:18
ChimeraTK::DummyRegisterAccessor< int >
ChimeraTK::Device::close
void close()
Close the device.
Definition: Device.cc:66
ChimeraTK::DummyMultiplexedRegisterAccessor< int >
DummyBackend.h
DummyRegisterTestSuite::DummyRegisterTestSuite
DummyRegisterTestSuite()
Definition: testDummyRegisterAccessor.cpp:72
init_unit_test
bool init_unit_test()
Definition: testDummyRegisterAccessor.cpp:82
boost_dynamic_init_test.h
DummyRegisterTest
Definition: testDummyRegisterAccessor.cpp:51
DummyRegisterTest::testMuxedRegisterAccessor
void testMuxedRegisterAccessor()
test the register accessor
Definition: testDummyRegisterAccessor.cpp:145
DummyRegisterTestSuite
Definition: testDummyRegisterAccessor.cpp:70
TestableDummyBackend::someMuxedRegister
DummyMultiplexedRegisterAccessor< int > someMuxedRegister
Definition: testDummyRegisterAccessor.cpp:34
InvalidDummyBackend::InvalidDummyBackend
InvalidDummyBackend(std::string mapFileName)
Definition: testDummyRegisterAccessor.cpp:42
TestableDummyBackend::TestableDummyBackend
TestableDummyBackend(std::string mapFileName)
Definition: testDummyRegisterAccessor.cpp:29
INVALID_MAPPING_FILE
#define INVALID_MAPPING_FILE
Definition: testDummyRegisterAccessor.cpp:23
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
DummyRegisterAccessor.h
DummyRegisterTest::testExceptions
void testExceptions()
test exceptions
Definition: testDummyRegisterAccessor.cpp:90
InvalidDummyBackend::invalidRegister
DummyMultiplexedRegisterAccessor< int > invalidRegister
Definition: testDummyRegisterAccessor.cpp:45
ChimeraTK::DummyBackend
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
Definition: DummyBackend.h:45
ChimeraTK
Definition: DummyBackend.h:16
DummyRegisterTest::DummyRegisterTest
DummyRegisterTest()
Definition: testDummyRegisterAccessor.cpp:53
DummyRegisterTest::testRegisterAccessor
void testRegisterAccessor()
test the register accessor
Definition: testDummyRegisterAccessor.cpp:97
InvalidDummyBackend
Definition: testDummyRegisterAccessor.cpp:40
TEST_MAPPING_FILE
#define TEST_MAPPING_FILE
Definition: testDummyRegisterAccessor.cpp:22
TestableDummyBackend::someRegister
DummyRegisterAccessor< int > someRegister
Definition: testDummyRegisterAccessor.cpp:33
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51