ifw-daq 3.1.0
IFW Data Acquisition modules
Loading...
Searching...
No Matches
testKeyword.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#include <algorithm>
9#include <gmock/gmock.h>
10#include <gtest/gtest.h>
11#include <nlohmann/json.hpp>
12#include <ostream>
13#include <random>
14
15#include <daq/error/report.hpp>
16#include <daq/fits/json.hpp>
17
18#include "matchers.hpp"
19
20using namespace daq::fits;
21using namespace std::string_view_literals;
22
23class TestLiteralKeyword : public ::testing::Test {
24public:
25 void ExpectKeyword(std::string const& record,
26 KeywordType type,
27 std::string_view name,
28 std::string_view logical_name) {
29 using namespace ::testing;
30 try {
31 LiteralKeyword kw(record);
32
33 EXPECT_THAT(record, StartsWith(std::string(kw.GetRecord())));
34 EXPECT_EQ(type, kw.GetType());
35 auto [kw_name, kw_type] = kw.GetName();
36 EXPECT_EQ(kw_name, logical_name);
37 EXPECT_EQ(type, kw_type);
38 } catch (...) {
40 throw;
41 }
42 }
43};
44
45TEST_F(TestLiteralKeyword, ConstructStrangeKeywords1) {
46 std::string too_long;
47 std::fill_n(std::back_inserter(too_long), constants::RECORD_LENGTH + 1, 'N');
48 ASSERT_EQ(too_long.size(), constants::RECORD_LENGTH + 1);
49 EXPECT_THROW(LiteralKeyword{too_long}, std::invalid_argument);
50}
51
52TEST_F(TestLiteralKeyword, ConstructStrangeKeywords4) {
53 LiteralKeyword kw{" "};
54 auto [name, type] = kw.GetName();
55 EXPECT_EQ(name, " ");
56 EXPECT_EQ(type, KeywordType::Commentary);
57 EXPECT_EQ(kw.GetRecord(), " ");
58}
59
60TEST_F(TestLiteralKeyword, ConstructStrangeKeywords3) {
61 LiteralKeyword kw{"A"};
62 auto [name, type] = kw.GetName();
63 EXPECT_EQ(name, "A");
64 EXPECT_EQ(type, KeywordType::Commentary);
65 EXPECT_EQ(kw.GetRecord(), "A");
66}
67
68TEST_F(TestLiteralKeyword, ConstructStrangeKeywords5) {
69 LiteralKeyword kw{"A = "};
70 auto [name, type] = kw.GetName();
71 EXPECT_EQ(name, "A");
72 EXPECT_EQ(type, KeywordType::Value);
73 EXPECT_EQ(kw.GetRecord(), "A =");
74}
75
76TEST_F(TestLiteralKeyword, ConstructStrangeKeywords6) {
77 LiteralKeyword kw{"HIERARCH ESO A=T/"};
78 auto [name, type] = kw.GetName();
79 EXPECT_EQ(name, "A");
80 EXPECT_EQ(type, KeywordType::Eso);
81 EXPECT_EQ(kw.GetRecord(), "HIERARCH ESO A=T/");
82}
83
84TEST_F(TestLiteralKeyword, ConstructStrangeKeywords7) {
85 LiteralKeyword kw{"HIERARCH ESO A=''/"};
86 auto [name, type] = kw.GetName();
87 EXPECT_EQ(name, "A");
88 EXPECT_EQ(type, KeywordType::Eso);
89 EXPECT_EQ(kw.GetRecord(), "HIERARCH ESO A=''/");
90}
91
92TEST_F(TestLiteralKeyword, ConstructStrangeKeywords8) {
93 LiteralKeyword kw{"HIERARCH ESO A=''''''/"};
94 auto [name, type] = kw.GetName();
95 EXPECT_EQ(name, "A");
96 EXPECT_EQ(type, KeywordType::Eso);
97 EXPECT_EQ(kw.GetRecord(), "HIERARCH ESO A=''''''/");
98}
99
100TEST_F(TestLiteralKeyword, ConstructStrangeKeywords9) {
101 LiteralKeyword kw{"KEYWORD1= ''/' /"};
102 auto [name, type] = kw.GetName();
103 EXPECT_EQ(name, "KEYWORD1");
104 EXPECT_EQ(type, KeywordType::Value);
105 EXPECT_EQ(kw.GetComponents().value, "''");
106 EXPECT_EQ(kw.GetComponents().comment, "' /");
107}
108
109TEST_F(TestLiteralKeyword, ConstructStrangeKeywords10) {
110 LiteralKeyword kw{"HIERARCH ESO HAS NO VALUE AFTER INDICATOR="};
111 auto [name, type] = kw.GetName();
112 EXPECT_EQ(name, "HAS NO VALUE AFTER INDICATOR");
113 EXPECT_EQ(type, KeywordType::Eso);
114 EXPECT_EQ(kw.GetComponents().value, "");
115 EXPECT_EQ(kw.GetComponents().comment, "");
116}
117
118TEST_F(TestLiteralKeyword, ConstructStrangeKeywords11) {
119 LiteralKeyword kw{"HIERARCH ESO HAS NO VALUE AFTER INDICATOR=/with comment"};
120 auto [name, type] = kw.GetName();
121 EXPECT_EQ(name, "HAS NO VALUE AFTER INDICATOR");
122 EXPECT_EQ(type, KeywordType::Eso);
123 EXPECT_EQ(kw.GetComponents().value, "");
124 EXPECT_EQ(kw.GetComponents().comment, "with comment");
125}
126
127TEST_F(TestLiteralKeyword, ConstructRegularKeywords) {
128 using namespace ::testing;
129 std::string_view record = "ORIGIN = 'ESO-PARANAL' / European Southern Observatory";
130
131 std::array<char, constants::RECORD_LENGTH> array_record = {' '};
132 std::copy(std::begin(record), std::end(record), std::begin(array_record));
133 LiteralKeyword kw(array_record);
134 EXPECT_THAT(std::string(kw.GetRecord()), StartsWith(std::string(record)));
135}
136
137TEST_F(TestLiteralKeyword, ValueKeywordTypes) {
138 try {
139 {
140 SCOPED_TRACE("");
141 ExpectKeyword("SIMPLE = T / Standard FITS ",
142 KeywordType::Value,
143 "SIMPLE ",
144 "SIMPLE");
145 }
146 {
147 SCOPED_TRACE("");
148 ExpectKeyword("DATE = '2019-12-12T04:30:53.8930' / Date the file was written",
149 KeywordType::Value,
150 "DATE ",
151 "DATE");
152 }
153 } catch (...) {
155 }
156}
157
158TEST_F(TestLiteralKeyword, StrangeValueKeywordTypes) {
159 EXPECT_THROW(LiteralKeyword("KEYWORD1= '"), std::invalid_argument);
160 EXPECT_THROW(LiteralKeyword("KEYWORD1= '''"), std::invalid_argument);
161}
162
163TEST_F(TestLiteralKeyword, InvalidEsoKeywordTypes) {
164 EXPECT_THROW(LiteralKeyword("HIERARCH ESO HAS TWO STRINGS ='two' 'strings'/"),
165 std::invalid_argument);
166 EXPECT_THROW(LiteralKeyword("HIERARCH ESO HAS TWO VALUES= T 0.1/"), std::invalid_argument);
167 EXPECT_THROW(LiteralKeyword("HIERARCH ESO HAS TWO VALUES= T F"), std::invalid_argument);
168}
169
170TEST_F(TestLiteralKeyword, EsoKeywordTypes) {
171 {
172 SCOPED_TRACE("");
173 ExpectKeyword("HIERARCH ESO ADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
174 KeywordType::Eso,
175 "HIERARCH",
176 "ADA ABSROT END");
177 }
178 {
179 SCOPED_TRACE("");
180 ExpectKeyword(
181 "HIERARCH ESO DEL DLT2 VCM CURV = 0.001512604 / mm-1 actual curv. of VCM beam i",
182 KeywordType::Eso,
183 "HIERARCH",
184 "DEL DLT2 VCM CURV");
185 }
186 {
187 SCOPED_TRACE("");
188 ExpectKeyword(
189 "HIERARCH ESO DEL DLT2 VCM CURV=0.001512604 / mm-1 actual curv. of VCM beam i",
190 KeywordType::Eso,
191 "HIERARCH",
192 "DEL DLT2 VCM CURV");
193 }
194 {
195 SCOPED_TRACE("");
196 ExpectKeyword("HIERARCH ESO N = 0.001512604 / mm-1 actual curv. of VCM beam i",
197 KeywordType::Eso,
198 "HIERARCH",
199 "N");
200 }
201 {
202 SCOPED_TRACE("");
203 ExpectKeyword("HIERARCH ESO N =0.001512604 / mm-1 actual curv. of VCM beam i",
204 KeywordType::Eso,
205 "HIERARCH",
206 "N");
207 }
208 {
209 SCOPED_TRACE("");
210 ExpectKeyword("HIERARCH ESO N= 0.001512604 / mm-1 actual curv. of VCM beam i",
211 KeywordType::Eso,
212 "HIERARCH",
213 "N");
214 }
215 {
216 SCOPED_TRACE("");
217 ExpectKeyword("HIERARCH ESO N=0.001512604 / mm-1 actual curv. of VCM beam i",
218 KeywordType::Eso,
219 "HIERARCH",
220 "N");
221 }
222}
223
224TEST_F(TestLiteralKeyword, EsoKeywordStringParsing) {
225 {
226 SCOPED_TRACE("");
227 LiteralKeyword kw("HIERARCH ESO KW VAL= '/path/to/somewhere'");
228 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
229 auto [kw_name, kw_type] = kw.GetName();
230 EXPECT_EQ(kw_name, "KW VAL");
231 auto c = kw.GetComponents();
232 EXPECT_EQ(c.value, "'/path/to/somewhere'");
233 EXPECT_EQ(c.comment, "");
234 }
235 {
236 SCOPED_TRACE("");
237 LiteralKeyword kw("HIERARCH ESO FOO BAR='''escaped'");
238 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
239 auto [kw_name, kw_type] = kw.GetName();
240 EXPECT_EQ(kw_name, "FOO BAR");
241 auto c = kw.GetComponents();
242 EXPECT_EQ(c.value, "'''escaped'");
243 EXPECT_EQ(c.comment, "");
244 }
245 {
246 SCOPED_TRACE("");
247 LiteralKeyword kw("HIERARCH ESO FOO BAR='/escaped'''");
248 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
249 auto [kw_name, kw_type] = kw.GetName();
250 EXPECT_EQ(kw_name, "FOO BAR");
251 auto c = kw.GetComponents();
252 EXPECT_EQ(c.value, "'/escaped'''");
253 EXPECT_EQ(c.comment, "");
254 }
255 {
256 SCOPED_TRACE("");
257 LiteralKeyword kw("HIERARCH ESO FOO BAR='escaped''/string'/c");
258 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
259 auto [kw_name, kw_type] = kw.GetName();
260 EXPECT_EQ(kw_name, "FOO BAR");
261 auto c = kw.GetComponents();
262 EXPECT_EQ(c.value, "'escaped''/string'");
263 EXPECT_EQ(c.comment, "c");
264 }
265 {
266 SCOPED_TRACE("");
267 LiteralKeyword kw("HIERARCH ESO FOO BAR='escaped''string' / with comment");
268 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
269 auto [kw_name, kw_type] = kw.GetName();
270 EXPECT_EQ(kw_name, "FOO BAR");
271 auto c = kw.GetComponents();
272 EXPECT_EQ(c.value, "'escaped''string'");
273 EXPECT_EQ(c.comment, "with comment");
274 }
275 {
276 SCOPED_TRACE("");
277 LiteralKeyword kw("HIERARCH ESO FOO BAR='escaped''string'/with comment");
278 EXPECT_EQ(kw.GetType(), KeywordType::Eso);
279 auto [kw_name, kw_type] = kw.GetName();
280 EXPECT_EQ(kw_name, "FOO BAR");
281 auto c = kw.GetComponents();
282 EXPECT_EQ(c.value, "'escaped''string'");
283 EXPECT_EQ(c.comment, "with comment");
284 }
285}
286
287TEST_F(TestLiteralKeyword, CommentaryKeywordTypes) {
288 {
289 SCOPED_TRACE("");
290 ExpectKeyword("COMMENT Some comment here", KeywordType::Commentary, "COMMENT ", "COMMENT");
291 }
292 {
293 SCOPED_TRACE("");
294 ExpectKeyword("HISTORY Some comment here", KeywordType::Commentary, "HISTORY ", "HISTORY");
295 }
296 {
297 SCOPED_TRACE("");
298 ExpectKeyword(
299 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer",
300 KeywordType::Commentary,
301 "HIERARCH ",
302 "HIERARCH");
303 }
304 {
305 SCOPED_TRACE("");
306 // Invalid ESO HIERARCH keyword
307 ExpectKeyword("HIERARCH ESOADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
308 KeywordType::Commentary,
309 "HIERARCH",
310 "HIERARCH");
311 }
312 {
313 SCOPED_TRACE("");
314 // Missing = disqualifies keyword to be an HIERARCH ESO keyword.
315 ExpectKeyword("HIERARCH ESO ADA ABSROT END 36.49838 / [deg] Abs rot angle at exp end",
316 KeywordType::Commentary,
317 "HIERARCH",
318 "HIERARCH");
319 }
320}
321
322TEST_F(TestLiteralKeyword, EqualityOperator) {
323 auto kw1 = LiteralKeyword("HIERARCH ESO UNKN A = T / Comment");
324 auto kw2 = LiteralKeyword("HIERARCH ESO UNKN B = T / Comment");
325 auto kw2_copy = kw2;
326 EXPECT_EQ(kw2, kw2_copy);
327 EXPECT_NE(kw1, kw2);
328 EXPECT_NE(KeywordVariant(kw1), KeywordVariant(kw2));
329 EXPECT_EQ(KeywordVariant(kw2_copy), KeywordVariant(kw2));
330}
331
332TEST_F(TestLiteralKeyword, OstreamOperator) {
333 // Setup
334 using namespace ::testing;
335 using namespace std::literals::string_view_literals;
336
337 // Test
338 {
339 auto view = "HIERARCH ESO TEL MOON DEC = 22.00047 / [deg] 22:00:01.7 DEC (J2000)"sv;
340 LiteralKeyword kw(view);
341 std::stringstream ss;
342 ss << kw;
343 EXPECT_EQ(ss.str(), view);
344 }
345 {
346 auto view = "COMMENT "sv;
347 LiteralKeyword kw(view);
348 std::stringstream ss;
349 ss << kw;
350 EXPECT_EQ(ss.str(), "COMMENT"sv);
351 }
352}
353/**
354 * Note that test cases must use `TypeParam` and cannot declare templated aliases.
355 */
356template <typename Type>
357class TestKeyword : public ::testing::Test {};
358
359using Types = ::testing::Types<ValueKeyword, EsoKeyword>;
361
362TYPED_TEST(TestKeyword, Construction) {
363 using Keyword = TypeParam;
364
365 Keyword orig("NAME", 1.0, "comment");
366 EXPECT_EQ(orig.name, "NAME");
367 EXPECT_EQ(orig.value, typename Keyword::ValueType(1.0));
368 EXPECT_EQ(orig.comment, "comment");
369
370 Keyword copy_assign;
371 copy_assign = orig;
372 EXPECT_EQ(orig, copy_assign);
373
374 Keyword move_assign("TOBE", "replaced");
375 move_assign = std::move(copy_assign);
376 EXPECT_EQ(orig, move_assign);
377
378 Keyword copy_construct(orig);
379 EXPECT_EQ(orig, copy_construct);
380
381 Keyword move_construct(std::move(copy_construct));
382 EXPECT_EQ(orig, move_construct);
383}
384
385TYPED_TEST(TestKeyword, OptionalComment) {
386 using Keyword = TypeParam;
387
388 Keyword orig("NAME", 1.0, std::nullopt);
389 EXPECT_EQ(orig.comment, std::nullopt);
390}
391
392/**
393 * Test that construction of keyword from a C string is stored as std::string and not a bool,
394 * which is the implicitly converted type for the variant construction otherwise.
395 */
396TYPED_TEST(TestKeyword, ConstructFromString) {
397 using Keyword = TypeParam;
398
399 Keyword kw("NAME", "str", "comment");
400 ASSERT_TRUE(std::holds_alternative<std::string>(kw.value));
401 EXPECT_EQ("str", std::get<std::string>(kw.value));
402}
403
405 using Keyword = TypeParam;
406
407 Keyword lhs("NAME", 1.0, "comment");
408 Keyword rhs("NAME", 1.0, "comment");
409
410 EXPECT_TRUE(lhs == rhs);
412 EXPECT_FALSE(lhs != rhs);
413
414 rhs.comment = std::nullopt;
415 EXPECT_NE(lhs, rhs);
416
417 rhs.comment = "comment ";
418 EXPECT_NE(lhs, rhs);
419}
420
422 using Keyword = TypeParam;
423
424 Keyword lhs("A", 1.0, "comment");
425 Keyword rhs("B", 1.0, "comment");
426
427 EXPECT_LT(lhs, rhs);
428 EXPECT_FALSE(rhs < lhs);
429 EXPECT_FALSE(lhs < lhs);
430}
431
432TYPED_TEST(TestKeyword, OstreamOperator) {
433 using Keyword = TypeParam;
434
435 // Setup
436 using namespace ::testing;
437
438 // Test
439 {
440 Keyword kw("NAME", std::string("value"), "comment");
441 std::stringstream ss;
442 ss << kw;
443 EXPECT_EQ(ss.str(), "name='NAME', value=(str)'value', comment='comment'");
444 }
445 {
446 Keyword kw("NAME", true, std::nullopt);
447 std::stringstream ss;
448 ss << kw;
449 EXPECT_EQ(ss.str(), "name='NAME', value=(bool)true, comment=n/a");
450 }
451 {
452 Keyword kw("NAME", 1234ul, std::nullopt);
453 std::stringstream ss;
454 ss << kw;
455 EXPECT_THAT(ss.str(), "name='NAME', value=(uint64_t)1234, comment=n/a");
456 }
457 {
458 Keyword kw("NAME", 1234l, std::nullopt);
459 std::stringstream ss;
460 ss << kw;
461 EXPECT_THAT(ss.str(), "name='NAME', value=(int64_t)1234, comment=n/a");
462 }
463 {
464 Keyword kw("NAME", 1.234, std::nullopt);
465 std::stringstream ss;
466 ss << kw;
467 EXPECT_THAT(ss.str(), "name='NAME', value=(double)1.234, comment=n/a");
468 }
469}
470
471TEST(TestKeywordCombinations, OperatorLessComparesKeywordName) {
472 EsoKeyword eso_kw("A", "B");
473 ValueKeyword value_kw("A", "B");
474
475 LiteralKeyword literal_value_kw1("B1 = B");
476 LiteralKeyword literal_value_kw2("B2 = B");
477 ASSERT_EQ(KeywordType::Value, literal_value_kw1.GetType());
478 ASSERT_EQ(KeywordType::Value, literal_value_kw2.GetType());
479
480 LiteralKeyword literal_eso_kw1("HIERARCH ESO A1 = B");
481 LiteralKeyword literal_eso_kw2("HIERARCH ESO A2 = B");
482 ASSERT_EQ(KeywordType::Eso, literal_eso_kw1.GetType());
483 ASSERT_EQ(KeywordType::Eso, literal_eso_kw2.GetType());
484
485 LiteralKeyword literal_commentary_kw1("COMMENT A");
486 LiteralKeyword literal_commentary_kw2("HIERARCH B");
487 ASSERT_EQ(KeywordType::Commentary, literal_commentary_kw1.GetType());
488 ASSERT_EQ(KeywordType::Commentary, literal_commentary_kw2.GetType());
489
490 EXPECT_FALSE(value_kw < eso_kw);
491 EXPECT_LT(KeywordVariant(value_kw), KeywordVariant(eso_kw));
492 EXPECT_LT(literal_value_kw1, literal_value_kw2);
493 EXPECT_FALSE(literal_value_kw1 < literal_eso_kw1);
494 EXPECT_FALSE(literal_value_kw1 < literal_eso_kw2);
495 EXPECT_LT(literal_eso_kw1, literal_eso_kw2);
496
497 EXPECT_LT(value_kw, literal_commentary_kw1);
498 EXPECT_LT(eso_kw, literal_commentary_kw1);
499 EXPECT_LT(literal_value_kw1, literal_commentary_kw1);
500 EXPECT_LT(literal_eso_kw1, literal_commentary_kw1);
501 EXPECT_LT(literal_commentary_kw1, literal_commentary_kw2);
502
503 EXPECT_FALSE(literal_eso_kw1 < eso_kw);
504 EXPECT_FALSE(value_kw < value_kw);
505 EXPECT_FALSE(eso_kw < eso_kw);
506 EXPECT_FALSE(eso_kw < value_kw);
507 EXPECT_FALSE(literal_eso_kw1 < value_kw);
508 EXPECT_FALSE(literal_commentary_kw1 < literal_commentary_kw1);
509 EXPECT_FALSE(literal_commentary_kw2 < literal_commentary_kw1);
510 EXPECT_FALSE(KeywordVariant(eso_kw) < KeywordVariant(value_kw));
511}
512
513TEST(TestKeywordCombinations, NameEquals) {
514 EsoKeyword eso_kw("A", "B");
515 ValueKeyword value_kw("A", "B");
516 LiteralKeyword literal_value_kw1("A = B");
517 ASSERT_EQ(literal_value_kw1.GetName().name, "A");
518
519 LiteralKeyword literal_eso_kw1("HIERARCH ESO A = B");
520 ASSERT_EQ(literal_eso_kw1.GetName().name, "A");
521 LiteralKeyword literal_commentary_kw1("COMMENT A");
522 LiteralKeyword literal_commentary_kw2("COMMENT B");
523
524 auto view = GetKeywordName(eso_kw);
525 EXPECT_EQ(view, eso_kw.GetName());
526
527 EXPECT_FALSE(NameEquals(value_kw, eso_kw));
528 EXPECT_FALSE(NameEquals(eso_kw, value_kw));
529
530 EXPECT_NE(literal_value_kw1.GetName(), literal_eso_kw1.GetName());
531 EXPECT_NE(literal_value_kw1.GetName(), literal_commentary_kw1.GetName());
532 EXPECT_EQ(eso_kw.GetName(), literal_eso_kw1.GetName());
533 EXPECT_EQ(literal_value_kw1.GetName(), value_kw.GetName());
534 EXPECT_EQ(literal_commentary_kw1.GetName(), literal_commentary_kw2.GetName());
535
536 EXPECT_TRUE(NameEquals(value_kw, ValueKeyword("A", "NOT B")));
537 EXPECT_TRUE(NameEquals(eso_kw, EsoKeyword("A", "NOT B")));
538 EXPECT_TRUE(NameEquals(value_kw, literal_value_kw1));
539 EXPECT_TRUE(NameEquals(eso_kw, literal_eso_kw1));
540 EXPECT_FALSE(NameEquals(eso_kw, literal_value_kw1));
541 EXPECT_FALSE(NameEquals(value_kw, eso_kw));
542}
543
545 using namespace daq::fits;
546 using namespace ::testing;
547 // Setup
548
549 // Initial values to be updated
550 KeywordVector to{
551 EsoKeyword("A", "A1-orig"),
552 ValueKeyword("A", "A2-orig"),
553 ValueKeyword("B", static_cast<uint64_t>(1u)),
554 EsoKeyword("B", "B"),
555 LiteralKeyword("C = 'orig' /"),
556 LiteralKeyword("HIERARCH ESO C = 'orig' /"),
557 LiteralKeyword("D = 'orig' /"),
558 LiteralKeyword("HIERARCH ESO D = 'orig' /"),
559 LiteralKeyword("E = 'orig' /"),
560 LiteralKeyword("HIERARCH ESO E = 'orig' /"),
561 };
562
563 // Overwrite the A, C & D keywords and insert the Z keywords
564 KeywordVector from{
565 EsoKeyword("A", "A1-updated"),
566 ValueKeyword("A", "A2-updated"),
567 ValueKeyword("C", "C-updated"),
568 EsoKeyword("C", "C-updated"),
569 LiteralKeyword("D = 'updated' /"),
570 LiteralKeyword("HIERARCH ESO D = 'updated' /"),
571 ValueKeyword("Z", "Z"),
572 EsoKeyword("Z", true),
573 };
574
575 KeywordVector result{
576 EsoKeyword("A", "A1-updated"),
577 ValueKeyword("A", "A2-updated"),
578 ValueKeyword("B", static_cast<uint64_t>(1u)),
579 EsoKeyword("B", "B"),
580 ValueKeyword("C", "C-updated"),
581 EsoKeyword("C", "C-updated"),
582 LiteralKeyword("D = 'updated' /"),
583 LiteralKeyword("HIERARCH ESO D = 'updated' /"),
584 LiteralKeyword("E = 'orig' /"),
585 LiteralKeyword("HIERARCH ESO E = 'orig' /"),
586 ValueKeyword("Z", "Z"),
587 EsoKeyword("Z", true),
588 };
589 // Run
590 UpdateKeywords(to, from);
591 EXPECT_THAT(to, ContainerEq(result));
592}
593
594TEST(KeywordVector, InsertKeywordsEnd) {
595 using namespace daq::fits;
596 using namespace ::testing;
597 // Setup
598
599 // Initial values to be updated
600 KeywordVector to{
601 EsoKeyword("A", "A1-orig"),
602 ValueKeyword("A", "A2-orig"),
603 ValueKeyword("B", static_cast<uint64_t>(1u)),
604 EsoKeyword("B", "B")
605 // << INSERT POSITION
606 };
607
608 // Overwrite the A keywords and insert the C keywords
609 KeywordVector from{EsoKeyword("A", "A1-updated"),
610 ValueKeyword("A", "A2-updated"),
611 ValueKeyword("C", "C"),
612 EsoKeyword("C", true)};
613
614 KeywordVector result{ValueKeyword("B", static_cast<uint64_t>(1u)),
615 EsoKeyword("B", "B"),
616 EsoKeyword("A", "A1-updated"),
617 ValueKeyword("A", "A2-updated"),
618 ValueKeyword("C", "C"),
619 EsoKeyword("C", true)
620
621 };
622 // Run
623 InsertKeywords(to, to.end(), from.begin(), from.end());
624 EXPECT_THAT(to, ContainerEq(result));
625}
626
627TEST(KeywordVector, InsertKeywordsBegin) {
628 using namespace daq::fits;
629 using namespace ::testing;
630 // Setup
631
632 // Initial values to be updated
633 KeywordVector to{// << INSERT POSITION
634 EsoKeyword("A", "A1-orig"),
635 ValueKeyword("A", "A2-orig"),
636 ValueKeyword("B", static_cast<uint64_t>(1u)),
637 EsoKeyword("B", "B")};
638
639 // Overwrite the A keywords and insert the C keywords
640 KeywordVector from{EsoKeyword("A", "A1-updated"),
641 ValueKeyword("A", "A2-updated"),
642 ValueKeyword("C", "C"),
643 EsoKeyword("C", true)};
644
645 KeywordVector result{EsoKeyword("A", "A1-updated"),
646 ValueKeyword("A", "A2-updated"),
647 ValueKeyword("C", "C"),
648 EsoKeyword("C", true),
649 ValueKeyword("B", static_cast<uint64_t>(1u)),
650 EsoKeyword("B", "B")
651
652 };
653 // Run
654 InsertKeywords(to, to.begin(), from.begin(), from.end());
655 EXPECT_THAT(to, ContainerEq(result));
656}
657
658TEST(KeywordVector, InsertKeywordsMiddle) {
659 using namespace daq::fits;
660 using namespace ::testing;
661 // Setup
662
663 // Initial values to be updated
664 KeywordVector to{EsoKeyword("A", "A1-orig"),
665 ValueKeyword("A", "A2-orig"),
666 ValueKeyword("B", static_cast<uint64_t>(1u)),
667 // << INSERT POSITION
668 EsoKeyword("B", "B")};
669
670 // Overwrite the A keywords and insert the C keywords
671 KeywordVector from{EsoKeyword("A", "A1-updated"),
672 ValueKeyword("A", "A2-updated"),
673 ValueKeyword("C", "C"),
674 EsoKeyword("C", true)};
675
676 KeywordVector result{ValueKeyword("B", static_cast<uint64_t>(1u)),
677 EsoKeyword("A", "A1-updated"),
678 ValueKeyword("A", "A2-updated"),
679 ValueKeyword("C", "C"),
680 EsoKeyword("C", true),
681 EsoKeyword("B", "B")
682
683 };
684
685 // Run
686 auto pos = to.begin();
687 std::advance(pos, 3);
688 InsertKeywords(to, pos, from.begin(), from.end());
689 EXPECT_THAT(to, ContainerEq(result));
690}
691
694
695 {
696 auto kw = ValueKeyword("DATE-OBS", "2019-12-12T04:25:48.0068", "Observing date");
697 EXPECT_EQ(Format(kw), fmt.Format(kw));
698 }
699 {
700 auto kw =
701 LiteralKeyword("DATE = '2019-12-12T04:30:53.8930' / Date the file was written");
702 EXPECT_EQ(Format(kw), fmt.Format(kw));
703 }
704 {
705 auto kw = EsoKeyword("ADA ABSROT END", 36.5, "[deg] Abs rot angle at exp end");
706 EXPECT_EQ(Format(kw), fmt.Format(kw));
707 }
708}
709
710TEST(TestFormatting, ValueKeyword) {
711 EXPECT_EQ(LiteralKeyword("DATE-OBS= '2019-12-12T04:25:48.0068' / Observing date"),
712 Format(ValueKeyword("DATE-OBS", "2019-12-12T04:25:48.0068", "Observing date")));
713 EXPECT_EQ(
714 LiteralKeyword("DATE = '2019-12-12T04:30:53.8930' / Date the file was written"),
715 Format(ValueKeyword("DATE", "2019-12-12T04:30:53.8930", "Date the file was written")));
716 EXPECT_EQ(LiteralKeyword("EQUINOX = 2000.0 / Standard FK5"),
717 Format(ValueKeyword("EQUINOX ", 2000.0, "Standard FK5")));
718 EXPECT_EQ(LiteralKeyword("EXTEND = T / FITS Extension may be present"),
719 Format(ValueKeyword("EXTEND", true, "FITS Extension may be present")));
720 EXPECT_EQ(LiteralKeyword("ORIGIN = 'ESO-PARANAL' / European Southern Observatory"),
721 Format(ValueKeyword("ORIGIN", "ESO-PARANAL", "European Southern Observatory")));
722 EXPECT_EQ(
723 LiteralKeyword("INHERIT = F / denotes the INHERIT keyword convention"),
724 Format(ValueKeyword("INHERIT", false, "denotes the INHERIT keyword convention")));
725
726 EXPECT_EQ(LiteralKeyword("XTENSION= 'IMAGE ' / Image extension"),
727 Format(ValueKeyword("XTENSION", "IMAGE", "Image extension")))
728 << "XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
729 EXPECT_EQ(LiteralKeyword("XTENSION= 'CUSTOM-EXTENSION-TYPE' / Image extension"),
730 Format(ValueKeyword("XTENSION", "CUSTOM-EXTENSION-TYPE", "Image extension")))
731 << "XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
732}
733
734TEST(TestFormatting, EsoKeyword) {
735 EXPECT_EQ(LiteralKeyword("HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end"),
736 Format(EsoKeyword("ADA ABSROT END", 36.5, "[deg] Abs rot angle at exp end")));
737 EXPECT_EQ(LiteralKeyword("HIERARCH ESO ADA ABSROT PPOS = 'POS' / sign of probe position"),
738 Format(EsoKeyword("ADA ABSROT PPOS", "POS", "sign of probe position")));
739 EXPECT_EQ(LiteralKeyword("HIERARCH ESO DET ACQ1 REV = 1 / Pre-processor framework revision"),
740 Format(EsoKeyword("DET ACQ1 REV", 1lu, "Pre-processor framework revision")));
741 EXPECT_EQ(LiteralKeyword("HIERARCH ESO DET ADC1 CLAMP = F / Clamp-and-Sample"),
742 Format(EsoKeyword("DET ADC1 CLAMP", false, "Clamp-and-Sample")));
743 EXPECT_EQ(
745 "HIERARCH ESO DET CLDC1 DCNM16 = 'DC16_RelaySwitchLowActive' / Name of bias volta"),
746 Format(
747 EsoKeyword("DET CLDC1 DCNM16", "DC16_RelaySwitchLowActive", "Name of bias voltage")));
748 EXPECT_EQ(
750 "HIERARCH ESO PCR SUMMARY NSCANNED = 1273000 / Total Number of scanned records."),
751 Format(EsoKeyword("PCR SUMMARY NSCANNED", 1273000ul, "Total Number of scanned records.")));
752 EXPECT_EQ(
754 "HIERARCH ESO INS TIM2 START = '2019-07-27T02:46:45.00' / Start UTC time in ISO f"),
755 Format(EsoKeyword("INS TIM2 START", "2019-07-27T02:46:45.00", "Start UTC time in ISO f")));
756}
757
758TEST(TestFormatting, LiteralKeyword) {
759 EXPECT_EQ(
761 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer"),
763 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer")));
764
765 EXPECT_EQ(
767 "HIERARCH ESO DET DID= '/home_local/eltdev/BUILDS/ifw-templates/test/temp/micado'"),
769 "HIERARCH ESO DET DID= '/home_local/eltdev/BUILDS/ifw-templates/test/temp/micado'")));
770
771 EXPECT_EQ(
773 "HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONX= T"),
774 Format(
775 EsoKeyword("LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONX", true)));
776 EXPECT_EQ(
778 "HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG= 'LONG LONG LONG LONG LONG LONX'"),
780 "LONG LONG LONG LONG LONG LONG LONG", "LONG LONG LONG LONG LONG LONX", "comment")));
781 EXPECT_EQ(
783 "HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG = 'LONG LONG LONG LONG LON' / te"),
785 "LONG LONG LONG LONG LONG LONG LONG", "LONG LONG LONG LONG LON", "test")));
786}
787
788TEST(TestFormatting, TooLongKeywords) {
789 // First test the longest possible ESO keyword while still formatting with padded value
790 // indicator ' = '.
791 EXPECT_EQ(LiteralKeyword("HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
792 "LONG LON = T"),
793 Format(EsoKeyword("LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LON",
794 true)));
795 // And packed `= ` value indicator
796 EXPECT_EQ(LiteralKeyword("HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
797 "LONG LONG= T"),
798 Format(EsoKeyword("LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG",
799 true)));
800 EXPECT_THROW(
801 LiteralKeyword("HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
802 "LONG LONX = T"),
803 std::invalid_argument);
804 EXPECT_THROW(Format(EsoKeyword(
805 "LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONXX", true)),
806 std::invalid_argument);
807 EXPECT_THROW(
808 Format(EsoKeyword("LONG LONG LONG LONG LONG LONG LONG", "LONG LONG LONG LONG LONG LONXX")),
809 std::invalid_argument);
810}
811
812TEST(TestFormatting, KeywordVariant) {
813 EXPECT_EQ(LiteralKeyword("ORIGIN = 'ESO-PARANAL' / European Southern Observatory"),
815 ValueKeyword("ORIGIN", "ESO-PARANAL", "European Southern Observatory"))));
816 EXPECT_EQ(LiteralKeyword("HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end"),
818 EsoKeyword("ADA ABSROT END", 36.5, "[deg] Abs rot angle at exp end"))));
819
820 auto kw = LiteralKeyword("HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end");
822}
823
824TEST(TestStandardSortV1, StableSortsValueKeywords) {
825 using namespace testing;
826 // Setup
827 std::vector<LiteralKeyword> kws;
828 kws.emplace_back("SIMPLE = T / Standard FITS");
829 kws.emplace_back("BITPIX = 8 / # of bits per pix value");
830 kws.emplace_back("NAXIS = 0 / # of axes in data array");
831
832 // Test
833 v1::StandardSort(kws);
834 EXPECT_THAT(kws,
835 ElementsAre(IsKeyword("SIMPLE", KeywordType::Value),
836 IsKeyword("BITPIX", KeywordType::Value),
837 IsKeyword("NAXIS", KeywordType::Value)));
838}
839
840TEST(TestStandardSortV1, StableSortsByKeywordType) {
841 using namespace testing;
842 // Setup
843 std::vector<LiteralKeyword> kws;
844 kws.emplace_back("COMMENT First");
845 kws.emplace_back("SIMPLE = T / Standard FITS");
846 kws.emplace_back("HIERARCH ESO KW = T / Comment");
847 kws.emplace_back("HIERARCH ESO DET A = T / Comment");
848 kws.emplace_back("COMMENT Second");
849 kws.emplace_back("BITPIX = 8 / # of bits per pix value");
850
851 // Test
852 auto sorted = kws;
853 v1::StandardSort(sorted);
854 EXPECT_THAT(sorted,
855 ElementsAre(IsKeyword("SIMPLE", KeywordType::Value),
856 IsKeyword("BITPIX", KeywordType::Value),
857 IsKeyword("DET A", KeywordType::Eso),
858 IsKeyword("KW", KeywordType::Eso),
859 kws[0],
860 kws[4]));
861}
862
863TEST(TestStandardSortV1, EsoKeywordsAreSortedByCategory) {
864 using namespace testing;
865 // Setup
866 std::vector<LiteralKeyword> kws;
867 kws.emplace_back("HIERARCH ESO DPR A = T / Comment");
868 kws.emplace_back("HIERARCH ESO DPR B = T / Comment");
869 kws.emplace_back("HIERARCH ESO DPR1 A = T / Comment");
870 kws.emplace_back("HIERARCH ESO DPR2 A = T / Comment");
871 kws.emplace_back("HIERARCH ESO OBS A = T / Comment");
872 kws.emplace_back("HIERARCH ESO OBS B = T / Comment");
873 kws.emplace_back("HIERARCH ESO TPL A = T / Comment");
874 kws.emplace_back("HIERARCH ESO TPL B = T / Comment");
875 kws.emplace_back("HIERARCH ESO GEN A = T / Comment");
876 kws.emplace_back("HIERARCH ESO GEN B = T / Comment");
877 kws.emplace_back("HIERARCH ESO TEL A = T / Comment");
878 kws.emplace_back("HIERARCH ESO TEL B = T / Comment");
879 kws.emplace_back("HIERARCH ESO ADA A = T / Comment");
880 kws.emplace_back("HIERARCH ESO ADA B = T / Comment");
881 kws.emplace_back("HIERARCH ESO INS A = T / Comment");
882 kws.emplace_back("HIERARCH ESO INS B = T / Comment");
883 kws.emplace_back("HIERARCH ESO DET A = T / Comment");
884 kws.emplace_back("HIERARCH ESO DET B = T / Comment");
885 kws.emplace_back("HIERARCH ESO DET1 A = T / Comment");
886 kws.emplace_back("HIERARCH ESO DET2 B = T / Comment");
887 kws.emplace_back("HIERARCH ESO DET3 A = T / Comment");
888 kws.emplace_back("HIERARCH ESO DET3 B = T / Comment");
889 kws.emplace_back("HIERARCH ESO DPRUN A = T / Comment");
890 kws.emplace_back("HIERARCH ESO UNK A = T / Comment");
891 kws.emplace_back("HIERARCH ESO UNK B = T / Comment");
892
893 auto [name, type] = kws[0].GetName();
894 ASSERT_EQ(name, "DPR A"sv);
895 ASSERT_EQ(type, KeywordType::Eso);
896
897 std::random_device rd;
898 std::mt19937 g(rd());
899 // Test
900 for (auto i = 0u; i < 20u; ++i) {
901 auto to_sort_kws = kws;
902 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
903 v1::StandardSort(to_sort_kws);
904 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
905 // Sorting again shouldn't do anything
906 v1::StandardSort(to_sort_kws);
907 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
908 }
909}
910
911TEST(TestStandardSortV1, EsoKeywordsAreSortedByNumberedCategory) {
912 using namespace testing;
913 // Setup
914 std::vector<LiteralKeyword> kws;
915 kws.emplace_back("HIERARCH ESO DPR Z = T / Comment");
916 kws.emplace_back("HIERARCH ESO DPR1 A = T / Comment");
917 kws.emplace_back("HIERARCH ESO DPR2 A = T / Comment");
918 kws.emplace_back("HIERARCH ESO DET ZZ ZZ = T / Comment");
919 kws.emplace_back("HIERARCH ESO DET1 A = T / Comment");
920 kws.emplace_back("HIERARCH ESO DET2 B = T / Comment");
921 kws.emplace_back("HIERARCH ESO DET3 A = T / Comment");
922 kws.emplace_back("HIERARCH ESO DET3 B = T / Comment");
923
924 std::random_device rd;
925 std::mt19937 g(rd());
926 // Test
927 for (auto i = 0u; i < 20u; ++i) {
928 auto to_sort_kws = kws;
929 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
930 v1::StandardSort(to_sort_kws);
931 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
932 // Sorting again shouldn't do anything
933 v1::StandardSort(to_sort_kws);
934 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
935 }
936}
937
938TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfCloslyMatched) {
939 using namespace testing;
940 // Setup
941 auto dpr = LiteralKeyword("HIERARCH ESO DPR=T");
942 auto det1 = LiteralKeyword("HIERARCH ESO DET1 A=T");
943 auto deta = LiteralKeyword("HIERARCH ESO DETA=Z/D");
944 EXPECT_TRUE(v1::StandardLess()(dpr, det1));
945 EXPECT_FALSE(v1::StandardLess()(det1, dpr));
946
947 EXPECT_TRUE(v1::StandardLess()(dpr, deta));
948 EXPECT_FALSE(v1::StandardLess()(deta, dpr));
949
950 EXPECT_TRUE(v1::StandardLess()(det1, deta));
951 EXPECT_FALSE(v1::StandardLess()(deta, det1));
952}
953
954TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfStrange) {
955 using namespace testing;
956 // Setup
957 std::vector<LiteralKeyword> kws;
958 kws.emplace_back("HIERARCH ESO A=T");
959 kws.emplace_back("HIERARCH ESO D=T");
960 kws.emplace_back("HIERARCH ESO D C=T/D");
961 kws.emplace_back("HIERARCH ESO E1=T");
962 kws.emplace_back("HIERARCH ESO E2 C=T/D");
963 kws.emplace_back("HIERARCH ESO F1A1=T");
964 kws.emplace_back("HIERARCH ESO F1A2 C=T/D");
965
966 std::random_device rd;
967 std::mt19937 g(rd());
968 // Test
969 for (auto i = 0u; i < 20u; ++i) {
970 auto to_sort_kws = kws;
971 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
972 v1::StandardSort(to_sort_kws);
973 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
974 }
975}
976
977TEST(TestStandardSortV1, CommentsSortedByName) {
978 using namespace testing;
979 // Setup
980 std::vector<LiteralKeyword> kws;
981 kws.emplace_back("COMMENT XXX");
982 kws.emplace_back("COMMENT AAA");
983 kws.emplace_back("HISTORY XXX");
984 kws.emplace_back("HISTORY AAA");
985
986 std::vector<LiteralKeyword> unordered;
987 unordered.emplace_back("HISTORY XXX");
988 unordered.emplace_back("COMMENT XXX");
989 unordered.emplace_back("HISTORY AAA");
990 unordered.emplace_back("COMMENT AAA");
991
992 // Test
993 v1::StandardSort(unordered);
994 EXPECT_THAT(unordered, ContainerEq(kws));
995}
996
997TEST(TestStandardSortV1, EsoKeywordsAreSortedAlphabetically) {
998 using namespace testing;
999 // Setup
1000 std::vector<LiteralKeyword> kws;
1001 kws.emplace_back("HIERARCH ESO KWB = T / Comment");
1002 kws.emplace_back("HIERARCH ESO KWA = T / Comment");
1003 kws.emplace_back("HIERARCH ESO KWA A = T / Comment");
1004 kws.emplace_back("HIERARCH ESO KWA1 A = T / Comment");
1005
1006 // Test
1007 v1::StandardSort(kws);
1008 EXPECT_THAT(kws,
1009 ElementsAre(IsKeyword("KWA", KeywordType::Eso),
1010 IsKeyword("KWA A", KeywordType::Eso),
1011 IsKeyword("KWA1 A", KeywordType::Eso),
1012 IsKeyword("KWB", KeywordType::Eso)));
1013}
Note that test cases must use TypeParam and cannot declare templated aliases.
void ExpectKeyword(std::string const &record, KeywordType type, std::string_view name, std::string_view logical_name)
Definition: testKeyword.cpp:25
Represents the literal 80-character FITS keyword record.
Definition: keyword.hpp:129
constexpr Components GetComponents() const &noexcept
Get components of the keyword in its literal form with insignifant whitespaces removed.
Definition: keyword.hpp:206
constexpr KeywordType GetType() const noexcept
Definition: keyword.hpp:174
std::string_view GetRecord() const &noexcept
Definition: keyword.cpp:532
constexpr KeywordNameView GetName() const &noexcept
Query logical keyword name.
Definition: keyword.hpp:190
Formats according to built-in rules without any dictionaries.
Definition: keyword.hpp:567
auto Format(KeywordVariant const &keyword) const -> LiteralKeyword override
Formats keyword.
Definition: keyword.cpp:812
Contains data structure for FITS keywords.
Contains common matchers.
void ReportNestedExceptions(std::ostream &os) noexcept
Definition: report.cpp:50
void StandardSort(std::vector< LiteralKeyword > &keywords)
Sorts keywords according to ESO DICD standards.
Definition: keyword.cpp:909
constexpr KeywordNameView GetKeywordName(EsoKeyword const &keyword) noexcept
Get keyword name from keyword.
Definition: keyword.hpp:436
void InsertKeywords(KeywordVector &keywords, KeywordVector::iterator position, KeywordVector::const_iterator from_first, KeywordVector::const_iterator from_last)
Insert keywords.
Definition: keyword.cpp:695
KeywordType
Type of FITS keyword.
Definition: keyword.hpp:68
bool NameEquals(KeywordVariant const &lhs, KeywordVariant const &rhs) noexcept
Compare logical keyword names of keyword of the same type.
Definition: keyword.cpp:606
LiteralKeyword Format(KeywordVariant const &keyword)
Definition: keyword.cpp:782
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
Definition: keyword.hpp:423
std::variant< ValueKeyword, EsoKeyword, LiteralKeyword > KeywordVariant
The different variants of keywords that are supported.
Definition: keyword.hpp:409
void UpdateKeywords(KeywordVector &to, KeywordVector const &from, ConflictPolicy policy=ConflictPolicy::Replace)
Updates to with keywords from from.
Definition: keyword.cpp:679
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
constexpr KeywordNameView GetName() const &noexcept
Query logical keyword name.
Definition: keyword.hpp:294
std::string_view name
Definition: keyword.hpp:84
Sorting function object.
Definition: keyword.hpp:604
TYPED_TEST(TestKeyword, Construction)
TYPED_TEST_CASE(TestKeyword, Types)
TEST(TestKeywordCombinations, OperatorLessComparesKeywordName)
::testing::Types< ValueKeyword, EsoKeyword > Types
TEST_F(TestLiteralKeyword, ConstructStrangeKeywords1)
Definition: testKeyword.cpp:45
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_EQ(meta.keyword_rules.size(), 1u)
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))