X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=unittests%2FSupport%2FYAMLIOTest.cpp;h=e7affa1698dcc7989ca59bdf23549f9164fac76d;hb=08224c0a7e6b26af0d918bb1a1a280f54cf23208;hp=52a8f6b88c243333e2ed26677ebcf6dc8ea02fe9;hpb=9fd7416b3b5c437e3390ea9679d77e0221bec0b5;p=oota-llvm.git diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 52a8f6b88c2..e7affa1698d 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -46,6 +46,9 @@ typedef std::vector FooBarSequence; LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar) +struct FooBarContainer { + FooBarSequence fbs; +}; namespace llvm { namespace yaml { @@ -56,6 +59,12 @@ namespace yaml { io.mapRequired("bar", fb.bar); } }; + + template <> struct MappingTraits { + static void mapping(IO &io, FooBarContainer &fb) { + io.mapRequired("fbs", fb.fbs); + } + }; } } @@ -84,6 +93,13 @@ TEST(YAMLIO, TestMapRead) { } } +TEST(YAMLIO, TestMalformedMapRead) { + FooBar doc; + Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(!!yin.error()); +} + // // Test the reading of a yaml sequence of mappings // @@ -102,6 +118,83 @@ TEST(YAMLIO, TestSequenceMapRead) { EXPECT_EQ(map2.bar, 9); } +// +// Test the reading of a map containing a yaml sequence of mappings +// +TEST(YAMLIO, TestContainerSequenceMapRead) { + { + FooBarContainer cont; + Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n"); + yin2 >> cont; + + EXPECT_FALSE(yin2.error()); + EXPECT_EQ(cont.fbs.size(), 2UL); + EXPECT_EQ(cont.fbs[0].foo, 3); + EXPECT_EQ(cont.fbs[0].bar, 5); + EXPECT_EQ(cont.fbs[1].foo, 7); + EXPECT_EQ(cont.fbs[1].bar, 9); + } + + { + FooBarContainer cont; + Input yin("---\nfbs:\n...\n"); + yin >> cont; + // Okay: Empty node represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: !!null null\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: ~\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: null\n...\n"); + yin >> cont; + // Okay: null represents an empty array. + EXPECT_FALSE(yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } +} + +// +// Test the reading of a map containing a malformed yaml sequence +// +TEST(YAMLIO, TestMalformedContainerSequenceMapRead) { + { + FooBarContainer cont; + Input yin("---\nfbs:\n foo: 3\n bar: 5\n...\n", nullptr, + suppressErrorMessages); + yin >> cont; + // Error: fbs is not a sequence. + EXPECT_TRUE(!!yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } + + { + FooBarContainer cont; + Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages); + yin >> cont; + // This should be an error. + EXPECT_TRUE(!!yin.error()); + EXPECT_EQ(cont.fbs.size(), 0UL); + } +} // // Test writing then reading back a sequence of mappings @@ -302,11 +395,23 @@ struct StringTypes { llvm::StringRef str3; llvm::StringRef str4; llvm::StringRef str5; + llvm::StringRef str6; + llvm::StringRef str7; + llvm::StringRef str8; + llvm::StringRef str9; + llvm::StringRef str10; + llvm::StringRef str11; std::string stdstr1; std::string stdstr2; std::string stdstr3; std::string stdstr4; std::string stdstr5; + std::string stdstr6; + std::string stdstr7; + std::string stdstr8; + std::string stdstr9; + std::string stdstr10; + std::string stdstr11; }; namespace llvm { @@ -319,11 +424,23 @@ namespace yaml { io.mapRequired("str3", st.str3); io.mapRequired("str4", st.str4); io.mapRequired("str5", st.str5); + io.mapRequired("str6", st.str6); + io.mapRequired("str7", st.str7); + io.mapRequired("str8", st.str8); + io.mapRequired("str9", st.str9); + io.mapRequired("str10", st.str10); + io.mapRequired("str11", st.str11); io.mapRequired("stdstr1", st.stdstr1); io.mapRequired("stdstr2", st.stdstr2); io.mapRequired("stdstr3", st.stdstr3); io.mapRequired("stdstr4", st.stdstr4); io.mapRequired("stdstr5", st.stdstr5); + io.mapRequired("stdstr6", st.stdstr6); + io.mapRequired("stdstr7", st.stdstr7); + io.mapRequired("stdstr8", st.stdstr8); + io.mapRequired("stdstr9", st.stdstr9); + io.mapRequired("stdstr10", st.stdstr10); + io.mapRequired("stdstr11", st.stdstr11); } }; } @@ -338,11 +455,23 @@ TEST(YAMLIO, TestReadWriteStringTypes) { map.str3 = "`ccc"; map.str4 = "@ddd"; map.str5 = ""; + map.str6 = "0000000004000000"; + map.str7 = "true"; + map.str8 = "FALSE"; + map.str9 = "~"; + map.str10 = "0.2e20"; + map.str11 = "0x30"; map.stdstr1 = "'eee"; map.stdstr2 = "\"fff"; map.stdstr3 = "`ggg"; map.stdstr4 = "@hhh"; map.stdstr5 = ""; + map.stdstr6 = "0000000004000000"; + map.stdstr7 = "true"; + map.stdstr8 = "FALSE"; + map.stdstr9 = "~"; + map.stdstr10 = "0.2e20"; + map.stdstr11 = "0x30"; llvm::raw_string_ostream ostr(intermediate); Output yout(ostr); @@ -355,11 +484,18 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); + 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(std::string::npos, flowOut.find("'''eee")); EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); EXPECT_NE(std::string::npos, flowOut.find("''\n")); + EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); { Input yin(intermediate); @@ -372,11 +508,13 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_TRUE(map.str3.equals("`ccc")); EXPECT_TRUE(map.str4.equals("@ddd")); EXPECT_TRUE(map.str5.equals("")); + EXPECT_TRUE(map.str6.equals("0000000004000000")); EXPECT_TRUE(map.stdstr1 == "'eee"); EXPECT_TRUE(map.stdstr2 == "\"fff"); EXPECT_TRUE(map.stdstr3 == "`ggg"); EXPECT_TRUE(map.stdstr4 == "@hhh"); EXPECT_TRUE(map.stdstr5 == ""); + EXPECT_TRUE(map.stdstr6 == "0000000004000000"); } } @@ -602,6 +740,7 @@ namespace yaml { return "malformed by"; } } + static bool mustQuote(StringRef) { return true; } }; } } @@ -640,6 +779,146 @@ TEST(YAMLIO, TestReadWriteMyCustomType) { } +//===----------------------------------------------------------------------===// +// Test BlockScalarTraits +//===----------------------------------------------------------------------===// + +struct MultilineStringType { + std::string str; +}; + +struct MultilineStringTypeMap { + MultilineStringType name; + MultilineStringType description; + MultilineStringType ingredients; + MultilineStringType recipes; + MultilineStringType warningLabels; + MultilineStringType documentation; + int price; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, MultilineStringTypeMap& s) { + io.mapRequired("name", s.name); + io.mapRequired("description", s.description); + io.mapRequired("ingredients", s.ingredients); + io.mapRequired("recipes", s.recipes); + io.mapRequired("warningLabels", s.warningLabels); + io.mapRequired("documentation", s.documentation); + io.mapRequired("price", s.price); + } + }; + + // MultilineStringType is formatted as a yaml block literal scalar. A value of + // "Hello\nWorld" would be represented in yaml as + // | + // Hello + // World + template <> + struct BlockScalarTraits { + static void output(const MultilineStringType &value, void *ctxt, + llvm::raw_ostream &out) { + out << value.str; + } + static StringRef input(StringRef scalar, void *ctxt, + MultilineStringType &value) { + value.str = scalar.str(); + return StringRef(); + } + }; +} +} + +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType) + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteMultilineStringType) { + std::string intermediate; + { + MultilineStringTypeMap map; + map.name.str = "An Item"; + map.description.str = "Hello\nWorld"; + map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n"; + map.recipes.str = "\n\nTest 1\n\n\n"; + map.warningLabels.str = ""; + map.documentation.str = "\n\n"; + map.price = 350; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + } + { + Input yin(intermediate); + MultilineStringTypeMap map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(map2.name.str, "An Item\n"); + EXPECT_EQ(map2.description.str, "Hello\nWorld\n"); + EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n"); + EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n"); + EXPECT_TRUE(map2.warningLabels.str.empty()); + EXPECT_TRUE(map2.documentation.str.empty()); + EXPECT_EQ(map2.price, 350); + } +} + +// +// Test writing then reading back custom values +// +TEST(YAMLIO, TestReadWriteBlockScalarDocuments) { + std::string intermediate; + { + std::vector documents; + MultilineStringType doc; + doc.str = "Hello\nWorld"; + documents.push_back(doc); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << documents; + + // Verify that the block scalar header was written out on the same line + // as the document marker. + EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |")); + } + { + Input yin(intermediate); + std::vector documents2; + yin >> documents2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(documents2.size(), size_t(1)); + EXPECT_EQ(documents2[0].str, "Hello\nWorld\n"); + } +} + +TEST(YAMLIO, TestReadWriteBlockScalarValue) { + std::string intermediate; + { + MultilineStringType doc; + doc.str = "Just a block\nscalar doc"; + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << doc; + } + { + Input yin(intermediate); + MultilineStringType doc; + yin >> doc; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc.str, "Just a block\nscalar doc\n"); + } +} + //===----------------------------------------------------------------------===// // Test flow sequences //===----------------------------------------------------------------------===// @@ -663,6 +942,8 @@ namespace yaml { value = n; return StringRef(); } + + static bool mustQuote(StringRef) { return false; } }; } } @@ -688,6 +969,26 @@ namespace yaml { } } +typedef std::vector MyNumberFlowSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence) + +struct NameAndNumbersFlow { + llvm::StringRef name; + std::vector sequenceOfNumbers; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, NameAndNumbersFlow& nn) { + io.mapRequired("name", nn.name); + io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers); + } + }; +} +} // // Test writing then reading back custom values @@ -735,6 +1036,51 @@ TEST(YAMLIO, TestReadWriteMyFlowSequence) { } +// +// Test writing then reading back a sequence of flow sequences. +// +TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) { + std::string intermediate; + { + NameAndNumbersFlow map; + map.name = "hello"; + MyNumberFlowSequence single = { 0 }; + MyNumberFlowSequence numbers = { 12, 1, -512 }; + map.sequenceOfNumbers.push_back(single); + map.sequenceOfNumbers.push_back(numbers); + map.sequenceOfNumbers.push_back(MyNumberFlowSequence()); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << map; + + // Verify sequences were written in flow style + // and that the parent sequence used '-'. + ostr.flush(); + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]")); + } + + { + Input yin(intermediate); + NameAndNumbersFlow map2; + yin >> map2; + + EXPECT_FALSE(yin.error()); + EXPECT_TRUE(map2.name.equals("hello")); + EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL); + EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL); + EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]); + EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL); + EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]); + EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]); + EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]); + EXPECT_TRUE(map2.sequenceOfNumbers[2].empty()); + } +} + //===----------------------------------------------------------------------===// // Test normalizing/denormalizing //===----------------------------------------------------------------------===// @@ -1156,11 +1502,96 @@ TEST(YAMLIO, TestValidatingInput) { std::vector docList; Input yin("--- \nvalue: 3.0\n" "--- \nvalue: -1.0\n...\n", - NULL, suppressErrorMessages); + nullptr, suppressErrorMessages); yin >> docList; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } +//===----------------------------------------------------------------------===// +// Test flow mapping +//===----------------------------------------------------------------------===// + +struct FlowFooBar { + int foo; + int bar; + + FlowFooBar() : foo(0), bar(0) {} + FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {} +}; + +typedef std::vector FlowFooBarSequence; + +LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar) + +struct FlowFooBarDoc { + FlowFooBar attribute; + FlowFooBarSequence seq; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, FlowFooBar &fb) { + io.mapRequired("foo", fb.foo); + io.mapRequired("bar", fb.bar); + } + + static const bool flow = true; + }; + + template <> + struct MappingTraits { + static void mapping(IO &io, FlowFooBarDoc &fb) { + io.mapRequired("attribute", fb.attribute); + io.mapRequired("seq", fb.seq); + } + }; +} +} + +// +// Test writing then reading back custom mappings +// +TEST(YAMLIO, TestReadWriteMyFlowMapping) { + std::string intermediate; + { + FlowFooBarDoc doc; + doc.attribute = FlowFooBar(42, 907); + doc.seq.push_back(FlowFooBar(1, 2)); + doc.seq.push_back(FlowFooBar(0, 0)); + doc.seq.push_back(FlowFooBar(-1, 1024)); + + llvm::raw_string_ostream ostr(intermediate); + Output yout(ostr); + yout << doc; + + // Verify that mappings were written in flow style + ostr.flush(); + llvm::StringRef flowOut(intermediate); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }")); + } + + { + Input yin(intermediate); + FlowFooBarDoc doc2; + yin >> doc2; + + EXPECT_FALSE(yin.error()); + EXPECT_EQ(doc2.attribute.foo, 42); + EXPECT_EQ(doc2.attribute.bar, 907); + EXPECT_EQ(doc2.seq.size(), 3UL); + EXPECT_EQ(doc2.seq[0].foo, 1); + EXPECT_EQ(doc2.seq[0].bar, 2); + EXPECT_EQ(doc2.seq[1].foo, 0); + EXPECT_EQ(doc2.seq[1].bar, 0); + EXPECT_EQ(doc2.seq[2].foo, -1); + EXPECT_EQ(doc2.seq[2].bar, 1024); + } +} //===----------------------------------------------------------------------===// // Test error handling @@ -1176,10 +1607,10 @@ TEST(YAMLIO, TestColorsReadError) { "c2: purple\n" "c3: green\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> map; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1193,11 +1624,11 @@ TEST(YAMLIO, TestFlagsReadError) { "f2: [ round, hollow ]\n" "f3: []\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> map; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1212,11 +1643,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint8Error) { "- 0\n" "- 257\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1231,11 +1662,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint16Error) { "- 0\n" "- 66000\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1250,11 +1681,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint32Error) { "- 0\n" "- 5000000000\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1269,11 +1700,11 @@ TEST(YAMLIO, TestReadBuiltInTypesUint64Error) { "- 0\n" "- 19446744073709551615\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1289,11 +1720,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint8OverError) { "- 127\n" "- 128\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1307,11 +1738,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) { "- 127\n" "- -129\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1327,11 +1758,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) { "- -32768\n" "- -32769\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1346,11 +1777,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint16OverError) { "- -32768\n" "- 32768\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1366,11 +1797,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) { "- -2147483648\n" "- -2147483649\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1384,11 +1815,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint32OverError) { "- -2147483648\n" "- 2147483649\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1404,11 +1835,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) { "- 9223372036854775807\n" "- -9223372036854775809\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1422,11 +1853,11 @@ TEST(YAMLIO, TestReadBuiltInTypesint64OverError) { "- 9223372036854775807\n" "- 9223372036854775809\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1441,11 +1872,11 @@ TEST(YAMLIO, TestReadBuiltInTypesFloatError) { "- -123.456\n" "- 1.2.3\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1460,11 +1891,11 @@ TEST(YAMLIO, TestReadBuiltInTypesDoubleError) { "- -123.456\n" "- 1.2.3\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1478,11 +1909,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex8Error) { "- 0xFE\n" "- 0x123\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } @@ -1497,11 +1928,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex16Error) { "- 0xFEFF\n" "- 0x12345\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1515,11 +1946,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex32Error) { "- 0xFEFF0000\n" "- 0x1234556789\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } // @@ -1533,11 +1964,11 @@ TEST(YAMLIO, TestReadBuiltInTypesHex64Error) { "- 0xFFEEDDCCBBAA9988\n" "- 0x12345567890ABCDEF0\n" "...\n", - /*Ctxt=*/NULL, + /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } TEST(YAMLIO, TestMalformedMapFailsGracefully) { @@ -1545,15 +1976,15 @@ TEST(YAMLIO, TestMalformedMapFailsGracefully) { { // 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); + Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } { - Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/NULL, suppressErrorMessages); + Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } } @@ -1625,7 +2056,7 @@ TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) { FooBar doc; Input yin(""); yin >> doc; - EXPECT_TRUE(yin.error()); + EXPECT_TRUE(!!yin.error()); } TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { @@ -1637,9 +2068,129 @@ TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) { TEST(YAMLIO, TestEmptyStringSucceedsForSequence) { std::vector seq; - Input yin("", /*Ctxt=*/NULL, suppressErrorMessages); + Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages); yin >> seq; EXPECT_FALSE(yin.error()); EXPECT_TRUE(seq.empty()); } + +struct FlowMap { + llvm::StringRef str1, str2, str3; + FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3) + : str1(str1), str2(str2), str3(str3) {} +}; + +struct FlowSeq { + llvm::StringRef str; + FlowSeq(llvm::StringRef S) : str(S) {} + FlowSeq() = default; +}; + +namespace llvm { +namespace yaml { + template <> + struct MappingTraits { + static void mapping(IO &io, FlowMap &fm) { + io.mapRequired("str1", fm.str1); + io.mapRequired("str2", fm.str2); + io.mapRequired("str3", fm.str3); + } + + static const bool flow = true; + }; + +template <> +struct ScalarTraits { + static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) { + out << value.str; + } + static StringRef input(StringRef scalar, void*, FlowSeq &value) { + value.str = scalar; + return ""; + } + + static bool mustQuote(StringRef S) { return false; } +}; +} +} + +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq) + +TEST(YAMLIO, TestWrapFlow) { + std::string out; + llvm::raw_string_ostream ostr(out); + FlowMap Map("This is str1", "This is str2", "This is str3"); + std::vector Seq; + Seq.emplace_back("This is str1"); + Seq.emplace_back("This is str2"); + Seq.emplace_back("This is str3"); + + { + // 20 is just bellow the total length of the first mapping field. + // We should wreap at every element. + Output yout(ostr, nullptr, 15); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, \n" + " str2: This is str2, \n" + " str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, \n" + " This is str2, \n" + " This is str3 ]\n" + "...\n"); + out.clear(); + } + { + // 25 will allow the second field to be output on the first line. + Output yout(ostr, nullptr, 25); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, str2: This is str2, \n" + " str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, This is str2, \n" + " This is str3 ]\n" + "...\n"); + out.clear(); + } + { + // 0 means no wrapping. + Output yout(ostr, nullptr, 0); + + yout << Map; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n" + "...\n"); + out.clear(); + + yout << Seq; + ostr.flush(); + EXPECT_EQ(out, + "---\n" + "[ This is str1, This is str2, This is str3 ]\n" + "...\n"); + out.clear(); + } +}