ChimeraTK-DeviceAccess 03.20.00
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
testDataConsistencyRealm.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
5#define BOOST_TEST_DYN_LINK
6// Define a name for the test module.
7#define BOOST_TEST_MODULE DataConsistencyRealmTest
8// Only after defining the name include the unit test header.
9#include <boost/test/unit_test.hpp>
10using namespace boost::unit_test_framework;
11
12#include "BackendFactory.h"
13#include "Device.h"
14#include "DummyBackend.h"
15
16namespace ctk = ChimeraTK;
17
18// Create a test suite which holds all your tests.
19BOOST_AUTO_TEST_SUITE(DataConsistencyRealmTestSuite)
20
21/**********************************************************************************************************************/
22
23static std::string cdd(
24 R"((dummy:1?map=testDataConsistencyRealm.map&DataConsistencyKeys={"/theKey":"MyIdRealm", "/anotherKey":"MyIdRealm"}))");
25static auto dummy =
26 boost::dynamic_pointer_cast<ctk::DummyBackend>(ctk::BackendFactory::getInstance().createBackend(cdd));
27static auto& realmStore = ctk::async::DataConsistencyRealmStore::getInstance();
28
29/**********************************************************************************************************************/
30
32 std::cout << "TestRealm" << std::endl;
33 auto realm = realmStore.getRealm("SingleRealm");
34
35 auto b = realm->getVersion(ctk::async::DataConsistencyKey(42));
36 auto c = realm->getVersion(ctk::async::DataConsistencyKey(42));
37 BOOST_TEST(b == c);
38
39 auto d = realm->getVersion(ctk::async::DataConsistencyKey(43));
40 BOOST_TEST(d > b);
41
42 ctk::VersionNumber last{nullptr};
43 for(uint64_t i = 1; i < 42; ++i) {
44 auto a = realm->getVersion(ctk::async::DataConsistencyKey(i));
45 BOOST_TEST(a != ctk::VersionNumber{nullptr});
46 BOOST_TEST(a < b);
47 if(last != ctk::VersionNumber{nullptr}) {
48 BOOST_TEST(a > last);
49 }
50 last = a;
51 }
52
53 auto b2 = realm->getVersion(ctk::async::DataConsistencyKey(42));
54 BOOST_TEST(b2 == b);
55
56 auto x = realm->getVersion(ctk::async::DataConsistencyKey(1000000000));
57 BOOST_TEST(x > d);
58
59 auto y = realm->getVersion(ctk::async::DataConsistencyKey(42));
60 BOOST_TEST(y == ctk::VersionNumber{nullptr});
61}
62
63/**********************************************************************************************************************/
64
65BOOST_AUTO_TEST_CASE(TestMultipleRealms) {
66 std::cout << "TestMultipleRealms" << std::endl;
67 auto realmA = realmStore.getRealm("RealmA");
68 auto realmB = realmStore.getRealm("RealmB");
69
70 // Two different realms shall not hand out the same version for the same key value. Also the realm store shall
71 // gives out different realms for different names.
72
73 auto a = realmA->getVersion(ctk::async::DataConsistencyKey(42));
74 auto b = realmB->getVersion(ctk::async::DataConsistencyKey(42));
75 BOOST_TEST(a != b);
76}
77
78/**********************************************************************************************************************/
79
80BOOST_AUTO_TEST_CASE(TestVersionConsistencyBetweenAccessors) {
81 std::cout << "TestVersionConsistencyBetweenAccessors" << std::endl;
82 ctk::Device dev(cdd);
83 dev.open();
84
85 auto realm = realmStore.getRealm("MyIdRealm");
87
88 auto key = dev.getScalarRegisterAccessor<uint32_t>("/theKey.DUMMY_WRITEABLE");
89 auto dataA = dev.getScalarRegisterAccessor<int32_t>("/dataA", 0, {ctk::AccessMode::wait_for_new_data});
90 auto dataB = dev.getScalarRegisterAccessor<int32_t>("/dataB", 0, {ctk::AccessMode::wait_for_new_data});
91 auto interrupt6 = dev.getScalarRegisterAccessor<int32_t>("/interrupt6", 0, {ctk::AccessMode::wait_for_new_data});
92
93 BOOST_REQUIRE(!dataA.readNonBlocking());
94 BOOST_REQUIRE(!dataB.readNonBlocking());
95 BOOST_REQUIRE(!interrupt6.readNonBlocking());
96
97 // check for initial value
98 key.setAndWrite(12);
100
101 BOOST_REQUIRE(dataA.readNonBlocking());
102 BOOST_REQUIRE(dataB.readNonBlocking());
103 BOOST_REQUIRE(interrupt6.readNonBlocking());
104 BOOST_REQUIRE(!dataA.readNonBlocking());
105 BOOST_REQUIRE(!dataB.readNonBlocking());
106 BOOST_REQUIRE(!interrupt6.readNonBlocking());
107
108 auto v1 = realm->getVersion(ctk::async::DataConsistencyKey(key));
109 BOOST_REQUIRE(v1 > v0);
110 BOOST_TEST(dataA.getVersionNumber() == v1);
111 BOOST_TEST(dataB.getVersionNumber() == v1);
112 BOOST_TEST(interrupt6.getVersionNumber() == v1);
113 BOOST_TEST(dataA.dataValidity() == ctk::DataValidity::ok);
114 BOOST_TEST(dataB.dataValidity() == ctk::DataValidity::ok);
115 BOOST_TEST(interrupt6.dataValidity() == ctk::DataValidity::ok);
116
117 // check for triggered interrupt
118 key.setAndWrite(42);
119 dummy->triggerInterrupt(6);
120
121 BOOST_REQUIRE(dataA.readNonBlocking());
122 BOOST_REQUIRE(dataB.readNonBlocking());
123 BOOST_REQUIRE(interrupt6.readNonBlocking());
124 BOOST_REQUIRE(!dataA.readNonBlocking());
125 BOOST_REQUIRE(!dataB.readNonBlocking());
126 BOOST_REQUIRE(!interrupt6.readNonBlocking());
127
128 auto v2 = realm->getVersion(ctk::async::DataConsistencyKey(key));
129 BOOST_REQUIRE(v2 > v1);
130 BOOST_TEST(dataA.getVersionNumber() == v2);
131 BOOST_TEST(dataB.getVersionNumber() == v2);
132 BOOST_TEST(interrupt6.getVersionNumber() == v2);
133 BOOST_TEST(dataA.dataValidity() == ctk::DataValidity::ok);
134 BOOST_TEST(dataB.dataValidity() == ctk::DataValidity::ok);
135 BOOST_TEST(interrupt6.dataValidity() == ctk::DataValidity::ok);
136
137 // check for repeated key value
138 dummy->triggerInterrupt(6);
139
140 BOOST_REQUIRE(dataA.readNonBlocking());
141 BOOST_REQUIRE(dataB.readNonBlocking());
142 BOOST_REQUIRE(interrupt6.readNonBlocking());
143 BOOST_REQUIRE(!dataA.readNonBlocking());
144 BOOST_REQUIRE(!dataB.readNonBlocking());
145 BOOST_REQUIRE(!interrupt6.readNonBlocking());
146
147 BOOST_TEST(dataA.getVersionNumber() == v2);
148 BOOST_TEST(dataB.getVersionNumber() == v2);
149 BOOST_TEST(interrupt6.getVersionNumber() == v2);
150 BOOST_TEST(dataA.dataValidity() == ctk::DataValidity::ok);
151 BOOST_TEST(dataB.dataValidity() == ctk::DataValidity::ok);
152 BOOST_TEST(interrupt6.dataValidity() == ctk::DataValidity::ok);
153
154 // check with backwards going key value
155 key.setAndWrite(40);
156 dummy->triggerInterrupt(6);
157
158 BOOST_REQUIRE(dataA.readNonBlocking());
159 BOOST_REQUIRE(dataB.readNonBlocking());
160 BOOST_REQUIRE(interrupt6.readNonBlocking());
161 BOOST_REQUIRE(!dataA.readNonBlocking());
162 BOOST_REQUIRE(!dataB.readNonBlocking());
163 BOOST_REQUIRE(!interrupt6.readNonBlocking());
164
165 auto v3 = realm->getVersion(ctk::async::DataConsistencyKey(key));
166 BOOST_REQUIRE(v3 < v2);
167 BOOST_REQUIRE(v3 > v1);
168 BOOST_TEST(dataA.getVersionNumber() == v2); // cannot go backwards with version numbers
169 BOOST_TEST(dataB.getVersionNumber() == v2);
170 BOOST_TEST(interrupt6.getVersionNumber() == v2);
171 BOOST_TEST(dataA.dataValidity() == ctk::DataValidity::faulty);
172 BOOST_TEST(dataB.dataValidity() == ctk::DataValidity::faulty);
173 BOOST_TEST(interrupt6.dataValidity() == ctk::DataValidity::ok);
174
175 dev.close();
176}
177
178/**********************************************************************************************************************/
179
180BOOST_AUTO_TEST_CASE(TestMultiInterrupt) {
181 std::cout << "TestMultiInterrupt" << std::endl;
182 ctk::Device dev(cdd);
183 dev.open();
184
185 auto realm = realmStore.getRealm("MyIdRealm");
187
188 auto keyA = dev.getScalarRegisterAccessor<uint32_t>("/theKey.DUMMY_WRITEABLE");
189 auto dataA = dev.getScalarRegisterAccessor<int32_t>("/dataA", 0, {ctk::AccessMode::wait_for_new_data});
190 auto intA = dev.getScalarRegisterAccessor<int32_t>("/interrupt6", 0, {ctk::AccessMode::wait_for_new_data});
191
192 auto keyB = dev.getScalarRegisterAccessor<uint32_t>("/anotherKey.DUMMY_WRITEABLE");
193 auto dataB = dev.getScalarRegisterAccessor<int32_t>("/dataC", 0, {ctk::AccessMode::wait_for_new_data});
194 auto intB = dev.getScalarRegisterAccessor<int32_t>("/interrupt123", 0, {ctk::AccessMode::wait_for_new_data});
195
196 BOOST_REQUIRE(!dataA.readNonBlocking());
197 BOOST_REQUIRE(!dataB.readNonBlocking());
198 BOOST_REQUIRE(!intA.readNonBlocking());
199 BOOST_REQUIRE(!intB.readNonBlocking());
200
201 // check for initial value
202 keyA.setAndWrite(12);
203 keyB.setAndWrite(15);
204 dev.activateAsyncRead();
205
206 BOOST_REQUIRE(dataA.readNonBlocking());
207 BOOST_REQUIRE(dataB.readNonBlocking());
208 BOOST_REQUIRE(intA.readNonBlocking());
209 BOOST_REQUIRE(intB.readNonBlocking());
210 BOOST_REQUIRE(!dataA.readNonBlocking());
211 BOOST_REQUIRE(!dataB.readNonBlocking());
212 BOOST_REQUIRE(!intA.readNonBlocking());
213 BOOST_REQUIRE(!intB.readNonBlocking());
214
215 auto v1 = realm->getVersion(ctk::async::DataConsistencyKey(keyA));
216 auto v2 = realm->getVersion(ctk::async::DataConsistencyKey(keyB));
217 BOOST_REQUIRE(v1 > v0);
218 BOOST_REQUIRE(v2 > v1);
219 BOOST_TEST(dataA.getVersionNumber() == v1);
220 BOOST_TEST(intA.getVersionNumber() == v1);
221 BOOST_TEST(dataB.getVersionNumber() == v2);
222 BOOST_TEST(intB.getVersionNumber() == v2);
223
224 // check for triggered interrupt
225 keyA.setAndWrite(15);
226 dummy->triggerInterrupt(6);
227
228 BOOST_REQUIRE(dataA.readNonBlocking());
229 BOOST_REQUIRE(intA.readNonBlocking());
230 BOOST_REQUIRE(!dataA.readNonBlocking());
231 BOOST_REQUIRE(!dataB.readNonBlocking());
232 BOOST_REQUIRE(!intA.readNonBlocking());
233 BOOST_REQUIRE(!intB.readNonBlocking());
234
235 BOOST_TEST(dataA.getVersionNumber() == v2);
236 BOOST_TEST(intA.getVersionNumber() == v2);
237
238 dev.close();
239}
240
241/**********************************************************************************************************************/
242
243BOOST_AUTO_TEST_SUITE_END()
Class allows to read/write registers from device.
Definition Device.h:39
void close()
Close the device.
Definition Device.cc:66
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
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 for generating and holding version numbers without exposing a numeric representation.
std::string cdd
BOOST_AUTO_TEST_CASE(TestRealm)