10 #include <fmt/format.h>
11 #include <gtest/gtest.h>
19 #include "mock/daqifMock.hpp"
22 using namespace ::testing;
23 using namespace std::literals;
39 , m_event_log(std::make_shared<
daq::ObservableEventLog>())
41 m_io_ctx, m_mal_mock, m_mgr_mock,
"ocm",
"/tmp", m_event_log)) {
44 m_metadata_sources =
"meta@zpb.rr://uri";
45 m_prim_sources =
"prim@zpb.rr://uri";
46 m_daq_properties = R
"(
55 "type": "valueKeyword",
84 TEST(TestParseSingleSource, Successful) {
88 EXPECT_EQ(expected, parsed);
91 TEST(TestParseSingleSource, LeadingOrTrailingSpacesAreAllowed) {
98 TEST(TestParseSingleSource, Incomplete) {
101 std::invalid_argument);
103 std::invalid_argument);
104 EXPECT_THROW(
ParseSourceUri(fmt::format(
"@,")), std::invalid_argument);
106 std::invalid_argument);
108 std::invalid_argument);
111 TEST(TestParseMultipleSources, Successful) {
114 std::vector<ParsedSource> result{expected1, expected2};
131 TEST(TestParseSingleSource, Empty) {
134 std::invalid_argument);
135 EXPECT_THROW(
ParseSourceUri(fmt::format(
"{}@,{} ", expected.
name,
"")), std::invalid_argument);
137 std::invalid_argument);
140 TEST(TestParseDaqContext, Successful) {
141 auto max_err_ms = 0.001;
143 auto properties_str = R
"(
147 "type": "esoKeyword",
152 "type": "valueKeyword",
161 EXPECT_THAT(
static_cast<double>(properties.await_interval.count()),
162 DoubleNear(100, max_err_ms));
165 auto properties_str = R
"(
171 EXPECT_THAT(
static_cast<double>(properties.await_interval.count()),
172 DoubleNear(1000, max_err_ms));
176 TEST(TestParseDaqContext, Failures) {
184 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).WillOnce(Return(
true));
187 auto fut = m_daq_impl->StartDaq(
"id",
"prefix", m_prim_sources, m_metadata_sources,
"");
189 ASSERT_TRUE(fut.is_ready()) <<
"future should be ready by now since daq with id already exist";
190 EXPECT_THROW(fut.get(), daqif::DaqException);
197 EXPECT_CALL(m_mgr_mock, MakeDaqId(_)).WillOnce(Return(
"id"));
199 .WillOnce(Return(ByMove(boost::make_ready_future<daq::State>(daq::State::Acquiring))));
201 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
202 .WillOnce(Return(fake_reply))
203 .RetiresOnSaturation();
206 auto fut = m_daq_impl->StartDaq(
"",
"prefix", m_prim_sources, m_metadata_sources,
"");
210 ASSERT_TRUE(fut.is_ready()) <<
"future should be ready immediately since we faked a "
211 "synchronous start with make_ready_future";
212 EXPECT_TRUE(fut.has_value());
213 auto reply = fut.get();
215 EXPECT_EQ(reply->getId(),
"id");
222 auto fut = m_daq_impl->StartDaq(
"id",
"prefix",
"", m_metadata_sources,
"INVALID JSON");
224 ASSERT_TRUE(fut.is_ready()) <<
"future should be ready by now since daq with id already exist";
225 EXPECT_THROW(fut.get(), daqif::DaqException);
233 auto fut = m_daq_impl->StartDaq(
"id",
"prefix",
"", m_metadata_sources,
"[]");
235 ASSERT_TRUE(fut.is_ready());
236 EXPECT_THROW(fut.get(), daqif::DaqException);
244 auto fut = m_daq_impl->StartDaq(
"id",
"/path/prefix",
"", m_metadata_sources, m_daq_properties);
246 ASSERT_TRUE(fut.is_ready());
247 EXPECT_THROW(fut.get(), daqif::DaqException);
254 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).WillOnce(Return(
false));
256 .WillOnce(Return(ByMove(boost::make_ready_future<daq::State>(daq::State::Acquiring))));
258 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
259 .WillOnce(Return(fake_reply))
260 .RetiresOnSaturation();
263 auto fut = m_daq_impl->StartDaq(
"id",
"prefix",
"", m_metadata_sources, m_daq_properties);
268 ASSERT_TRUE(fut.is_ready()) <<
"future should be ready immediately since we faked a "
269 "synchronous start with make_ready_future";
270 EXPECT_TRUE(fut.has_value());
271 auto reply = fut.get();
273 EXPECT_EQ(reply->getId(),
"id");
278 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).WillOnce(Return(
false));
279 EXPECT_CALL(m_mgr_mock, StartDaqAsync(_)).WillOnce(Throw(std::runtime_error(
"error")));
282 auto fut = m_daq_impl->StartDaq(
"id",
"prefix",
"", m_metadata_sources,
"");
284 ASSERT_TRUE(fut.is_ready()) <<
"future should be ready immediately since we faked a "
285 "synchronous start with make_ready_future";
286 EXPECT_THROW(fut.get(), daqif::DaqException)
287 <<
"future should have contained the ICD exception type";
293 EXPECT_CALL(m_mgr_mock, MakeDaqId(_)).WillOnce(Return(
"fileid"));
294 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).WillOnce(Return(
false));
296 .WillOnce(Return(ByMove(boost::make_exceptional_future<daq::State>(
300 auto fut = m_daq_impl->StartDaq(
"id",
"prefix",
"", m_metadata_sources,
"");
302 ASSERT_TRUE(fut.is_ready())
303 <<
"future should be ready now since we faked a synchronous start with make_ready_future";
304 EXPECT_THROW(fut.get(), daqif::DaqException)
305 <<
"future should have contained the ICD exception type";
311 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
false));
313 EXPECT_CALL(m_mgr_mock, StopDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
314 .Times(Between(0, 1))
315 .WillOnce(Return(ByMove(
316 boost::make_exceptional_future<daq::Status>(std::invalid_argument(
"no such id")))));
319 auto reply_fut = m_daq_impl->StopDaq(
"id");
321 ASSERT_TRUE(reply_fut.is_ready());
322 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
331 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
332 EXPECT_CALL(m_mgr_mock, StopDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
333 .WillOnce(Return(ByMove(boost::make_ready_future<daq::Status>(status))));
334 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
335 .WillOnce(Return(fake_reply))
336 .RetiresOnSaturation();
339 auto reply_fut = m_daq_impl->StopDaq(
"id");
341 ASSERT_TRUE(reply_fut.is_ready());
342 std::shared_ptr<daqif::DaqReply> reply = reply_fut.get();
343 EXPECT_EQ(reply->getId(),
"id");
352 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
354 .WillOnce(Return(ByMove(boost::make_ready_future<daq::Status>(status))));
355 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
356 .WillOnce(Return(fake_reply))
357 .RetiresOnSaturation();
360 auto reply_fut = m_daq_impl->ForceStopDaq(
"id");
362 ASSERT_TRUE(reply_fut.is_ready());
363 std::shared_ptr<daqif::DaqReply> reply = reply_fut.get();
364 EXPECT_EQ(reply->getId(),
"id");
370 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
false));
371 EXPECT_CALL(m_mgr_mock, AbortDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
372 .Times(Between(0, 1))
373 .WillOnce(Return(ByMove(
374 boost::make_exceptional_future<daq::Status>(std::invalid_argument(
"no such id")))));
377 auto reply_fut = m_daq_impl->AbortDaq(
"id");
379 ASSERT_TRUE(reply_fut.is_ready());
380 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
388 reply_status.state = daq::State::Aborted;
391 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
392 EXPECT_CALL(m_mgr_mock, AbortDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
393 .WillOnce(Return(ByMove(boost::make_ready_future<daq::Status>(reply_status))));
394 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
395 .WillOnce(Return(fake_reply))
396 .RetiresOnSaturation();
399 auto reply_fut = m_daq_impl->AbortDaq(
"id");
401 ASSERT_TRUE(reply_fut.is_ready());
402 std::shared_ptr<daqif::DaqReply> reply = reply_fut.get();
403 EXPECT_EQ(reply->getId(),
"id");
410 reply_status.state = daq::State::Aborted;
413 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
415 .WillOnce(Return(ByMove(boost::make_ready_future<daq::Status>(reply_status))));
416 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
417 .WillOnce(Return(fake_reply))
418 .RetiresOnSaturation();
421 auto reply_fut = m_daq_impl->ForceAbortDaq(
"id");
423 ASSERT_TRUE(reply_fut.is_ready());
424 std::shared_ptr<daqif::DaqReply> reply = reply_fut.get();
425 EXPECT_EQ(reply->getId(),
"id");
430 std::string keywords = R
"(
433 "type":"valueKeyword",
450 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
452 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqReply"))
453 .WillOnce(Return(fake_reply))
454 .RetiresOnSaturation();
457 auto reply_fut = m_daq_impl->UpdateKeywords(
"id", keywords);
459 ASSERT_TRUE(reply_fut.is_ready());
460 std::shared_ptr<daqif::DaqReply> reply = reply_fut.get();
461 EXPECT_EQ(reply->getId(),
"id");
462 EXPECT_EQ(reply->getError(),
false);
467 std::string keywords_with_trailing_comma = R
"(
470 "type":"valueKeyword",
482 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
486 auto reply_fut = m_daq_impl->UpdateKeywords(
"id", keywords_with_trailing_comma);
488 ASSERT_TRUE(reply_fut.is_ready());
489 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
494 std::string keywords_with_unknown_type = R
"(
497 "type":"unknownKeywordHere",
504 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
508 auto reply_fut = m_daq_impl->UpdateKeywords(
"id", keywords_with_unknown_type);
510 ASSERT_TRUE(reply_fut.is_ready());
511 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
516 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
false));
517 EXPECT_CALL(m_mgr_mock, GetStatus(
"id"sv))
518 .Times(Between(0, 1))
519 .WillOnce(Throw(std::invalid_argument(
"no such id")));
522 auto reply_fut = m_daq_impl->GetStatus(
"id");
523 EXPECT_FALSE(reply_fut.is_ready())
524 <<
"future cannot be ready since implementation should use provided executor to provide "
527 ASSERT_TRUE(reply_fut.is_ready());
528 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
536 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
537 EXPECT_CALL(m_mgr_mock, GetStatus(
"id"sv)).Times(Between(0, 1)).WillOnce(Return(status));
538 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqStatus"))
539 .WillOnce(Return(fake_reply))
540 .RetiresOnSaturation();
543 auto reply_fut = m_daq_impl->GetStatus(
"id");
544 EXPECT_FALSE(reply_fut.is_ready())
545 <<
"future cannot be ready since implementation should use provided executor to provide "
548 ASSERT_TRUE(reply_fut.is_ready());
549 std::shared_ptr<daqif::DaqStatus> reply = reply_fut.get();
550 EXPECT_EQ(reply->getId(),
"id");
551 EXPECT_EQ(reply->getFileId(),
"fileid");
552 EXPECT_EQ(reply->getError(),
false);
553 EXPECT_EQ(reply->getState(), daqif::StateAcquiring);
554 EXPECT_EQ(reply->getSubState(), daqif::Acquiring);
559 auto status1 = std::make_shared<daq::ObservableStatus>(
"completed",
"fileid1");
560 auto status2 = std::make_shared<daq::ObservableStatus>(
"active1",
"fileid2");
561 auto status3 = std::make_shared<daq::ObservableStatus>(
"active2",
"fileid3");
562 auto status4 = std::make_shared<daq::ObservableStatus>(
"completed",
"fileid4");
564 status1->SetState(daq::State::Aborted);
565 status4->SetState(daq::State::Aborted);
567 auto daq1 = std::make_shared<DaqControllerFake>(status1);
568 auto daq2 = std::make_shared<DaqControllerFake>(status2);
569 auto daq3 = std::make_shared<DaqControllerFake>(status3);
570 auto daq4 = std::make_shared<DaqControllerFake>(status4);
571 std::vector<std::shared_ptr<daq::DaqController const>> daqs;
572 daqs.push_back(daq1);
573 daqs.push_back(daq2);
574 daqs.push_back(daq3);
575 daqs.push_back(daq4);
580 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_DaqStatus"))
581 .WillOnce(Return(st1))
582 .WillOnce(Return(st2))
583 .RetiresOnSaturation();
585 EXPECT_CALL(m_mgr_mock, GetDaqControllers()).WillOnce(Return(daqs));
588 auto reply_fut = m_daq_impl->GetActiveList();
590 ASSERT_TRUE(reply_fut.is_ready());
591 auto reply = reply_fut.get();
592 EXPECT_EQ(reply.size(), 2u);
593 EXPECT_EQ(reply[0]->getId(),
"active1");
594 EXPECT_EQ(reply[1]->getId(),
"active2");
603 auto fut = m_daq_impl->AwaitDaqState(
"id", daqif::StateAcquiring, daqif::Acquiring, 0.0);
605 ASSERT_TRUE(fut.is_ready());
606 EXPECT_THROW(fut.get(), daqif::DaqException);
611 auto fut = m_daq_impl->AwaitDaqState(
"id", daqif::StateMerging, daqif::Acquiring, 1.0);
613 ASSERT_TRUE(fut.is_ready());
614 EXPECT_THROW(fut.get(), daqif::DaqException);
621 status.
state = daq::State::Acquiring;
623 boost::promise<daq::Result<daq::Status>> promise;
624 EXPECT_CALL(m_mgr_mock, AwaitDaqStateAsync(
"id"sv, daq::State::Acquiring, 1000ms))
625 .WillOnce(Return(ByMove(promise.get_future())));
629 EXPECT_CALL(m_mal_mock, getDataEntityUnsafe(_,
"daqif_AwaitDaqReply"))
630 .WillOnce(Return(reply))
631 .RetiresOnSaturation();
634 auto fut = m_daq_impl->AwaitDaqState(
"id", daqif::StateAcquiring, daqif::Acquiring, 1.0);
635 ASSERT_FALSE(fut.is_ready());
636 promise.set_value({
false, status});
639 auto val = fut.get();
640 EXPECT_FALSE(val->getTimeout());
641 auto status = val->getStatus();
642 EXPECT_EQ(status->getId(),
"id");
643 EXPECT_EQ(status->getError(),
false);
644 EXPECT_EQ(status->getState(), daqif::StateAcquiring);
645 EXPECT_EQ(status->getSubState(), daqif::Acquiring);
653 boost::promise<daq::State> mgr_promise;
654 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).WillOnce(Return(
false));
655 EXPECT_CALL(m_mgr_mock, MakeDaqId(_)).WillOnce(Return(
"fileid"));
656 EXPECT_CALL(m_mgr_mock, StartDaqAsync(_)).WillOnce(Return(ByMove(mgr_promise.get_future())));
659 auto reply_fut = m_daq_impl->StartDaq(
"id",
"prefix", m_prim_sources, m_metadata_sources,
"");
664 mgr_promise.set_value(daq::State::Acquiring);
668 ASSERT_TRUE(reply_fut.is_ready());
669 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
676 boost::promise<daq::Status> mgr_promise;
679 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
680 EXPECT_CALL(m_mgr_mock, StopDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
681 .WillOnce(Return(ByMove(mgr_promise.get_future())));
684 auto reply_fut = m_daq_impl->StopDaq(
"id");
689 mgr_promise.set_value(
694 ASSERT_TRUE(reply_fut.is_ready());
695 EXPECT_THROW(reply_fut.get(), daqif::DaqException);
702 boost::promise<daq::Status> mgr_promise;
705 reply_status.state = daq::State::Aborted;
708 EXPECT_CALL(m_mgr_mock, HaveDaq(
"id"sv, _)).Times(Between(0, 1)).WillRepeatedly(Return(
true));
709 EXPECT_CALL(m_mgr_mock, AbortDaqAsync(
"id"sv, daq::ErrorPolicy::Strict))
710 .WillOnce(Return(ByMove(mgr_promise.get_future())));
713 auto reply_fut = m_daq_impl->AbortDaq(
"id");
718 mgr_promise.set_value(reply_status);
722 ASSERT_TRUE(reply_fut.is_ready());
723 EXPECT_THROW(reply_fut.get(), daqif::DaqException);