ChimeraTK-DeviceAccess 03.25.00
Loading...
Searching...
No Matches
testSharedDummyBackend.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 SharedDummyBackendTest
6#include "BackendFactory.h"
7#include "Device.h"
8#include "ProcessManagement.h"
10#include "sharedDummyHelpers.h"
11#include "Utilities.h"
12
13#include <boost/filesystem.hpp>
14#include <boost/interprocess/managed_shared_memory.hpp>
15#include <boost/test/unit_test.hpp>
16
17#include <unistd.h>
18
19#include <algorithm>
20#include <chrono>
21#include <cstdlib>
22#include <string>
23#include <thread>
24#include <utility>
25#include <vector>
26
27namespace {
28
29 using namespace ChimeraTK;
30 using namespace boost::unit_test_framework;
31
32 static TestLocker testLocker("shareddummyTest.dmap");
33
34 struct TestFixture {
35 bool testRegisterNotInCatalogue(const std::string& registerPath) {
36 // Also get the backend to test the catalogue
37 auto backendInstance = BackendFactory::getInstance().createBackend("SHDMEMDEV");
38
39 auto catalogue = backendInstance->getRegisterCatalogue();
40
41 // the register is not in the iterable catalogue (might be a hidden register though)
42 bool found = false;
43 for(auto& info : catalogue) {
44 if(info.getRegisterName() == registerPath) {
45 found = true;
46 break;
47 }
48 }
49
50 return !found;
51 }
52 };
53
54 BOOST_AUTO_TEST_SUITE(SharedDummyBackendTestSuite)
55
56 /********************************************************************************************************************/
57
58 BOOST_AUTO_TEST_CASE(testOpenClose) {
59 setDMapFilePath("shareddummyTest.dmap");
60
61 Device dev;
62 BOOST_CHECK(!dev.isOpened());
63 dev.open("SHDMEMDEV");
64 BOOST_CHECK(dev.isOpened());
65 dev.close();
66 BOOST_CHECK(!dev.isOpened());
67 dev.open();
68 BOOST_CHECK(dev.isOpened());
69 // you must always be able to call open and close again
70 dev.open();
71 BOOST_CHECK(dev.isOpened());
72 dev.open("SHDMEMDEV");
73 BOOST_CHECK(dev.isOpened());
74 dev.close();
75 BOOST_CHECK(!dev.isOpened());
76 dev.close();
77 BOOST_CHECK(!dev.isOpened());
78 }
79
80 /********************************************************************************************************************/
81
82 BOOST_AUTO_TEST_CASE(testReadWrite) {
83 setDMapFilePath("shareddummyTest.dmap");
84
85 Device dev;
86 BOOST_CHECK(!dev.isOpened());
87 dev.open("SHDMEMDEV");
88 BOOST_CHECK(dev.isOpened());
89
90 // Write/read some values to/from the shared memory
91 ChimeraTK::OneDRegisterAccessor<int> processVars11 = dev.getOneDRegisterAccessor<int>("FEATURE1/AREA");
92 int n = 0;
93 std::generate(processVars11.begin(), processVars11.end(), [n]() mutable { return n++; });
94 processVars11.write();
95 processVars11.read();
96
97 ChimeraTK::OneDRegisterAccessor<int> processVars23 = dev.getOneDRegisterAccessor<int>("FEATURE2/AREA3");
98 n = 0;
99 std::generate(processVars23.begin(), processVars23.end(), [n]() mutable { return n++; });
100 processVars23.write();
101 processVars23.read();
102
103 // Write to memory and check values mirrored by another process
104 ChimeraTK::OneDRegisterAccessor<int> processVarsWrite21 = dev.getOneDRegisterAccessor<int>("FEATURE2/AREA1");
105 n = 0;
106 std::generate(processVarsWrite21.begin(), processVarsWrite21.end(), [n]() mutable { return n++; });
107 processVarsWrite21.write();
108
109 // start second accessing application
110 BOOST_CHECK(!std::system("./testSharedDummyBackendExt "
111 "--run_test=SharedDummyBackendTestSuite/testReadWrite"));
112
113 // Check if values have been written back by the other application
114 ChimeraTK::OneDRegisterAccessor<int> processVarsRead = dev.getOneDRegisterAccessor<int>("FEATURE2/AREA2");
115 processVarsRead.read();
116
117 BOOST_CHECK(static_cast<std::vector<int>>(processVarsWrite21) == static_cast<std::vector<int>>(processVarsRead));
118 dev.close();
119 }
120
121 /********************************************************************************************************************/
122
123 BOOST_FIXTURE_TEST_CASE(testWriteToReadOnly, TestFixture) {
124 setDMapFilePath("shareddummyTest.dmap");
125 Device dev;
126 dev.open("SHDMEMDEV");
127
128 ScalarRegisterAccessor<int> roRegisterOne{dev.getScalarRegisterAccessor<int>("WORD_READ_ONLY_1")};
129 ScalarRegisterAccessor<int> roRegisterTwo_dw{
130 dev.getScalarRegisterAccessor<int>("WORD_READ_ONLY_2.DUMMY_WRITEABLE")};
131
132 BOOST_CHECK(roRegisterOne.isReadOnly());
133 BOOST_CHECK(!roRegisterOne.isWriteable());
134 BOOST_CHECK(!roRegisterTwo_dw.isReadOnly());
135 BOOST_CHECK(roRegisterTwo_dw.isWriteable());
136
137 BOOST_CHECK(testRegisterNotInCatalogue("WORD_READ_ONLY_2.DUMMY_WRITEABLE"));
138
139 BOOST_CHECK_THROW(roRegisterOne.write(), ChimeraTK::logic_error);
140
141 roRegisterOne = 0;
142 roRegisterTwo_dw = 25;
143 roRegisterTwo_dw.write();
144
145 // Start second accessing application
146 // This is complementary and has a writeable accessor to WORD_READ_ONLY_1
147 // to which it mirrors the value of the second register
148 BOOST_CHECK(!std::system("./testSharedDummyBackendExt "
149 "--run_test=SharedDummyBackendTestSuite/testWriteToReadOnly"));
150
151 roRegisterOne.read();
152 BOOST_CHECK_EQUAL(roRegisterTwo_dw, roRegisterOne);
153
154 dev.close();
155 }
156
157 /********************************************************************************************************************/
158
159 BOOST_FIXTURE_TEST_CASE(testCreateBackend, TestFixture) {
160 setDMapFilePath("shareddummyTest.dmap");
161 auto backendInst1 = BackendFactory::getInstance().createBackend("SHDMEMDEV");
162 auto backendInst2 = BackendFactory::getInstance().createBackend("SHDMEMDEV");
163 auto backendInst3 = BackendFactory::getInstance().createBackend("SHDMEMDEV2");
164
165 BOOST_CHECK(backendInst1.get() == backendInst2.get());
166 BOOST_CHECK(backendInst3.get() != backendInst2.get());
167 }
168
169} // anonymous namespace
170
171/**********************************************************************************************************************/
172BOOST_AUTO_TEST_SUITE_END()
static BackendFactory & getInstance()
Static function to get an instance of factory.
boost::shared_ptr< DeviceBackend > createBackend(const std::string &aliasOrUri)
Create a new backend and return the instance as a shared pointer.
Class allows to read/write registers from device.
Definition Device.h:39
bool isOpened() const
Check if the device is currently opened.
Definition Device.cc:73
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
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 open(std::string const &aliasName)
Open a device by the given alias name from the DMAP file.
Definition Device.cc:58
Accessor class to read and write registers transparently by using the accessor object like a vector o...
Accessor class to read and write scalar registers transparently by using the accessor object like a v...
bool write(ChimeraTK::VersionNumber versionNumber={})
Write the data to device.
void read()
Read the data from the device.
Exception thrown when a logic error has occured.
Definition Exception.h:51
void setDMapFilePath(std::string dmapFilePath)
Set the location of the dmap file.
BOOST_AUTO_TEST_CASE(testSerialize)
BOOST_FIXTURE_TEST_CASE(testSlowReader, DeviceFixture)