ChimeraTK-DeviceAccess-TangoBackend 00.01.02
Loading...
Searching...
No Matches
testUnifiedBackend.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#include <ChimeraTK/SupportedUserTypes.h>
5
6#include <tango/idl/tango.h>
7#define BOOST_TEST_DYN_LINK
8#define BOOST_TEST_MODULE testUnifiedBackendTest
9
10#include "TangoServerLauncher.h"
11
12#include <ChimeraTK/UnifiedBackendTest.h>
13
14#include <tango/tango.h>
15
16#include <boost/filesystem.hpp>
17#include <boost/process.hpp>
18#include <boost/test/unit_test.hpp>
19
20#include <chrono>
21#include <filesystem>
22#include <random>
23
24using namespace boost::unit_test_framework;
25using namespace ChimeraTK;
26
28
29/**********************************************************************************************************************/
30
31template<typename DERIVED>
33 DERIVED* derived{static_cast<DERIVED*>(this)};
34
35 bool isWriteable() { return true; }
36 bool isReadable() { return true; }
37 ChimeraTK::AccessModeFlags supportedFlags() { return {}; }
38 size_t nChannels() { return 1; }
39 size_t writeQueueLength() { return std::numeric_limits<size_t>::max(); }
40 size_t nRuntimeErrorCases() { return 1; }
41 using rawUserType = std::nullptr_t;
42
43 static constexpr auto capabilities = TestCapabilities<>()
44 .enableTestCatalogue()
45 .disableForceDataLossWrite()
46 .disableAsyncReadInconsistency()
47 .disableSwitchReadOnly()
48 .disableSwitchWriteOnly();
49
50 void setForceRuntimeError(bool enable, size_t) {
51 if(enable) {
53 }
54 else {
56 }
57 }
58};
59
60/**********************************************************************************************************************/
61
62template<typename DERIVED>
65 using AllRegisterDefaults<DERIVED>::derived;
66 size_t nElementsPerChannel() { return 1; }
67
68 template<typename UserType>
69 std::vector<std::vector<UserType>> generateValue() {
70 return {{ChimeraTK::numericToUserType<UserType>(static_cast<typename DERIVED::minimumUserType>(
71 derived->template getRemoteValue<typename DERIVED::minimumUserType>()[0][0] + derived->increment))}};
72 }
73
74 template<typename UserType>
75 std::vector<std::vector<UserType>> getRemoteValue() {
76 auto v = ChimeraTK::numericToUserType<UserType>(derived->getValue());
77 return {{v}};
78 }
79
81 auto v = derived->template generateValue<typename DERIVED::minimumUserType>()[0][0];
82 derived->setValue(v);
83 }
84};
85
86template<typename DERIVED>
88 using AllRegisterDefaults<DERIVED>::derived;
89 size_t nElementsPerChannel() { return 1; }
90
91 template<typename UserType>
92 std::vector<std::vector<UserType>> getRemoteValue() {
93 auto v = ChimeraTK::numericToUserType<UserType>(derived->getValue());
94 return {{v}};
95 }
96
98 auto v = derived->template generateValue<typename DERIVED::minimumUserType>()[0][0];
99 derived->setValue(v);
100 }
101};
102
103/**********************************************************************************************************************/
104
105template<typename DERIVED>
108 using AllRegisterDefaults<DERIVED>::derived;
109
110 template<typename UserType>
111 std::vector<std::vector<UserType>> generateValue() {
112 auto curval = derived->template getRemoteValue<typename DERIVED::minimumUserType>()[0];
113 std::vector<UserType> val;
114 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
115 val.push_back(ChimeraTK::numericToUserType<UserType>(curval[i] + (i + 1) * derived->increment));
116 }
117 return {val};
118 }
119
120 template<typename UserType>
121 std::vector<std::vector<UserType>> getRemoteValue() {
122 std::vector<UserType> val;
123 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
124 val.push_back(ChimeraTK::numericToUserType<UserType>(derived->getValue(i)));
125 }
126 return {val};
127 }
128
129 template<typename REMOTE_TYPE>
131 auto val = derived->template generateValue<typename DERIVED::minimumUserType>()[0];
132 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
133 derived->setValue(i, ChimeraTK::userTypeToUserType<REMOTE_TYPE, typename DERIVED::minimumUserType>(val[i]));
134 }
135 }
136};
137
138/**********************************************************************************************************************/
139
140struct RegSomeInt : ScalarDefaults<RegSomeInt> {
141 std::string path() { return "IntScalar"; }
142 std::string writePath() { return "IntScalar"; }
143 std::string readPath() { return "IntScalar"; }
144 using minimumUserType = int32_t;
145 int32_t increment{3};
146
148 std::string attrName = writePath();
149 auto attr = Tango::DeviceAttribute(attrName, v);
150 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
151 }
152
154 Tango::DevLong value;
155 std::string path = readPath();
156 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
157 attr >> value;
158
159 return value;
160 }
161};
162
163struct RegSomeRoInt : ScalarDefaults<RegSomeRoInt> {
164 std::string path() { return "IntRoScalar"; }
165 std::string writePath() { return "IntScalar"; }
166 std::string readPath() { return "IntScalar"; }
167 typedef int32_t minimumUserType;
168 int32_t increment{3};
169
170 static constexpr auto capabilities = ScalarDefaults<RegSomeInt>::capabilities.enableTestReadOnly();
171
173 std::string path = writePath();
174 auto attr = Tango::DeviceAttribute(path, v);
175 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
176 }
177
179 Tango::DevLong value;
180 std::string path = readPath();
181 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
182 attr >> value;
183
184 return value;
185 }
186};
187
188struct RegSomeWoInt : ScalarDefaults<RegSomeWoInt> {
189 std::string path() { return "IntWoScalar"; }
190 std::string writePath() { return "IntScalar"; }
191 std::string readPath() { return "IntScalar"; }
192 typedef int32_t minimumUserType;
193 int32_t increment{3};
194
195 static constexpr auto capabilities = ScalarDefaults<RegSomeInt>::capabilities.enableTestWriteOnly();
196
198 std::string path = writePath();
199 auto attr = Tango::DeviceAttribute(path, v);
200 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
201 }
202
204 Tango::DevLong value;
205 std::string path = readPath();
206 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
207 attr >> value;
208
209 return value;
210 }
211};
212
213struct RegSomeBool : ScalarDefaults<RegSomeBool> {
214 std::string path() { return "BooleanScalar"; }
215 std::string writePath() { return "BooleanScalar"; }
216 std::string readPath() { return "BooleanScalar"; }
217
218 typedef ChimeraTK::Boolean minimumUserType;
219
220 bool increment{false};
221
223 try {
224 std::string path = writePath();
225 auto attr = Tango::DeviceAttribute(path, bool(v));
226 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
227 }
228 catch(CORBA::Exception& ex) {
229 Tango::Except::print_exception(ex);
230 assert(false);
231 }
232 }
233
235 Tango::DevBoolean value;
236 try {
237 std::string path = readPath();
238 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
239 attr >> value;
240 }
241 catch(CORBA::Exception& ex) {
242 Tango::Except::print_exception(ex);
243 assert(false);
244 }
245
246 return value;
247 }
248};
249
250struct RegSomeRoBool : ScalarDefaults<RegSomeRoBool> {
251 std::string path() { return "BooleanRoScalar"; }
252 std::string writePath() { return "BooleanScalar"; }
253 std::string readPath() { return "BooleanScalar"; }
254
255 using minimumUserType = ChimeraTK::Boolean;
256
257 bool increment{false};
258
259 static constexpr auto capabilities = ScalarDefaults<RegSomeInt>::capabilities.enableTestReadOnly();
260
262 std::string path = readPath();
263 auto attr = Tango::DeviceAttribute(path, bool(v));
264 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
265 }
266
268 Tango::DevBoolean value;
269 std::string path = readPath();
270 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
271 attr >> value;
272
273 return value;
274 }
275};
276
277struct RegSomeWoBool : ScalarDefaults<RegSomeWoBool> {
278 std::string path() { return "BooleanWoScalar"; }
279 std::string writePath() { return "BooleanScalar"; }
280 std::string readPath() { return "BooleanScalar"; }
281
282 typedef ChimeraTK::Boolean minimumUserType;
283
284 bool increment{false};
285
286 static constexpr auto capabilities = ScalarDefaults<RegSomeInt>::capabilities.enableTestWriteOnly();
287
289 std::string path = writePath();
290 auto attr = Tango::DeviceAttribute(path, bool(v));
291 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
292 }
293
295 Tango::DevBoolean value;
296 std::string path = readPath();
297 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
298 attr >> value;
299
300 return value;
301 }
302};
303
304struct RegSomeString : ScalarDefaults<RegSomeString> {
305 std::string path() { return "StringScalar"; }
306 std::string writePath() { return "StringScalar"; }
307 std::string readPath() { return "StringScalar"; }
308
309 typedef std::string minimumUserType;
310
311 std::string increment;
312
314 std::string path = writePath();
315 auto attr = Tango::DeviceAttribute(path, v);
316 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
317 }
318
319 template<typename UserType>
320 std::vector<std::vector<UserType>> generateValue() {
321 assert(false);
322 }
323
325 std::string value;
326 std::string path = readPath();
327 auto attr = TangoServerLauncher::self->remoteProxy->read_attribute(path);
328 attr >> value;
329
330 return value;
331 }
332
333 size_t someValue{42};
334};
335
336template<>
337std::vector<std::vector<std::string>> RegSomeString::generateValue<std::string>() {
338 ++someValue;
339 return {{"This is a string: " + std::to_string(someValue)}};
340}
341
342struct RegSomeIntArray : ArrayDefaults<RegSomeIntArray> {
343 std::string path() { return "IntSpectrum"; }
344 std::string writePath() { return "IntSpectrum"; }
345 std::string readPath() { return "IntSpectrum"; }
346 size_t nElementsPerChannel() { return 10; }
347 typedef int32_t minimumUserType;
348 int32_t increment{12};
349
350 void setValue(int i, Tango::DevLong v) {
351 try {
352 std::string path = readPath();
353 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
354
355 std::vector<Tango::DevLong> values(10, {});
356 attrRead >> values;
357
358 values[i] = v;
359 // for some reason, the vector returned by Tango is one too large
360 values.resize(10);
361
362 path = writePath();
363 auto attr = Tango::DeviceAttribute(path, values);
364 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
365 }
366 catch(CORBA::Exception& ex) {
367 Tango::Except::print_exception(ex);
368 assert(false);
369 }
370 }
371
372 void setRemoteValue() { setRemoteValueImpl<Tango::DevLong>(); }
373
374 Tango::DevLong getValue(int i) {
375 std::string path = readPath();
376 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
377
378 std::vector<Tango::DevLong> values;
379 attrRead >> values;
380
381 return values[i];
382 }
383};
384
385struct RegSomeStringArray : ArrayDefaults<RegSomeStringArray> {
387
388 std::string path() { return "StringSpectrum"; }
389 std::string writePath() { return "StringSpectrum"; }
390 std::string readPath() { return "StringSpectrum"; }
391
392 size_t nElementsPerChannel() { return 10; }
393 using minimumUserType = std::string;
394 int32_t increment{12};
395
396 void setValue(int i, std::string v) {
397 std::string path = readPath();
398 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
399
400 std::vector<std::string> values;
401 attrRead >> values;
402
403 values[i] = v;
404
405 // for some reason, the vector returned by Tango is one too large
406 values.resize(10);
407
408 path = writePath();
409 auto attr = Tango::DeviceAttribute(path, values);
410 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
411 }
412
413 void setRemoteValue() { setRemoteValueImpl<std::string>(); }
414
415 std::string getValue(int i) {
416 std::string path = readPath();
417 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
418
419 std::vector<std::string> values;
420 attrRead >> values;
421
422 return values[i];
423 }
424
425 template<typename UserType>
426 std::vector<std::vector<UserType>> generateValue() {
427 assert(false);
428 }
429
430 size_t someValue{23};
431};
432
433template<>
434std::vector<std::vector<std::string>> RegSomeStringArray::generateValue<std::string>() {
435 std::vector<std::string> value;
436 ++someValue;
437
438 std::vector<std::string> val;
439 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
440 val.push_back("This is a string " + std::to_string(someValue + (i + 1)));
441 ++someValue;
442 }
443 return {val};
444}
445
446struct RegSomeBooleanArray : ArrayDefaults<RegSomeBooleanArray> {
448
449 std::string path() { return "BooleanSpectrum"; }
450 std::string writePath() { return "BooleanSpectrum"; }
451 std::string readPath() { return "BooleanSpectrum"; }
452
453 size_t nElementsPerChannel() { return 10; }
454 using minimumUserType = ChimeraTK::Boolean;
455 int32_t increment{12};
456
457 void setValue(int i, bool v) {
458 std::string path = readPath();
459 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
460
461 std::vector<Tango::DevBoolean> values;
462 try {
463 attrRead >> values;
464 }
465 catch(Tango::DevFailed& ex) {
466 Tango::Except::print_exception(ex);
467 }
468
469 values[i] = v;
470
471 // for some reason, the vector returned by Tango is one too large
472 values.resize(10);
473
474 path = writePath();
475 auto attr = Tango::DeviceAttribute(path, values);
476 TangoServerLauncher::self->remoteProxy->write_attribute(attr);
477 }
478
479 void setRemoteValue() { setRemoteValueImpl<ChimeraTK::Boolean>(); }
480
481 ChimeraTK::Boolean getValue(int i) {
482 std::string path = readPath();
483 auto attrRead = TangoServerLauncher::self->remoteProxy->read_attribute(path);
484
485 std::vector<Tango::DevBoolean> values;
486 attrRead >> values;
487
488 return {values[i]};
489 }
490
491 template<typename UserType>
492 std::vector<std::vector<UserType>> generateValue() {
493 assert(false);
494 }
495
496 size_t someValue{23};
497};
498
499template<>
500std::vector<std::vector<ChimeraTK::Boolean>> RegSomeBooleanArray::generateValue<ChimeraTK::Boolean>() {
501 std::vector<ChimeraTK::Boolean> value;
502 ++someValue;
503
504 std::vector<ChimeraTK::Boolean> val;
505 val.reserve(derived->nElementsPerChannel());
506 for(size_t i = 0; i < derived->nElementsPerChannel(); ++i) {
507 val.emplace_back((i % 2) == 1);
508 }
509 return {val};
510}
511
512/**********************************************************************************************************************/
513
514BOOST_AUTO_TEST_CASE(unifiedBackendTest) {
515 auto ubt = ChimeraTK::UnifiedBackendTest<>()
516 .addRegister<RegSomeInt>()
517 .addRegister<RegSomeRoInt>()
518 .addRegister<RegSomeWoInt>()
519 .addRegister<RegSomeBool>()
520 .addRegister<RegSomeRoBool>()
521 .addRegister<RegSomeWoBool>()
522 .addRegister<RegSomeString>()
523 .addRegister<RegSomeIntArray>()
524 .addRegister<RegSomeStringArray>()
525 .addRegister<RegSomeBooleanArray>();
526
527 ubt.runTests("(tango:" + TangoServerLauncher::self->getClientUrl() + "?cacheFile=unifiedBackendTestCache.json)");
528}
529
530/**********************************************************************************************************************/
static constexpr auto capabilities
void setForceRuntimeError(bool enable, size_t)
ChimeraTK::AccessModeFlags supportedFlags()
std::vector< std::vector< UserType > > getRemoteValue()
std::vector< std::vector< UserType > > generateValue()
std::string writePath()
std::string readPath()
void setValue(minimumUserType v)
std::string path()
minimumUserType getValue()
ChimeraTK::Boolean minimumUserType
ChimeraTK::Boolean getValue(int i)
void setValue(int i, bool v)
ChimeraTK::Boolean minimumUserType
std::vector< std::vector< UserType > > generateValue()
Tango::DevLong getValue(int i)
void setValue(int i, Tango::DevLong v)
minimumUserType getValue()
void setValue(minimumUserType v)
std::string path()
std::string writePath()
std::string readPath()
void setValue(minimumUserType v)
static constexpr auto capabilities
minimumUserType getValue()
ChimeraTK::Boolean minimumUserType
std::string readPath()
std::string writePath()
std::string readPath()
void setValue(minimumUserType v)
std::string writePath()
minimumUserType getValue()
static constexpr auto capabilities
std::string getValue(int i)
std::vector< std::vector< UserType > > generateValue()
void setValue(int i, std::string v)
std::string readPath()
std::string minimumUserType
minimumUserType getValue()
std::vector< std::vector< UserType > > generateValue()
void setValue(minimumUserType v)
std::string writePath()
ChimeraTK::Boolean minimumUserType
static constexpr auto capabilities
minimumUserType getValue()
void setValue(minimumUserType v)
std::string readPath()
std::string writePath()
std::string writePath()
std::string readPath()
static constexpr auto capabilities
void setValue(minimumUserType v)
minimumUserType getValue()
std::vector< std::vector< UserType > > generateValue()
std::vector< std::vector< UserType > > getRemoteValue()
std::vector< std::vector< UserType > > getRemoteValue()
void stop()
Shut down the Tango server.
static TangoServerLauncher * self
std::shared_ptr< Tango::DeviceProxy > remoteProxy
BOOST_GLOBAL_FIXTURE(TangoServerLauncher)
BOOST_AUTO_TEST_CASE(unifiedBackendTest)