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