ifw-daq  1.0.0
IFW Data Acquisition modules
testJson.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @ingroup daq_ocm_fits_test
4  * @copyright 2021 ESO - European Southern Observatory
5  *
6  * @brief Unit tests for json handling.
7  */
8 
9 #include <gtest/gtest.h>
10 #include <nlohmann/json.hpp>
11 #include <ostream>
12 
13 #include <daq/fits/json.hpp>
14 
15 using namespace daq::fits;
16 
17 class TestJson : public ::testing::Test {
18 public:
19 };
20 
21 TEST_F(TestJson, ParseInvalidJsonThrowsNlohmannException) {
22  // Setup
23  auto trailing_comma = R"(
24  [
25  {
26  "type": "valueKeyword",
27  "name": "STRKW",
28  "value": "VALUE STRING"
29  },
30  ]
31  )";
32 
33  // Test
34  EXPECT_THROW(ParseJsonKeywords(trailing_comma), nlohmann::json::exception);
35 }
36 
37 TEST_F(TestJson, ParseValueKeywords) {
38  // Setup
39  auto keywords_str = R"(
40  [
41  {
42  "type": "valueKeyword",
43  "name": "STRKW",
44  "value": "VALUE STRING"
45  },
46  {
47  "type": "valueKeyword",
48  "name": "BOOLKW",
49  "value": true
50  },
51  {
52  "type": "valueKeyword",
53  "name": "INTMIN",
54  "value": -9223372036854775807
55  },
56  {
57  "type": "valueKeyword",
58  "name": "INTMAX",
59  "value": 9223372036854775807
60  },
61  {
62  "type": "valueKeyword",
63  "name": "UINTMAX",
64  "value": 18446744073709551615
65  },
66  {
67  "type": "valueKeyword",
68  "name": "FLOATMIN",
69  "value": -1.79769313486231e+308
70  },
71  {
72  "type": "valueKeyword",
73  "name": "FLOATMAX",
74  "value": 1.79769313486231e+308
75  }
76  ]
77  )";
78 
79  // Test
80  std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
81  ASSERT_EQ(7u, parsed.size());
82  for (auto const& kw_var : parsed) {
83  ASSERT_TRUE(std::holds_alternative<ValueKeyword>(kw_var));
84  }
85 
86  {
87  ValueKeyword kw = std::get<ValueKeyword>(parsed[0]);
88  EXPECT_EQ(ValueKeyword("STRKW", std::string("VALUE STRING"), std::nullopt), kw);
89  }
90  {
91  ValueKeyword kw = std::get<ValueKeyword>(parsed[1]);
92  EXPECT_EQ(ValueKeyword("BOOLKW", true, std::nullopt), kw);
93  }
94  {
95  ValueKeyword kw = std::get<ValueKeyword>(parsed[2]);
96  EXPECT_EQ(ValueKeyword("INTMIN", int64_t(-9223372036854775807), std::nullopt), kw);
97  }
98  {
99  ValueKeyword kw = std::get<ValueKeyword>(parsed[3]);
100  EXPECT_EQ(ValueKeyword("INTMAX", uint64_t(9223372036854775807), std::nullopt), kw);
101  }
102  {
103  ValueKeyword kw = std::get<ValueKeyword>(parsed[4]);
104  EXPECT_EQ(ValueKeyword("UINTMAX", 18446744073709551615u, std::nullopt), kw);
105  }
106  {
107  ValueKeyword kw = std::get<ValueKeyword>(parsed[5]);
108  EXPECT_EQ(ValueKeyword("FLOATMIN", -1.79769313486231e+308, std::nullopt), kw);
109  }
110  {
111  ValueKeyword kw = std::get<ValueKeyword>(parsed[6]);
112  EXPECT_EQ(ValueKeyword("FLOATMAX", 1.79769313486231e+308, std::nullopt), kw);
113  }
114 }
115 
116 TEST_F(TestJson, ParseEsoKeywords) {
117  // Setup
118  auto keywords_str = R"(
119  [
120  {
121  "type": "esoKeyword",
122  "name": "STRKW",
123  "value": "VALUE STRING"
124  },
125  {
126  "type": "esoKeyword",
127  "name": "BOOLKW",
128  "value": true
129  },
130  {
131  "type": "esoKeyword",
132  "name": "INTMIN",
133  "value": -9223372036854775807
134  },
135  {
136  "type": "esoKeyword",
137  "name": "INTMAX",
138  "value": 9223372036854775807
139  },
140  {
141  "type": "esoKeyword",
142  "name": "UINTMAX",
143  "value": 18446744073709551615
144  },
145  {
146  "type": "esoKeyword",
147  "name": "FLOATMIN",
148  "value": -1.79769313486231e+308
149  },
150  {
151  "type": "esoKeyword",
152  "name": "FLOATMAX",
153  "value": 1.79769313486231e+308
154  },
155  {
156  "type": "esoKeyword",
157  "name": "KW WITH SPACE",
158  "value": "spaces"
159  }
160  ]
161  )";
162 
163  // Test
164  std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
165  ASSERT_EQ(8u, parsed.size());
166  for (auto const& kw_var : parsed) {
167  ASSERT_TRUE(std::holds_alternative<EsoKeyword>(kw_var));
168  }
169 
170  {
171  EsoKeyword kw = std::get<EsoKeyword>(parsed[0]);
172  EXPECT_EQ(EsoKeyword("STRKW", std::string("VALUE STRING"), std::nullopt), kw);
173  }
174  {
175  EsoKeyword kw = std::get<EsoKeyword>(parsed[1]);
176  EXPECT_EQ(EsoKeyword("BOOLKW", true, std::nullopt), kw);
177  }
178  {
179  EsoKeyword kw = std::get<EsoKeyword>(parsed[2]);
180  EXPECT_EQ(EsoKeyword("INTMIN", int64_t(-9223372036854775807), std::nullopt), kw);
181  }
182  {
183  EsoKeyword kw = std::get<EsoKeyword>(parsed[3]);
184  EXPECT_EQ(EsoKeyword("INTMAX", uint64_t(9223372036854775807), std::nullopt), kw);
185  }
186  {
187  EsoKeyword kw = std::get<EsoKeyword>(parsed[4]);
188  EXPECT_EQ(EsoKeyword("UINTMAX", 18446744073709551615u, std::nullopt), kw);
189  }
190  {
191  EsoKeyword kw = std::get<EsoKeyword>(parsed[5]);
192  EXPECT_EQ(EsoKeyword("FLOATMIN", -1.79769313486231e+308, std::nullopt), kw);
193  }
194  {
195  EsoKeyword kw = std::get<EsoKeyword>(parsed[6]);
196  EXPECT_EQ(EsoKeyword("FLOATMAX", 1.79769313486231e+308, std::nullopt), kw);
197  }
198  {
199  EsoKeyword kw = std::get<EsoKeyword>(parsed[7]);
200  EXPECT_EQ(EsoKeyword("KW WITH SPACE", "spaces", std::nullopt), kw);
201  }
202 }
203 
204 TEST_F(TestJson, ParseOptionalKeywordComment) {
205  // Setup
206  auto keywords_str = R"(
207  [
208  {
209  "type": "valueKeyword",
210  "name": "STRKW1",
211  "value": "VALUE STRING",
212  "comment": "this is a comment"
213  },
214  {
215  "type": "esoKeyword",
216  "name": "STRKW2",
217  "value": "VALUE STRING",
218  "comment": "this is also a comment"
219  }
220  ]
221  )";
222 
223  // Test
224  std::vector<KeywordVariant> parsed = ParseJsonKeywords(keywords_str);
225  ASSERT_EQ(2u, parsed.size());
226  ASSERT_TRUE(std::holds_alternative<ValueKeyword>(parsed[0]));
227  ASSERT_TRUE(std::holds_alternative<EsoKeyword>(parsed[1]));
228 
229  {
230  ValueKeyword kw = std::get<ValueKeyword>(parsed[0]);
231  EXPECT_EQ(ValueKeyword("STRKW1", std::string("VALUE STRING"), "this is a comment"), kw);
232  }
233  {
234  EsoKeyword kw = std::get<EsoKeyword>(parsed[1]);
235  EXPECT_EQ(EsoKeyword("STRKW2", std::string("VALUE STRING"), "this is also a comment"), kw);
236  }
237 }
238 
239 TEST_F(TestJson, ParseEmptyArray) {
240  // Setup
241  auto keywords_str = R"(
242  []
243  )";
244  auto res = ParseJsonKeywords(keywords_str);
245  EXPECT_EQ(0u, res.size());
246 }
247 
248 TEST_F(TestJson, ParseFailsIfNotAnArray) {
249  // Setup
250  auto keywords_str = R"(
251  {
252  "type": "valueKeyword",
253  "name": "FLOATMAX",
254  "value": 1.79769313486231e+308
255  }
256  )";
257  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
258 }
259 
260 TEST_F(TestJson, ParseFailsIfNotAnObjectInArray) {
261  // Setup
262  auto keywords_str = R"(
263  [
264  1,
265  [],
266  "",
267  null
268  ]
269  )";
270  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
271 }
272 
273 TEST_F(TestJson, ParseFailsIfObjectMissTypeProperty) {
274  // Setup
275  auto keywords_str = R"(
276  [
277  {
278  "name": "FLOATMAX",
279  "value": "value"
280  }
281  ]
282  )";
283  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
284 }
285 
286 TEST_F(TestJson, ParseFailsIfObjectHasUnknownTypeProperty) {
287  // Setup
288  auto keywords_str = R"(
289  [
290  {
291  "type": "unknown",
292  "name": "FLOATMAX",
293  "value": 1.79769313486231e+308
294  }
295  ]
296  )";
297  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
298 }
299 
300 TEST_F(TestJson, ParseFailsIfTypeIsNotString) {
301  // Setup
302  auto keywords_str = R"(
303  [
304  {
305  "type": true,
306  "name": "FLOATMAX",
307  "value": 1.79769313486231e+308
308  }
309  ]
310  )";
311  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
312 }
313 
314 TEST_F(TestJson, ParseFailsIfObjectMissNameProperty) {
315  // Setup
316  auto keywords_str = R"(
317  [
318  {
319  "type": "valueKeyword",
320  "value": 1.79769313486231e+308
321  }
322  ]
323  )";
324  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
325 }
326 
327 TEST_F(TestJson, ParseFailsIfObjectMissValue) {
328  // Setup
329  auto keywords_str = R"(
330  [
331  {
332  "type": "valueKeyword",
333  "name": "FLOATMAX"
334  }
335  ]
336  )";
337  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
338 }
339 
340 TEST_F(TestJson, ParseFailsIfObjectHasUnsupportedValueType) {
341  // Setup
342  auto keywords_str = R"(
343  [
344  {
345  "type": "valueKeyword",
346  "name": "NAME",
347  "value": {"foo": true}
348  }
349  ]
350  )";
351  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
352 }
353 
354 TEST_F(TestJson, ParseFailsIfNameIsNotString) {
355  // Setup
356  auto keywords_str = R"(
357  [
358  {
359  "type": "valueKeyword",
360  "name": 1.0,
361  "value": "value"
362  }
363  ]
364  )";
365  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
366 }
367 
368 TEST_F(TestJson, ParseFailsIfObjectHasCommentThatIsNotString) {
369  // Setup
370  auto keywords_str = R"(
371  [
372  {
373  "type": "valueKeyword",
374  "name": "NAME",
375  "value": "value",
376  "comment": 1.0
377  }
378  ]
379  )";
380  EXPECT_THROW(ParseJsonKeywords(keywords_str), std::invalid_argument);
381 }
daq::TEST_F
TEST_F(TestSource, Constructors)
Definition: testSource.cpp:34
daq::fits
Definition: cfitsio.cpp:14
daq::fits::EsoKeyword
BasicKeyword< EsoKeywordTraits > EsoKeyword
ESO hiearchical keyword.
Definition: keyword.hpp:99
daq::fits::BasicKeyword
A type safe version of FormattedKeyword that consist of the three basic components of a FITS keyword ...
Definition: keyword.hpp:51
TestJson
Definition: testJson.cpp:17
json.hpp
Contains data structure for FITS keywords.
daq::fits::ValueKeyword
BasicKeyword< ValueKeywordTraits > ValueKeyword
Standard FITS value keyword.
Definition: keyword.hpp:92
daq::fits::ParseJsonKeywords
std::vector< KeywordVariant > ParseJsonKeywords(char const *keywords)
Parse and return FITS keywords.
Definition: json.cpp:73