ifw-daq  2.1.0-pre1
IFW Data Acquisition modules
testMerge.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_dpm_merge_test
4  * @copyright ESO - European Southern Observatory
5  */
6 #include "merge.hpp"
7 
8 #include <fmt/format.h>
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 #include <log4cplus/loggingmacros.h>
12 
13 #include <daq/fits/cfitsio.hpp>
14 
15 using namespace ::testing;
16 
17 namespace daq::dpm::merge {
18 
20  MOCK_METHOD(void, PostAlert, (std::string const& id, std::string const& message), (override));
21 };
22 
25 };
26 
28  MOCK_METHOD(void, SortKeywords, (std::vector<fits::LiteralKeyword> & keywords), ());
29 };
30 
33  Process,
35  (const, override));
36 };
37 
38 /**
39  * Fixture that sets up a in-place target FITS file with standard HDU keywords
40  * - SIMPLE
41  * - BITPIX
42  * - NAXIS
43  * - EXTEND
44  */
45 class TestMergeKeywords : public Test {
46 public:
48  : Test()
49  , m_dry_run(false)
50  , m_mock_reporter()
52  , m_mock_sorter()
53  , m_logger(log4cplus::Logger::getInstance("test.dpm.merge"))
55  , m_params{"arcfile.fits", "origfile.fits"}
56  , m_target_buffer(4096u)
57  , m_target("target",
58  "fakefile.fits",
59  std::make_unique<StandardKeywordRuleProcessor>(),
60  std::move(m_target_buffer).GetOwnedFile()) {
61  }
62 
63  void SetUp() override {
65 
66  // clang-format off
67  ON_CALL(m_mock_formatter, FormatKeyword(_))
68  .WillByDefault(
69  Invoke([](auto const& kw) {
70  return fits::Format(kw);
71  }
72  )
73  );
74  // clang-format on
75  }
76  void TearDown() override {
77  }
78  void ExpectStandardKeywords(std::vector<fits::LiteralKeyword>& kws) {
79  auto datasum = kws.back();
80  kws.pop_back();
81  auto checksum = kws.back();
82  kws.pop_back();
83  EXPECT_EQ("DATASUM", datasum.GetName().name);
84  EXPECT_EQ("CHECKSUM", checksum.GetName().name);
85 
86  auto arcfile = kws.back();
87  kws.pop_back();
88  auto origfile = kws.back();
89  kws.pop_back();
90 
91  EXPECT_EQ("ORIGFILE", origfile.GetName().name);
92  EXPECT_EQ(fmt::format("'{}'", m_params.origfile), origfile.GetComponents().value);
93  EXPECT_EQ("ARCFILE", arcfile.GetName().name);
94  EXPECT_EQ(fmt::format("'{}'", m_params.arcfile), arcfile.GetComponents().value);
95  }
96 
97  bool m_dry_run;
101 
102  log4cplus::Logger m_logger;
103 
107 
109 };
110 
111 TEST_F(TestMergeKeywords, MergeEmptyStillSortsKeywords) {
112  // Setup
113  std::vector<SourceTypes> sources;
114 
115  auto before = fits::ReadKeywords(m_target.GetFitsFile(), 1);
116  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
117  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
118 
119  // Test
120  Merge(m_ops, m_params, m_target, sources, m_dry_run);
121  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
122  ASSERT_EQ(after.size(), before.size() + 4u)
123  << "4 keywords should be added by DPM (2x checksum, ARCFILE, ORIFILE)";
124  ExpectStandardKeywords(after);
125  EXPECT_THAT(after, ContainerEq(before));
126 }
127 
128 /** Test that primary HDU keywords are sorted */
129 TEST_F(TestMergeKeywords, NoSourceStillSortsPrimaryHdu) {
130  // Setup
131  std::vector<SourceTypes> sources;
132  auto before = fits::ReadKeywords(m_target.GetFitsFile(), 1);
133 
134  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
135  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
136 
137  // Test
138  Merge(m_ops, m_params, m_target, sources, m_dry_run);
139  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
140  ASSERT_EQ(after.size(), before.size() + 4u)
141  << "4 keywords should be added by DPM (2x checksum, ARCFILE, ORIFILE)";
142  ExpectStandardKeywords(after);
143 
144  EXPECT_THAT(after, ContainerEq(before));
145 }
146 
147 /** Test merging some keywords from a single source */
148 TEST_F(TestMergeKeywords, MergeSingleKeywordList) {
149  // Setup
150  std::vector<SourceTypes> sources;
151  auto kw1 = fits::LiteralKeyword("HIERARCH ESO UNKN A = T / Comment");
152  auto kw2 = fits::LiteralKeyword("HIERARCH ESO UNKN B = T / Comment");
153  fits::KeywordVector kws = {kw1, kw2};
154 
155  sources.emplace_back(std::in_place_type<FitsKeywordsSource>,
156  "tcs",
157  kws,
158  std::make_unique<StandardKeywordRuleProcessor>());
159  auto expected_kws = fits::ReadKeywords(m_target.GetFitsFile(), 1);
160  expected_kws.push_back(kw1);
161  expected_kws.push_back(kw2);
162 
163  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
164  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
165 
166  // Test
167  Merge(m_ops, m_params, m_target, sources, m_dry_run);
168 
169  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
170  // Two checksum keywords are added
171  ASSERT_EQ(after.size(), expected_kws.size() + 4u);
172  ExpectStandardKeywords(after);
173 
174  EXPECT_THAT(after, ContainerEq(expected_kws));
175 }
176 
177 TEST_F(TestMergeKeywords, MergeFailsIfTransformsCauseInvalidKeyword) {
178  // Setup
179  std::vector<SourceTypes> sources;
180  auto kw1 = fits::LiteralKeyword("HIERARCH ESO UNKN A = T / Comment");
181  fits::KeywordVector kws = {kw1};
182 
183  auto kw_processor = std::make_unique<MockKeywordProcessor>();
184  EXPECT_CALL(*kw_processor, Process(_, _))
185  .WillRepeatedly(Throw(std::invalid_argument("keyword too long")));
186  sources.emplace_back(
187  std::in_place_type<FitsKeywordsSource>, "tcs", kws, std::move(kw_processor));
188  auto expected_kws = fits::ReadKeywords(m_target.GetFitsFile(), 1);
189  expected_kws.push_back(kw1);
190 
191  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).Times(0);
192  EXPECT_CALL(m_mock_sorter, SortKeywords(_)).Times(0);
193 
194  // Test
195  EXPECT_THROW(Merge(m_ops, m_params, m_target, sources, m_dry_run), std::runtime_error);
196 }
197 
198 } // namespace daq::dpm::merge
daq::dpm::merge::Operations
Definition: merge.hpp:88
daq::fits::MemoryFitsFile
In-memory FITS file.
Definition: cfitsio.hpp:37
daq::dpm::merge::MockFormatter::MOCK_METHOD
MOCK_METHOD(fits::LiteralKeyword, FormatKeyword,(fits::KeywordVariant const &keyword),())
daq::fits::KeywordVariant
std::variant< ValueKeyword, EsoKeyword, LiteralKeyword > KeywordVariant
The different variants of keywords that are supported.
Definition: keyword.hpp:400
daq::dpm::merge::Params::origfile
std::string origfile
Definition: merge.hpp:102
daq::dpm::KeywordRuleProcessor::DefaultRule
DefaultRule
Definition: keywordRule.hpp:20
daq::fits::ReadKeywords
std::vector< LiteralKeyword > ReadKeywords(fitsfile *ptr, int hdu_num)
Read keywords from HDU identifed by absolute position hdu_num.
Definition: cfitsio.cpp:181
daq::dpm::KeywordRuleProcessor::Process
virtual fits::KeywordVector Process(fits::KeywordVector const &, DefaultRule default_rule) const =0
daq::dpm::merge::MockSorter
Definition: testMerge.cpp:27
daq::dpm::merge::TestMergeKeywords::m_params
Params m_params
Definition: testMerge.cpp:105
daq::dpm::merge::TestMergeKeywords::m_target_buffer
fits::MemoryFitsFile m_target_buffer
Definition: testMerge.cpp:106
daq::dpm::merge::KeywordSorter::SortKeywords
virtual void SortKeywords(std::vector< fits::LiteralKeyword > &keywords)=0
Sort keywords.
daq::dpm::merge::TestMergeKeywords::m_mock_reporter
MockReporter m_mock_reporter
Definition: testMerge.cpp:98
daq::dpm::merge::MockKeywordProcessor::MOCK_METHOD
MOCK_METHOD(fits::KeywordVector, Process,(fits::KeywordVector const &, KeywordRuleProcessor::DefaultRule),(const, override))
daq::dpm::merge::StatusReporter
Interface to reporter (implementations exist for JSON or human readable)
Definition: merge.hpp:26
daq::dpm::merge::TestMergeKeywords::m_logger
log4cplus::Logger m_logger
Definition: testMerge.cpp:102
daq::dpm::merge::TestMergeKeywords::m_dry_run
bool m_dry_run
Definition: testMerge.cpp:97
daq::fits::Format
LiteralKeyword Format(KeywordVariant const &keyword)
Definition: keyword.cpp:622
daq::dpm::merge::Merge
void Merge(Operations ops, Params const &params, TargetSource &target, std::vector< SourceTypes > const &sources, bool dry_run)
Merge sources into the target target.
Definition: merge.cpp:286
daq::dpm::merge::TestMergeKeywords::ExpectStandardKeywords
void ExpectStandardKeywords(std::vector< fits::LiteralKeyword > &kws)
Definition: testMerge.cpp:78
daq::dpm::merge::Params
Definition: merge.hpp:100
daq::dpm::merge::TestMergeKeywords::m_target
TargetSource m_target
Definition: testMerge.cpp:108
daq::dpm::merge::TestMergeKeywords::TearDown
void TearDown() override
Definition: testMerge.cpp:76
daq::dpm::merge::KeywordSorter
Definition: merge.hpp:44
daq::dpm::merge::TestMergeKeywords::SetUp
void SetUp() override
Definition: testMerge.cpp:63
daq::dpm::merge::TargetSource
Target FITS file.
Definition: sources.hpp:111
daq::dpm::merge::MockKeywordProcessor
Definition: testMerge.cpp:31
daq::dpm::merge
Definition: entrypoint.cpp:26
daq::dpm::merge::TestMergeKeywords::m_ops
Operations m_ops
Definition: testMerge.cpp:104
daq::dpm::merge::MockReporter::MOCK_METHOD
MOCK_METHOD(void, PostAlert,(std::string const &id, std::string const &message),(override))
cfitsio.hpp
Contains functions and data structures related to cfitsio.
daq::dpm::merge::TestMergeKeywords::TestMergeKeywords
TestMergeKeywords()
Definition: testMerge.cpp:47
daq::fits::KeywordVector
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
Definition: keyword.hpp:414
daq::dpm::merge::TestMergeKeywords::m_mock_sorter
MockSorter m_mock_sorter
Definition: testMerge.cpp:100
daq::fits::InitPrimaryHduNoImage
void InitPrimaryHduNoImage(fitsfile *ptr)
Initializes an empty FITS file with a primary HDU.
Definition: cfitsio.cpp:125
daq::dpm::merge::TestMergeKeywords
Fixture that sets up a in-place target FITS file with standard HDU keywords.
Definition: testMerge.cpp:45
daq::dpm::merge::StatusReporter::PostAlert
virtual void PostAlert(std::string const &id, std::string const &message)=0
Post event.
merge.hpp
daq::dpm::merge::MockSorter::MOCK_METHOD
MOCK_METHOD(void, SortKeywords,(std::vector< fits::LiteralKeyword > &keywords),())
daq::dpm::merge::TEST_F
TEST_F(TestMergeKeywords, MergeEmptyStillSortsKeywords)
Definition: testMerge.cpp:111
daq::dpm::KeywordRuleProcessor
Interface for keyword rule processors.
Definition: keywordRule.hpp:18
daq::dpm::merge::KeywordFormatter
Definition: merge.hpp:34
daq::dpm::merge::Params::arcfile
std::string arcfile
Definition: merge.hpp:101
daq::fits::LiteralKeyword
Represents the literal 80-character FITS keyword record.
Definition: keyword.hpp:125
daq::dpm::merge::TestMergeKeywords::m_mock_formatter
MockFormatter m_mock_formatter
Definition: testMerge.cpp:99
daq::dpm::merge::MockReporter
Definition: testMerge.cpp:19
daq::dpm::merge::MockFormatter
Definition: testMerge.cpp:23
daq::dpm::merge::KeywordFormatter::FormatKeyword
virtual fits::LiteralKeyword FormatKeyword(fits::KeywordVariant const &keyword)=0
Format keyword.