ifw-daq  2.1.0-pre1
IFW Data Acquisition modules
testDpmService.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_common_libdpm
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 Unit tests for daq::dpm::DpmService
9  */
10 
11 #include <daq/dpm/scheduler.hpp>
12 
13 #include <utility>
14 
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 #include <daq/test/progress.hpp>
19 
20 #include "daqifFake.hpp"
21 #include "mock/mockMal.hpp"
22 #include "mock/mockScheduler.hpp"
23 #include "mock/mockWorkspace.hpp"
24 #include <daq/dpm/dpmService.hpp>
25 
26 namespace daq::dpm {
27 
28 class TestDpmService : public ::testing::Test {
29 public:
31  }
32 
33  void SetUp() override {
34  m_service =
35  std::make_unique<DpmService>(m_executor, m_mal_mock, m_ws_mock, m_scheduler_mock);
36  }
37  void TearDown() override {
38  // Execute possibly pending completions handlers.
39  EXPECT_NO_THROW(m_io_ctx.poll());
40  }
41 
42 protected:
43  boost::asio::io_context m_io_ctx;
45 
49 
50  std::unique_ptr<DpmService> m_service;
51 };
52 
53 using namespace ::testing;
54 
55 TEST_F(TestDpmService, QueryStorageStatusSuceeds) {
56  // Setup
57  std::filesystem::space_info status = {};
58  status.available = 123;
59  status.free = 456;
60  status.capacity = 789;
61 
62  EXPECT_CALL(m_ws_mock, QueryStorageStatus()).WillOnce(Return(status));
63 
64  auto* fake_reply(new daqif::StorageStatusFake);
65  EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_, "daqif_StorageStatus"))
66  .WillOnce(Return(fake_reply))
67  .RetiresOnSaturation();
68 
69  // Run
70  auto fut = m_service->QueryStorageStatus();
71  m_io_ctx.poll();
72 
73  ASSERT_TRUE(fut.is_ready());
74  auto daqif_status = fut.get();
75  EXPECT_EQ(daqif_status->getCapacity(), status.capacity);
76  EXPECT_EQ(daqif_status->getFree(), status.free);
77  EXPECT_EQ(daqif_status->getAvailable(), status.available);
78 }
79 
80 TEST_F(TestDpmService, QueryStorageStatusFails) {
81  // Setup
82  EXPECT_CALL(m_ws_mock, QueryStorageStatus()).WillOnce(Throw(std::runtime_error("ERROR")));
83 
84  // Run
85  auto fut = m_service->QueryStorageStatus();
86  m_io_ctx.poll();
87 
88  ASSERT_TRUE(fut.is_ready());
89  EXPECT_THROW(fut.get(), daqif::Exception);
90 }
91 
92 TEST_F(TestDpmService, QueueDaqSucceeds) {
93  // Setup
94  auto* fake_reply(new daqif::DaqReplyFake);
95  EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_, "daqif_DaqReply"))
96  .WillOnce(Return(fake_reply))
97  .RetiresOnSaturation();
98  EXPECT_CALL(m_scheduler_mock, QueueDaq("SPEC")).WillOnce(Return("ID"));
99 
100  // Run
101  auto fut = m_service->QueueDaq("SPEC");
102  m_io_ctx.poll();
103 
104  ASSERT_TRUE(fut.is_ready());
105  auto reply = fut.get();
106  EXPECT_EQ(reply->getId(), "ID");
107 }
108 
109 TEST_F(TestDpmService, QueueDaqThrows) {
110  // Setup
111  EXPECT_CALL(m_scheduler_mock, QueueDaq("SPEC")).WillOnce(Throw(std::runtime_error("ID")));
112 
113  // Run
114  auto fut = m_service->QueueDaq("SPEC");
115  m_io_ctx.poll();
116 
117  ASSERT_TRUE(fut.is_ready());
118  EXPECT_THROW(fut.get(), daqif::DaqException);
119 }
120 
121 TEST_F(TestDpmService, AbortDaqSucceeds) {
122  // Setup
123  auto* fake_reply(new daqif::DaqReplyFake);
124  EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_, "daqif_DaqReply"))
125  .WillOnce(Return(fake_reply))
126  .RetiresOnSaturation();
127  EXPECT_CALL(m_scheduler_mock, AbortDaq("TEST.ID")).Times(1);
128 
129  // Run
130  auto fut = m_service->AbortDaq("TEST.ID");
131  m_io_ctx.poll();
132 
133  ASSERT_TRUE(fut.is_ready());
134  auto reply = fut.get();
135  EXPECT_EQ(reply->getId(), "TEST.ID");
136  EXPECT_FALSE(reply->getError());
137 }
138 
139 TEST_F(TestDpmService, AbortDaqThrows) {
140  // Setup
141  EXPECT_CALL(m_scheduler_mock, AbortDaq("ID")).WillOnce(Throw(std::runtime_error("ID")));
142 
143  // Run
144  auto fut = m_service->AbortDaq("ID");
145  m_io_ctx.poll();
146 
147  ASSERT_TRUE(fut.is_ready());
148  EXPECT_THROW(fut.get(), daqif::DaqException);
149 }
150 
151 TEST_F(TestDpmService, GetDaqStatusSucceeds) {
152  // Setup
153  auto* fake_reply(new daqif::DaqStatusFake);
154  EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_, "daqif_DaqStatus"))
155  .WillOnce(Return(fake_reply))
156  .RetiresOnSaturation();
157 
158  Status status = {};
159  status.id = "TEST.ID";
160  status.state = State::Merging;
161  EXPECT_CALL(m_scheduler_mock, GetDaqStatus("TEST.ID")).WillOnce(Return(status));
162 
163  // Run
164  auto fut = m_service->GetDaqStatus("TEST.ID");
165  m_io_ctx.poll();
166 
167  ASSERT_TRUE(fut.is_ready());
168  auto reply = fut.get();
169  EXPECT_EQ(reply->getId(), "TEST.ID");
170  EXPECT_EQ(reply->getState(), daqif::StateMerging);
171  EXPECT_EQ(reply->getSubState(), daqif::Merging);
172  EXPECT_FALSE(reply->getError());
173 }
174 
175 TEST_F(TestDpmService, GetDaqStatusThrows) {
176  // Setup
177  EXPECT_CALL(m_scheduler_mock, GetDaqStatus("TEST.ID"))
178  .WillOnce(Throw(std::runtime_error("oops")));
179 
180  // Run
181  auto fut = m_service->GetDaqStatus("TEST.ID");
182  m_io_ctx.poll();
183 
184  ASSERT_TRUE(fut.is_ready());
185  EXPECT_THROW(fut.get(), daqif::DaqException);
186 }
187 
188 TEST_F(TestDpmService, GetActiveDaqsSucceeds) {
189  // Setup
190  auto* fake_reply1(new daqif::DaqStatusFake);
191  auto* fake_reply2(new daqif::DaqStatusFake);
192  EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_, "daqif_DaqStatus"))
193  .WillOnce(Return(fake_reply1))
194  .WillOnce(Return(fake_reply2))
195  .RetiresOnSaturation();
196 
197  Status status1 = {};
198  status1.id = "TEST.ID";
199  status1.state = State::Transferring;
200 
201  Status status2 = {};
202  status2.id = "TEST.ID2";
203  status2.state = State::AbortingMerging;
204 
205  std::vector<std::string> ids = {"TEST.ID", "TEST.ID2"};
206  EXPECT_CALL(m_scheduler_mock, GetQueue()).WillOnce(Return(ids));
207  EXPECT_CALL(m_scheduler_mock, GetDaqStatus("TEST.ID")).WillOnce(Return(status1));
208  EXPECT_CALL(m_scheduler_mock, GetDaqStatus("TEST.ID2")).WillOnce(Return(status2));
209 
210  // Run
211  auto fut = m_service->GetActiveDaqs();
212  m_io_ctx.poll();
213 
214  ASSERT_TRUE(fut.is_ready());
215  std::vector<std::shared_ptr<::daqif::DaqStatus>> reply = fut.get();
216  ASSERT_EQ(reply.size(), 2u);
217 
218  EXPECT_EQ(reply[0]->getId(), "TEST.ID");
219  EXPECT_EQ(reply[0]->getState(), daqif::StateMerging);
220  EXPECT_EQ(reply[0]->getSubState(), daqif::Transferring);
221  EXPECT_FALSE(reply[0]->getError());
222 
223  EXPECT_EQ(reply[1]->getId(), "TEST.ID2");
224  EXPECT_EQ(reply[1]->getState(), daqif::StateMerging);
225  EXPECT_EQ(reply[1]->getSubState(), daqif::Aborting);
226  EXPECT_FALSE(reply[1]->getError());
227 }
228 
229 TEST_F(TestDpmService, GetActiveDaqsThrowws) {
230  // Setup
231  std::vector<std::string> ids = {"TEST.ID", "TEST.ID2"};
232  EXPECT_CALL(m_scheduler_mock, GetQueue()).WillOnce(Return(ids));
233  EXPECT_CALL(m_scheduler_mock, GetDaqStatus("TEST.ID"))
234  .WillOnce(Throw(std::runtime_error("oops")));
235 
236  // Run
237  auto fut = m_service->GetActiveDaqs();
238  m_io_ctx.poll();
239 
240  ASSERT_TRUE(fut.is_ready());
241  EXPECT_THROW(fut.get(), daqif::DaqException);
242 }
243 } // namespace daq::dpm
progress.hpp
Defines shared test progress utilities.
rad::IoExecutor
Adapts boost::asio::io_context into a compatible boost::thread Executor type.
Definition: ioExecutor.hpp:12
daq::State::Transferring
@ Transferring
Input files are being transferred.
daq::dpm::TestDpmService::m_service
std::unique_ptr< DpmService > m_service
Definition: testDpmService.cpp:50
scheduler.hpp
daq::dpm::Scheduler and related class declarations.
daq::dpm::TestDpmService::m_scheduler_mock
daq::dpm::MockScheduler m_scheduler_mock
Definition: testDpmService.cpp:48
daq::State::Merging
@ Merging
DAQ is being merged.
daqif::StorageStatusFake
Definition: daqifFake.hpp:144
daqifFake.hpp
daq::dpm::TestDpmService::TearDown
void TearDown() override
Definition: testDpmService.cpp:37
daq::dpm
Definition: testDpSpec.cpp:16
daq::dpm::TestDpmService::m_mal_mock
MockMal m_mal_mock
Definition: testDpmService.cpp:46
mockMal.hpp
Mocks for daq::dpm::Workspace and daq::dpm::DaqWorkspace.
daq::Status::id
std::string id
Definition: status.hpp:136
daqif::DaqStatusFake
Definition: daqifFake.hpp:39
dpmService.hpp
daq::dpm::DpmService implements MAL services daqif::DpmControl and daqif::DpmDaqControl.
daq::dpm::TestDpmService::SetUp
void SetUp() override
Definition: testDpmService.cpp:33
daq::dpm::TEST_F
TEST_F(TestParseOrigin, ParseSucceeds)
Definition: testDpSpec.cpp:20
daq::dpm::TestDpmService::m_ws_mock
daq::dpm::MockWorkspace m_ws_mock
Definition: testDpmService.cpp:47
daq::Status
Non observable status object that keeps stores status of data acquisition.
Definition: status.hpp:120
daqif::DaqReplyFake
Definition: daqifFake.hpp:7
daq::Status::state
State state
Definition: status.hpp:138
daq::dpm::MockWorkspace
Definition: mockWorkspace.hpp:18
daq::dpm::TestDpmService::m_io_ctx
boost::asio::io_context m_io_ctx
Definition: testDpmService.cpp:43
daq::dpm::TestDpmService
Definition: testDpmService.cpp:28
MockMal
Definition: mockMal.hpp:16
daq::dpm::TestDpmService::m_executor
rad::IoExecutor m_executor
Definition: testDpmService.cpp:44
daq::dpm::TestDpmService::TestDpmService
TestDpmService()
Definition: testDpmService.cpp:30
mockScheduler.hpp
Mocks for daq::dpm::Scheduler and daq::dpm::DaqScheduler.
daq::dpm::MockScheduler
Definition: mockScheduler.hpp:19