ifw-daq  3.0.0-pre2
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::nullopt,
60  std::make_unique<StandardKeywordRuleProcessor>(),
61  std::move(m_target_buffer).GetOwnedFile()) {
62  }
63 
64  void SetUp() override {
66 
67  // clang-format off
68  ON_CALL(m_mock_formatter, FormatKeyword(_))
69  .WillByDefault(
70  Invoke([](auto const& kw) {
71  return fits::Format(kw);
72  }
73  )
74  );
75  // clang-format on
76  }
77  void TearDown() override {
78  }
79  void ExpectStandardKeywords(std::vector<fits::LiteralKeyword>& kws) {
80  auto datasum = kws.back();
81  kws.pop_back();
82  auto checksum = kws.back();
83  kws.pop_back();
84  EXPECT_EQ("DATASUM", datasum.GetName().name);
85  EXPECT_EQ("CHECKSUM", checksum.GetName().name);
86 
87  auto arcfile = kws.back();
88  kws.pop_back();
89  auto origfile = kws.back();
90  kws.pop_back();
91 
92  EXPECT_EQ("ORIGFILE", origfile.GetName().name);
93  EXPECT_EQ(fmt::format("'{}'", m_params.origfile), origfile.GetComponents().value);
94  EXPECT_EQ("ARCFILE", arcfile.GetName().name);
95  EXPECT_EQ(fmt::format("'{}'", m_params.arcfile), arcfile.GetComponents().value);
96  }
97 
98  bool m_dry_run;
102 
103  log4cplus::Logger m_logger;
104 
108 
110 };
111 
112 TEST_F(TestMergeKeywords, MergeEmptyStillSortsKeywords) {
113  // Setup
114  std::vector<SourceTypes> sources;
115 
116  auto before = fits::ReadKeywords(m_target.GetFitsFile(), 1);
117  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
118  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
119 
120  // Test
121  Merge(m_ops, m_params, m_target, sources, m_dry_run);
122  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
123  ASSERT_EQ(after.size(), before.size() + 4u)
124  << "4 keywords should be added by DPM (2x checksum, ARCFILE, ORIFILE)";
125  ExpectStandardKeywords(after);
126  EXPECT_THAT(after, ContainerEq(before));
127 }
128 
129 /** Test that primary HDU keywords are sorted */
130 TEST_F(TestMergeKeywords, NoSourceStillSortsPrimaryHdu) {
131  // Setup
132  std::vector<SourceTypes> sources;
133  auto before = fits::ReadKeywords(m_target.GetFitsFile(), 1);
134 
135  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
136  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
137 
138  // Test
139  Merge(m_ops, m_params, m_target, sources, m_dry_run);
140  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
141  ASSERT_EQ(after.size(), before.size() + 4u)
142  << "4 keywords should be added by DPM (2x checksum, ARCFILE, ORIFILE)";
143  ExpectStandardKeywords(after);
144 
145  EXPECT_THAT(after, ContainerEq(before));
146 }
147 
148 /** Test merging some keywords from a single source */
149 TEST_F(TestMergeKeywords, MergeSingleKeywordList) {
150  // Setup
151  std::vector<SourceTypes> sources;
152  auto kw1 = fits::LiteralKeyword("HIERARCH ESO UNKN A = T / Comment");
153  auto kw2 = fits::LiteralKeyword("HIERARCH ESO UNKN B = T / Comment");
154  fits::KeywordVector kws = {kw1, kw2};
155 
156  sources.emplace_back(std::in_place_type<FitsKeywordsSource>,
157  "tcs",
158  kws,
159  std::nullopt,
160  std::make_unique<StandardKeywordRuleProcessor>());
161  auto expected_kws = fits::ReadKeywords(m_target.GetFitsFile(), 1);
162  expected_kws.push_back(kw1);
163  expected_kws.push_back(kw2);
164 
165  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).WillRepeatedly(DoDefault());
166  EXPECT_CALL(m_mock_sorter, SortKeywords(_));
167 
168  // Test
169  Merge(m_ops, m_params, m_target, sources, m_dry_run);
170 
171  auto after = fits::ReadKeywords(m_target.GetFitsFile(), 1);
172  // Two checksum keywords are added
173  ASSERT_EQ(after.size(), expected_kws.size() + 4u);
174  ExpectStandardKeywords(after);
175 
176  EXPECT_THAT(after, ContainerEq(expected_kws));
177 }
178 
179 TEST_F(TestMergeKeywords, MergeFailsIfTransformsCauseInvalidKeyword) {
180  // Setup
181  std::vector<SourceTypes> sources;
182  auto kw1 = fits::LiteralKeyword("HIERARCH ESO UNKN A = T / Comment");
183  fits::KeywordVector kws = {kw1};
184 
185  auto kw_processor = std::make_unique<MockKeywordProcessor>();
186  EXPECT_CALL(*kw_processor, Process(_, _))
187  .WillRepeatedly(Throw(std::invalid_argument("keyword too long")));
188  sources.emplace_back(
189  std::in_place_type<FitsKeywordsSource>, "tcs", kws, std::nullopt, std::move(kw_processor));
190  auto expected_kws = fits::ReadKeywords(m_target.GetFitsFile(), 1);
191  expected_kws.push_back(kw1);
192 
193  EXPECT_CALL(m_mock_formatter, FormatKeyword(_)).Times(0);
194  EXPECT_CALL(m_mock_sorter, SortKeywords(_)).Times(0);
195 
196  // Test
197  EXPECT_THROW(Merge(m_ops, m_params, m_target, sources, m_dry_run), std::runtime_error);
198 }
199 
200 } // namespace daq::dpm::merge
Contains functions and data structures related to cfitsio.
Interface for keyword rule processors.
Definition: keywordRule.hpp:18
virtual fits::KeywordVector Process(fits::KeywordVector const &, DefaultRule default_rule) const =0
virtual fits::LiteralKeyword FormatKeyword(fits::KeywordVariant const &keyword)=0
Format keyword.
virtual void SortKeywords(std::vector< fits::LiteralKeyword > &keywords)=0
Sort keywords.
Interface to reporter (implementations exist for JSON or human readable)
Definition: merge.hpp:26
virtual void PostAlert(std::string const &id, std::string const &message)=0
Post event.
Fixture that sets up a in-place target FITS file with standard HDU keywords.
Definition: testMerge.cpp:45
void ExpectStandardKeywords(std::vector< fits::LiteralKeyword > &kws)
Definition: testMerge.cpp:79
fits::MemoryFitsFile m_target_buffer
Definition: testMerge.cpp:107
Represents the literal 80-character FITS keyword record.
Definition: keyword.hpp:125
In-memory FITS file.
Definition: cfitsio.hpp:38
std::string arcfile
Definition: merge.hpp:101
std::string origfile
Definition: merge.hpp:102
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
TEST_F(TestMergeKeywords, MergeEmptyStillSortsKeywords)
Definition: testMerge.cpp:112
LiteralKeyword Format(KeywordVariant const &keyword)
Definition: keyword.cpp:626
void InitPrimaryHduNoImage(fitsfile *ptr)
Initializes an empty FITS file with a primary HDU.
Definition: cfitsio.cpp:125
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
Definition: keyword.hpp:414
std::variant< ValueKeyword, EsoKeyword, LiteralKeyword > KeywordVariant
The different variants of keywords that are supported.
Definition: keyword.hpp:400
std::vector< LiteralKeyword > ReadKeywords(fitsfile *ptr, int hdu_num)
Read keywords from HDU identifed by absolute position hdu_num.
Definition: cfitsio.cpp:181
MOCK_METHOD(fits::LiteralKeyword, FormatKeyword,(fits::KeywordVariant const &keyword),())
MOCK_METHOD(fits::KeywordVector, Process,(fits::KeywordVector const &, KeywordRuleProcessor::DefaultRule),(const, override))
MOCK_METHOD(void, PostAlert,(std::string const &id, std::string const &message),(override))
MOCK_METHOD(void, SortKeywords,(std::vector< fits::LiteralKeyword > &keywords),())
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_EQ(meta.keyword_rules.size(), 1u)