12 #include <gmock/gmock.h>
13 #include <gtest/gtest.h>
14 #include <nlohmann/json.hpp>
22 using namespace std::string_view_literals;
28 std::string_view name,
29 std::string_view logical_name) {
30 using namespace ::testing;
34 EXPECT_THAT(record, StartsWith(kw.
GetRecord()));
36 auto [kw_name, kw_type] = kw.
GetName();
37 EXPECT_EQ(kw_name, logical_name);
38 EXPECT_EQ(type, kw_type);
48 std::fill_n(std::back_inserter(too_long), constants::RECORD_LENGTH + 1,
'N');
49 ASSERT_EQ(too_long.size(), constants::RECORD_LENGTH + 1);
55 auto [name, type] = kw.
GetName();
58 EXPECT_EQ(kw.GetRecord(),
" ");
63 auto [name, type] = kw.
GetName();
66 EXPECT_EQ(kw.GetRecord(),
"A");
71 auto [name, type] = kw.
GetName();
74 EXPECT_EQ(kw.GetRecord(),
"A =");
79 auto [name, type] = kw.
GetName();
82 EXPECT_EQ(kw.GetRecord(),
"HIERARCH ESO A=T/");
87 auto [name, type] = kw.
GetName();
90 EXPECT_EQ(kw.GetRecord(),
"HIERARCH ESO A=''/");
94 using namespace ::testing;
95 std::string_view record =
"ORIGIN = 'ESO-PARANAL' / European Southern Observatory";
97 std::array<char, constants::RECORD_LENGTH> array_record = {
' '};
98 std::copy(std::begin(record), std::end(record), std::begin(array_record));
100 EXPECT_THAT(kw.
GetRecord(), StartsWith(record));
107 ExpectKeyword(
"SIMPLE = T / Standard FITS ",
114 ExpectKeyword(
"DATE = '2019-12-12T04:30:53.8930' / Date the file was written",
125 EXPECT_THROW(
LiteralKeyword(
"HIERARCH ESO HAS NO VALUE AFTER INDICATOR="),
126 std::invalid_argument);
132 ExpectKeyword(
"HIERARCH ESO ADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
140 "HIERARCH ESO DEL DLT2 VCM CURV = 0.001512604 / mm-1 actual curv. of VCM beam i",
143 "DEL DLT2 VCM CURV");
148 "HIERARCH ESO DEL DLT2 VCM CURV=0.001512604 / mm-1 actual curv. of VCM beam i",
151 "DEL DLT2 VCM CURV");
155 ExpectKeyword(
"HIERARCH ESO N = 0.001512604 / mm-1 actual curv. of VCM beam i",
162 ExpectKeyword(
"HIERARCH ESO N =0.001512604 / mm-1 actual curv. of VCM beam i",
169 ExpectKeyword(
"HIERARCH ESO N= 0.001512604 / mm-1 actual curv. of VCM beam i",
176 ExpectKeyword(
"HIERARCH ESO N=0.001512604 / mm-1 actual curv. of VCM beam i",
195 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer",
203 ExpectKeyword(
"HIERARCH ESOADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
211 ExpectKeyword(
"HIERARCH ESO ADA ABSROT END 36.49838 / [deg] Abs rot angle at exp end",
222 EXPECT_EQ(kw2, kw2_copy);
230 using namespace ::testing;
231 using namespace std::literals::string_view_literals;
235 auto view =
"HIERARCH ESO TEL MOON DEC = 22.00047 / [deg] 22:00:01.7 DEC (J2000)"sv;
237 std::stringstream ss;
239 EXPECT_EQ(ss.str(), view);
242 auto view =
"COMMENT "sv;
244 std::stringstream ss;
246 EXPECT_EQ(ss.str(),
"COMMENT"sv);
252 template <
typename Type>
255 using Types = ::testing::Types<ValueKeyword, EsoKeyword>;
259 using Keyword = TypeParam;
261 Keyword orig(
"NAME", 1.0,
"comment");
262 EXPECT_EQ(orig.name,
"NAME");
263 EXPECT_EQ(orig.value,
typename Keyword::ValueType(1.0));
264 EXPECT_EQ(orig.comment,
"comment");
268 EXPECT_EQ(orig, copy_assign);
270 Keyword move_assign(
"TOBE",
"replaced");
271 move_assign = std::move(copy_assign);
272 EXPECT_EQ(orig, move_assign);
274 Keyword copy_construct(orig);
275 EXPECT_EQ(orig, copy_construct);
277 Keyword move_construct(std::move(copy_construct));
278 EXPECT_EQ(orig, move_construct);
282 using Keyword = TypeParam;
284 Keyword orig(
"NAME", 1.0, std::nullopt);
285 EXPECT_EQ(orig.comment, std::nullopt);
293 using Keyword = TypeParam;
295 Keyword kw(
"NAME",
"str",
"comment");
296 ASSERT_TRUE(std::holds_alternative<std::string>(kw.value));
297 EXPECT_EQ(
"str", std::get<std::string>(kw.value));
301 using Keyword = TypeParam;
303 Keyword lhs(
"NAME", 1.0,
"comment");
304 Keyword rhs(
"NAME", 1.0,
"comment");
306 EXPECT_TRUE(lhs == rhs);
308 EXPECT_FALSE(lhs != rhs);
310 rhs.comment = std::nullopt;
313 rhs.comment =
"comment ";
318 using Keyword = TypeParam;
320 Keyword lhs(
"A", 1.0,
"comment");
321 Keyword rhs(
"B", 1.0,
"comment");
324 EXPECT_FALSE(rhs < lhs);
325 EXPECT_FALSE(lhs < lhs);
329 using Keyword = TypeParam;
332 using namespace ::testing;
336 Keyword kw(
"NAME", std::string(
"value"),
"comment");
337 std::stringstream ss;
339 EXPECT_EQ(ss.str(),
"name='NAME', value=(str)'value', comment='comment'");
342 Keyword kw(
"NAME",
true, std::nullopt);
343 std::stringstream ss;
345 EXPECT_EQ(ss.str(),
"name='NAME', value=(bool)true, comment=n/a");
348 Keyword kw(
"NAME", 1234ul, std::nullopt);
349 std::stringstream ss;
351 EXPECT_THAT(ss.str(),
"name='NAME', value=(uint64_t)1234, comment=n/a");
354 Keyword kw(
"NAME", 1234l, std::nullopt);
355 std::stringstream ss;
357 EXPECT_THAT(ss.str(),
"name='NAME', value=(int64_t)1234, comment=n/a");
360 Keyword kw(
"NAME", 1.234, std::nullopt);
361 std::stringstream ss;
363 EXPECT_THAT(ss.str(),
"name='NAME', value=(double)1.234, comment=n/a");
367 TEST(TestKeywordCombinations, OperatorLessComparesKeywordName) {
386 EXPECT_FALSE(value_kw < eso_kw);
388 EXPECT_LT(literal_value_kw1, literal_value_kw2);
389 EXPECT_FALSE(literal_value_kw1 < literal_eso_kw1);
390 EXPECT_FALSE(literal_value_kw1 < literal_eso_kw2);
391 EXPECT_LT(literal_eso_kw1, literal_eso_kw2);
393 EXPECT_LT(value_kw, literal_commentary_kw1);
394 EXPECT_LT(eso_kw, literal_commentary_kw1);
395 EXPECT_LT(literal_value_kw1, literal_commentary_kw1);
396 EXPECT_LT(literal_eso_kw1, literal_commentary_kw1);
397 EXPECT_LT(literal_commentary_kw1, literal_commentary_kw2);
399 EXPECT_FALSE(literal_eso_kw1 < eso_kw);
400 EXPECT_FALSE(value_kw < value_kw);
401 EXPECT_FALSE(eso_kw < eso_kw);
402 EXPECT_FALSE(eso_kw < value_kw);
403 EXPECT_FALSE(literal_eso_kw1 < value_kw);
404 EXPECT_FALSE(literal_commentary_kw1 < literal_commentary_kw1);
405 EXPECT_FALSE(literal_commentary_kw2 < literal_commentary_kw1);
418 EXPECT_EQ(view, eso_kw.
GetName());
423 EXPECT_NE(literal_value_kw1.
GetName(), literal_eso_kw1.
GetName());
424 EXPECT_NE(literal_value_kw1.
GetName(), literal_commentary_kw1.
GetName());
427 EXPECT_EQ(literal_commentary_kw1.
GetName(), literal_commentary_kw2.
GetName());
435 using namespace ::testing;
458 EXPECT_THAT(to, ContainerEq(result));
463 using namespace ::testing;
491 EXPECT_THAT(to, ContainerEq(result));
496 using namespace ::testing;
522 EXPECT_THAT(to, ContainerEq(result));
527 using namespace ::testing;
553 auto pos = to.begin();
554 std::advance(pos, 3);
556 EXPECT_THAT(to, ContainerEq(result));
560 EXPECT_EQ(
LiteralKeyword(
"DATE-OBS= '2019-12-12T04:25:48.0068' / Observing date"),
563 LiteralKeyword(
"DATE = '2019-12-12T04:30:53.8930' / Date the file was written"),
564 Format(
ValueKeyword(
"DATE",
"2019-12-12T04:30:53.8930",
"Date the file was written")));
567 EXPECT_EQ(
LiteralKeyword(
"EXTEND = T / FITS Extension may be present"),
569 EXPECT_EQ(
LiteralKeyword(
"ORIGIN = 'ESO-PARANAL' / European Southern Observatory"),
572 LiteralKeyword(
"INHERIT = F / denotes the INHERIT keyword convention"),
577 <<
"XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
578 EXPECT_EQ(
LiteralKeyword(
"XTENSION= 'CUSTOM-EXTENSION-TYPE' / Image extension"),
580 <<
"XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
584 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end"),
585 Format(
EsoKeyword(
"ADA ABSROT END", 36.5,
"[deg] Abs rot angle at exp end")));
586 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO ADA ABSROT PPOS = 'POS' / sign of probe position"),
588 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO DET ACQ1 REV = 1 / Pre-processor framework revision"),
589 Format(
EsoKeyword(
"DET ACQ1 REV", 1lu,
"Pre-processor framework revision")));
590 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO DET ADC1 CLAMP = F / Clamp-and-Sample"),
594 "HIERARCH ESO DET CLDC1 DCNM16 = 'DC16_RelaySwitchLowActive' / Name of bias volta"),
596 EsoKeyword(
"DET CLDC1 DCNM16",
"DC16_RelaySwitchLowActive",
"Name of bias voltage")));
599 "HIERARCH ESO PCR SUMMARY NSCANNED = 1273000 / Total Number of scanned records."),
600 Format(
EsoKeyword(
"PCR SUMMARY NSCANNED", 1273000ul,
"Total Number of scanned records.")));
603 "HIERARCH ESO INS TIM2 START = '2019-07-27T02:46:45.00' / Start UTC time in ISO f"),
604 Format(
EsoKeyword(
"INS TIM2 START",
"2019-07-27T02:46:45.00",
"Start UTC time in ISO f")));
610 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer"),
612 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer")));
615 TEST(TestFormatting, TooLongKeywords) {
618 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
620 Format(
EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LON",
623 LiteralKeyword(
"HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
625 std::invalid_argument);
627 "LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONX",
true)),
628 std::invalid_argument);
630 Format(
EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG",
"LONG LONG LONG LONG LONG LONX")),
631 std::invalid_argument);
635 EXPECT_EQ(
LiteralKeyword(
"ORIGIN = 'ESO-PARANAL' / European Southern Observatory"),
637 ValueKeyword(
"ORIGIN",
"ESO-PARANAL",
"European Southern Observatory"))));
638 EXPECT_EQ(
LiteralKeyword(
"HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end"),
640 EsoKeyword(
"ADA ABSROT END", 36.5,
"[deg] Abs rot angle at exp end"))));
642 auto kw =
LiteralKeyword(
"HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end");
646 TEST(TestStandardSortV1, StableSortsValueKeywords) {
647 using namespace testing;
649 std::vector<LiteralKeyword> kws;
650 kws.emplace_back(
"SIMPLE = T / Standard FITS");
651 kws.emplace_back(
"BITPIX = 8 / # of bits per pix value");
652 kws.emplace_back(
"NAXIS = 0 / # of axes in data array");
662 TEST(TestStandardSortV1, StableSortsByKeywordType) {
663 using namespace testing;
665 std::vector<LiteralKeyword> kws;
666 kws.emplace_back(
"COMMENT First");
667 kws.emplace_back(
"SIMPLE = T / Standard FITS");
668 kws.emplace_back(
"HIERARCH ESO KW = T / Comment");
669 kws.emplace_back(
"HIERARCH ESO DET A = T / Comment");
670 kws.emplace_back(
"COMMENT Second");
671 kws.emplace_back(
"BITPIX = 8 / # of bits per pix value");
685 TEST(TestStandardSortV1, EsoKeywordsAreSortedByCategory) {
686 using namespace testing;
688 std::vector<LiteralKeyword> kws;
689 kws.emplace_back(
"HIERARCH ESO DPR A = T / Comment");
690 kws.emplace_back(
"HIERARCH ESO DPR B = T / Comment");
691 kws.emplace_back(
"HIERARCH ESO DPR1 A = T / Comment");
692 kws.emplace_back(
"HIERARCH ESO DPR2 A = T / Comment");
693 kws.emplace_back(
"HIERARCH ESO OBS A = T / Comment");
694 kws.emplace_back(
"HIERARCH ESO OBS B = T / Comment");
695 kws.emplace_back(
"HIERARCH ESO TPL A = T / Comment");
696 kws.emplace_back(
"HIERARCH ESO TPL B = T / Comment");
697 kws.emplace_back(
"HIERARCH ESO GEN A = T / Comment");
698 kws.emplace_back(
"HIERARCH ESO GEN B = T / Comment");
699 kws.emplace_back(
"HIERARCH ESO TEL A = T / Comment");
700 kws.emplace_back(
"HIERARCH ESO TEL B = T / Comment");
701 kws.emplace_back(
"HIERARCH ESO ADA A = T / Comment");
702 kws.emplace_back(
"HIERARCH ESO ADA B = T / Comment");
703 kws.emplace_back(
"HIERARCH ESO INS A = T / Comment");
704 kws.emplace_back(
"HIERARCH ESO INS B = T / Comment");
705 kws.emplace_back(
"HIERARCH ESO DET A = T / Comment");
706 kws.emplace_back(
"HIERARCH ESO DET B = T / Comment");
707 kws.emplace_back(
"HIERARCH ESO DET1 A = T / Comment");
708 kws.emplace_back(
"HIERARCH ESO DET2 B = T / Comment");
709 kws.emplace_back(
"HIERARCH ESO DET3 A = T / Comment");
710 kws.emplace_back(
"HIERARCH ESO DET3 B = T / Comment");
711 kws.emplace_back(
"HIERARCH ESO DPRUN A = T / Comment");
712 kws.emplace_back(
"HIERARCH ESO UNK A = T / Comment");
713 kws.emplace_back(
"HIERARCH ESO UNK B = T / Comment");
715 auto [name, type] = kws[0].GetName();
716 ASSERT_EQ(name,
"DPR A"sv);
719 std::random_device rd;
720 std::mt19937 g(rd());
722 for (
auto i = 0u;
i < 20u; ++
i) {
723 auto to_sort_kws = kws;
724 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
726 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
729 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
733 TEST(TestStandardSortV1, EsoKeywordsAreSortedByNumberedCategory) {
734 using namespace testing;
736 std::vector<LiteralKeyword> kws;
737 kws.emplace_back(
"HIERARCH ESO DPR Z = T / Comment");
738 kws.emplace_back(
"HIERARCH ESO DPR1 A = T / Comment");
739 kws.emplace_back(
"HIERARCH ESO DPR2 A = T / Comment");
740 kws.emplace_back(
"HIERARCH ESO DET ZZ ZZ = T / Comment");
741 kws.emplace_back(
"HIERARCH ESO DET1 A = T / Comment");
742 kws.emplace_back(
"HIERARCH ESO DET2 B = T / Comment");
743 kws.emplace_back(
"HIERARCH ESO DET3 A = T / Comment");
744 kws.emplace_back(
"HIERARCH ESO DET3 B = T / Comment");
746 std::random_device rd;
747 std::mt19937 g(rd());
749 for (
auto i = 0u;
i < 20u; ++
i) {
750 auto to_sort_kws = kws;
751 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
753 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
756 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
760 TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfCloslyMatched) {
761 using namespace testing;
776 TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfStrange) {
777 using namespace testing;
779 std::vector<LiteralKeyword> kws;
780 kws.emplace_back(
"HIERARCH ESO A=T");
781 kws.emplace_back(
"HIERARCH ESO D=T");
782 kws.emplace_back(
"HIERARCH ESO D C=T/D");
783 kws.emplace_back(
"HIERARCH ESO E1=T");
784 kws.emplace_back(
"HIERARCH ESO E2 C=T/D");
785 kws.emplace_back(
"HIERARCH ESO F1A1=T");
786 kws.emplace_back(
"HIERARCH ESO F1A2 C=T/D");
788 std::random_device rd;
789 std::mt19937 g(rd());
791 for (
auto i = 0u;
i < 20u; ++
i) {
792 auto to_sort_kws = kws;
793 std::shuffle(std::begin(to_sort_kws), std::end(to_sort_kws), g);
795 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
799 TEST(TestStandardSortV1, CommentsSortedByName) {
800 using namespace testing;
802 std::vector<LiteralKeyword> kws;
803 kws.emplace_back(
"COMMENT XXX");
804 kws.emplace_back(
"COMMENT AAA");
805 kws.emplace_back(
"HISTORY XXX");
806 kws.emplace_back(
"HISTORY AAA");
808 std::vector<LiteralKeyword> unordered;
809 unordered.emplace_back(
"HISTORY XXX");
810 unordered.emplace_back(
"COMMENT XXX");
811 unordered.emplace_back(
"HISTORY AAA");
812 unordered.emplace_back(
"COMMENT AAA");
816 EXPECT_THAT(unordered, ContainerEq(kws));
819 TEST(TestStandardSortV1, EsoKeywordsAreSortedAlphabetically) {
820 using namespace testing;
822 std::vector<LiteralKeyword> kws;
823 kws.emplace_back(
"HIERARCH ESO KWB = T / Comment");
824 kws.emplace_back(
"HIERARCH ESO KWA = T / Comment");
825 kws.emplace_back(
"HIERARCH ESO KWA A = T / Comment");
826 kws.emplace_back(
"HIERARCH ESO KWA1 A = T / Comment");