10 #include <fmt/ostream.h>
12 #include <gtest/gtest.h>
19 using namespace ::testing;
20 using namespace std::literals::string_view_literals;
21 using namespace std::chrono_literals;
40 TestManagerImpl() : m_io_ctx(), m_executor(m_io_ctx), m_manager(m_executor,
"INS") {
48 m_daq1_status = std::make_shared<ObservableStatus>(m_daq_id_1);
49 m_daq2_status = std::make_shared<ObservableStatus>(m_daq_id_2);
50 m_daq1 = std::make_shared<DaqControllerMock>();
51 m_daq2 = std::make_shared<DaqControllerMock>();
53 EXPECT_CALL(*m_daq1, GetId()).WillRepeatedly(ReturnRef(m_daq_id_1));
54 EXPECT_CALL(*m_daq2, GetId()).WillRepeatedly(ReturnRef(m_daq_id_2));
55 EXPECT_CALL(*m_daq1, GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(m_daq1_status));
56 EXPECT_CALL(*m_daq2, GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(m_daq2_status));
57 EXPECT_CALL(Const(*m_daq1),
58 GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(m_daq1_status));
59 EXPECT_CALL(Const(*m_daq2),
60 GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(m_daq2_status));
62 m_manager.AddDaq(m_daq1);
63 m_manager.AddDaq(m_daq2);
72 std::shared_ptr<DaqControllerMock>
m_daq1;
73 std::shared_ptr<DaqControllerMock>
m_daq2;
81 boost::asio::io_context io_ctx;
90 boost::asio::io_context io_ctx;
94 auto id = std::string(
"id");
95 auto status = std::make_shared<ObservableStatus>(
id);;
96 auto daq = std::make_shared<DaqControllerMock>();
97 EXPECT_CALL(*
daq, GetId()).WillRepeatedly(ReturnRef(
id));
98 EXPECT_CALL(*
daq, GetStatus()).WillRepeatedly(Return(status));
101 EXPECT_CALL(o, CallOperator(_));
110 boost::asio::io_context io_ctx;
112 auto id = std::string(
"id");
113 auto status = std::make_shared<ObservableStatus>(
id);;
114 auto daq = std::make_shared<DaqControllerMock>();
115 EXPECT_CALL(*
daq, GetId()).Times(AnyNumber()).WillRepeatedly(ReturnRef(
id));
116 EXPECT_CALL(*
daq, GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(status));
117 EXPECT_CALL(Const(*
daq),
118 GetStatus()).Times(AnyNumber()).WillRepeatedly(Return(status));
120 boost::future<Result<Status>> res;
127 ASSERT_FALSE(res.is_ready());
132 ASSERT_TRUE(res.is_ready());
139 std::regex regex(
"INSTR\\.\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}");
141 EXPECT_TRUE(std::regex_match(
id, regex))
142 <<
"Instrument ID should be truncated to 5 characters if too long";
145 std::regex regex(
"INS\\.\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}");
146 auto id = m_manager.MakeDaqId();
147 EXPECT_TRUE(std::regex_match(
id, regex));
152 EXPECT_NE(id1, id2) <<
"Adding jitter should have made the ID different";
157 EXPECT_THROW(m_manager.AddDaq(m_daq1), std::invalid_argument);
162 auto fut = m_manager.StartDaqAsync(
"nonexistant-id"sv);
163 ASSERT_TRUE(fut.is_ready());
164 EXPECT_THROW(fut.get(), std::invalid_argument);
170 EXPECT_CALL(*m_daq1, StartAsync())
171 .WillOnce(Return(ByMove(boost::make_ready_future<State>(State::Starting))));
174 auto fut = m_manager.StartDaqAsync(
"daq1"sv);
175 ASSERT_TRUE(fut.is_ready());
176 EXPECT_EQ(fut.get(), State::Starting);
181 auto fut = m_manager.StopDaqAsync(
"nonexistant-id"sv, daq::ErrorPolicy::Strict);
182 ASSERT_TRUE(fut.is_ready());
183 EXPECT_THROW(fut.get(), std::invalid_argument);
190 EXPECT_CALL(*m_daq1, StopAsync(daq::ErrorPolicy::Strict))
191 .WillOnce(Return(ByMove(boost::make_ready_future<Status>(
Status(
"daq1", State::Stopped,
192 false, {}, {}, t)))));
195 auto fut = m_manager.StopDaqAsync(
"daq1"sv, daq::ErrorPolicy::Strict);
196 ASSERT_TRUE(fut.is_ready());
197 auto status = fut.get();
198 EXPECT_EQ(status.state, State::Stopped);
199 EXPECT_EQ(status.error,
false);
205 ASSERT_TRUE(fut.is_ready());
206 EXPECT_THROW(fut.get(), std::invalid_argument);
213 reply_status.state = State::Aborting;
214 EXPECT_CALL(*m_daq1, AbortAsync(ErrorPolicy::Strict))
215 .WillOnce(Return(ByMove(boost::make_ready_future<Status>(reply_status))));
218 auto fut = m_manager.AbortDaqAsync(
"daq1"sv, ErrorPolicy::Strict);
219 ASSERT_TRUE(fut.is_ready());
220 auto result = fut.get();
221 EXPECT_EQ(result.state, State::Aborting);
222 EXPECT_FALSE(result.error);
233 m_manager.UpdateKeywords(
"daq1"sv, keywords);
240 EXPECT_THROW(m_manager.UpdateKeywords(
"nonexistant-id"sv, keywords), std::invalid_argument);
247 auto status = m_manager.GetStatus(
"daq1"sv);
248 EXPECT_EQ(status.id,
"daq1");
249 EXPECT_EQ(status.state, daq::State::NotStarted);
250 EXPECT_FALSE(status.error);
255 EXPECT_THROW(m_manager.GetStatus(
"nonexistant"sv), std::invalid_argument);
262 auto fut = m_manager.AwaitDaqStateAsync(
"daq1"sv, daq::State::NotStarted, 10ms);
265 ASSERT_TRUE(fut.is_ready());
266 auto [timeout, result] = fut.get();
267 EXPECT_FALSE(timeout);
268 EXPECT_EQ(result, m_daq1->GetStatus()->GetStatus());
274 auto fut = m_manager.AwaitDaqStateAsync(
"daq1"sv, daq::State::Acquiring, 10ms);
275 ASSERT_FALSE(fut.is_ready());
276 m_daq1_status->SetState(daq::State::Acquiring);
279 ASSERT_TRUE(fut.is_ready());
280 auto [timeout, result] = fut.get();
281 EXPECT_FALSE(timeout);
282 EXPECT_EQ(result, m_daq1->GetStatus()->GetStatus());
288 auto fut = m_manager.AwaitDaqStateAsync(
"daq1"sv, daq::State::Acquiring, 0ms);
289 ASSERT_FALSE(fut.is_ready());
292 ASSERT_TRUE(fut.is_ready()) <<
"Timer should have triggered to make the future ready";
293 auto [timeout, result] = fut.get();
294 EXPECT_TRUE(timeout);
295 EXPECT_EQ(result, m_daq1->GetStatus()->GetStatus());