ChimeraTK-DeviceAccess  03.18.00
testOneDRegisterAccessor.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 #define BOOST_TEST_DYN_LINK
4 #define BOOST_TEST_MODULE OneDRegisterAccessorTest
5 #include <boost/test/unit_test.hpp>
6 using namespace boost::unit_test_framework;
7 
8 #include "BackendFactory.h"
9 #include "Device.h"
10 #include "DummyBackend.h"
11 #include "DummyRegisterAccessor.h"
12 #include "OneDRegisterAccessor.h"
13 #include "WriteCountingBackend.h"
14 
15 #include <boost/bind/bind.hpp>
16 #include <boost/date_time/posix_time/posix_time.hpp>
17 #include <boost/function.hpp>
18 #include <boost/lambda/lambda.hpp>
19 #include <boost/make_shared.hpp>
20 
21 #include <algorithm>
22 #include <math.h>
23 
24 using namespace boost::unit_test_framework;
25 using namespace ChimeraTK;
26 
27 /**********************************************************************************************************************/
28 
29 struct Fixture {
30  Fixture() {
31  setDMapFilePath("dummies.dmap");
32  device.open("(WriteCountingDummy?map=goodMapFile.map)");
33  }
34 
36 };
37 
38 /**********************************************************************************************************************/
39 
40 BOOST_FIXTURE_TEST_CASE(testRegisterAccessor, Fixture) {
41  std::cout << "testRegisterAccessor" << std::endl;
42 
43  // obtain register accessor with integral type
44  OneDRegisterAccessor<int> intRegister = device.getOneDRegisterAccessor<int>("APP0/MODULE0");
45  BOOST_CHECK(intRegister.isReadOnly() == false);
46  BOOST_CHECK(intRegister.isReadable());
47  BOOST_CHECK(intRegister.isWriteable());
48 
49  // check number of elements getter
50  BOOST_CHECK(intRegister.getNElements() == 3);
51 
52  // test operator[] on r.h.s.
53  device.write<int>("APP0/MODULE0", std::vector<int>({5, -77, 99}));
54  intRegister.read();
55  BOOST_CHECK(intRegister[0] == 5);
56  BOOST_CHECK(intRegister[1] == -77);
57  BOOST_CHECK(intRegister[2] == 99);
58 
59  // test operator[] on l.h.s.
60  intRegister[0] = -666;
61  intRegister[1] = 999;
62  intRegister[2] = 222;
63  intRegister.write();
64  BOOST_CHECK(device.read<int>("APP0/MODULE0", 3) == std::vector<int>({-666, 999, 222}));
65 
66  // test data() function
67  int* ptr = intRegister.data();
68  BOOST_CHECK(ptr[0] = -666);
69  BOOST_CHECK(ptr[1] = 999);
70  BOOST_CHECK(ptr[2] = 222);
71  ptr[0] = 123;
72  ptr[1] = 456;
73  ptr[2] = 789;
74  BOOST_CHECK(intRegister[0] = 123);
75  BOOST_CHECK(intRegister[1] = 456);
76  BOOST_CHECK(intRegister[2] = 789);
77 
78  // test iterators with begin and end
79  int ic = 0;
80  for(OneDRegisterAccessor<int>::iterator it = intRegister.begin(); it != intRegister.end(); ++it) {
81  *it = 1000 * (ic + 1);
82  ic++;
83  }
84  intRegister.write();
85  BOOST_CHECK(device.read<int>("APP0/MODULE0", 3) == std::vector<int>({1000, 2000, 3000}));
86 
87  // test iterators with rbegin and rend
88  ic = 0;
89  for(OneDRegisterAccessor<int>::reverse_iterator it = intRegister.rbegin(); it != intRegister.rend(); ++it) {
90  *it = 333 * (ic + 1);
91  ic++;
92  }
93  intRegister.write();
94  BOOST_CHECK(device.read<int>("APP0/MODULE0", 3) == std::vector<int>({999, 666, 333}));
95 
96  // test const iterators in both directions
97  device.write("APP0/MODULE0", std::vector<int>({1234, 2468, 3702}));
98  intRegister.read();
99  const OneDRegisterAccessor<int> const_intRegister = intRegister;
100  ic = 0;
101  for(OneDRegisterAccessor<int>::const_iterator it = const_intRegister.begin(); it != const_intRegister.end(); ++it) {
102  BOOST_CHECK(*it == 1234 * (ic + 1));
103  ic++;
104  }
105  ic = 0;
106  for(OneDRegisterAccessor<int>::const_reverse_iterator it = const_intRegister.rbegin(); it != const_intRegister.rend();
107  ++it) {
108  BOOST_CHECK(*it == 1234 * (3 - ic));
109  ic++;
110  }
111 
112  // test swap with std::vector
113  std::vector<int> x(3);
114  x[0] = 11;
115  x[1] = 22;
116  x[2] = 33;
117  intRegister.swap(x);
118  BOOST_CHECK(x[0] == 1234);
119  BOOST_CHECK(x[1] == 2468);
120  BOOST_CHECK(x[2] == 3702);
121  BOOST_CHECK(intRegister[0] == 11);
122  BOOST_CHECK(intRegister[1] == 22);
123  BOOST_CHECK(intRegister[2] == 33);
124 
125  // obtain register accessor with fractional type, to check if fixed-point
126  // conversion is working (3 fractional bits)
127  OneDRegisterAccessor<double> floatRegister = device.getOneDRegisterAccessor<double>("MODULE0/WORD_USER1");
128 
129  // test operator[] on r.h.s.
130  device.write("APP0/MODULE0", std::vector<int>({-120, 2468}));
131  floatRegister.read();
132  BOOST_CHECK(floatRegister[0] == -120. / 8.);
133 
134  // test operator[] on l.h.s.
135  floatRegister[0] = 42. / 8.;
136  floatRegister.write();
137  BOOST_CHECK(device.read<int>("APP0/MODULE0", 2) == std::vector<int>({42, 2468}));
138 }
139 
140 /**********************************************************************************************************************/
141 
142 BOOST_FIXTURE_TEST_CASE(testWriteIfDifferent, Fixture) {
143  std::cout << "testWriteIfDifferent" << std::endl;
144 
145  OneDRegisterAccessor<int> accessor = device.getOneDRegisterAccessor<int>("APP0/MODULE0");
146 
147  // dummy register accessor for comparison
148  auto backend = boost::dynamic_pointer_cast<WriteCountingBackend>(device.getBackend());
149  BOOST_CHECK(backend != NULL);
150  DummyRegisterAccessor<int> dummy(backend.get(), "APP0", "MODULE0");
151 
152  // Inital write and writeIfDifferent with same value
153  accessor = {501, 502, 503};
154  accessor.write();
155  size_t counterBefore = backend->writeCount;
156  accessor.writeIfDifferent({501, 502, 503}); // should not write
157  size_t counterAfter = backend->writeCount;
158  BOOST_CHECK(counterBefore == counterAfter);
159 
160  // writeIfDifferent with different value
161  counterBefore = backend->writeCount;
162  accessor.writeIfDifferent({501, 504, 503}); // should write
163  counterAfter = backend->writeCount;
164  BOOST_CHECK(counterAfter == counterBefore + 1);
165 
166  // writeIfDifferent with same value, but explicit version number
167  counterBefore = backend->writeCount;
168  accessor.writeIfDifferent({501, 504, 503}, VersionNumber{}); // should not write
169  counterAfter = backend->writeCount;
170  BOOST_CHECK(counterAfter == counterBefore);
171 
172  // writeIfDifferent with different value, and explicit version number
173  counterBefore = backend->writeCount;
174  accessor.writeIfDifferent({505, 504, 503}, VersionNumber{}); // should write
175  counterAfter = backend->writeCount;
176  BOOST_CHECK(counterAfter == counterBefore + 1);
177 
178  // writeIfDifferent with same value, but different DataValidity
179  counterBefore = backend->writeCount;
180  accessor.writeIfDifferent({505, 504, 503}, VersionNumber{nullptr}, DataValidity::faulty); // should write
181  counterAfter = backend->writeCount;
182  BOOST_CHECK(counterAfter == counterBefore + 1);
183 
184  // writeIfDifferent with same value, but different DataValidity (now back at OK)
185  counterBefore = backend->writeCount;
186  accessor.writeIfDifferent({505, 504, 503}); // should write
187  counterAfter = backend->writeCount;
188  BOOST_CHECK(counterAfter == counterBefore + 1);
189 
190  device.close();
191 }
192 
193 /**********************************************************************************************************************/
ChimeraTK::OneDRegisterAccessor::rend
reverse_iterator rend()
Definition: OneDRegisterAccessor.h:67
ChimeraTK::OneDRegisterAccessor::rbegin
reverse_iterator rbegin()
Definition: OneDRegisterAccessor.h:64
ChimeraTK::TransferElementAbstractor::isReadOnly
bool isReadOnly() const
Check if transfer element is read only, i.e.
Definition: TransferElementAbstractor.h:102
ChimeraTK::TransferElementAbstractor::isWriteable
bool isWriteable() const
Check if transfer element is writeable.
Definition: TransferElementAbstractor.h:112
ChimeraTK::OneDRegisterAccessor::reverse_iterator
typename std::vector< UserType >::reverse_iterator reverse_iterator
Definition: OneDRegisterAccessor.h:56
ChimeraTK::OneDRegisterAccessor::end
iterator end()
Definition: OneDRegisterAccessor.h:61
device
ctk::Device device
Definition: testExceptionDummyDevice.cc:18
ChimeraTK::DummyRegisterAccessor< int >
Fixture::device
Device device
Definition: testOneDRegisterAccessor.cpp:35
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::OneDRegisterAccessor::writeIfDifferent
void writeIfDifferent(const std::vector< UserType > &newValue, VersionNumber versionNumber=VersionNumber{nullptr}, DataValidity validity=DataValidity::ok)
Convenience function to set and write new value if it differes from the current value.
Definition: OneDRegisterAccessor.h:210
DummyBackend.h
ChimeraTK::Device::read
UserType read(const RegisterPath &registerPathName, const AccessModeFlags &flags=AccessModeFlags({})) const
Inefficient convenience function to read a single-word register without obtaining an accessor.
Definition: Device.h:293
OneDRegisterAccessor.h
ChimeraTK::OneDRegisterAccessor::getNElements
unsigned int getNElements()
Return number of elements/samples in the register.
Definition: OneDRegisterAccessor.h:51
ChimeraTK::OneDRegisterAccessor::iterator
typename std::vector< UserType >::iterator iterator
Definition: OneDRegisterAccessor.h:54
BOOST_FIXTURE_TEST_CASE
BOOST_FIXTURE_TEST_CASE(testRegisterAccessor, Fixture)
Definition: testOneDRegisterAccessor.cpp:40
ChimeraTK::TransferElementAbstractor::isReadable
bool isReadable() const
Check if transfer element is readable.
Definition: TransferElementAbstractor.h:107
ChimeraTK::OneDRegisterAccessor::const_iterator
typename std::vector< UserType >::const_iterator const_iterator
Definition: OneDRegisterAccessor.h:55
ChimeraTK::OneDRegisterAccessor
Accessor class to read and write registers transparently by using the accessor object like a vector o...
Definition: OneDRegisterAccessor.h:20
ChimeraTK::OneDRegisterAccessor::data
UserType * data()
Return a direct pointer to the memory buffer storng the elements.
Definition: OneDRegisterAccessor.h:96
Device.h
Fixture
Definition: testAsyncRead.cpp:122
ChimeraTK::Device
Class allows to read/write registers from device.
Definition: Device.h:39
ChimeraTK::OneDRegisterAccessor::swap
void swap(std::vector< UserType > &x) noexcept
Swap content of (cooked) buffer with std::vector.
Definition: OneDRegisterAccessor.h:154
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
BackendFactory.h
ChimeraTK::OneDRegisterAccessor::begin
iterator begin()
Definition: OneDRegisterAccessor.h:58
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
WriteCountingBackend.h
ChimeraTK::TransferElementAbstractor::write
bool write(ChimeraTK::VersionNumber versionNumber={})
Write the data to device.
Definition: TransferElementAbstractor.h:89
ChimeraTK::Device::write
void write(const RegisterPath &registerPathName, UserType value, const AccessModeFlags &flags=AccessModeFlags({}))
Inefficient convenience function to write a single-word register without obtaining an accessor.
Definition: Device.h:314
Fixture::Fixture
Fixture()
Definition: testOneDRegisterAccessor.cpp:30
ChimeraTK::setDMapFilePath
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
Definition: Utilities.cpp:327
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::TransferElementAbstractor::read
void read()
Read the data from the device.
Definition: TransferElementAbstractor.h:57
ChimeraTK::OneDRegisterAccessor::const_reverse_iterator
typename std::vector< UserType >::const_reverse_iterator const_reverse_iterator
Definition: OneDRegisterAccessor.h:57