diff options
Diffstat (limited to 'unittests/Support/YAMLIOTest.cpp')
-rw-r--r-- | unittests/Support/YAMLIOTest.cpp | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 914b22f0fcdf..133648065240 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -13,6 +13,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/Format.h" #include "llvm/Support/YAMLTraits.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" using llvm::yaml::Input; @@ -25,6 +26,7 @@ using llvm::yaml::Hex8; using llvm::yaml::Hex16; using llvm::yaml::Hex32; using llvm::yaml::Hex64; +using ::testing::StartsWith; @@ -249,6 +251,72 @@ TEST(YAMLIO, TestGivenFilename) { EXPECT_TRUE(!!yin.error()); } +struct WithStringField { + std::string str1; + std::string str2; + std::string str3; +}; + +namespace llvm { +namespace yaml { +template <> struct MappingTraits<WithStringField> { + static void mapping(IO &io, WithStringField &fb) { + io.mapRequired("str1", fb.str1); + io.mapRequired("str2", fb.str2); + io.mapRequired("str3", fb.str3); + } +}; +} // namespace yaml +} // namespace llvm + +TEST(YAMLIO, MultilineStrings) { + WithStringField Original; + Original.str1 = "a multiline string\nfoobarbaz"; + Original.str2 = "another one\rfoobarbaz"; + Original.str3 = "a one-line string"; + + std::string Serialized; + { + llvm::raw_string_ostream OS(Serialized); + Output YOut(OS); + YOut << Original; + } + auto Expected = "---\n" + "str1: 'a multiline string\n" + "foobarbaz'\n" + "str2: 'another one\r" + "foobarbaz'\n" + "str3: a one-line string\n" + "...\n"; + ASSERT_EQ(Serialized, Expected); + + // Also check it parses back without the errors. + WithStringField Deserialized; + { + Input YIn(Serialized); + YIn >> Deserialized; + ASSERT_FALSE(YIn.error()) + << "Parsing error occurred during deserialization. Serialized string:\n" + << Serialized; + } + EXPECT_EQ(Original.str1, Deserialized.str1); + EXPECT_EQ(Original.str2, Deserialized.str2); + EXPECT_EQ(Original.str3, Deserialized.str3); +} + +TEST(YAMLIO, NoQuotesForTab) { + WithStringField WithTab; + WithTab.str1 = "aba\tcaba"; + std::string Serialized; + { + llvm::raw_string_ostream OS(Serialized); + Output YOut(OS); + YOut << WithTab; + } + auto ExpectedPrefix = "---\n" + "str1: aba\tcaba\n"; + EXPECT_THAT(Serialized, StartsWith(ExpectedPrefix)); +} //===----------------------------------------------------------------------===// // Test built-in types @@ -533,6 +601,7 @@ struct StringTypes { std::string stdstr9; std::string stdstr10; std::string stdstr11; + std::string stdstr12; }; namespace llvm { @@ -562,6 +631,7 @@ namespace yaml { io.mapRequired("stdstr9", st.stdstr9); io.mapRequired("stdstr10", st.stdstr10); io.mapRequired("stdstr11", st.stdstr11); + io.mapRequired("stdstr12", st.stdstr12); } }; } @@ -593,6 +663,7 @@ TEST(YAMLIO, TestReadWriteStringTypes) { map.stdstr9 = "~"; map.stdstr10 = "0.2e20"; map.stdstr11 = "0x30"; + map.stdstr12 = "- match"; llvm::raw_string_ostream ostr(intermediate); Output yout(ostr); @@ -611,6 +682,7 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'- match'\n")); EXPECT_NE(std::string::npos, flowOut.find("'''eee")); EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); @@ -2460,7 +2532,10 @@ static void TestEscaped(llvm::StringRef Input, llvm::StringRef Expected) { yamlize(xout, Input, true, Ctx); ostr.flush(); - EXPECT_EQ(Expected, out); + + // Make a separate StringRef so we get nice byte-by-byte output. + llvm::StringRef Got(out); + EXPECT_EQ(Expected, Got); } TEST(YAMLIO, TestEscaped) { @@ -2481,4 +2556,16 @@ TEST(YAMLIO, TestEscaped) { // UTF8 with single quote inside double quote TestEscaped("parameter 'параметр' is unused", "\"parameter 'параметр' is unused\""); + + // String with embedded non-printable multibyte UTF-8 sequence (U+200B + // zero-width space). The thing to test here is that we emit a + // unicode-scalar level escape like \uNNNN (at the YAML level), and don't + // just pass the UTF-8 byte sequence through as with quoted printables. + { + const unsigned char foobar[10] = {'f', 'o', 'o', + 0xE2, 0x80, 0x8B, // UTF-8 of U+200B + 'b', 'a', 'r', + 0x0}; + TestEscaped((char const *)foobar, "\"foo\\u200Bbar\""); + } } |