diff options
Diffstat (limited to 'unittests/Support/YAMLIOTest.cpp')
-rw-r--r-- | unittests/Support/YAMLIOTest.cpp | 441 |
1 files changed, 393 insertions, 48 deletions
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 0993d8c..6c0b9e6 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -58,14 +58,24 @@ namespace yaml { // TEST(YAMLIO, TestMapRead) { FooBar doc; - Input yin("---\nfoo: 3\nbar: 5\n...\n"); - yin >> doc; + { + Input yin("---\nfoo: 3\nbar: 5\n...\n"); + yin >> doc; - EXPECT_FALSE(yin.error()); - EXPECT_EQ(doc.foo, 3); - EXPECT_EQ(doc.bar,5); -} + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.foo, 3); + EXPECT_EQ(doc.bar, 5); + } + { + Input yin("{foo: 3, bar: 5}"); + yin >> doc; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.foo, 3); + EXPECT_EQ(doc.bar, 5); + } +} // // Test the reading of a yaml sequence of mappings @@ -273,7 +283,64 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { } } +struct StringTypes { + llvm::StringRef str1; + llvm::StringRef str2; + llvm::StringRef str3; + llvm::StringRef str4; + llvm::StringRef str5; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<StringTypes> { + static void mapping(IO &io, StringTypes& st) { + io.mapRequired("str1", st.str1); + io.mapRequired("str2", st.str2); + io.mapRequired("str3", st.str3); + io.mapRequired("str4", st.str4); + io.mapRequired("str5", st.str5); + } + }; +} +} + +TEST(YAMLIO, TestReadWriteStringTypes) { + std::string intermediate; + { + StringTypes map; + map.str1 = "'aaa"; + map.str2 = "\"bbb"; + map.str3 = "`ccc"; + map.str4 = "@ddd"; + map.str5 = ""; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); + + { + Input yin(intermediate); + StringTypes map; + yin >> map; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map.str1.equals("'aaa")); + EXPECT_TRUE(map.str2.equals("\"bbb")); + EXPECT_TRUE(map.str3.equals("`ccc")); + EXPECT_TRUE(map.str4.equals("@ddd")); + EXPECT_TRUE(map.str5.equals("")); + } +} //===----------------------------------------------------------------------===// // Test ScalarEnumerationTraits @@ -600,9 +667,9 @@ TEST(YAMLIO, TestReadWriteMyFlowSequence) { map.numbers.push_back(1024); llvm::raw_string_ostream ostr(intermediate); - Output yout(ostr); + Output yout(ostr); yout << map; - + // Verify sequences were written in flow style ostr.flush(); llvm::StringRef flowOut(intermediate); @@ -932,6 +999,161 @@ TEST(YAMLIO, TestSequenceDocListWriteAndRead) { } } +//===----------------------------------------------------------------------===// +// Test document tags +//===----------------------------------------------------------------------===// + +struct MyDouble { + MyDouble() : value(0.0) { } + MyDouble(double x) : value(x) { } + double value; +}; + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble) + + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<MyDouble> { + static void mapping(IO &io, MyDouble &d) { + if (io.mapTag("!decimal", true)) { + mappingDecimal(io, d); + } else if (io.mapTag("!fraction")) { + mappingFraction(io, d); + } + } + static void mappingDecimal(IO &io, MyDouble &d) { + io.mapRequired("value", d.value); + } + static void mappingFraction(IO &io, MyDouble &d) { + double num, denom; + io.mapRequired("numerator", num); + io.mapRequired("denominator", denom); + // convert fraction to double + d.value = num/denom; + } + }; + } +} + + +// +// Test the reading of two different tagged yaml documents. +// +TEST(YAMLIO, TestTaggedDocuments) { + std::vector<MyDouble> docList; + Input yin("--- !decimal\nvalue: 3.0\n" + "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n"); + yin >> docList; + EXPECT_FALSE(yin.error()); + EXPECT_EQ(docList.size(), 2UL); + EXPECT_EQ(docList[0].value, 3.0); + EXPECT_EQ(docList[1].value, 4.5); +} + + + +// +// Test writing then reading back tagged documents +// +TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { + std::string intermediate; + { + MyDouble a(10.25); + MyDouble b(-3.75); + std::vector<MyDouble> docList; + docList.push_back(a); + docList.push_back(b); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << docList; + } + + { + Input yin(intermediate); + std::vector<MyDouble> docList2; + yin >> docList2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(docList2.size(), 2UL); + EXPECT_EQ(docList2[0].value, 10.25); + EXPECT_EQ(docList2[1].value, -3.75); + } +} + + +//===----------------------------------------------------------------------===// +// Test dyn_cast<> on IO object +//===----------------------------------------------------------------------===// + +struct DynCast { + int value; +}; +typedef std::vector<DynCast> DynCastSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast) + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<DynCast> { + static void mapping(IO &io, DynCast& info) { + // Change 10 to 13 when writing yaml. + if (Output *output = dyn_cast<Output>(&io)) { + (void)output; + if (info.value == 10) + info.value = 13; + } + io.mapRequired("value", info.value); + // Change 20 to 23 when parsing yaml. + if (Input *input = dyn_cast<Input>(&io)) { + (void)input; + if (info.value == 20) + info.value = 23; + } + } + }; +} +} + +// +// Test writing then reading back a sequence of mappings +// +TEST(YAMLIO, TestDynCast) { + std::string intermediate; + { + DynCast entry1; + entry1.value = 10; + DynCast entry2; + entry2.value = 20; + DynCast entry3; + entry3.value = 30; + DynCastSequence seq; + seq.push_back(entry1); + seq.push_back(entry2); + seq.push_back(entry3); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << seq; + } + + { + Input yin(intermediate); + DynCastSequence seq2; + yin >> seq2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(seq2.size(), 3UL); + EXPECT_EQ(seq2[0].value, 13); // Verify changed to 13. + EXPECT_EQ(seq2[1].value, 23); // Verify changed to 23. + EXPECT_EQ(seq2[2].value, 30); // Verify stays same. + } +} + + //===----------------------------------------------------------------------===// // Test error handling @@ -952,8 +1174,9 @@ TEST(YAMLIO, TestColorsReadError) { "c1: blue\n" "c2: purple\n" "c3: green\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> map; EXPECT_TRUE(yin.error()); } @@ -968,8 +1191,9 @@ TEST(YAMLIO, TestFlagsReadError) { "f1: [ big ]\n" "f2: [ round, hollow ]\n" "f3: []\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> map; EXPECT_TRUE(yin.error()); @@ -986,8 +1210,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { "- 255\n" "- 0\n" "- 257\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1004,8 +1229,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { "- 65535\n" "- 0\n" "- 66000\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1022,8 +1248,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { "- 4000000000\n" "- 0\n" "- 5000000000\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1040,8 +1267,9 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { "- 18446744073709551615\n" "- 0\n" "- 19446744073709551615\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1059,8 +1287,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { "- 0\n" "- 127\n" "- 128\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1076,8 +1305,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { "- 0\n" "- 127\n" "- -129\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1095,8 +1325,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { "- 0\n" "- -32768\n" "- -32769\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1113,8 +1344,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { "- 0\n" "- -32768\n" "- 32768\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1132,8 +1364,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { "- 0\n" "- -2147483648\n" "- -2147483649\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1149,8 +1382,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { "- 0\n" "- -2147483648\n" "- 2147483649\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1168,8 +1402,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { "- 0\n" "- 9223372036854775807\n" "- -9223372036854775809\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1185,8 +1420,9 @@ TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { "- 0\n" "- 9223372036854775807\n" "- 9223372036854775809\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1203,8 +1439,9 @@ TEST(YAMLIO, TestReadBuiltInTypesFloatError) { "- 1000.1\n" "- -123.456\n" "- 1.2.3\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1221,8 +1458,9 @@ TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { "- 1000.1\n" "- -123.456\n" "- 1.2.3\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1238,8 +1476,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { "- 0x12\n" "- 0xFE\n" "- 0x123\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1256,8 +1495,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { "- 0x0012\n" "- 0xFEFF\n" "- 0x12345\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1273,8 +1513,9 @@ TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { "- 0x0012\n" "- 0xFEFF0000\n" "- 0x1234556789\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); @@ -1290,10 +1531,114 @@ TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { "- 0x0012\n" "- 0xFFEEDDCCBBAA9988\n" "- 0x12345567890ABCDEF0\n" - "...\n"); - yin.setDiagHandler(suppressErrorMessages); + "...\n", + /*Ctxt=*/NULL, + suppressErrorMessages); yin >> seq; EXPECT_TRUE(yin.error()); } +TEST(YAMLIO, TestMalformedMapFailsGracefully) { + FooBar doc; + { + // We pass the suppressErrorMessages handler to handle the error + // message generated in the constructor of Input. + Input yin("{foo:3, bar: 5}", /*Ctxt=*/NULL, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(yin.error()); + } + + { + Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(yin.error()); + } +} + +struct OptionalTest { + std::vector<int> Numbers; +}; + +struct OptionalTestSeq { + std::vector<OptionalTest> Tests; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest) +namespace llvm { +namespace yaml { + template <> + struct MappingTraits<OptionalTest> { + static void mapping(IO& IO, OptionalTest &OT) { + IO.mapOptional("Numbers", OT.Numbers); + } + }; + + template <> + struct MappingTraits<OptionalTestSeq> { + static void mapping(IO &IO, OptionalTestSeq &OTS) { + IO.mapOptional("Tests", OTS.Tests); + } + }; +} +} + +TEST(YAMLIO, SequenceElideTest) { + // Test that writing out a purely optional structure with its fields set to + // default followed by other data is properly read back in. + OptionalTestSeq Seq; + OptionalTest One, Two, Three, Four; + int N[] = {1, 2, 3}; + Three.Numbers.assign(N, N + 3); + Seq.Tests.push_back(One); + Seq.Tests.push_back(Two); + Seq.Tests.push_back(Three); + Seq.Tests.push_back(Four); + + std::string intermediate; + { + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << Seq; + } + + Input yin(intermediate); + OptionalTestSeq Seq2; + yin >> Seq2; + + EXPECT_FALSE(yin.error()); + + EXPECT_EQ(4UL, Seq2.Tests.size()); + + EXPECT_TRUE(Seq2.Tests[0].Numbers.empty()); + EXPECT_TRUE(Seq2.Tests[1].Numbers.empty()); + + EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]); + EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]); + EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]); + + EXPECT_TRUE(Seq2.Tests[3].Numbers.empty()); +} + +TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { + FooBar doc; + Input yin(""); + yin >> doc; + EXPECT_TRUE(yin.error()); +} + +TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { + OptionalTest doc; + Input yin(""); + yin >> doc; + EXPECT_FALSE(yin.error()); +} + +TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { + std::vector<uint8_t> seq; + Input yin("", /*Ctxt=*/NULL, suppressErrorMessages); + yin >> seq; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(seq.empty()); +} |