12 #include <log4cplus/loggingmacros.h>
17 #include "mock/mockWorkspace.hpp"
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
24 using namespace ::testing;
28 std::unique_ptr<RsyncAsyncProcessIf>
operator()(boost::asio::io_context&,
33 auto rsync = std::make_unique<MockRsyncAsyncProcess>();
37 procs.push_back(rsync.get());
43 std::vector<MockRsyncAsyncProcess*>
procs;
50 std::unique_ptr<AsyncProcessIf>
operator()(boost::asio::io_context&, std::vector<std::string>) {
51 auto rsync = std::make_unique<MockRsyncAsyncProcess>();
55 procs.push_back(rsync.get());
61 std::vector<MockAsyncProcess*>
procs;
111 std::filesystem::path sources_root =
"sources";
118 if (std::holds_alternative<json::FitsFileSource>(s)) {
119 auto const& source = std::get<json::FitsFileSource>(s);
124 auto ws = std::make_unique<daq::dpm::MockDaqWorkspace>();
128 EXPECT_CALL(*ws, LoadSpecification()).WillRepeatedly(Return(
m_dpspec));
129 EXPECT_CALL(*ws, GetSourcesPath()).WillRepeatedly(Return(std::filesystem::path(
"sources")));
130 EXPECT_CALL(*ws, GetSourceLookupPath())
131 .WillRepeatedly(Return(std::filesystem::path(
"sources.json")));
132 EXPECT_CALL(*ws, GetPath())
134 .WillRepeatedly(Return(std::filesystem::path(
"")));
152 template <
class Pred>
156 if (
m_io_ctx.poll_one() == 0 || p()) {
168 std::unique_ptr<DaqControllerImpl>
m_daq;
173 using namespace ::testing;
178 EXPECT_CALL(*m_ws_mock_ptr, StoreSourceLookup(_));
189 m_dpspec.target.source = std::nullopt;
190 m_dpspec.sources.clear();
204 ASSERT_TRUE(m_dpspec.target.source);
205 ASSERT_TRUE(m_dpspec.sources.size() == 1);
207 m_resources.net_receive.SetLimit(0);
210 EXPECT_EQ(m_resolver.GetMapping().size(), 2u)
211 <<
"Setup should have added target and one extra source";
212 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/target.fits")))
214 .WillRepeatedly(Return(
false));
215 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/source.fits")))
217 .WillRepeatedly(Return(
false));
223 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/source.fits")))
224 .WillOnce(Return(
true));
225 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/target.fits")))
226 .WillOnce(Return(
true));
230 for (
auto& proc : m_rsync_factory.procs) {
231 proc->promise.set_value(0);
241 ASSERT_TRUE(m_dpspec.target.source);
242 ASSERT_TRUE(m_dpspec.sources.size() == 1);
244 m_resources.net_receive.SetLimit(0);
247 EXPECT_EQ(m_resolver.GetMapping().size(), 2u)
248 <<
"Setup should have added target and one extra source";
249 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/target.fits")))
250 .WillOnce(Return(
false));
251 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"sources/source.fits")))
252 .WillOnce(Return(
false));
259 EXPECT_CALL(*m_ws_mock_ptr,
266 for (
auto& proc : m_rsync_factory.procs) {
267 proc->promise.set_value(
error++);
273 EXPECT_TRUE(m_daq->IsStopped());
285 m_initial_status.error =
true;
289 EXPECT_CALL(*m_ws_mock_ptr, Exists(_)).WillRepeatedly(Return(
true));
305 EXPECT_CALL(*m_ws_mock_ptr, GetSpecificationPath())
306 .WillRepeatedly(Return(
"specification.json"));
307 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"TEST.ID.fits")))
308 .WillOnce(Return(
false));
314 ASSERT_EQ(m_proc_factory.procs.size(), 1u);
315 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"TEST.ID.fits")))
316 .WillRepeatedly(Return(
true));
319 EXPECT_CALL(*m_ws_mock_ptr,
323 HasSubstr(
"Writing keywords required resizing")))),
329 EXPECT_CALL(*m_ws_mock_ptr, MakeResultSymlink(std::filesystem::path(
"TEST.ID.fits")));
332 std::string message =
333 R
"({"content":{"id":"primary_hdu_resize","message":"Writing keywords required resizing of primary HDU: Add space for at least 73 keywords to avoid resize"},"timestamp":1650964356522093759,"type":"alert"})";
334 m_proc_factory.procs[0]->stdout(8, message);
337 m_proc_factory.procs[0]->stdout(8,
"This is invalid JSON");
340 m_proc_factory.procs[0]->promise.set_value(0);
355 m_initial_status.error =
true;
358 EXPECT_CALL(*m_ws_mock_ptr, Exists(std::filesystem::path(
"TEST.ID.fits")))
359 .WillRepeatedly(Return(
true));
367 ASSERT_EQ(m_proc_factory.procs.size(), 0u);
Provides location of fits source file.
void Add(SourceFile const &source, std::filesystem::path const &path)
Adds path so it is resolved using source_name and location.
auto GetMapping() const noexcept -> Mapping const &
Get native representation of source mapping for serialization.
DaqControllerOptions m_options
rad::IoExecutor m_executor
boost::asio::io_context m_io_ctx
std::unique_ptr< DaqControllerImpl > m_daq
daq::dpm::MockDaqWorkspace * m_ws_mock_ptr
void PollUntil(Pred &&p)
Poll one handler at a time until predicate has been satisifed or io_context runs out of work.
SourceResolver m_resolver
FakeProcFactory m_proc_factory
void PostSetUp()
Specifically sets up expectations and other things based on current state.
FakeRsyncFactory m_rsync_factory
Adapts boost::asio::io_context into a compatible boost::thread Executor type.
Mocks for daq::RsyncAsyncProcessIf.
Mocks for daq::dpm::Scheduler and daq::dpm::DaqScheduler.
TEST_F(TestDaqController, ScheduledTransitionsToTransferring)
Options for DaqController.
Location ParseSourceLocation(std::string const &location_str)
Parse location string from DpSpec into component parts.
std::optional< FitsFileSource > source
std::vector< SourceTypes > sources
Close representation of the JSON structure but with stronger types.
@ Completed
Completed DAQ.
@ Scheduled
daq is acknowledged by dpm and is scheduled for merging (i.e.
@ Merging
DAQ is being merged.
@ Transferring
Input files are being transferred.
Options controlling rsync invocation.
daq::dpm::Scheduler and related class declarations.
Non observable status object that keeps stores status of data acquisition.
std::vector< Alert > alerts
Active alerts.
std::vector< MockAsyncProcess * > procs
std::unique_ptr< AsyncProcessIf > operator()(boost::asio::io_context &, std::vector< std::string >)
std::function< void(MockAsyncProcess &)> Hook
std::unique_ptr< RsyncAsyncProcessIf > operator()(boost::asio::io_context &, std::string, std::string, RsyncOptions const &, RsyncAsyncProcess::DryRun)
std::function< void(MockRsyncAsyncProcess &)> Hook
std::vector< MockRsyncAsyncProcess * > procs
std::filesystem::path path
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_EQ(meta.keyword_rules.size(), 1u)