ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
testDpSpec.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_dpm_libmerge
4 * @copyright ESO - European Southern Observatory
5 */
7#include <daq/json/dpSpec.hpp>
8
9#include <gmock/gmock.h>
10#include <gtest/gtest.h>
11
12#include <daq/test/expect.hpp>
13
14using namespace testing;
15
16namespace daq::json {
17
18class TestParseLocation : public ::testing::Test {};
19
20TEST_F(TestParseLocation, ParseSucceeds) {
21 {
22 Location o = ParseSourceLocation("user@foo");
23 EXPECT_EQ(o.host, "");
24 EXPECT_EQ(o.path, "foo");
25 }
26 {
28 EXPECT_EQ(o.host, "");
29 EXPECT_EQ(o.path, "foo");
30 }
31 {
32 Location o = ParseSourceLocation("host:~/files/file.fits");
33 EXPECT_EQ(o.host, "host");
34 EXPECT_EQ(o.path, "~/files/file.fits");
35 }
36 {
37 Location o = ParseSourceLocation("host:/path/to/file:with:colons.fits");
38 EXPECT_EQ(o.host, "host");
39 EXPECT_EQ(o.path, "/path/to/file:with:colons.fits");
40 }
41 {
42 Location o = ParseSourceLocation("user@host:/path/to/file:with:colons.fits");
43 EXPECT_EQ(o.host, "host");
44 EXPECT_EQ(o.path, "/path/to/file:with:colons.fits");
45 }
46}
47
49 EXPECT_THROW(ParseSourceLocation("user@"), std::invalid_argument);
50 EXPECT_THROW(ParseSourceLocation("@"), std::invalid_argument);
51 EXPECT_THROW(ParseSourceLocation(":"), std::invalid_argument);
52 EXPECT_THROW(ParseSourceLocation("user@:"), std::invalid_argument);
53}
54
55class TestParseDpSpec : public ::testing::Test {
56public:
57 void SetUp() {
58 using namespace nlohmann;
59 m_spec = R"(
60 {
61 "id": "TEST.ID",
62 "target": {
63 "fileId": "TEST.FILEID",
64 "source": {
65 "sourceName": "dcs",
66 "location": "dcs-host:/path/to/somefile.fits",
67 "keywordRules": [
68 {
69 "type": "transform",
70 "selectionPatterns": [
71 "+e INS *"
72 ],
73 "regex": "^INS ",
74 "format": "INS2 "
75 },
76 {
77 "type": "filter",
78 "selectionPatterns": [
79 "+e INS2 *",
80 "+v VALUEKW"
81 ]
82 }
83 ]
84 }
85 },
86 "sources": [
87 {
88 "type": "fitsKeywords",
89 "sourceName": "ocm",
90 "keywordRules": [
91 {
92 "type": "filter",
93 "selectionPatterns": [
94 "+e *",
95 "+v *"
96 ]
97 }
98 ],
99 "keywords": [
100 {
101 "type": "valueKeyword",
102 "name": "ORIGIN",
103 "value": "ESO-PARANAL"
104 },
105 {
106 "type": "valueKeyword",
107 "name": "TELESCOP",
108 "value": "ESO-ELT"
109 },
110 {
111 "type": "valueKeyword",
112 "name": "OBJECT",
113 "value": "OBJECT,SKY"
114 },
115 {
116 "type": "esoKeyword",
117 "name": "OCS TEMPL ID",
118 "value": "template-id"
119 },
120 {
121 "type": "literalKeyword",
122 "value": "COMMENT Example of a commentary keyword."
123 }
124 ]
125 },
126 {
127 "type": "fitsKeywords",
128 "sourceName": "tcs",
129 "keywordRules": [
130 ],
131 "keywords": [
132 {
133 "type": "esoKeyword",
134 "name": "TEL AIRM START",
135 "value": 1.072
136 },
137 {
138 "type": "esoKeyword",
139 "name": "TEL AIRM END",
140 "value": 1.08
141 }
142 ]
143 },
144 {
145 "type": "fitsFile",
146 "sourceName": "fcs",
147 "location": "fcs-host:/path/to/somefile.fits",
148 "alertUnmergeable": false,
149 "keywordRules": [
150 {
151 "type": "filter",
152 "selectionPatterns": [
153 "+e INS *",
154 "-e INS TEMP[12] *",
155 "+v VALUEKW"
156 ]
157 },
158 {
159 "type": "transform",
160 "selectionPatterns": [
161 "+e INS *"
162 ],
163 "regex": "^INS ",
164 "format": "INS2 "
165 }
166 ]
167 }
168 ],
169 "receivers": [
170 {
171 "type": "olasReceiver",
172 "host": "1.2.3.4",
173 "path": "/absolute/path"
174 }
175 ]
176 }
177 )"_json;
178 }
179
180 nlohmann::json m_spec;
181};
182
183TEST_F(TestParseDpSpec, ParseSucceeds) {
184 DpSpec spec = ParseDpSpec(m_spec);
185 EXPECT_EQ(spec.id, "TEST.ID");
186 EXPECT_EQ(spec.target.file_id, "TEST.FILEID");
187
188 ASSERT_TRUE(spec.target.source.has_value());
189 EXPECT_EQ(spec.target.source->source_name, "dcs");
190
191 ASSERT_EQ(spec.target.source->keyword_rules.size(), 2u);
192 auto const& transform = std::get<KeywordTransform>(spec.target.source->keyword_rules.at(0));
193 ASSERT_EQ(transform.selection_patterns.size(), 1);
194 EXPECT_EQ(transform.selection_patterns[0], "+e INS *");
195 EXPECT_EQ(transform.format, "INS2 ");
196 auto const& filter = std::get<KeywordFilter>(spec.target.source->keyword_rules.at(1));
197 EXPECT_THAT(filter.selection_patterns, ElementsAre("+e INS2 *", "+v VALUEKW"));
198
199 ASSERT_EQ(3u, spec.sources.size());
200 auto const& ocm_kws_var = spec.sources[0];
201 ASSERT_TRUE(std::holds_alternative<FitsKeywordsSource>(ocm_kws_var));
202 auto const& tcs_kws_var = spec.sources[1];
203 ASSERT_TRUE(std::holds_alternative<FitsKeywordsSource>(tcs_kws_var));
204 auto const& fcs_fits_var = spec.sources[2];
205 ASSERT_TRUE(std::holds_alternative<FitsFileSource>(fcs_fits_var));
206 auto const& ocm_kws = std::get<FitsKeywordsSource>(spec.sources[0]);
207 auto const& tcs_kws = std::get<FitsKeywordsSource>(spec.sources[1]);
208 auto const& fcs_fits = std::get<FitsFileSource>(spec.sources[2]);
209
210 {
211 EXPECT_EQ(ocm_kws.source_name, "ocm");
212 ASSERT_EQ(ocm_kws.keyword_rules.size(), 1);
213 auto const& filter = std::get<KeywordFilter>(ocm_kws.keyword_rules.at(0));
214 ASSERT_EQ(filter.selection_patterns.size(), 2);
215 EXPECT_THAT(filter.selection_patterns, ElementsAre("+e *", "+v *"));
216 }
217
218 EXPECT_EQ(tcs_kws.source_name, "tcs");
219 EXPECT_EQ(fcs_fits.source_name, "fcs");
220 EXPECT_EQ(fcs_fits.alert_unmergeable, false);
221
222 {
223 // check receiver list
224 ASSERT_EQ(1u, spec.receivers.size());
225 auto const& olas_variant = spec.receivers[0];
226 ASSERT_TRUE(std::holds_alternative<OlasReceiver>(olas_variant));
227 auto const& olas_receiver = std::get<OlasReceiver>(olas_variant);
228 EXPECT_EQ(olas_receiver.host, "1.2.3.4");
229 EXPECT_EQ(olas_receiver.path, "/absolute/path/");
230 }
231}
232
233TEST_F(TestParseDpSpec, ParseSucceedsWithOptionalTarget) {
234 m_spec["target"].erase("targetSource");
235 EXPECT_NO_THROW(ParseDpSpec(m_spec));
236}
237
238TEST_F(TestParseDpSpec, ParseSucceedsWithOptionalSources) {
239 m_spec.erase("sources");
240 EXPECT_NO_THROW(ParseDpSpec(m_spec));
241}
242
243TEST_F(TestParseDpSpec, ParseSucceedsWithOptionalSourcesEmpty) {
244 m_spec["sources"] = nlohmann::json::array();
245 EXPECT_NO_THROW(ParseDpSpec(m_spec));
246}
247
248TEST_F(TestParseDpSpec, ParseSucceedsWithOptionalReceivers) {
249 m_spec.erase("receivers");
250 EXPECT_NO_THROW(ParseDpSpec(m_spec));
251}
252
253TEST_F(TestParseDpSpec, ParseSucceedsWithOptionalReceiversEmpty) {
254 m_spec["receivers"] = nlohmann::json::array();
255 EXPECT_NO_THROW(ParseDpSpec(m_spec));
256}
257
258TEST_F(TestParseDpSpec, ParseFailsWithMissingId) {
259 m_spec.erase("id");
261 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/id\).*missing.*)"));
262}
263
264TEST_F(TestParseDpSpec, ParseFailsWithMissingFileId) {
265 m_spec["target"].erase("fileId");
267 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/target/fileId\).*missing.*)"));
268}
269
270TEST_F(TestParseDpSpec, ParseFailsWithFileIdWrongType) {
271 m_spec["target"]["fileId"] = 0u;
274 MatchesRegex(R"(.*\‍(/target/fileId\).*must be a string.*)"));
275}
276
277TEST_F(TestParseDpSpec, ParseFailsWithKeywordsBadType) {
278 m_spec["sources"][0]["keywords"][0]["type"] = "";
281 MatchesRegex(R"(.*\‍(/sources/0/keywords/0/type\).*empty.*)"));
282}
283
284TEST_F(TestParseDpSpec, ParseFailsWithKeywordsNotDefined) {
285 m_spec["sources"][0].erase("keywords");
287 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/sources/0/keywords\).*missing.*)"));
288}
289TEST_F(TestParseDpSpec, ParseSucceedsWithKeywordRulesNotDefined) {
290 m_spec["sources"][2].erase("keywordRules");
291 EXPECT_NO_THROW(ParseDpSpec(m_spec));
292}
293
294TEST_F(TestParseDpSpec, ParseFailsWithMissingSources) {
295 m_spec["target"].erase("source");
296 m_spec["sources"] = nlohmann::json::array();
297
299 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/sources\).*At least one.*)"));
300}
301
302TEST_F(TestParseDpSpec, ParseFailsWithUnknownSourceType) {
303 m_spec["sources"][0]["type"] = "unknown";
304
306 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/sources/0/type\).*unknown.*)"));
307}
308
309TEST_F(TestParseDpSpec, ParseFailsWithUnknownSourceTypeNotObject) {
310 m_spec["sources"][0] = 0;
311
313 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/sources/0\).*object.*)"));
314}
315
316TEST_F(TestParseDpSpec, ParseFailsWithUnknownSourcesWrongType) {
317 m_spec["sources"] = 0;
318
320 ParseDpSpec(m_spec), DpSpecError, MatchesRegex(R"(.*\‍(/sources\).*array.*)"));
321}
322
323TEST_F(TestParseDpSpec, ParseFailsWithWrongAlertUnmergedType) {
324 m_spec["sources"][2]["alertUnmergeable"] = "true";
325
328 MatchesRegex(R"(.*\‍(/sources/2/alertUnmergeable\).*must be a boolean.*)"));
329}
330
331} // namespace daq::json
#define EXPECT_THROW_WITH_MESSAGE(stmt, etype, matcher)
Expect that stmt throws exception of type etype and that the exception message matches matcher.
Definition: expect.hpp:15
std::string id
DAQ id.
Definition: dpSpec.hpp:45
Location ParseSourceLocation(std::string const &location_str)
Parse location string from DpSpec into component parts.
Definition: dpSpec.cpp:90
DpSpec ParseDpSpec(Json const &json)
Parse JSON to construct the DpSpec structure.
Definition: dpSpec.cpp:47
Target target
Describes target which will become the data produtc.
Definition: dpSpec.hpp:49
TEST_F(TestParseLocation, ParseSucceeds)
Definition: testDpSpec.cpp:20
std::optional< FitsFileSource > source
Definition: dpSpec.hpp:37
nlohmann::json m_spec
ReceiverList receivers
Ordered container of receivers where to deliver the target data product.
Definition: dpSpec.hpp:59
std::vector< SourceTypes > sources
List of sources to create data product from.
Definition: dpSpec.hpp:54
daq::json::TestParseStartDaqV2Spec _json
Close representation of the JSON structure but with stronger types.
Definition: dpSpec.hpp:30
Describes parsed location string into its components "host" and "path".
Definition: dpSpec.hpp:73
std::filesystem::path path
Definition: dpSpec.hpp:79
std::string host
Definition: dpSpec.hpp:78
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
auto const & olas_receiver
ASSERT_EQ(meta.keyword_rules.size(), 1u)
auto const & transform
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))