ChimeraTK-DeviceAccess 03.29.00
Loading...
Searching...
No Matches
testMapFileSearch.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 MapFileSearch
6#include <boost/test/unit_test.hpp>
7using namespace boost::unit_test_framework;
8
9#include "BackendFactory.h"
10#include "DummyBackend.h"
11#include "Exception.h"
12#include "ProcessManagement.h"
13#include "Utilities.h"
14
15#include <boost/filesystem.hpp>
16
17#include <filesystem>
18#include <fstream>
19
20using namespace ChimeraTK;
21
22namespace fs = std::filesystem;
23
24/**********************************************************************************************************************/
25
31 std::string resolvedMapFileName() const { return _resolvedMapFileName; }
32};
33
34/**********************************************************************************************************************/
35
37 fs::path baseDir;
38 fs::path workDir;
40
42 previousWorkDir = fs::current_path();
43 baseDir = fs::temp_directory_path() / "testMapFileSearch";
44 fs::remove_all(baseDir);
45 workDir = baseDir / "work";
46 fs::create_directories(workDir);
47 // the working directory represents the "current working directory" that
48 // relative map paths are resolved against
49 fs::current_path(workDir);
51 }
52
54 fs::current_path(previousWorkDir);
55 fs::remove_all(baseDir);
56 }
57
59 static void writeMapFile(const fs::path& path, const std::string& registerName) {
60 if(!path.parent_path().empty()) {
61 fs::create_directories(path.parent_path());
62 }
63 std::ofstream file(path);
64 file << "/Board/" << registerName << " 1 0 4 1 32 0 1 RW\n";
65 }
66
68 static void writeDMapFile(const fs::path& path, const std::string& mapName) {
69 if(!path.parent_path().empty()) {
70 fs::create_directories(path.parent_path());
71 }
72 std::ofstream file(path);
73 file << "DUMMY (dummy?map=" << mapName << ")\n";
74 }
75
76 static void setDMapPath(const std::string& dmapPath) { BackendFactory::getInstance().setDMapFilePath(dmapPath); }
77
78 static std::string canonical(const std::string& path) { return boost::filesystem::canonical(path).string(); }
79};
80
81/**********************************************************************************************************************/
82
83BOOST_AUTO_TEST_SUITE(MapFileSearchTestSuite)
84
85/**********************************************************************************************************************/
86
87BOOST_FIXTURE_TEST_CASE(RelativeMapResolvedRelativeToDmapDirectory, MapFileSearchFixture) {
88 // map file placed next to the dmap file, not present in the cwd
89 writeDMapFile("dmapdir/test.dmap", "map1.map");
90 writeMapFile("dmapdir/map1.map", "fromDmapDir");
91 setDMapPath("dmapdir/test.dmap");
92
93 MapFileSearchBackend backend("map1.map");
94
95 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), canonical("dmapdir/map1.map"));
96 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromDmapDir"));
97}
98
99/**********************************************************************************************************************/
100
101BOOST_FIXTURE_TEST_CASE(RelativeMapResolvedRelativeToCwd, MapFileSearchFixture) {
102 // map file only present in the cwd, dmap file in a different directory
103 writeDMapFile("dmapdir/test.dmap", "map2.map");
104 writeMapFile("map2.map", "fromCwd");
105 setDMapPath("dmapdir/test.dmap");
106
107 MapFileSearchBackend backend("map2.map");
108
109 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), canonical("map2.map"));
110 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromCwd"));
111}
112
113/**********************************************************************************************************************/
114
115BOOST_FIXTURE_TEST_CASE(MapFileInBothDmapDirAndCwdDmapDirWins, MapFileSearchFixture) {
116 // the same map file name in both the dmap directory and the cwd
117 writeDMapFile("dmapdir/test.dmap", "map3.map");
118 writeMapFile("dmapdir/map3.map", "fromDmapDir");
119 writeMapFile("map3.map", "fromCwd");
120 setDMapPath("dmapdir/test.dmap");
121
122 MapFileSearchBackend backend("map3.map");
123
124 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), canonical("dmapdir/map3.map"));
125 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromDmapDir"));
126 BOOST_CHECK(!backend.getRegisterCatalogue().hasRegister("/Board/fromCwd"));
127}
128
129/**********************************************************************************************************************/
130
132 // an absolute map path is used directly, independent of the dmap path
133 writeDMapFile("dmapdir/test.dmap", "map4.map");
134 writeMapFile("other/map4.map", "fromAbsolute");
135 setDMapPath("dmapdir/test.dmap");
136
137 std::string absolutePath = canonical("other/map4.map");
138 MapFileSearchBackend backend(absolutePath);
139
140 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), absolutePath);
141 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromAbsolute"));
142}
143
144/**********************************************************************************************************************/
145
146BOOST_FIXTURE_TEST_CASE(NoDmapPathSetRelativeMapResolvedRelativeToCwd, MapFileSearchFixture) {
147 // no dmap path set at all: a relative map path resolves relative to the cwd
148 writeMapFile("map5.map", "fromCwd");
149
150 MapFileSearchBackend backend("map5.map");
151
152 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), canonical("map5.map"));
153 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromCwd"));
154}
155
156/**********************************************************************************************************************/
157
158BOOST_FIXTURE_TEST_CASE(RelativeDmapPathDmapDirRelativeToCwd, MapFileSearchFixture) {
159 // a relative dmap path is interpreted relative to the cwd
160 writeDMapFile("dmapdir/sub/test.dmap", "map6.map");
161 writeMapFile("dmapdir/sub/map6.map", "fromDmapDirSub");
162 setDMapPath("dmapdir/sub/test.dmap");
163
164 MapFileSearchBackend backend("map6.map");
165
166 BOOST_CHECK_EQUAL(backend.resolvedMapFileName(), canonical("dmapdir/sub/map6.map"));
167 BOOST_CHECK(backend.getRegisterCatalogue().hasRegister("/Board/fromDmapDirSub"));
168}
169
170/**********************************************************************************************************************/
171
172BOOST_FIXTURE_TEST_CASE(MissingMapFileThrowsClearError, MapFileSearchFixture) {
173 // a missing map file leads to a clear error, not a crash
174 writeDMapFile("dmapdir/test.dmap", "nonexistent.map");
175 setDMapPath("dmapdir/test.dmap");
176
177 BOOST_CHECK_THROW(MapFileSearchBackend backend("nonexistent.map"), ChimeraTK::logic_error);
178}
179
180/**********************************************************************************************************************/
181
182BOOST_FIXTURE_TEST_CASE(SharedDummyShmNameDerivedFromResolvedPath, MapFileSearchFixture) {
183 // two different relative spellings of the same map file resolve to the same
184 // canonical absolute path, so the shared dummy SHM segment name (derived from
185 // the resolved path) is identical for both: no asymmetry between the map
186 // parsing and the SHM hash
187 writeMapFile("shared.map", "fromCwd");
188
189 MapFileSearchBackend backend1("shared.map");
190 MapFileSearchBackend backend2("./shared.map");
191
192 BOOST_CHECK_EQUAL(backend1.resolvedMapFileName(), canonical("shared.map"));
193 BOOST_CHECK_EQUAL(backend1.resolvedMapFileName(), backend2.resolvedMapFileName());
194
195 std::size_t instanceIdHash = Utilities::shmDummyInstanceIdHash("1", {{"map", "shared.map"}});
196 std::string userName = getUserName();
197 BOOST_CHECK_EQUAL(Utilities::createShmName(instanceIdHash, backend1.resolvedMapFileName(), userName),
198 Utilities::createShmName(instanceIdHash, backend2.resolvedMapFileName(), userName));
199}
200
201/**********************************************************************************************************************/
202
203BOOST_AUTO_TEST_SUITE_END()
std::string getUserName()
static BackendFactory & getInstance()
Static function to get an instance of factory.
void setDMapFilePath(std::string dMapFilePath)
This function sets the _DMapFilePath.
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
DummyBackend(const std::string &mapFileName, const std::string &dataConsistencyKeyDescriptor="")
RegisterCatalogue getRegisterCatalogue() const override
Return the register catalogue with detailed information on all registers.
std::string _resolvedMapFileName
The resolved absolute path of the map file used for parsing and for any derived naming (e....
bool hasRegister(const RegisterPath &registerPathName) const
Check if register with the given path name exists.
Exception thrown when a logic error has occured.
Definition Exception.h:51
std::size_t shmDummyInstanceIdHash(const std::string &address, const std::map< std::string, std::string > &parameters)
Generates shm dummy instanceId hash from address and parameter map, Intended for use with parseDevice...
std::string createShmName(std::size_t instanceIdHash, const std::string &mapFileName, const std::string &userName)
Generates shm dummy name from parameter hashes.
Test-only backend exposing the resolved map file name computed by the NumericAddressedBackend base cl...
std::string resolvedMapFileName() const
static void setDMapPath(const std::string &dmapPath)
static void writeMapFile(const fs::path &path, const std::string &registerName)
Write a map file containing a single register with the given name.
static void writeDMapFile(const fs::path &path, const std::string &mapName)
Write a minimal, parseable dmap file referencing the given map file.
static std::string canonical(const std::string &path)
BOOST_FIXTURE_TEST_CASE(RelativeMapResolvedRelativeToDmapDirectory, MapFileSearchFixture)