9#include <gmock/gmock.h>
10#include <gtest/gtest.h>
11#include <nlohmann/json.hpp>
21using namespace std::string_view_literals;
27 std::string_view name,
28 std::string_view logical_name) {
29 using namespace ::testing;
33 EXPECT_THAT(record, StartsWith(std::string(kw.
GetRecord())));
35 auto [kw_name, kw_type] = kw.
GetName();
47 std::fill_n(std::back_inserter(too_long), constants::RECORD_LENGTH + 1,
'N');
48 ASSERT_EQ(too_long.size(), constants::RECORD_LENGTH + 1);
54 auto [name, type] = kw.
GetName();
62 auto [name, type] = kw.
GetName();
70 auto [name, type] = kw.
GetName();
78 auto [name, type] = kw.
GetName();
81 EXPECT_EQ(kw.GetRecord(),
"HIERARCH ESO A=T/");
86 auto [name, type] = kw.
GetName();
89 EXPECT_EQ(kw.GetRecord(),
"HIERARCH ESO A=''/");
94 auto [name, type] = kw.
GetName();
97 EXPECT_EQ(kw.GetRecord(),
"HIERARCH ESO A=''''''/");
102 auto [name, type] = kw.
GetName();
105 EXPECT_EQ(kw.GetComponents().value,
"''");
106 EXPECT_EQ(kw.GetComponents().comment,
"' /");
111 auto [name, type] = kw.
GetName();
112 EXPECT_EQ(name,
"HAS NO VALUE AFTER INDICATOR");
115 EXPECT_EQ(kw.GetComponents().comment,
"");
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");
124 EXPECT_EQ(kw.GetComponents().comment,
"with comment");
128 using namespace ::testing;
129 std::string_view record =
"ORIGIN = 'ESO-PARANAL' / European Southern Observatory";
131 std::array<char, constants::RECORD_LENGTH> array_record = {
' '};
132 std::copy(std::begin(record), std::end(record), std::begin(array_record));
134 EXPECT_THAT(std::string(kw.
GetRecord()), StartsWith(std::string(record)));
141 ExpectKeyword(
"SIMPLE = T / Standard FITS ",
148 ExpectKeyword(
"DATE = '2019-12-12T04:30:53.8930' / Date the file was written",
159 EXPECT_THROW(
LiteralKeyword(
"KEYWORD1= '"), std::invalid_argument);
160 EXPECT_THROW(
LiteralKeyword(
"KEYWORD1= '''"), std::invalid_argument);
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);
173 ExpectKeyword(
"HIERARCH ESO ADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
181 "HIERARCH ESO DEL DLT2 VCM CURV = 0.001512604 / mm-1 actual curv. of VCM beam i",
184 "DEL DLT2 VCM CURV");
189 "HIERARCH ESO DEL DLT2 VCM CURV=0.001512604 / mm-1 actual curv. of VCM beam i",
192 "DEL DLT2 VCM CURV");
196 ExpectKeyword(
"HIERARCH ESO N = 0.001512604 / mm-1 actual curv. of VCM beam i",
203 ExpectKeyword(
"HIERARCH ESO N =0.001512604 / mm-1 actual curv. of VCM beam i",
210 ExpectKeyword(
"HIERARCH ESO N= 0.001512604 / mm-1 actual curv. of VCM beam i",
217 ExpectKeyword(
"HIERARCH ESO N=0.001512604 / mm-1 actual curv. of VCM beam i",
229 auto [kw_name, kw_type] = kw.
GetName();
232 EXPECT_EQ(c.value,
"'/path/to/somewhere'");
239 auto [kw_name, kw_type] = kw.
GetName();
249 auto [kw_name, kw_type] = kw.
GetName();
259 auto [kw_name, kw_type] = kw.
GetName();
262 EXPECT_EQ(c.value,
"'escaped''/string'");
267 LiteralKeyword kw(
"HIERARCH ESO FOO BAR='escaped''string' / with comment");
269 auto [kw_name, kw_type] = kw.
GetName();
277 LiteralKeyword kw(
"HIERARCH ESO FOO BAR='escaped''string'/with comment");
279 auto [kw_name, kw_type] = kw.
GetName();
290 ExpectKeyword(
"COMMENT Some comment here", KeywordType::Commentary,
"COMMENT ",
"COMMENT");
294 ExpectKeyword(
"HISTORY Some comment here", KeywordType::Commentary,
"HISTORY ",
"HISTORY");
299 "HIERARCH DET.CAM.ID = 'TestCamera1Id' / System wide unique ID allocated to camer",
300 KeywordType::Commentary,
307 ExpectKeyword(
"HIERARCH ESOADA ABSROT END = 36.49838 / [deg] Abs rot angle at exp end",
308 KeywordType::Commentary,
315 ExpectKeyword(
"HIERARCH ESO ADA ABSROT END 36.49838 / [deg] Abs rot angle at exp end",
316 KeywordType::Commentary,
334 using namespace ::testing;
335 using namespace std::literals::string_view_literals;
339 auto view =
"HIERARCH ESO TEL MOON DEC = 22.00047 / [deg] 22:00:01.7 DEC (J2000)"sv;
341 std::stringstream ss;
346 auto view =
"COMMENT "sv;
348 std::stringstream ss;
356template <
typename Type>
359using Types = ::testing::Types<ValueKeyword, EsoKeyword>;
363 using Keyword = TypeParam;
365 Keyword orig(
"NAME", 1.0,
"comment");
367 EXPECT_EQ(orig.value,
typename Keyword::ValueType(1.0));
374 Keyword move_assign(
"TOBE",
"replaced");
375 move_assign = std::move(copy_assign);
378 Keyword copy_construct(orig);
381 Keyword move_construct(std::move(copy_construct));
386 using Keyword = TypeParam;
388 Keyword orig(
"NAME", 1.0, std::nullopt);
397 using Keyword = TypeParam;
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));
405 using Keyword = TypeParam;
407 Keyword lhs(
"NAME", 1.0,
"comment");
408 Keyword rhs(
"NAME", 1.0,
"comment");
410 EXPECT_TRUE(lhs == rhs);
412 EXPECT_FALSE(lhs != rhs);
414 rhs.comment = std::nullopt;
417 rhs.comment =
"comment ";
422 using Keyword = TypeParam;
424 Keyword lhs(
"A", 1.0,
"comment");
425 Keyword rhs(
"B", 1.0,
"comment");
428 EXPECT_FALSE(rhs < lhs);
429 EXPECT_FALSE(lhs < lhs);
433 using Keyword = TypeParam;
436 using namespace ::testing;
440 Keyword kw(
"NAME", std::string(
"value"),
"comment");
441 std::stringstream ss;
443 EXPECT_EQ(ss.str(),
"name='NAME', value=(str)'value', comment='comment'");
446 Keyword kw(
"NAME",
true, std::nullopt);
447 std::stringstream ss;
449 EXPECT_EQ(ss.str(),
"name='NAME', value=(bool)true, comment=n/a");
452 Keyword kw(
"NAME", 1234ul, std::nullopt);
453 std::stringstream ss;
455 EXPECT_THAT(ss.str(),
"name='NAME', value=(uint64_t)1234, comment=n/a");
458 Keyword kw(
"NAME", 1234l, std::nullopt);
459 std::stringstream ss;
461 EXPECT_THAT(ss.str(),
"name='NAME', value=(int64_t)1234, comment=n/a");
464 Keyword kw(
"NAME", 1.234, std::nullopt);
465 std::stringstream ss;
467 EXPECT_THAT(ss.str(),
"name='NAME', value=(double)1.234, comment=n/a");
471TEST(TestKeywordCombinations, OperatorLessComparesKeywordName) {
490 EXPECT_FALSE(value_kw < 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);
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);
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);
530 EXPECT_NE(literal_value_kw1.
GetName(), literal_eso_kw1.
GetName());
531 EXPECT_NE(literal_value_kw1.
GetName(), literal_commentary_kw1.
GetName());
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));
546 using namespace ::testing;
591 EXPECT_THAT(to, ContainerEq(result));
596 using namespace ::testing;
624 EXPECT_THAT(to, ContainerEq(result));
629 using namespace ::testing;
655 EXPECT_THAT(to, ContainerEq(result));
660 using namespace ::testing;
686 auto pos = to.begin();
687 std::advance(pos, 3);
689 EXPECT_THAT(to, ContainerEq(result));
696 auto kw =
ValueKeyword(
"DATE-OBS",
"2019-12-12T04:25:48.0068",
"Observing date");
701 LiteralKeyword(
"DATE = '2019-12-12T04:30:53.8930' / Date the file was written");
705 auto kw =
EsoKeyword(
"ADA ABSROT END", 36.5,
"[deg] Abs rot angle at exp end");
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")));
723 LiteralKeyword(
"INHERIT = F / denotes the INHERIT keyword convention"),
728 <<
"XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
731 <<
"XTENSION has an exception and must be padded to be minimum 8 chars for legacy reasons";
736 Format(
EsoKeyword(
"ADA ABSROT END", 36.5,
"[deg] Abs rot angle at exp end")));
740 Format(
EsoKeyword(
"DET ACQ1 REV", 1lu,
"Pre-processor framework revision")));
745 "HIERARCH ESO DET CLDC1 DCNM16 = 'DC16_RelaySwitchLowActive' / Name of bias volta"),
747 EsoKeyword(
"DET CLDC1 DCNM16",
"DC16_RelaySwitchLowActive",
"Name of bias voltage")));
750 "HIERARCH ESO PCR SUMMARY NSCANNED = 1273000 / Total Number of scanned records."),
751 Format(
EsoKeyword(
"PCR SUMMARY NSCANNED", 1273000ul,
"Total Number of scanned records.")));
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")));
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")));
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'")));
773 "HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONX= T"),
775 EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONX",
true)));
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")));
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")));
788TEST(TestFormatting, TooLongKeywords) {
793 Format(
EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LON",
798 Format(
EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG",
801 LiteralKeyword(
"HIERARCH ESO LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG "
803 std::invalid_argument);
805 "LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONG LONXX",
true)),
806 std::invalid_argument);
808 Format(
EsoKeyword(
"LONG LONG LONG LONG LONG LONG LONG",
"LONG LONG LONG LONG LONG LONXX")),
809 std::invalid_argument);
815 ValueKeyword(
"ORIGIN",
"ESO-PARANAL",
"European Southern Observatory"))));
818 EsoKeyword(
"ADA ABSROT END", 36.5,
"[deg] Abs rot angle at exp end"))));
820 auto kw =
LiteralKeyword(
"HIERARCH ESO ADA ABSROT END = 36.5 / [deg] Abs rot angle at exp end");
824TEST(TestStandardSortV1, StableSortsValueKeywords) {
825 using namespace testing;
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");
835 ElementsAre(IsKeyword(
"SIMPLE", KeywordType::Value),
836 IsKeyword(
"BITPIX", KeywordType::Value),
837 IsKeyword(
"NAXIS", KeywordType::Value)));
840TEST(TestStandardSortV1, StableSortsByKeywordType) {
841 using namespace testing;
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");
855 ElementsAre(IsKeyword(
"SIMPLE", KeywordType::Value),
856 IsKeyword(
"BITPIX", KeywordType::Value),
857 IsKeyword(
"DET A", KeywordType::Eso),
858 IsKeyword(
"KW", KeywordType::Eso),
863TEST(TestStandardSortV1, EsoKeywordsAreSortedByCategory) {
864 using namespace testing;
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");
893 auto [name, type] = kws[0].GetName();
897 std::random_device rd;
898 std::mt19937 g(rd());
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);
904 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
907 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
911TEST(TestStandardSortV1, EsoKeywordsAreSortedByNumberedCategory) {
912 using namespace testing;
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");
924 std::random_device rd;
925 std::mt19937 g(rd());
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);
931 ASSERT_THAT(to_sort_kws, ContainerEq(kws));
934 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
938TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfCloslyMatched) {
939 using namespace testing;
954TEST(TestStandardSortV1, EsoKeywordAreSortedEvenIfStrange) {
955 using namespace testing;
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");
966 std::random_device rd;
967 std::mt19937 g(rd());
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);
973 EXPECT_THAT(to_sort_kws, ContainerEq(kws));
977TEST(TestStandardSortV1, CommentsSortedByName) {
978 using namespace testing;
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");
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");
994 EXPECT_THAT(unordered, ContainerEq(kws));
997TEST(TestStandardSortV1, EsoKeywordsAreSortedAlphabetically) {
998 using namespace testing;
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");
1009 ElementsAre(IsKeyword(
"KWA", KeywordType::Eso),
1010 IsKeyword(
"KWA A", KeywordType::Eso),
1011 IsKeyword(
"KWA1 A", KeywordType::Eso),
1012 IsKeyword(
"KWB", KeywordType::Eso)));
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)
Represents the literal 80-character FITS keyword record.
constexpr Components GetComponents() const &noexcept
Get components of the keyword in its literal form with insignifant whitespaces removed.
constexpr KeywordType GetType() const noexcept
std::string_view GetRecord() const &noexcept
constexpr KeywordNameView GetName() const &noexcept
Query logical keyword name.
Contains data structure for FITS keywords.
Contains common matchers.
void ReportNestedExceptions(std::ostream &os) noexcept
void StandardSort(std::vector< LiteralKeyword > &keywords)
Sorts keywords according to ESO DICD standards.
constexpr KeywordNameView GetKeywordName(EsoKeyword const &keyword) noexcept
Get keyword name from keyword.
void InsertKeywords(KeywordVector &keywords, KeywordVector::iterator position, KeywordVector::const_iterator from_first, KeywordVector::const_iterator from_last)
Insert keywords.
KeywordType
Type of FITS keyword.
bool NameEquals(KeywordVariant const &lhs, KeywordVariant const &rhs) noexcept
Compare logical keyword names of keyword of the same type.
LiteralKeyword Format(KeywordVariant const &keyword)
std::vector< KeywordVariant > KeywordVector
Vector of keywords.
std::variant< ValueKeyword, EsoKeyword, LiteralKeyword > KeywordVariant
The different variants of keywords that are supported.
void UpdateKeywords(KeywordVector &to, KeywordVector const &from, ConflictPolicy policy=ConflictPolicy::Replace)
Updates to with keywords from from.
BasicKeyword< ValueKeywordTraits > ValueKeyword
Standard FITS value keyword.
BasicKeyword< EsoKeywordTraits > EsoKeyword
ESO hiearchical keyword.
A type safe version of LiteralKeyword that consist of the three basic components of a FITS keyword ke...
constexpr KeywordNameView GetName() const &noexcept
Query logical keyword name.
TYPED_TEST(TestKeyword, Construction)
TYPED_TEST_CASE(TestKeyword, Types)
TEST(TestKeywordCombinations, OperatorLessComparesKeywordName)
::testing::Types< ValueKeyword, EsoKeyword > Types
TEST_F(TestLiteralKeyword, ConstructStrangeKeywords1)
EXPECT_EQ(meta.rr_uri, "zpb.rr://meta")
ASSERT_EQ(meta.keyword_rules.size(), 1u)
ASSERT_TRUE(std::holds_alternative< OlasReceiver >(spec.receivers[0]))