ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testVoidRegisterAccessor.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 VoidRegisterAccessorTest
6#include <boost/test/unit_test.hpp>
7using namespace boost::unit_test_framework;
8
9#include "Device.h"
10#include "DummyBackend.h"
12using namespace ChimeraTK;
13
14#include <future>
15
16void testAsyncRO(RegisterPath name, unsigned int interruptNumber) {
17 // The typical use case: The underlying register is a read-only interrput
18 Device d("(dummy?map=goodMapFile.map)");
19 d.open();
21
22 // don't use auto here to check that we get the right type
23 // The typical use case: The underlying register is a void interrput
24 VoidRegisterAccessor asyncAccessor = d.getVoidRegisterAccessor(name, {AccessMode::wait_for_new_data});
25 BOOST_CHECK(asyncAccessor.isReadOnly());
26 BOOST_CHECK(asyncAccessor.isReadable());
27 BOOST_CHECK(!asyncAccessor.isWriteable());
28
29 asyncAccessor.read(); // the initial value has arrived
30
31 auto isReadFinished = std::async(std::launch::async, [&] { asyncAccessor.read(); });
32
33 BOOST_CHECK(isReadFinished.wait_for(std::chrono::seconds(1)) == std::future_status::timeout);
34
35 auto dummy = boost::dynamic_pointer_cast<DummyBackend>(d.getBackend());
36
37 dummy->triggerInterrupt(interruptNumber);
38 BOOST_CHECK(isReadFinished.wait_for(std::chrono::seconds(3)) == std::future_status::ready);
39
40 // check that the implementations for readNonBlocking() and readLatest() delegate to the right function (the return
41 // value still contains information) Trigger twice, then evaluate
42 dummy->triggerInterrupt(interruptNumber);
43 dummy->triggerInterrupt(interruptNumber);
44 BOOST_CHECK(asyncAccessor.readNonBlocking());
45 BOOST_CHECK(asyncAccessor.readNonBlocking());
46 BOOST_CHECK(!asyncAccessor.readNonBlocking()); // third readNonBlocking return false
47
48 dummy->triggerInterrupt(interruptNumber);
49 dummy->triggerInterrupt(interruptNumber);
50 BOOST_CHECK(asyncAccessor.readLatest());
51 BOOST_CHECK(!asyncAccessor.readLatest()); // second readLatest return false
52}
53
55 testAsyncRO("MODULE0/INTERRUPT_VOID1", 3);
56 testAsyncRO("MODULE0/INTERRUPT_TYPE", 6);
57}
58
60 Device d("(ExceptionDummy?map=goodMapFile.map)");
61 d.open();
63
64 auto writeableAsyncAccessor =
65 d.getVoidRegisterAccessor("MODULE0/INTERRUPT_TYPE/DUMMY_WRITEABLE"); //, {AccessMode::wait_for_new_data});
66 BOOST_CHECK(!writeableAsyncAccessor.isReadOnly());
67 // BOOST_CHECK(writeableAsyncAccessor.isReadable());
68 BOOST_CHECK(writeableAsyncAccessor.isWriteable());
69
70 auto writeableIntAccessor = d.getScalarRegisterAccessor<int>("MODULE0/INTERRUPT_TYPE/DUMMY_WRITEABLE");
71 writeableIntAccessor = 42;
72 writeableIntAccessor.write();
73 /*
74 // finally check that async read still works
75 writeableAsyncAccessor.read();
76 auto isReadFinished = std::async(std::launch::async, [&] { writeableAsyncAccessor.read(); });
77 BOOST_CHECK(isReadFinished.wait_for(std::chrono::seconds(1)) == std::future_status::timeout);
78 auto dummy = boost::dynamic_pointer_cast<DummyBackend>(d.getBackend());
79 dummy->triggerInterrupt(5, 6);
80 BOOST_CHECK(isReadFinished.wait_for(std::chrono::seconds(3)) == std::future_status::ready);
81*/
82 // writing always writes 0, although the variable was read/triggerd when there was a 42 on the hardware
83 writeableAsyncAccessor.write();
84 writeableIntAccessor.read();
85 BOOST_CHECK_EQUAL(int(writeableIntAccessor), 0);
86}
87
89 // Void registers without wait_for_new_data don't make sense if they are not writeable
90 Device d("(dummy?map=goodMapFile.map)");
91 d.open();
92
93 BOOST_CHECK_THROW(std::ignore = d.getVoidRegisterAccessor("MODULE0/INTERRUPT_VOID1"), ChimeraTK::logic_error);
94}
95
97 // Just take a normal RW register, get a void register and write to it
98 Device d("(dummy?map=goodMapFile.map)");
99 d.open();
100
101 auto voidAccessor = d.getVoidRegisterAccessor("MODULE1/TEST_AREA");
102 BOOST_CHECK(!voidAccessor.isReadOnly());
103 BOOST_CHECK(!voidAccessor.isReadable());
104 BOOST_CHECK(voidAccessor.isWriteable());
105 BOOST_CHECK_THROW(voidAccessor.read(), ChimeraTK::logic_error);
106 BOOST_CHECK_THROW(voidAccessor.readNonBlocking(), ChimeraTK::logic_error);
107 BOOST_CHECK_THROW(voidAccessor.readLatest(), ChimeraTK::logic_error);
108
109 // data accessor to the same register
110 auto intAccessor = d.getOneDRegisterAccessor<unsigned int>("MODULE1/TEST_AREA");
111
112 for(unsigned int i = 0; i < intAccessor.getNElements(); ++i) {
113 intAccessor[i] = i + 42;
114 }
115 intAccessor.write(); // write non-zero to the device
116
117 voidAccessor.write(); // write 0 (which is void converted to int
118
119 intAccessor.read(); // read back what is on the device
120
121 for(auto val : intAccessor) {
122 BOOST_CHECK_EQUAL(val, 0);
123 }
124}
Class allows to read/write registers from device.
Definition Device.h:39
boost::shared_ptr< DeviceBackend > getBackend()
Obtain the backend.
Definition Device.cc:111
VoidRegisterAccessor getVoidRegisterAccessor(const RegisterPath &registerPathName, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a VoidRegisterAccessor object for the given register.
Definition Device.cc:103
ScalarRegisterAccessor< UserType > getScalarRegisterAccessor(const RegisterPath &registerPathName, size_t wordOffsetInRegister=0, const AccessModeFlags &flags=AccessModeFlags({})) const
Get a ScalarRegisterObject object for the given register.
Definition Device.h:266
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
void activateAsyncRead() noexcept
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
Definition Device.cc:91
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
Class to store a register path name.
bool isWriteable() const
Check if transfer element is writeable.
Accessor class to read and write void-typed registers.
Exception thrown when a logic error has occured.
Definition Exception.h:51
BOOST_AUTO_TEST_CASE(TestAsyncRO)
void testAsyncRO(RegisterPath name, unsigned int interruptNumber)