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