#include #include "../src/nfc.hh" // for illegal_utf8 exception #include using namespace pEp; using std::string_view; namespace { struct TestEntry { string_view input; string_view nfc; }; typedef TestEntry TE; std::ostream& operator<<(std::ostream& o, const TestEntry& tt) { return o << "input=«" << tt.input << "», nfc=«" << tt.nfc << "» "; } } // end of anonymous namespace TEST(NfcTestString, Simple) { pEp::nfc_string s; EXPECT_TRUE(s.empty()); EXPECT_EQ(s.size(), 0); s.reserve(1000); EXPECT_GE(s.capacity(), 1000); s = "Ha\u0308user"; // non-NFC input will be normalized. EXPECT_NE(s.get(), std::string("Ha\u0308user")); EXPECT_EQ(s.get(), std::string("Häuser")); s.insert(0, "U\u0308ber"); EXPECT_EQ(s.get(), std::string("ÜberHäuser")); s += "\u0328\u030c"; // COMBINING OGONEK (below), COMBINING CARON (above) // r absorbs the caron into U+0159, the combining ogonek remains separate EXPECT_EQ(s.get(), std::string("ÜberHäuse\u0159\u0328")); EXPECT_EQ(s.size(), 15); EXPECT_THROW(s.substr(1), pEp::illegal_utf); EXPECT_THROW(s.substr(2, 10), pEp::illegal_utf); // removal of the r-with-caron let the remaining ogonek combine with the e to U+0119 (E WITH OGONEK) EXPECT_EQ(s.erase(11, 2).get(), "ÜberHäus\u0119"); EXPECT_TRUE(s.starts_with("Üb")); EXPECT_FALSE(s.starts_with("Üx")); EXPECT_TRUE(s.ends_with("s\u0119")); EXPECT_FALSE(s.ends_with("ss\u0119")); EXPECT_EQ(s.find("Über"), 0u); EXPECT_EQ(s.find("ber"), 2u); EXPECT_EQ(s.find("über"), UTF8::nfc_string::npos); EXPECT_EQ(s.find("Übel"), UTF8::nfc_string::npos); } TEST(NfcTestString, Exceptions) { pEp::nfc_string s; EXPECT_THROW(s = "Meep\xc0\x80.", pEp::illegal_utf); EXPECT_THROW(s += '\377', pEp::illegal_utf); }