ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
testJson.cpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup daq_ocm_fits_test
4 * @copyright 2022 ESO - European Southern Observatory
5 *
6 * @brief Unit tests for json handling.
7 */
8
9#include <gtest/gtest.h>
10#include <gmock/gmock.h>
11
12#include <nlohmann/json.hpp>
13#include <ostream>
14
15#include <daq/fits/json.hpp>
16
17using namespace daq::fits;
18
19class TestJson : public ::testing::Test {
20public:
21};
22
23TEST_F(TestJson, ParseInvalidJsonThrowsNlohmannException) {
24 // Setup
25 auto trailing_comma = R"(
26 [
27 {
28 "type": "valueKeyword",
29 "name": "STRKW",
30 "value": "VALUE STRING"
31 },
32 ]
33 )";
34
35 // Test
36 EXPECT_THROW(ParseJsonKeywords(trailing_comma), nlohmann::json::exception);
37}
38
39TEST_F(TestJson, ParseValueKeywords) {
40 // Setup
41 auto keywords_str = R"(
42 [
43 {
44 "type": "valueKeyword",
45 "name": "STRKW",
46 "value": "VALUE STRING"
47 },
48 {
49 "type": "valueKeyword",
50 "name": "BOOLKW",
51 "value": true
52 },
53 {
54 "type": "valueKeyword",
55 "name": "INTMIN",
56 "value": -9223372036854775807
57 },
58 {
59 "type": "valueKeyword",
60 "name": "INTMAX",
61 "value": 9223372036854775807
62 },
63 {
64 "type": "valueKeyword",
65 "name": "UINTMAX",
66 "value": 18446744073709551615
67 },
68 {
69 "type": "valueKeyword",
70 "name": "FLOATMIN",
71 "value": -1.79769313486231e+308
72 },
73 {
74 "type": "valueKeyword",
75 "name": "FLOATMAX",
76 "value": 1.79769313486231e+308
77 }
78 ]
79 )";
80
81 // Test
82 std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
83 ASSERT_EQ(7u, parsed.size());
84 for (auto const& kw_var : parsed) {
85 ASSERT_TRUE(std::holds_alternative<ValueKeyword>(kw_var));
86 }
87
88 {
89 ValueKeyword kw = std::get<ValueKeyword>(parsed[0]);
90 EXPECT_EQ(ValueKeyword("STRKW", std::string("VALUE STRING"), std::nullopt), kw);
91 }
92 {
93 ValueKeyword kw = std::get<ValueKeyword>(parsed[1]);
94 EXPECT_EQ(ValueKeyword("BOOLKW", true, std::nullopt), kw);
95 }
96 {
97 ValueKeyword kw = std::get<ValueKeyword>(parsed[2]);
98 EXPECT_EQ(ValueKeyword("INTMIN", int64_t(-9223372036854775807), std::nullopt), kw);
99 }
100 {
101 ValueKeyword kw = std::get<ValueKeyword>(parsed[3]);
102 EXPECT_EQ(ValueKeyword("INTMAX", uint64_t(9223372036854775807), std::nullopt), kw);
103 }
104 {
105 ValueKeyword kw = std::get<ValueKeyword>(parsed[4]);
106 EXPECT_EQ(ValueKeyword("UINTMAX", 18446744073709551615u, std::nullopt), kw);
107 }
108 {
109 ValueKeyword kw = std::get<ValueKeyword>(parsed[5]);
110 EXPECT_EQ(ValueKeyword("FLOATMIN", -1.79769313486231e+308, std::nullopt), kw);
111 }
112 {
113 ValueKeyword kw = std::get<ValueKeyword>(parsed[6]);
114 EXPECT_EQ(ValueKeyword("FLOATMAX", 1.79769313486231e+308, std::nullopt), kw);
115 }
116}
117
118TEST_F(TestJson, ParseEsoKeywords) {
119 // Setup
120 auto keywords_str = R"(
121 [
122 {
123 "type": "esoKeyword",
124 "name": "STRKW",
125 "value": "VALUE STRING"
126 },
127 {
128 "type": "esoKeyword",
129 "name": "BOOLKW",
130 "value": true
131 },
132 {
133 "type": "esoKeyword",
134 "name": "INTMIN",
135 "value": -9223372036854775807
136 },
137 {
138 "type": "esoKeyword",
139 "name": "INTMAX",
140 "value": 9223372036854775807
141 },
142 {
143 "type": "esoKeyword",
144 "name": "UINTMAX",
145 "value": 18446744073709551615
146 },
147 {
148 "type": "esoKeyword",
149 "name": "FLOATMIN",
150 "value": -1.79769313486231e+308
151 },
152 {
153 "type": "esoKeyword",
154 "name": "FLOATMAX",
155 "value": 1.79769313486231e+308
156 },
157 {
158 "type": "esoKeyword",
159 "name": "KW WITH SPACE",
160 "value": "spaces"
161 }
162 ]
163 )";
164
165 // Test
166 std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
167 ASSERT_EQ(8u, parsed.size());
168 for (auto const& kw_var : parsed) {
169 ASSERT_TRUE(std::holds_alternative<EsoKeyword>(kw_var));
170 }
171
172 {
173 EsoKeyword kw = std::get<EsoKeyword>(parsed[0]);
174 EXPECT_EQ(EsoKeyword("STRKW", std::string("VALUE STRING"), std::nullopt), kw);
175 }
176 {
177 EsoKeyword kw = std::get<EsoKeyword>(parsed[1]);
178 EXPECT_EQ(EsoKeyword("BOOLKW", true, std::nullopt), kw);
179 }
180 {
181 EsoKeyword kw = std::get<EsoKeyword>(parsed[2]);
182 EXPECT_EQ(EsoKeyword("INTMIN", int64_t(-9223372036854775807), std::nullopt), kw);
183 }
184 {
185 EsoKeyword kw = std::get<EsoKeyword>(parsed[3]);
186 EXPECT_EQ(EsoKeyword("INTMAX", uint64_t(9223372036854775807), std::nullopt), kw);
187 }
188 {
189 EsoKeyword kw = std::get<EsoKeyword>(parsed[4]);
190 EXPECT_EQ(EsoKeyword("UINTMAX", 18446744073709551615u, std::nullopt), kw);
191 }
192 {
193 EsoKeyword kw = std::get<EsoKeyword>(parsed[5]);
194 EXPECT_EQ(EsoKeyword("FLOATMIN", -1.79769313486231e+308, std::nullopt), kw);
195 }
196 {
197 EsoKeyword kw = std::get<EsoKeyword>(parsed[6]);
198 EXPECT_EQ(EsoKeyword("FLOATMAX", 1.79769313486231e+308, std::nullopt), kw);
199 }
200 {
201 EsoKeyword kw = std::get<EsoKeyword>(parsed[7]);
202 EXPECT_EQ(EsoKeyword("KW WITH SPACE", "spaces", std::nullopt), kw);
203 }
204}
205
206TEST_F(TestJson, ParseLiteralKeyword) {
207 // Setup
208 auto keywords_str = R"(
209 [
210 {
211 "type": "literalKeyword",
212 "value": "SIMPLE = T / Standard FITS"
213 },
214 {
215 "type": "literalKeyword",
216 "value": "OBJECT = 'target.cat' / Original target."
217 },
218 {
219 "type": "literalKeyword",
220 "value": "HIERARCH ESO KW = T / Comment"
221 }
222 ]
223 )";
224
225 // Test
226 std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
227 ASSERT_EQ(3u, parsed.size());
228 for (auto const& kw_var : parsed) {
229 ASSERT_TRUE(std::holds_alternative<LiteralKeyword>(kw_var));
230 }
231
232 {
233 LiteralKeyword kw = std::get<LiteralKeyword>(parsed[0]);
234 EXPECT_EQ(LiteralKeyword("SIMPLE = T / Standard FITS"), kw);
235 }
236 {
237 LiteralKeyword kw = std::get<LiteralKeyword>(parsed[1]);
238 EXPECT_EQ(LiteralKeyword("OBJECT = 'target.cat' / Original target."), kw);
239 EXPECT_EQ("OBJECT = 'target.cat' / Original target.", kw.GetRecord());
240 }
241 {
242 LiteralKeyword kw = std::get<LiteralKeyword>(parsed[2]);
243 EXPECT_EQ(LiteralKeyword("HIERARCH ESO KW = T / Comment"), kw);
244 }
245}
246
247TEST_F(TestJson, ParseOptionalKeywordComment) {
248 // Setup
249 auto keywords_str = R"(
250 [
251 {
252 "type": "valueKeyword",
253 "name": "STRKW1",
254 "value": "VALUE STRING",
255 "comment": "this is a comment"
256 },
257 {
258 "type": "esoKeyword",
259 "name": "STRKW2",
260 "value": "VALUE STRING",
261 "comment": "this is also a comment"
262 }
263 ]
264 )";
265
266 // Test
267 std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
268 ASSERT_EQ(2u, parsed.size());
269 ASSERT_TRUE(std::holds_alternative<ValueKeyword>(parsed[0]));
270 ASSERT_TRUE(std::holds_alternative<EsoKeyword>(parsed[1]));
271
272 {
273 ValueKeyword kw = std::get<ValueKeyword>(parsed[0]);
274 EXPECT_EQ(ValueKeyword("STRKW1", std::string("VALUE STRING"), "this is a comment"), kw);
275 }
276 {
277 EsoKeyword kw = std::get<EsoKeyword>(parsed[1]);
278 EXPECT_EQ(EsoKeyword("STRKW2", std::string("VALUE STRING"), "this is also a comment"), kw);
279 }
280}
281
282TEST_F(TestJson, ParseEmptyArray) {
283 // Setup
284 auto keywords_str = R"(
285 []
286 )";
287 auto res = ParseJsonKeywords(keywords_str);
288 EXPECT_EQ(0u, res.size());
289}
290
291TEST_F(TestJson, ParseFailsIfNotAnArray) {
292 // Setup
293 auto keywords_str = R"(
294 {
295 "type": "valueKeyword",
296 "name": "FLOATMAX",
297 "value": 1.79769313486231e+308
298 }
299 )";
300 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
301}
302
303TEST_F(TestJson, ParseFailsIfNotAnObjectInArray) {
304 // Setup
305 auto keywords_str = R"(
306 [
307 1,
308 [],
309 "",
310 null
311 ]
312 )";
313 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
314}
315
316TEST_F(TestJson, ParseFailsIfObjectMissTypeProperty) {
317 // Setup
318 auto keywords_str = R"(
319 [
320 {
321 "name": "FLOATMAX",
322 "value": "value"
323 }
324 ]
325 )";
326 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
327}
328
329TEST_F(TestJson, ParseFailsIfObjectHasUnknownTypeProperty) {
330 // Setup
331 auto keywords_str = R"(
332 [
333 {
334 "type": "unknown",
335 "name": "FLOATMAX",
336 "value": 1.79769313486231e+308
337 }
338 ]
339 )";
340 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
341}
342
343TEST_F(TestJson, ParseFailsIfTypeIsNotString) {
344 // Setup
345 auto keywords_str = R"(
346 [
347 {
348 "type": true,
349 "name": "FLOATMAX",
350 "value": 1.79769313486231e+308
351 }
352 ]
353 )";
354 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
355}
356
357TEST_F(TestJson, ParseFailsIfObjectMissNameProperty) {
358 // Setup
359 auto keywords_str = R"(
360 [
361 {
362 "type": "valueKeyword",
363 "value": 1.79769313486231e+308
364 }
365 ]
366 )";
367 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
368}
369
370TEST_F(TestJson, ParseFailsIfObjectMissValue) {
371 // Setup
372 auto keywords_str = R"(
373 [
374 {
375 "type": "valueKeyword",
376 "name": "FLOATMAX"
377 }
378 ]
379 )";
380 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
381}
382
383TEST_F(TestJson, ParseFailsIfLiteralKeywordMissValue) {
384 // Setup
385 auto keywords_str = R"(
386 [
387 {
388 "type": "literalKeyword"
389 }
390 ]
391 )";
392 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
393}
394
395TEST_F(TestJson, ParseFailsIfLiteralKeywordValueIsNotString) {
396 // Setup
397 auto keywords_str = R"(
398 [
399 {
400 "type": "literalKeyword",
401 "value": null
402 }
403 ]
404 )";
405 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
406}
407
408TEST_F(TestJson, ParseFailsIfLiteralKeywordValueTooLong) {
409 // Setup
410 auto keywords_str = R"(
411 [
412 {
413 "type": "literalKeyword",
414 "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0"
415 }
416 ]
417 )";
418 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
419}
420
421TEST_F(TestJson, ParseFailsIfObjectHasUnsupportedValueType) {
422 // Setup
423 auto keywords_str = R"(
424 [
425 {
426 "type": "valueKeyword",
427 "name": "NAME",
428 "value": {"foo": true}
429 }
430 ]
431 )";
432 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
433}
434
435TEST_F(TestJson, ParseFailsIfNameIsNotString) {
436 // Setup
437 auto keywords_str = R"(
438 [
439 {
440 "type": "valueKeyword",
441 "name": 1.0,
442 "value": "value"
443 }
444 ]
445 )";
446 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
447}
448
449TEST_F(TestJson, ParseFailsIfObjectHasCommentThatIsNotString) {
450 // Setup
451 auto keywords_str = R"(
452 [
453 {
454 "type": "valueKeyword",
455 "name": "NAME",
456 "value": "value",
457 "comment": 1.0
458 }
459 ]
460 )";
461 EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
462}
463
465 KeywordVector kws;
466 kws.push_back(ValueKeyword("NAME", "VALUE", "COMMENT"));
467 kws.push_back(ValueKeyword("NAME2", 1.0, "COMMENT"));
468 kws.push_back(ValueKeyword("NAME3", false));
469 kws.push_back(EsoKeyword("FOO BAR", -1234l, "COMMENT"));
470 kws.push_back(EsoKeyword("FOO BAR BAZ", 1234lu, "COMMENT"));
471 kws.push_back(LiteralKeyword("HIERARCH ESO KW = T / Comment"));
472
473 auto json = SerializeJsonKeywords(kws);
474 auto parsed_kws = ParseJsonKeywords(json);
475
476 EXPECT_THAT(parsed_kws, ::testing::ContainerEq(kws));
477}
Represents the literal 80-character FITS keyword record.
Definition: keyword.hpp:129
std::string_view GetRecord() const &noexcept
Definition: keyword.cpp:532
Contains data structure for FITS keywords.
TEST_F(TestJson, ParseInvalidJsonThrowsNlohmannException)
Definition: testJson.cpp:23
nlohmann::json SerializeJsonKeywords(std::vector< KeywordVariant > const &keywords)
SerializeJsons keyword to JSON.
Definition: json.cpp:200
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
Definition: keyword.hpp:423
std::vector< KeywordVariant > ParseJsonKeywords(char const *keywords)
Parse and return FITS keywords.
Definition: json.cpp:124
BasicKeyword< ValueKeywordTraits > ValueKeyword
Standard FITS value keyword.
Definition: keyword.hpp:339
BasicKeyword< EsoKeywordTraits > EsoKeyword
ESO hiearchical keyword.
Definition: keyword.hpp:346
A type safe version of LiteralKeyword that consist of the three basic components of a FITS keyword ke...
Definition: keyword.hpp:275
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_EQ(meta.keyword_rules.size(), 1u)
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))