#include #include "../src/nfc.hh" // for illegal_utf8 exception #include using namespace pEp; using std::u16string_view; namespace pEp { std::string escape_utf16(u16string_view s); } namespace { struct TestEntry { u16string_view input; bool is_nfc; IsNFC quick; u16string_view nfc; }; typedef TestEntry TE; std::ostream& operator<<(std::ostream& o, const TestEntry& tt) { return o << "input=«" << pEp::escape_utf16(tt.input) << "», isNfc=" << tt.is_nfc << ", quick=" << tt.quick << ". "; } const char16_t nullo[4] = { 0, 0, 0, 0 }; const std::vector testValues = { { u"", true, IsNFC::Yes, u"" }, // always start with the simple case ;-) { u"123", true, IsNFC::Yes, u"123" }, // some ASCII digits. Still easy. { u"\n\\\b", true, IsNFC::Yes, u"\n\\\b" }, // backslash escapes for ASCII and control chars { u"ä", true, IsNFC::Yes, u"ä" }, // small a with diaeresis { u"\u0105", true, IsNFC::Yes, u"\u0105" }, // small a with ogonek { u"a\u0308", false, IsNFC::Maybe, u"ä" }, // a + combining diaresis { u"a\u0328", false, IsNFC::Maybe, u"\u0105" }, // a + combining ogonek { u"a\u0328\u0308", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (ogonek + diaeresis) { u"a\u0308\u0328", false, IsNFC::Maybe, u"\u0105\u0308" }, // a + + (diaeresis + ogonek) { u"\u0105\u0308", true, IsNFC::Maybe, u"\u0105\u0308" }, // small a with ogonek + combining diaeresis { u"ä\u0328", false, IsNFC::Maybe, u"\u0105\u0308" }, // a diaeresis + combining ogonek // Already implemented, because and have neither "No" nor "Maybe" NFC class: { u"a\u0305\u033c", false, IsNFC::No, u"a\u033c\u0305" }, // a + + (overline + seagull_below) { u"a\u033c\u0305", true, IsNFC::Yes, u"a\u033c\u0305" }, // a + + (seagull_below + overline) // MUSICAL SYMBOL SIXTEENTH NOTE -> will be decomposed and not re-composed according to Unicode data, for whatever reason. :-/ { u"\U0001D161", false, IsNFC::No, u"\U0001d15f\U0001d16f" }, { u16string_view(nullo, 1), true, IsNFC::Yes, u16string_view(nullo, 1) }, // Yeah, 1 NUL byte { u16string_view(nullo, 4), true, IsNFC::Yes, u16string_view(nullo, 4) }, // Yeah, 4 NUL bytes { u"EOF", true, IsNFC::Yes, u"EOF" } }; } // end of anonymous namespace class Nfc16Test : public ::testing::TestWithParam { // intentionally left blank for now. }; INSTANTIATE_TEST_SUITE_P(Nfc16TestInstance, Nfc16Test, testing::ValuesIn(testValues)); TEST_P(Nfc16Test, Meh) { const auto& v = GetParam(); EXPECT_EQ(v.quick, UTF16::isNFC_quick_check(v.input)); EXPECT_EQ(v.is_nfc, UTF16::isNFC(v.input)); EXPECT_EQ(v.nfc, UTF16::toNFC(v.input)); if (v.is_nfc) { EXPECT_EQ(v.input, UTF16::toNFC(v.input)); } }