ChimeraTK-DeviceAccess  03.18.00
testDataConsistencyGroup.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 DataConsistencyGroupTest
6 #include <boost/test/unit_test.hpp>
7 using namespace boost::unit_test_framework;
8 
9 #include "DataConsistencyGroup.h"
10 #include "Device.h"
11 #include "NDRegisterAccessor.h"
12 
13 using namespace ChimeraTK;
14 
15 BOOST_AUTO_TEST_SUITE(DataConsistencyGroupTestSuite)
16 
17 // notice: you cannot read from this accessor. It will block forever because there is nobody to write into the
18 // _readQueue.
19 template<typename UserType>
20 class Accessor : public NDRegisterAccessor<UserType> {
21  public:
22  Accessor() : NDRegisterAccessor<UserType>("", {AccessMode::wait_for_new_data}) {}
23 
24  ~Accessor() override {}
25 
26  void doReadTransferSynchronously() override {}
27 
28  bool doWriteTransfer(ChimeraTK::VersionNumber) override { return true; }
29 
31 
33 
34  void doPreRead(TransferType) override {}
35 
36  void doPostRead(TransferType, bool /*hasNewData*/) override {}
37 
38  // AccessModeFlags getAccessModeFlags() const override { return {AccessMode::wait_for_new_data}; }
39  bool isReadOnly() const override { return false; }
40  bool isReadable() const override { return true; }
41  bool isWriteable() const override { return true; }
42 
43  std::vector<boost::shared_ptr<TransferElement>> getHardwareAccessingElements() override {
44  return {this->shared_from_this()};
45  }
46  std::list<boost::shared_ptr<TransferElement>> getInternalElements() override { return {}; }
47 
48  // VersionNumber getVersionNumber() const override { return currentVersion; }
49 
50  // VersionNumber currentVersion;
51 };
52 
53 BOOST_AUTO_TEST_CASE(testDataConsistencyGroup) {
54  boost::shared_ptr<Accessor<int>> acc_1 = boost::make_shared<Accessor<int>>();
55  boost::shared_ptr<Accessor<int>> acc_2 = boost::make_shared<Accessor<int>>();
56 
57  DataConsistencyGroup dcgroup({acc_1, acc_2});
58 
59  // until now all versions are {nullptr}
60  // prepare the version numbers in the dcgroup by writing (which set new version numbers)
61  acc_1->write();
62  acc_2->write();
63 
64  BOOST_CHECK(dcgroup.update(acc_1->getId()) == false);
65 
66  BOOST_CHECK(dcgroup.update(acc_2->getId()) == false);
67 
68  // now update acc_1 with the newer version number from acc_2
69  acc_1->write(acc_2->getVersionNumber());
70 
71  BOOST_CHECK(dcgroup.update(acc_1->getId()) == true);
72  BOOST_CHECK(dcgroup.update(acc_1->getId()) == true);
73  BOOST_CHECK(dcgroup.update(acc_2->getId()) == true);
74  BOOST_CHECK(dcgroup.update(acc_2->getId()) == true);
75  BOOST_CHECK(dcgroup.update(acc_2->getId()) == true);
76 }
77 
78 BOOST_AUTO_TEST_CASE(testMoreDataConsistencyGroup) {
79  boost::shared_ptr<Accessor<int>> acc_1 = boost::make_shared<Accessor<int>>();
80  boost::shared_ptr<Accessor<int>> acc_2 = boost::make_shared<Accessor<int>>();
81  boost::shared_ptr<Accessor<int>> acc_3 = boost::make_shared<Accessor<int>>();
82  boost::shared_ptr<Accessor<int>> acc_4 = boost::make_shared<Accessor<int>>();
83 
84  DataConsistencyGroup dcgroup({acc_1, acc_2, acc_3, acc_4});
85  // 4 different version numbers
86  acc_1->write();
87  acc_2->write();
88  acc_3->write();
89  acc_4->write();
90  BOOST_CHECK(dcgroup.update(acc_1->getId()) == false);
91  BOOST_CHECK(dcgroup.update(acc_2->getId()) == false);
92  BOOST_CHECK(dcgroup.update(acc_3->getId()) == false);
93  BOOST_CHECK(dcgroup.update(acc_4->getId()) == false);
94 
95  // 3 different version numbers, acc_1 and acc_2 are the same
96  VersionNumber v; // a new version number
97  acc_1->write(v);
98  acc_2->write(v);
99  BOOST_CHECK(dcgroup.update(acc_1->getId()) == false);
100  BOOST_CHECK(dcgroup.update(acc_2->getId()) == false);
101  BOOST_CHECK(dcgroup.update(acc_3->getId()) == false);
102  BOOST_CHECK(dcgroup.update(acc_4->getId()) == false);
103 
104  acc_3->write(v);
105  BOOST_CHECK(dcgroup.update(acc_1->getId()) == false);
106  BOOST_CHECK(dcgroup.update(acc_2->getId()) == false);
107  BOOST_CHECK(dcgroup.update(acc_3->getId()) == false);
108  BOOST_CHECK(dcgroup.update(acc_4->getId()) == false);
109 
110  acc_4->write(v);
111  BOOST_CHECK(dcgroup.update(acc_1->getId()) == false);
112  BOOST_CHECK(dcgroup.update(acc_2->getId()) == false);
113  BOOST_CHECK(dcgroup.update(acc_3->getId()) == false);
114  BOOST_CHECK(dcgroup.update(acc_4->getId()) == true);
115  BOOST_CHECK(dcgroup.update(acc_2->getId()) == true);
116  BOOST_CHECK(dcgroup.update(acc_4->getId()) == true);
117  BOOST_CHECK(dcgroup.update(acc_3->getId()) == true);
118  BOOST_CHECK(dcgroup.update(acc_1->getId()) == true);
119 
120  // push an accessor that does not belong to DataConsistencyGroup, should be ignored, although it hat the same version
121  // number
122  boost::shared_ptr<Accessor<int>> acc_5 = boost::make_shared<Accessor<int>>();
123  acc_5->write(v);
124  BOOST_CHECK(dcgroup.update(acc_5->getId()) == false);
125 }
126 
127 // The same TransferElement shall be allowed to be part of multiple DataConsistencyGroups at the same time.
128 BOOST_AUTO_TEST_CASE(testMultipleDataConsistencyGroup) {
129  boost::shared_ptr<Accessor<int>> acc_1 = boost::make_shared<Accessor<int>>();
130  boost::shared_ptr<Accessor<int>> acc_2 = boost::make_shared<Accessor<int>>();
131  boost::shared_ptr<Accessor<int>> acc_3 = boost::make_shared<Accessor<int>>();
132  boost::shared_ptr<Accessor<int>> acc_4 = boost::make_shared<Accessor<int>>();
133  DataConsistencyGroup dcgroup_1({acc_1, acc_2, acc_3});
134  DataConsistencyGroup dcgroup_2({acc_1, acc_3, acc_4});
135  VersionNumber v;
136  acc_1->write(v);
137  acc_2->write(v);
138  acc_3->write(v);
139  acc_4->write(v);
140  BOOST_CHECK(dcgroup_1.update(acc_1->getId()) == false);
141  BOOST_CHECK(dcgroup_1.update(acc_2->getId()) == false);
142  BOOST_CHECK(dcgroup_1.update(acc_3->getId()) == true);
143  BOOST_CHECK(dcgroup_1.update(acc_4->getId()) == false); // ignored
144  BOOST_CHECK(dcgroup_2.update(acc_1->getId()) == false);
145  BOOST_CHECK(dcgroup_2.update(acc_3->getId()) == false);
146  BOOST_CHECK(dcgroup_2.update(acc_4->getId()) == true);
147  BOOST_CHECK(dcgroup_2.update(acc_2->getId()) == false); // ignored
148 }
149 
150 BOOST_AUTO_TEST_CASE(testVersionNumberChange) {
151  VersionNumber v1{};
152  VersionNumber v2{};
153  VersionNumber v3{};
154 
155  boost::shared_ptr<Accessor<int>> acc_1 = boost::make_shared<Accessor<int>>();
156  boost::shared_ptr<Accessor<int>> acc_2 = boost::make_shared<Accessor<int>>();
157 
158  DataConsistencyGroup dcgroup_1({acc_1, acc_2});
159 
160  acc_2->write(v2);
161  BOOST_CHECK_EQUAL(dcgroup_1.update(acc_2->getId()), false);
162 
163  acc_1->write(v1);
164  BOOST_CHECK_EQUAL(dcgroup_1.update(acc_1->getId()), false);
165 
166  acc_1->write(v2);
167  BOOST_CHECK_EQUAL(dcgroup_1.update(acc_1->getId()), true);
168 
169  acc_1->write(v3);
170  acc_2->write(v3);
171  BOOST_CHECK_EQUAL(dcgroup_1.update(acc_1->getId()), false);
172  BOOST_CHECK_EQUAL(dcgroup_1.update(acc_2->getId()), true);
173 }
174 
175 BOOST_AUTO_TEST_CASE(testException) {
176  Device dev;
177  dev.open("(dummy?map=registerAccess.map)");
178  auto acc = dev.getScalarRegisterAccessor<int>("BOARD.WORD_FIRMWARE");
179  DataConsistencyGroup dcgroup;
180  // accessors without wait_for_new_data cannot be added.
181  BOOST_CHECK_THROW(dcgroup.add(acc), ChimeraTK::logic_error);
182 }
183 
184 BOOST_AUTO_TEST_SUITE_END()
DataConsistencyGroup.h
Accessor::isReadOnly
bool isReadOnly() const override
Definition: testDataConsistencyGroup.cpp:39
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(testDataConsistencyGroup)
Definition: testDataConsistencyGroup.cpp:53
Accessor::getInternalElements
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Definition: testDataConsistencyGroup.cpp:46
Accessor::doPostWrite
void doPostWrite(TransferType, VersionNumber) override
Definition: testDataConsistencyGroup.cpp:32
Accessor::getHardwareAccessingElements
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Definition: testDataConsistencyGroup.cpp:43
Accessor::Accessor
Accessor()
Definition: testDataConsistencyGroup.cpp:22
NDRegisterAccessor.h
ChimeraTK::DataConsistencyGroup
Group several registers (= TransferElement) which ensures data consistency across multiple variables ...
Definition: DataConsistencyGroup.h:19
Accessor
Definition: testDataConsistencyGroup.cpp:20
Accessor::doPreRead
void doPreRead(TransferType) override
Definition: testDataConsistencyGroup.cpp:34
Device.h
Accessor::doWriteTransfer
bool doWriteTransfer(ChimeraTK::VersionNumber) override
Definition: testDataConsistencyGroup.cpp:28
Accessor::doPostRead
void doPostRead(TransferType, bool) override
Definition: testDataConsistencyGroup.cpp:36
Accessor::doPreWrite
void doPreWrite(TransferType, VersionNumber) override
Definition: testDataConsistencyGroup.cpp:30
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
Accessor::~Accessor
~Accessor() override
Definition: testDataConsistencyGroup.cpp:24
ChimeraTK::Device
Class allows to read/write registers from device.
Definition: Device.h:39
Accessor::isWriteable
bool isWriteable() const override
Definition: testDataConsistencyGroup.cpp:41
ChimeraTK::Device::open
void open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition: Device.cc:58
ChimeraTK::Device::getScalarRegisterAccessor
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:263
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
Accessor::doReadTransferSynchronously
void doReadTransferSynchronously() override
Definition: testDataConsistencyGroup.cpp:26
Accessor::isReadable
bool isReadable() const override
Definition: testDataConsistencyGroup.cpp:40
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::NDRegisterAccessor
N-dimensional register accessor.
Definition: ForwardDeclarations.h:17
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51