ifw-daq  3.0.1
IFW Data Acquisition modules
testWorkspace.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_test
4  * @copyright (c) Copyright ESO 2022
5  * All Rights Reserved
6  * ESO (eso.org) is an Intergovernmental Organisation, and therefore special legal conditions apply.
7  *
8  * @brief daq::dpm::Workspace integration tests
9  */
10 #include <fstream>
11 #include <thread>
12 
13 #include <gtest/gtest.h>
14 
15 #include <daq/dpm/workspace.hpp>
16 #include <daq/error/report.hpp>
17 
18 namespace fs = std::filesystem;
19 
20 class WorkspaceTest : public ::testing::Test {
21 public:
23  }
24  void SetUp() override {
25  std::string tpl("daqLibdpmTest-workspace-XXXXXX");
26  mkdtemp(tpl.data());
27  m_root = fs::current_path() / tpl;
28 
29  ASSERT_FALSE(m_root.empty());
30 
31  m_spec = R"(
32  {
33  "id": "TEST.ID",
34  "target": {
35  "fileId": "TEST.FILEID",
36  "source": {
37  "sourceName": "dcs",
38  "location": "dcs-host:/path/to/somefile.fits",
39  "path": "dcs/somefile.fits"
40  }
41  },
42  "sources": [
43  ]
44  }
45  )"_json;
46  }
47 
48  void TearDown() override {
49  if (!m_root.empty()) {
50  fs::remove_all(m_root);
51  }
52  }
53 
54 protected:
55  fs::path m_root;
56  nlohmann::json m_spec;
57 };
58 
59 class DaqWorkspaceTest : public WorkspaceTest {};
60 
61 TEST_F(WorkspaceTest, GetPath) {
62  daq::dpm::WorkspaceImpl ws(m_root);
63  EXPECT_EQ(m_root, ws.GetPath());
64 }
65 
66 TEST_F(WorkspaceTest, ConstructionInitializeWorkspaceWithExistingRoot) {
67  ASSERT_FALSE(fs::exists(m_root / "in-progress"));
68  ASSERT_FALSE(fs::exists(m_root / "archive"));
69  daq::dpm::WorkspaceImpl workspace(m_root);
70 
71  ASSERT_TRUE(fs::exists(m_root / "in-progress"));
72  ASSERT_TRUE(fs::exists(m_root / "archive"));
73 }
74 
75 TEST_F(WorkspaceTest, ConstructionInitializeWorkspaceWithNonexistingRoot) {
76  fs::remove(m_root);
77  ASSERT_FALSE(fs::exists(m_root / "in-progress"));
78  ASSERT_FALSE(fs::exists(m_root / "archive"));
79  daq::dpm::WorkspaceImpl workspace(m_root);
80 
81  ASSERT_TRUE(fs::exists(m_root / "in-progress"));
82  ASSERT_TRUE(fs::exists(m_root / "archive"));
83 }
84 
85 TEST_F(WorkspaceTest, ConstructionFailsIfRootIsAfile) {
86  fs::remove(m_root);
87  std::ofstream(m_root).put('z');
88  EXPECT_THROW(daq::dpm::WorkspaceImpl{m_root}, std::invalid_argument);
89 }
90 
91 TEST_F(WorkspaceTest, InitializeDaq) {
92  try {
93  daq::dpm::WorkspaceImpl ws(m_root);
94  auto daq_ws = ws.InitializeDaq("DAQ");
95  auto daq_ws_root = m_root / "in-progress" / "DAQ";
96  EXPECT_EQ(daq_ws->GetPath(), daq_ws_root);
97  EXPECT_TRUE(fs::exists(daq_ws_root)) << "Path: " << daq_ws_root;
98  } catch (...) {
99  daq::error::NestedExceptionReporter r(std::current_exception());
100  throw std::runtime_error(r.Str());
101  }
102 }
103 
104 TEST_F(WorkspaceTest, ArchiveDaq) {
105  try {
106  {
107  daq::dpm::WorkspaceImpl ws(m_root);
108  auto daq_ws = ws.InitializeDaq("DAQ");
109  daq::Status status("DAQ", "1");
110  daq_ws->StoreStatus(status);
111  ws.ArchiveDaq("DAQ");
112  auto daq_ws_root = m_root / "archive" / "DAQ";
113  EXPECT_TRUE(fs::exists(daq_ws_root)) << "Path: " << daq_ws_root;
114  EXPECT_TRUE(fs::exists(daq_ws_root / "status.json"));
115  EXPECT_FALSE(fs::exists(m_root / "in-progress" / "DAQ"));
116 
117  EXPECT_EQ(ws.LoadArchivedStatus("DAQ")->file_id, "1");
118  }
119  {
120  // Reuse DAQ id and archive it again. It should rename previously archived DAQ to make
121  // room for new such that <archive>/<daq> always refer to the newest archived DAQ.
122  daq::dpm::WorkspaceImpl ws(m_root);
123  auto daq_ws = ws.InitializeDaq("DAQ");
124  daq::Status status("DAQ", "2");
125  daq_ws->StoreStatus(status);
126  ws.ArchiveDaq("DAQ");
127  auto daq_ws_root = m_root / "archive" / "DAQ";
128  EXPECT_TRUE(fs::exists(daq_ws_root)) << "Path: " << daq_ws_root;
129  EXPECT_TRUE(fs::exists(daq_ws_root / "status.json"));
130  EXPECT_FALSE(fs::exists(m_root / "in-progress" / "DAQ"));
131 
132  EXPECT_EQ(ws.LoadArchivedStatus("DAQ")->file_id, "2");
133  }
134 
135  } catch (...) {
136  daq::error::NestedExceptionReporter r(std::current_exception());
137  throw std::runtime_error(r.Str());
138  }
139 }
140 
141 TEST_F(WorkspaceTest, RemoveDaq) {
142  try {
143  daq::dpm::WorkspaceImpl ws(m_root);
144  auto daq_ws = ws.InitializeDaq("DAQ");
145  ws.RemoveDaq("DAQ");
146  EXPECT_FALSE(fs::exists(m_root / "in-progress" / "DAQ"));
147  EXPECT_FALSE(fs::exists(m_root / "archive" / "DAQ"));
148  } catch (...) {
149  daq::error::NestedExceptionReporter r(std::current_exception());
150  throw std::runtime_error(r.Str());
151  }
152 }
153 
154 TEST_F(DaqWorkspaceTest, LoadStoreSpecification) {
155  try {
156  daq::dpm::DaqWorkspaceImpl ws(m_root, m_root);
157  EXPECT_FALSE(fs::exists(m_root / "specification.json"));
158  ws.StoreSpecification(m_spec.dump());
159  EXPECT_TRUE(fs::exists(m_root / "specification.json"));
160 
161  auto spec = ws.LoadSpecification();
162  EXPECT_EQ(spec.id, "TEST.ID");
163  } catch (...) {
164  daq::error::NestedExceptionReporter r(std::current_exception());
165  throw std::runtime_error(r.Str());
166  }
167 }
168 
169 TEST_F(DaqWorkspaceTest, LoadStoreStatus) {
170  try {
171  daq::dpm::DaqWorkspaceImpl ws(m_root, m_root);
172  EXPECT_FALSE(fs::exists(m_root / "status.json"));
173  daq::Status store_status = {};
174  store_status.id = "DAQ";
175  store_status.state = daq::State::Merging;
176  ws.StoreStatus(store_status);
177  EXPECT_TRUE(fs::exists(m_root / "status.json"));
178  EXPECT_EQ(store_status, ws.LoadStatus());
179  } catch (...) {
180  daq::error::NestedExceptionReporter r(std::current_exception());
181  throw std::runtime_error(r.Str());
182  }
183 }
184 
185 TEST_F(DaqWorkspaceTest, LoadStoreLookup) {
186  try {
187  daq::dpm::DaqWorkspaceImpl ws(m_root, m_root);
188  EXPECT_FALSE(fs::exists(m_root / "sources.json"));
190  ws.StoreSourceLookup(store);
191  EXPECT_TRUE(fs::exists(m_root / "sources.json"));
192  EXPECT_EQ(store, ws.LoadSourceLookup());
193  } catch (...) {
194  daq::error::NestedExceptionReporter r(std::current_exception());
195  throw std::runtime_error(r.Str());
196  }
197 }
nlohmann::json m_spec
void TearDown() override
void SetUp() override
void StoreSpecification(std::string const &specification) const override
Get file name of the data product specification stored in StoreSpecification()
Definition: workspace.cpp:319
void StoreSourceLookup(SourceResolver::Mapping const &status) const override
Definition: workspace.cpp:293
auto LoadSpecification() const -> json::DpSpec override
Get file name of the data product specification stored in StoreSpecification()
Definition: workspace.cpp:307
void StoreStatus(Status const &status) const override
Definition: workspace.cpp:250
auto LoadSourceLookup() const -> SourceResolver::Mapping override
Definition: workspace.cpp:283
auto LoadStatus() const -> Status override
Definition: workspace.cpp:240
std::map< SourceFile, std::string > Mapping
Implementation of daq::dpm::Workspace.
Definition: workspace.hpp:215
auto LoadArchivedStatus(std::string const &daq_id) const -> std::optional< Status > override
Loads a previously initialized DAQ workspace.
Definition: workspace.cpp:163
auto InitializeDaq(std::string const &daq_id) -> std::unique_ptr< DaqWorkspace > override
Initializes new DAQ Workspace.
Definition: workspace.cpp:153
void RemoveDaq(std::string const &daq_id) override
Removes workspace and all containing files for DAQ without archiving it.
Definition: workspace.cpp:177
auto GetPath() const -> std::filesystem::path override
Definition: workspace.hpp:234
auto ArchiveDaq(std::string const &daq_id) -> std::filesystem::path override
Archives specified DAQ witout deleting any files, typically by moving it to a specific location in th...
Definition: workspace.cpp:181
Adapter object intended to be used in contexts without direct access to the output-stream object.
Definition: report.hpp:54
std::string Str() const
Convenience function for constructing a std::string from the exception.
Definition: report.cpp:97
daq::dpm::Workspace interface and implementation declaration
nlohmann::json m_spec
daq::json::TestParseStartDaqV2Spec _json
@ Merging
DAQ is being merged.
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:153
State state
Definition: status.hpp:176
std::string id
Definition: status.hpp:174
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))
TEST_F(WorkspaceTest, GetPath)