ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testSubdeviceBackendUnified.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 SubdeviceBackendUnifiedTest
6#include <boost/test/unit_test.hpp>
7using namespace boost::unit_test_framework;
8
9#include "Device.h"
12#include "UnifiedBackendTest.h"
13
14using namespace ChimeraTK;
15
16BOOST_AUTO_TEST_SUITE(SubdeviceBackendUnifiedTestSuite)
17
18/**********************************************************************************************************************/
19
20static std::string cdd("(ExceptionDummy:1?map=SubdeviceTarget.map)");
21static auto target = boost::dynamic_pointer_cast<ExceptionDummy>(BackendFactory::getInstance().createBackend(cdd));
22
23/**********************************************************************************************************************/
24
25template<typename Register>
26struct AreaType : Register {
27 bool isWriteable() { return true; }
28 bool isReadable() { return true; }
30 size_t nChannels() { return 1; }
31 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
32 size_t nRuntimeErrorCases() { return 1; }
33
34 static constexpr auto capabilities =
35 TestCapabilities<>().disableForceDataLossWrite().disableAsyncReadInconsistency().enableTestRawTransfer();
36
37 DummyRegisterAccessor<uint32_t> acc{target.get(), "APP.0", "THE_AREA"};
38
39 template<typename UserType>
40 std::vector<std::vector<UserType>> generateValue(bool raw = false) {
41 std::vector<UserType> v;
42 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
43 assert(i + this->address() / 4 < 10);
44 typename Register::minimumUserType e = acc[i + this->address() / 4] + this->increment * (i + 1);
45 auto limited = this->limitGenerated(e);
46 v.push_back(raw ? this->toRaw(limited) : limited);
47 }
48 return {v};
49 }
50
51 // Use the same implementation for raw and cooked.
52 // Type can be UserType or RawType
53 template<typename Type>
54 std::vector<std::vector<Type>> getRemoteValue(bool raw = false) {
55 std::vector<Type> v;
56 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
57 assert(i + this->address() / 4 < 10);
58 auto rawVal = acc[i + this->address() / 4];
59 v.push_back((raw ? rawVal : this->fromRaw(rawVal)));
60 }
61 return {v};
62 }
63
65 auto v = generateValue<typename Register::minimumUserType>()[0];
66 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
67 assert(i + this->address() / 4 < 10);
68 acc[i + this->address() / 4] = this->toRaw(v[i]);
69 }
70 }
71
72 void setForceRuntimeError(bool enable, size_t) {
73 target->throwExceptionRead = enable;
74 target->throwExceptionWrite = enable;
75 target->throwExceptionOpen = enable;
76 }
77};
78
79/**********************************************************************************************************************/
80
81struct StaticCore {
83 assert(target != nullptr);
84 data.setWriteCallback([this] { this->writeCallback(); });
85 area.setWriteCallback([this] { this->writeCallback(); });
86 }
87
88 DummyRegisterAccessor<uint32_t> address{target.get(), "APP.1", "ADDRESS"};
89 DummyRegisterAccessor<uint32_t> data{target.get(), "APP.1", "DATA"};
90 DummyRegisterAccessor<uint32_t> area{target.get(), "APP.0", "THE_AREA"};
91 DummyRegisterAccessor<uint32_t> status{target.get(), "APP.1", "STATUS"};
92 size_t lastAddress{32};
93 std::vector<uint32_t> currentValue{std::vector<uint32_t>(lastAddress)};
94 size_t areaSize{10};
95 std::vector<std::vector<uint32_t>> currentAreaValue{lastAddress, std::vector<uint32_t>(areaSize)};
96
97 bool useStatus{true};
98 bool useArea{false};
99
101 if(useStatus) status = 1;
102 if(address >= lastAddress) {
103 std::cout << "Error: address (" << address << ") >= lastAddress (" << lastAddress << ")!" << std::endl;
104 }
105 BOOST_REQUIRE(address < lastAddress);
106 if(!useArea) {
108 }
109 else {
110 assert(area.getNumberOfElements() == areaSize);
111 for(size_t i = 0; i < areaSize; ++i) {
113 }
114 }
115 usleep(432);
116 if(useStatus) status = 0;
117 }
118};
119static StaticCore core;
120
121/**********************************************************************************************************************/
122
123template<typename Register>
124struct Regs3Type : Register {
125 bool isWriteable() { return true; }
126 bool isReadable() { return false; }
128 size_t nChannels() { return 1; }
129 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
130 size_t nRuntimeErrorCases() { return 1; }
131
132 static constexpr auto capabilities = TestCapabilities<>()
134 .disableAsyncReadInconsistency()
135 .enableTestRawTransfer()
136 .disableTestPartialAccessor();
137
138 template<typename Type>
139 std::vector<std::vector<Type>> generateValue(bool raw = false) {
140 std::vector<Type> v;
141 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
142 uint32_t cv;
143 if(!core.useArea) {
144 cv = core.currentValue[i + this->address()];
145 }
146 else {
147 cv = core.currentAreaValue[this->address() + i / core.areaSize][i % core.areaSize];
148 }
149 // Do the calculation in cooked, and convert back to raw if necessary
150 typename Register::minimumUserType e = this->fromRaw(cv) + this->increment * (i + 1);
151 auto limited = this->limitGenerated(e);
152 v.push_back(raw ? this->toRaw(limited) : limited);
153 }
154 return {v};
155 }
156
157 template<typename Type>
158 std::vector<std::vector<Type>> getRemoteValue(bool raw = false) {
159 std::vector<Type> v;
160 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
161 Type rawValue;
162 if(!core.useArea) {
163 rawValue = core.currentValue[i + this->address()];
164 }
165 else {
166 rawValue = core.currentAreaValue[this->address() + i / core.areaSize][i % core.areaSize];
167 }
168 v.push_back(raw ? rawValue : this->fromRaw(rawValue));
169 }
170 return {v};
171 }
172
174 auto v = generateValue<typename Register::minimumUserType>()[0];
175 for(size_t i = 0; i < this->nElementsPerChannel(); ++i) {
176 if(!core.useArea) {
177 core.currentValue[i + this->address()] = this->toRaw(v[i]);
178 }
179 else {
180 core.currentAreaValue[this->address() + i / core.areaSize][i % core.areaSize] = this->toRaw(v[i]);
181 }
182 }
183 }
184
185 void setForceRuntimeError(bool enable, size_t) {
186 target->throwExceptionRead = enable;
187 target->throwExceptionWrite = enable;
188 target->throwExceptionOpen = enable;
189 }
190};
191
192/**********************************************************************************************************************/
193
195 std::string path() { return "/APP.0/MY_REGISTER1"; }
196 size_t nElementsPerChannel() { return 1; }
197 size_t address() { return 0; }
198 uint32_t toRaw(uint32_t v) { return v; }
199 uint32_t fromRaw(uint32_t v) { return v; }
200 uint32_t limitGenerated(uint32_t e) { return e; }
201 uint32_t increment = 7;
202 typedef uint32_t minimumUserType;
203 typedef int32_t rawUserType;
204};
205
206/**********************************************************************************************************************/
207
208struct MyArea1 {
209 std::string path() { return "/APP.0/MY_AREA1"; }
210 size_t nElementsPerChannel() { return 6; }
211 size_t address() { return 8; }
212 uint32_t toRaw(float v) { return v * 65536.F; }
213 float fromRaw(uint32_t v) { return v / 65536.F; }
214 float limitGenerated(float e) {
215 while(e > 32768.F) e -= 65535.F;
216 while(e < -32767.F) e += 65535.F;
217 return e;
218 }
219 float increment = 666. / 65536.;
220 typedef float minimumUserType;
221 typedef int32_t rawUserType;
222};
223
224/**********************************************************************************************************************/
225
227 std::string path() { return "/APP.0/THE_AREA_1"; }
228 size_t nElementsPerChannel() { return 10; }
229 size_t address() { return 0; }
230 uint32_t toRaw(uint32_t v) { return v; }
231 uint32_t fromRaw(uint32_t v) { return v; }
232 uint32_t limitGenerated(uint32_t e) { return e; }
233 uint32_t increment = 17;
234 typedef uint32_t minimumUserType;
235 typedef int32_t rawUserType;
236};
237
238/**********************************************************************************************************************/
239
241 std::string path() { return "/APP.0/THE_AREA_2"; }
242 size_t nElementsPerChannel() { return 25; }
243 size_t address() { return 7; }
244 uint32_t toRaw(float v) { return v * 65536.F; }
245 float fromRaw(uint32_t v) { return v / 65536.F; }
246 float limitGenerated(float e) {
247 while(e > 32768.F) e -= 65535.F;
248 while(e < -32767.F) e += 65535.F;
249 return e;
250 }
251 float increment = 42. / 65536.;
252 typedef float minimumUserType;
253 typedef int32_t rawUserType;
254};
255
256/**********************************************************************************************************************/
257
258BOOST_AUTO_TEST_CASE(TestUnifiedSimple) {
259 // test area type
261 "(subdevice?type=area&device=" + cdd + "&area=APP.0.THE_AREA&map=Subdevice.map)");
262}
263
264/**********************************************************************************************************************/
265
266BOOST_AUTO_TEST_CASE(TestUnified3Reg) {
267 // test 3regs type
269 "(subdevice?type=3regs&device=" + cdd +
270 "&address=APP.1.ADDRESS&data=APP.1.DATA&status=APP.1.STATUS&map=Subdevice.map)");
271}
272
273/**********************************************************************************************************************/
274
275BOOST_AUTO_TEST_CASE(TestUnified2Reg) {
276 // test 2regs type
277 core.useStatus = false;
279 "(subdevice?type=2regs&device=" + cdd + "&address=APP.1.ADDRESS&data=APP.1.DATA&sleep=1000&map=Subdevice.map)");
280}
281
282/**********************************************************************************************************************/
283
284BOOST_AUTO_TEST_CASE(TestUnifiedMuxed3Reg) {
285 // test different use case of 3regs mode: multiplexing of an area
286 core.useStatus = true;
287 core.useArea = true;
288 core.lastAddress = 10;
290 "(subdevice?type=3regs&device=" + cdd +
291 "&address=APP.1.ADDRESS&data=APP.0.THE_AREA&status=APP.1.STATUS&map=SubdeviceMuxedArea.map)");
292}
293
294/**********************************************************************************************************************/
295
296BOOST_AUTO_TEST_SUITE_END()
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
static BackendFactory & getInstance()
Static function to get an instance of factory.
Register accessor for accessing single word or 1D array registers internally of a DummyBackend implem...
unsigned int getNumberOfElements()
return number of elements
void setWriteCallback(const std::function< void()> &writeCallback)
Set callback function which is called when the register is written to (through the normal Device inte...
Class to test any backend for correct behaviour.
UnifiedBackendTest< typename boost::mpl::push_back< VECTOR_OF_REGISTERS_T, REG_T >::type > addRegister()
Add a register to be used by the test.
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
static constexpr auto capabilities
void setForceRuntimeError(bool enable, size_t)
DummyRegisterAccessor< uint32_t > acc
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > generateValue(bool raw=false)
std::vector< std::vector< Type > > getRemoteValue(bool raw=false)
Descriptor for the test capabilities for each register.
constexpr TestCapabilities< _syncRead, TestCapability::disabled, _asyncReadInconsistency, _switchReadOnly, _switchWriteOnly, _writeNeverLosesData, _testWriteOnly, _testReadOnly, _testRawTransfer, _testCatalogue, _setRemoteValueIncrementsVersion, _testPartialAccessor > disableForceDataLossWrite() const
uint32_t fromRaw(uint32_t v)
uint32_t toRaw(uint32_t v)
uint32_t limitGenerated(uint32_t e)
float fromRaw(uint32_t v)
uint32_t toRaw(float v)
float limitGenerated(float e)
float fromRaw(uint32_t v)
uint32_t limitGenerated(uint32_t e)
uint32_t toRaw(uint32_t v)
uint32_t fromRaw(uint32_t v)
void setForceRuntimeError(bool enable, size_t)
static constexpr auto capabilities
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< Type > > getRemoteValue(bool raw=false)
std::vector< std::vector< Type > > generateValue(bool raw=false)
DummyRegisterAccessor< uint32_t > address
std::vector< uint32_t > currentValue
DummyRegisterAccessor< uint32_t > area
std::vector< std::vector< uint32_t > > currentAreaValue
DummyRegisterAccessor< uint32_t > status
DummyRegisterAccessor< uint32_t > data
std::string cdd
BOOST_AUTO_TEST_CASE(TestUnifiedSimple)