| #include "yaml-cpp/emitterstyle.h" |
| #include "yaml-cpp/eventhandler.h" |
| #include "yaml-cpp/yaml.h" // IWYU pragma: keep |
| #include "gtest/gtest.h" |
| |
| namespace YAML { |
| namespace { |
| |
| class NullEventHandler : public EventHandler { |
| virtual void OnDocumentStart(const Mark&) {} |
| virtual void OnDocumentEnd() {} |
| |
| virtual void OnNull(const Mark&, anchor_t) {} |
| virtual void OnAlias(const Mark&, anchor_t) {} |
| virtual void OnScalar(const Mark&, const std::string&, anchor_t, |
| const std::string&) {} |
| |
| virtual void OnSequenceStart(const Mark&, const std::string&, anchor_t, |
| EmitterStyle::value /* style */) {} |
| virtual void OnSequenceEnd() {} |
| |
| virtual void OnMapStart(const Mark&, const std::string&, anchor_t, |
| EmitterStyle::value /* style */) {} |
| virtual void OnMapEnd() {} |
| }; |
| |
| class EmitterTest : public ::testing::Test { |
| protected: |
| void ExpectEmit(const std::string& expected) { |
| EXPECT_EQ(expected, out.c_str()); |
| EXPECT_TRUE(out.good()) << "Emitter raised: " << out.GetLastError(); |
| if (expected == out.c_str()) { |
| std::stringstream stream(expected); |
| Parser parser; |
| NullEventHandler handler; |
| parser.HandleNextDocument(handler); |
| } |
| } |
| |
| Emitter out; |
| }; |
| |
| TEST_F(EmitterTest, SimpleScalar) { |
| out << "Hello, World!"; |
| |
| ExpectEmit("Hello, World!"); |
| } |
| |
| TEST_F(EmitterTest, SimpleQuotedScalar) { |
| Node n(Load("\"test\"")); |
| out << n; |
| ExpectEmit("test"); |
| } |
| |
| TEST_F(EmitterTest, DumpAndSize) { |
| Node n(Load("test")); |
| EXPECT_EQ("test", Dump(n)); |
| out << n; |
| EXPECT_EQ(4, out.size()); |
| } |
| |
| TEST_F(EmitterTest, NullScalar) { |
| Node n(Load("null")); |
| out << n; |
| ExpectEmit("~"); |
| } |
| |
| TEST_F(EmitterTest, AliasScalar) { |
| Node n(Load("[&a str, *a]")); |
| out << n; |
| ExpectEmit("[&1 str, *1]"); |
| } |
| |
| TEST_F(EmitterTest, StringFormat) { |
| out << BeginSeq; |
| out.SetStringFormat(SingleQuoted); |
| out << "string"; |
| out.SetStringFormat(DoubleQuoted); |
| out << "string"; |
| out.SetStringFormat(Literal); |
| out << "string"; |
| out << EndSeq; |
| |
| ExpectEmit("- 'string'\n- \"string\"\n- |\n string"); |
| } |
| |
| TEST_F(EmitterTest, IntBase) { |
| out << BeginSeq; |
| out.SetIntBase(Dec); |
| out << 1024; |
| out.SetIntBase(Hex); |
| out << 1024; |
| out.SetIntBase(Oct); |
| out << 1024; |
| out << EndSeq; |
| |
| ExpectEmit("- 1024\n- 0x400\n- 02000"); |
| } |
| |
| TEST_F(EmitterTest, NumberPrecision) { |
| out.SetFloatPrecision(3); |
| out.SetDoublePrecision(2); |
| out << BeginSeq; |
| out << 3.1425926f; |
| out << 53.5893; |
| out << 2384626.4338; |
| out << EndSeq; |
| |
| ExpectEmit("- 3.14\n- 54\n- 2.4e+06"); |
| } |
| |
| TEST_F(EmitterTest, SimpleSeq) { |
| out << BeginSeq; |
| out << "eggs"; |
| out << "bread"; |
| out << "milk"; |
| out << EndSeq; |
| |
| ExpectEmit("- eggs\n- bread\n- milk"); |
| } |
| |
| TEST_F(EmitterTest, SimpleFlowSeq) { |
| out << Flow; |
| out << BeginSeq; |
| out << "Larry"; |
| out << "Curly"; |
| out << "Moe"; |
| out << EndSeq; |
| |
| ExpectEmit("[Larry, Curly, Moe]"); |
| } |
| |
| TEST_F(EmitterTest, EmptyFlowSeq) { |
| out << Flow; |
| out << BeginSeq; |
| out << EndSeq; |
| |
| ExpectEmit("[]"); |
| } |
| |
| TEST_F(EmitterTest, EmptyBlockSeqWithBegunContent) { |
| out << BeginSeq; |
| out << BeginSeq << Comment("comment") << EndSeq; |
| out << BeginSeq << Newline << EndSeq; |
| out << EndSeq; |
| |
| ExpectEmit(R"(- |
| # comment |
| [] |
| - |
| |
| [])"); |
| } |
| |
| TEST_F(EmitterTest, EmptyBlockMapWithBegunContent) { |
| out << BeginSeq; |
| out << BeginMap << Comment("comment") << EndMap; |
| out << BeginMap << Newline << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit(R"(- # comment |
| {} |
| - |
| {})"); |
| } |
| |
| TEST_F(EmitterTest, EmptyFlowSeqWithBegunContent) { |
| out << Flow; |
| out << BeginSeq; |
| out << BeginSeq << Comment("comment") << EndSeq; |
| out << BeginSeq << Newline << EndSeq; |
| out << EndSeq; |
| |
| ExpectEmit(R"([[ # comment |
| ], [ |
| ]])"); |
| } |
| |
| TEST_F(EmitterTest, EmptyFlowMapWithBegunContent) { |
| out << Flow; |
| out << BeginSeq; |
| out << BeginMap << Comment("comment") << EndMap; |
| out << BeginMap << Newline << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit(R"([{ # comment |
| }, { |
| }])"); |
| } |
| |
| TEST_F(EmitterTest, NestedBlockSeq) { |
| out << BeginSeq; |
| out << "item 1"; |
| out << BeginSeq << "subitem 1" |
| << "subitem 2" << EndSeq; |
| out << EndSeq; |
| |
| ExpectEmit("- item 1\n-\n - subitem 1\n - subitem 2"); |
| } |
| |
| TEST_F(EmitterTest, NestedFlowSeq) { |
| out << BeginSeq; |
| out << "one"; |
| out << Flow << BeginSeq << "two" |
| << "three" << EndSeq; |
| out << EndSeq; |
| |
| ExpectEmit("- one\n- [two, three]"); |
| } |
| |
| TEST_F(EmitterTest, SimpleMap) { |
| out << BeginMap; |
| out << Key << "name"; |
| out << Value << "Ryan Braun"; |
| out << Key << "position"; |
| out << Value << "3B"; |
| out << EndMap; |
| |
| ExpectEmit("name: Ryan Braun\nposition: 3B"); |
| } |
| |
| TEST_F(EmitterTest, SimpleFlowMap) { |
| out << Flow; |
| out << BeginMap; |
| out << Key << "shape"; |
| out << Value << "square"; |
| out << Key << "color"; |
| out << Value << "blue"; |
| out << EndMap; |
| |
| ExpectEmit("{shape: square, color: blue}"); |
| } |
| |
| TEST_F(EmitterTest, MapAndList) { |
| out << BeginMap; |
| out << Key << "name"; |
| out << Value << "Barack Obama"; |
| out << Key << "children"; |
| out << Value << BeginSeq << "Sasha" |
| << "Malia" << EndSeq; |
| out << EndMap; |
| |
| ExpectEmit("name: Barack Obama\nchildren:\n - Sasha\n - Malia"); |
| } |
| |
| TEST_F(EmitterTest, ListAndMap) { |
| out << BeginSeq; |
| out << "item 1"; |
| out << BeginMap; |
| out << Key << "pens" << Value << 8; |
| out << Key << "pencils" << Value << 14; |
| out << EndMap; |
| out << "item 2"; |
| out << EndSeq; |
| |
| ExpectEmit("- item 1\n- pens: 8\n pencils: 14\n- item 2"); |
| } |
| |
| TEST_F(EmitterTest, NestedBlockMap) { |
| out << BeginMap; |
| out << Key << "name"; |
| out << Value << "Fred"; |
| out << Key << "grades"; |
| out << Value; |
| out << BeginMap; |
| out << Key << "algebra" << Value << "A"; |
| out << Key << "physics" << Value << "C+"; |
| out << Key << "literature" << Value << "B"; |
| out << EndMap; |
| out << EndMap; |
| |
| ExpectEmit( |
| "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B"); |
| } |
| |
| TEST_F(EmitterTest, NestedFlowMap) { |
| out << Flow; |
| out << BeginMap; |
| out << Key << "name"; |
| out << Value << "Fred"; |
| out << Key << "grades"; |
| out << Value; |
| out << BeginMap; |
| out << Key << "algebra" << Value << "A"; |
| out << Key << "physics" << Value << "C+"; |
| out << Key << "literature" << Value << "B"; |
| out << EndMap; |
| out << EndMap; |
| |
| ExpectEmit("{name: Fred, grades: {algebra: A, physics: C+, literature: B}}"); |
| } |
| |
| TEST_F(EmitterTest, MapListMix) { |
| out << BeginMap; |
| out << Key << "name"; |
| out << Value << "Bob"; |
| out << Key << "position"; |
| out << Value; |
| out << Flow << BeginSeq << 2 << 4 << EndSeq; |
| out << Key << "invincible" << Value << OnOffBool << false; |
| out << EndMap; |
| |
| ExpectEmit("name: Bob\nposition: [2, 4]\ninvincible: off"); |
| } |
| |
| TEST_F(EmitterTest, SimpleLongKey) { |
| out << LongKey; |
| out << BeginMap; |
| out << Key << "height"; |
| out << Value << "5'9\""; |
| out << Key << "weight"; |
| out << Value << 145; |
| out << EndMap; |
| |
| ExpectEmit("? height\n: 5'9\"\n? weight\n: 145"); |
| } |
| |
| TEST_F(EmitterTest, SingleLongKey) { |
| const std::string shortKey(1024, 'a'); |
| const std::string longKey(1025, 'a'); |
| out << BeginMap; |
| out << Key << "age"; |
| out << Value << "24"; |
| out << LongKey << Key << "height"; |
| out << Value << "5'9\""; |
| out << Key << "weight"; |
| out << Value << 145; |
| out << Key << shortKey; |
| out << Value << "1"; |
| out << Key << longKey; |
| out << Value << "1"; |
| out << EndMap; |
| |
| ExpectEmit("age: 24\n? height\n: 5'9\"\nweight: 145\n" + shortKey + |
| ": 1\n? " + longKey + "\n: 1"); |
| } |
| |
| TEST_F(EmitterTest, ComplexLongKey) { |
| out << LongKey; |
| out << BeginMap; |
| out << Key << BeginSeq << 1 << 3 << EndSeq; |
| out << Value << "monster"; |
| out << Key << Flow << BeginSeq << 2 << 0 << EndSeq; |
| out << Value << "demon"; |
| out << EndMap; |
| |
| ExpectEmit("? - 1\n - 3\n: monster\n? [2, 0]\n: demon"); |
| } |
| |
| TEST_F(EmitterTest, AutoLongKey) { |
| out << BeginMap; |
| out << Key << BeginSeq << 1 << 3 << EndSeq; |
| out << Value << "monster"; |
| out << Key << Flow << BeginSeq << 2 << 0 << EndSeq; |
| out << Value << "demon"; |
| out << Key << "the origin"; |
| out << Value << "angel"; |
| out << EndMap; |
| |
| ExpectEmit("? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel"); |
| } |
| |
| TEST_F(EmitterTest, ScalarFormat) { |
| out << BeginSeq; |
| out << "simple scalar"; |
| out << SingleQuoted << "explicit single-quoted scalar"; |
| out << DoubleQuoted << "explicit double-quoted scalar"; |
| out << "auto-detected\ndouble-quoted scalar"; |
| out << "a non-\"auto-detected\" double-quoted scalar"; |
| out << Literal |
| << "literal scalar\nthat may span\nmany, many\nlines " |
| "and have \"whatever\" crazy\tsymbols that we like"; |
| out << EndSeq; |
| |
| ExpectEmit( |
| "- simple scalar\n- 'explicit single-quoted scalar'\n- \"explicit " |
| "double-quoted scalar\"\n- \"auto-detected\\ndouble-quoted " |
| "scalar\"\n- a " |
| "non-\"auto-detected\" double-quoted scalar\n- |\n literal scalar\n " |
| " " |
| "that may span\n many, many\n lines and have \"whatever\" " |
| "crazy\tsymbols that we like"); |
| } |
| |
| TEST_F(EmitterTest, LiteralWithoutTrailingSpaces) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "key"; |
| out << YAML::Value << YAML::Literal; |
| out << "expect that with two newlines\n\n" |
| "no spaces are emitted in the empty line"; |
| out << YAML::EndMap; |
| |
| ExpectEmit( |
| "key: |\n" |
| " expect that with two newlines\n\n" |
| " no spaces are emitted in the empty line"); |
| } |
| |
| TEST_F(EmitterTest, AutoLongKeyScalar) { |
| out << BeginMap; |
| out << Key << Literal << "multi-line\nscalar"; |
| out << Value << "and its value"; |
| out << EndMap; |
| |
| ExpectEmit("? |\n multi-line\n scalar\n: and its value"); |
| } |
| |
| TEST_F(EmitterTest, LongKeyFlowMap) { |
| out << Flow; |
| out << BeginMap; |
| out << Key << "simple key"; |
| out << Value << "and value"; |
| out << LongKey << Key << "long key"; |
| out << Value << "and its value"; |
| out << EndMap; |
| |
| ExpectEmit("{simple key: and value, ? long key: and its value}"); |
| } |
| |
| TEST_F(EmitterTest, BlockMapAsKey) { |
| out << BeginMap; |
| out << Key; |
| out << BeginMap; |
| out << Key << "key" << Value << "value"; |
| out << Key << "next key" << Value << "next value"; |
| out << EndMap; |
| out << Value; |
| out << "total value"; |
| out << EndMap; |
| |
| ExpectEmit("? key: value\n next key: next value\n: total value"); |
| } |
| |
| TEST_F(EmitterTest, TaggedBlockMapAsKey) { |
| out << BeginMap; |
| out << Key; |
| out << LocalTag("innerMap"); |
| out << BeginMap; |
| out << Key << "key" << Value << "value"; |
| out << EndMap; |
| out << Value; |
| out << "outerValue"; |
| out << EndMap; |
| |
| ExpectEmit(R"(? !innerMap |
| key: value |
| : outerValue)"); |
| } |
| |
| TEST_F(EmitterTest, TaggedBlockListAsKey) { |
| out << BeginMap; |
| out << Key; |
| out << LocalTag("innerList"); |
| out << BeginSeq; |
| out << "listItem"; |
| out << EndSeq; |
| out << Value; |
| out << "outerValue"; |
| out << EndMap; |
| |
| ExpectEmit(R"(? !innerList |
| - listItem |
| : outerValue)"); |
| } |
| |
| TEST_F(EmitterTest, AliasAndAnchor) { |
| out << BeginSeq; |
| out << Anchor("fred"); |
| out << BeginMap; |
| out << Key << "name" << Value << "Fred"; |
| out << Key << "age" << Value << 42; |
| out << EndMap; |
| out << Alias("fred"); |
| out << EndSeq; |
| |
| ExpectEmit("- &fred\n name: Fred\n age: 42\n- *fred"); |
| } |
| |
| TEST_F(EmitterTest, AliasOnKey) { |
| out << BeginSeq; |
| out << Anchor("name") << "Name"; |
| out << BeginMap; |
| out << Key << Alias("name") << Value << "Fred"; |
| out << EndMap; |
| out << Flow << BeginMap; |
| out << Key << Alias("name") << Value << "Mike"; |
| out << EndMap; |
| out << EndSeq; |
| ExpectEmit(R"(- &name Name |
| - *name : Fred |
| - {*name : Mike})"); |
| } |
| |
| TEST_F(EmitterTest, AliasAndAnchorWithNull) { |
| out << BeginSeq; |
| out << Anchor("fred") << Null; |
| out << Alias("fred"); |
| out << EndSeq; |
| |
| ExpectEmit("- &fred ~\n- *fred"); |
| } |
| |
| TEST_F(EmitterTest, AliasAndAnchorInFlow) { |
| out << Flow << BeginSeq; |
| out << Anchor("fred"); |
| out << BeginMap; |
| out << Key << "name" << Value << "Fred"; |
| out << Key << "age" << Value << 42; |
| out << EndMap; |
| out << Alias("fred"); |
| out << EndSeq; |
| |
| ExpectEmit("[&fred {name: Fred, age: 42}, *fred]"); |
| } |
| |
| TEST_F(EmitterTest, SimpleVerbatimTag) { |
| out << VerbatimTag("!foo") << "bar"; |
| |
| ExpectEmit("!<!foo> bar"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInBlockSeq) { |
| out << BeginSeq; |
| out << VerbatimTag("!foo") << "bar"; |
| out << "baz"; |
| out << EndSeq; |
| |
| ExpectEmit("- !<!foo> bar\n- baz"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInFlowSeq) { |
| out << Flow << BeginSeq; |
| out << VerbatimTag("!foo") << "bar"; |
| out << "baz"; |
| out << EndSeq; |
| |
| ExpectEmit("[!<!foo> bar, baz]"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInFlowSeqWithNull) { |
| out << Flow << BeginSeq; |
| out << VerbatimTag("!foo") << Null; |
| out << "baz"; |
| out << EndSeq; |
| |
| ExpectEmit("[!<!foo> ~, baz]"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInBlockMap) { |
| out << BeginMap; |
| out << Key << VerbatimTag("!foo") << "bar"; |
| out << Value << VerbatimTag("!waz") << "baz"; |
| out << EndMap; |
| |
| ExpectEmit("? !<!foo> bar\n: !<!waz> baz"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInFlowMap) { |
| out << Flow << BeginMap; |
| out << Key << VerbatimTag("!foo") << "bar"; |
| out << Value << "baz"; |
| out << EndMap; |
| |
| ExpectEmit("{!<!foo> bar: baz}"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagInFlowMapWithNull) { |
| out << Flow << BeginMap; |
| out << Key << VerbatimTag("!foo") << Null; |
| out << Value << "baz"; |
| out << EndMap; |
| |
| ExpectEmit("{!<!foo> ~: baz}"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagWithEmptySeq) { |
| out << VerbatimTag("!foo") << BeginSeq << EndSeq; |
| |
| ExpectEmit("!<!foo>\n[]"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagWithEmptyMap) { |
| out << VerbatimTag("!bar") << BeginMap << EndMap; |
| |
| ExpectEmit("!<!bar>\n{}"); |
| } |
| |
| TEST_F(EmitterTest, VerbatimTagWithEmptySeqAndMap) { |
| out << BeginSeq; |
| out << VerbatimTag("!foo") << BeginSeq << EndSeq; |
| out << VerbatimTag("!bar") << BeginMap << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit("- !<!foo>\n []\n- !<!bar>\n {}"); |
| } |
| |
| TEST_F(EmitterTest, ByKindTagWithScalar) { |
| out << BeginSeq; |
| out << DoubleQuoted << "12"; |
| out << "12"; |
| out << TagByKind << "12"; |
| out << EndSeq; |
| |
| ExpectEmit("- \"12\"\n- 12\n- ! 12"); |
| } |
| |
| TEST_F(EmitterTest, LocalTagInNameHandle) { |
| out << LocalTag("a", "foo") << "bar"; |
| |
| ExpectEmit("!a!foo bar"); |
| } |
| |
| TEST_F(EmitterTest, LocalTagWithScalar) { |
| out << LocalTag("foo") << "bar"; |
| |
| ExpectEmit("!foo bar"); |
| } |
| |
| TEST_F(EmitterTest, ComplexDoc) { |
| out << BeginMap; |
| out << Key << "receipt"; |
| out << Value << "Oz-Ware Purchase Invoice"; |
| out << Key << "date"; |
| out << Value << "2007-08-06"; |
| out << Key << "customer"; |
| out << Value; |
| out << BeginMap; |
| out << Key << "given"; |
| out << Value << "Dorothy"; |
| out << Key << "family"; |
| out << Value << "Gale"; |
| out << EndMap; |
| out << Key << "items"; |
| out << Value; |
| out << BeginSeq; |
| out << BeginMap; |
| out << Key << "part_no"; |
| out << Value << "A4786"; |
| out << Key << "descrip"; |
| out << Value << "Water Bucket (Filled)"; |
| out << Key << "price"; |
| out << Value << 1.47; |
| out << Key << "quantity"; |
| out << Value << 4; |
| out << EndMap; |
| out << BeginMap; |
| out << Key << "part_no"; |
| out << Value << "E1628"; |
| out << Key << "descrip"; |
| out << Value << "High Heeled \"Ruby\" Slippers"; |
| out << Key << "price"; |
| out << Value << 100.27; |
| out << Key << "quantity"; |
| out << Value << 1; |
| out << EndMap; |
| out << EndSeq; |
| out << Key << "bill-to"; |
| out << Value << Anchor("id001"); |
| out << BeginMap; |
| out << Key << "street"; |
| out << Value << Literal << "123 Tornado Alley\nSuite 16"; |
| out << Key << "city"; |
| out << Value << "East Westville"; |
| out << Key << "state"; |
| out << Value << "KS"; |
| out << EndMap; |
| out << Key << "ship-to"; |
| out << Value << Alias("id001"); |
| out << EndMap; |
| |
| ExpectEmit( |
| "receipt: Oz-Ware Purchase Invoice\ndate: 2007-08-06\ncustomer:\n " |
| "given: Dorothy\n family: Gale\nitems:\n - part_no: A4786\n " |
| "descrip: Water Bucket (Filled)\n price: 1.47\n quantity: 4\n - " |
| "part_no: E1628\n descrip: High Heeled \"Ruby\" Slippers\n price: " |
| "100.27\n quantity: 1\nbill-to: &id001\n street: |\n 123 Tornado " |
| "Alley\n Suite 16\n city: East Westville\n state: KS\nship-to: " |
| "*id001"); |
| } |
| |
| TEST_F(EmitterTest, STLContainers) { |
| out << BeginSeq; |
| std::vector<int> primes; |
| primes.push_back(2); |
| primes.push_back(3); |
| primes.push_back(5); |
| primes.push_back(7); |
| primes.push_back(11); |
| primes.push_back(13); |
| out << Flow << primes; |
| std::map<std::string, int> ages; |
| ages["Daniel"] = 26; |
| ages["Jesse"] = 24; |
| out << ages; |
| out << EndSeq; |
| |
| ExpectEmit("- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24"); |
| } |
| |
| TEST_F(EmitterTest, CommentStyle) { |
| out.SetPreCommentIndent(1); |
| out.SetPostCommentIndent(2); |
| out << BeginMap; |
| out << Key << "method"; |
| out << Value << "least squares" << Comment("should we change this method?"); |
| out << EndMap; |
| |
| ExpectEmit("method: least squares # should we change this method?"); |
| } |
| |
| TEST_F(EmitterTest, SimpleComment) { |
| out << BeginMap; |
| out << Key << "method"; |
| out << Value << "least squares" << Comment("should we change this method?"); |
| out << EndMap; |
| |
| ExpectEmit("method: least squares # should we change this method?"); |
| } |
| |
| TEST_F(EmitterTest, MultiLineComment) { |
| out << BeginSeq; |
| out << "item 1" |
| << Comment( |
| "really really long\ncomment that couldn't " |
| "possibly\nfit on one line"); |
| out << "item 2"; |
| out << EndSeq; |
| |
| ExpectEmit( |
| "- item 1 # really really long\n # comment that couldn't " |
| "possibly\n # fit on one line\n- item 2"); |
| } |
| |
| TEST_F(EmitterTest, ComplexComments) { |
| out << BeginMap; |
| out << LongKey << Key << "long key" << Comment("long key"); |
| out << Value << "value"; |
| out << EndMap; |
| |
| ExpectEmit("? long key # long key\n: value"); |
| } |
| |
| TEST_F(EmitterTest, InitialComment) { |
| out << Comment("A comment describing the purpose of the file."); |
| out << BeginMap << Key << "key" << Value << "value" << EndMap; |
| |
| ExpectEmit("# A comment describing the purpose of the file.\nkey: value"); |
| } |
| |
| TEST_F(EmitterTest, InitialCommentWithDocIndicator) { |
| out << BeginDoc << Comment("A comment describing the purpose of the file."); |
| out << BeginMap << Key << "key" << Value << "value" << EndMap; |
| |
| ExpectEmit( |
| "---\n# A comment describing the purpose of the file.\nkey: value"); |
| } |
| |
| TEST_F(EmitterTest, CommentInFlowSeq) { |
| out << Flow << BeginSeq << "foo" << Comment("foo!") << "bar" << EndSeq; |
| |
| ExpectEmit("[foo, # foo!\nbar]"); |
| } |
| |
| TEST_F(EmitterTest, CommentInFlowMap) { |
| out << Flow << BeginMap; |
| out << Key << "foo" << Value << "foo value"; |
| out << Key << "bar" << Value << "bar value" << Comment("bar!"); |
| out << Key << "baz" << Value << "baz value" << Comment("baz!"); |
| out << EndMap; |
| |
| ExpectEmit( |
| "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}"); |
| } |
| |
| TEST_F(EmitterTest, Indentation) { |
| out << Indent(4); |
| out << BeginSeq; |
| out << BeginMap; |
| out << Key << "key 1" << Value << "value 1"; |
| out << Key << "key 2" << Value << BeginSeq << "a" |
| << "b" |
| << "c" << EndSeq; |
| out << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit( |
| "- key 1: value 1\n key 2:\n - a\n - b\n - " |
| " c"); |
| } |
| |
| TEST_F(EmitterTest, SimpleGlobalSettings) { |
| out.SetIndent(4); |
| out.SetMapFormat(LongKey); |
| |
| out << BeginSeq; |
| out << BeginMap; |
| out << Key << "key 1" << Value << "value 1"; |
| out << Key << "key 2" << Value << Flow << BeginSeq << "a" |
| << "b" |
| << "c" << EndSeq; |
| out << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit("- ? key 1\n : value 1\n ? key 2\n : [a, b, c]"); |
| } |
| |
| TEST_F(EmitterTest, GlobalLongKeyOnSeq) { |
| out.SetMapFormat(LongKey); |
| |
| out << BeginMap; |
| out << Key << Anchor("key"); |
| out << BeginSeq << "a" |
| << "b" << EndSeq; |
| out << Value << Anchor("value"); |
| out << BeginSeq << "c" |
| << "d" << EndSeq; |
| out << Key << Alias("key") << Value << Alias("value"); |
| out << EndMap; |
| |
| ExpectEmit(R"(? &key |
| - a |
| - b |
| : &value |
| - c |
| - d |
| ? *key |
| : *value)"); |
| } |
| |
| TEST_F(EmitterTest, GlobalLongKeyOnMap) { |
| out.SetMapFormat(LongKey); |
| |
| out << BeginMap; |
| out << Key << Anchor("key"); |
| out << BeginMap << "a" |
| << "b" << EndMap; |
| out << Value << Anchor("value"); |
| out << BeginMap << "c" |
| << "d" << EndMap; |
| out << Key << Alias("key") << Value << Alias("value"); |
| out << EndMap; |
| |
| ExpectEmit(R"(? &key |
| ? a |
| : b |
| : &value |
| ? c |
| : d |
| ? *key |
| : *value)"); |
| } |
| |
| TEST_F(EmitterTest, GlobalSettingStyleOnSeqNode) { |
| Node n(Load(R"(foo: |
| - 1 |
| - 2 |
| - 3 |
| bar: aa)")); |
| out.SetSeqFormat(YAML::Flow); |
| out << n; |
| ExpectEmit(R"(foo: [1, 2, 3] |
| bar: aa)"); |
| } |
| |
| TEST_F(EmitterTest, GlobalSettingStyleOnMapNode) { |
| Node n(Load(R"(- |
| foo: a |
| bar: b |
| - 2 |
| - 3)")); |
| out.SetMapFormat(YAML::Flow); |
| out << n; |
| ExpectEmit(R"(- {foo: a, bar: b} |
| - 2 |
| - 3)"); |
| } |
| |
| TEST_F(EmitterTest, ComplexGlobalSettings) { |
| out << BeginSeq; |
| out << Block; |
| out << BeginMap; |
| out << Key << "key 1" << Value << "value 1"; |
| out << Key << "key 2" << Value; |
| out.SetSeqFormat(Flow); |
| out << BeginSeq << "a" |
| << "b" |
| << "c" << EndSeq; |
| out << EndMap; |
| out << BeginMap; |
| out << Key << BeginSeq << 1 << 2 << EndSeq; |
| out << Value << BeginMap << Key << "a" << Value << "b" << EndMap; |
| out << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit("- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b"); |
| } |
| |
| TEST_F(EmitterTest, Null) { |
| out << BeginSeq; |
| out << Null; |
| out << BeginMap; |
| out << Key << "null value" << Value << Null; |
| out << Key << Null << Value << "null key"; |
| out << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit("- ~\n- null value: ~\n ~: null key"); |
| } |
| |
| TEST_F(EmitterTest, OutputCharset) { |
| out << BeginSeq; |
| out.SetOutputCharset(EmitNonAscii); |
| out << "\x24 \xC2\xA2 \xE2\x82\xAC"; |
| out.SetOutputCharset(EscapeNonAscii); |
| out << "\x24 \xC2\xA2 \xE2\x82\xAC"; |
| out << EndSeq; |
| |
| ExpectEmit("- \x24 \xC2\xA2 \xE2\x82\xAC\n- \"\x24 \\xa2 \\u20ac\""); |
| } |
| |
| TEST_F(EmitterTest, EscapedUnicode) { |
| out << EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; |
| |
| ExpectEmit("\"$ \\xa2 \\u20ac \\U00024b62\""); |
| } |
| |
| TEST_F(EmitterTest, Unicode) { |
| out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; |
| ExpectEmit("\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"); |
| } |
| |
| TEST_F(EmitterTest, DoubleQuotedUnicode) { |
| out << DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; |
| ExpectEmit("\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""); |
| } |
| |
| TEST_F(EmitterTest, EscapedJsonString) { |
| out.SetStringFormat(DoubleQuoted); |
| out.SetOutputCharset(EscapeAsJson); |
| out << "\" \\ " |
| "\x01 \x02 \x03 \x04 \x05 \x06 \x07 \x08 \x09 \x0A \x0B \x0C \x0D \x0E \x0F " |
| "\x10 \x11 \x12 \x13 \x14 \x15 \x16 \x17 \x18 \x19 \x1A \x1B \x1C \x1D \x1E \x1F " |
| "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; |
| |
| ExpectEmit(R"("\" \\ \u0001 \u0002 \u0003 \u0004 \u0005 \u0006 \u0007 \b \t )" |
| R"(\n \u000b \f \r \u000e \u000f \u0010 \u0011 \u0012 \u0013 )" |
| R"(\u0014 \u0015 \u0016 \u0017 \u0018 \u0019 \u001a \u001b )" |
| R"(\u001c \u001d \u001e \u001f )" |
| "$ \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""); |
| } |
| |
| TEST_F(EmitterTest, EscapedCharacters) { |
| out << BeginSeq |
| << '\x00' |
| << '\x0C' |
| << '\x0D' |
| << EndSeq; |
| |
| ExpectEmit("- \"\\x00\"\n- \"\\f\"\n- \"\\r\""); |
| } |
| |
| TEST_F(EmitterTest, CharactersEscapedAsJson) { |
| out.SetOutputCharset(EscapeAsJson); |
| out << BeginSeq |
| << '\x00' |
| << '\x0C' |
| << '\x0D' |
| << EndSeq; |
| |
| ExpectEmit("- \"\\u0000\"\n- \"\\f\"\n- \"\\r\""); |
| } |
| |
| TEST_F(EmitterTest, DoubleQuotedString) { |
| out << DoubleQuoted << "\" \\ \n \t \r \b \x15 \xEF\xBB\xBF \x24"; |
| ExpectEmit("\"\\\" \\\\ \\n \\t \\r \\b \\x15 \\ufeff $\""); |
| } |
| |
| struct Foo { |
| Foo() : x(0) {} |
| Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {} |
| |
| int x; |
| std::string bar; |
| }; |
| |
| Emitter& operator<<(Emitter& out, const Foo& foo) { |
| out << BeginMap; |
| out << Key << "x" << Value << foo.x; |
| out << Key << "bar" << Value << foo.bar; |
| out << EndMap; |
| return out; |
| } |
| |
| TEST_F(EmitterTest, UserType) { |
| out << BeginSeq; |
| out << Foo(5, "hello"); |
| out << Foo(3, "goodbye"); |
| out << EndSeq; |
| |
| ExpectEmit("- x: 5\n bar: hello\n- x: 3\n bar: goodbye"); |
| } |
| |
| TEST_F(EmitterTest, UserType2) { |
| out << BeginSeq; |
| out << Foo(5, "\r"); |
| out << EndSeq; |
| |
| ExpectEmit("- x: 5\n bar: \"\\r\""); |
| } |
| |
| TEST_F(EmitterTest, UserTypeInContainer) { |
| std::vector<Foo> fv; |
| fv.push_back(Foo(5, "hello")); |
| fv.push_back(Foo(3, "goodbye")); |
| out << fv; |
| |
| ExpectEmit("- x: 5\n bar: hello\n- x: 3\n bar: goodbye"); |
| } |
| |
| template <typename T> |
| Emitter& operator<<(Emitter& out, const T* v) { |
| if (v) |
| out << *v; |
| else |
| out << Null; |
| return out; |
| } |
| |
| TEST_F(EmitterTest, PointerToInt) { |
| int foo = 5; |
| int* bar = &foo; |
| int* baz = 0; |
| out << BeginSeq; |
| out << bar << baz; |
| out << EndSeq; |
| |
| ExpectEmit("- 5\n- ~"); |
| } |
| |
| TEST_F(EmitterTest, PointerToUserType) { |
| Foo foo(5, "hello"); |
| Foo* bar = &foo; |
| Foo* baz = 0; |
| out << BeginSeq; |
| out << bar << baz; |
| out << EndSeq; |
| |
| ExpectEmit("- x: 5\n bar: hello\n- ~"); |
| } |
| |
| TEST_F(EmitterTest, NewlineAtEnd) { |
| out << "Hello" << Newline << Newline; |
| ExpectEmit("Hello\n\n"); |
| } |
| |
| TEST_F(EmitterTest, NewlineInBlockSequence) { |
| out << BeginSeq; |
| out << "a" << Newline << "b" |
| << "c" << Newline << "d"; |
| out << EndSeq; |
| ExpectEmit("- a\n\n- b\n- c\n\n- d"); |
| } |
| |
| TEST_F(EmitterTest, NewlineInFlowSequence) { |
| out << Flow << BeginSeq; |
| out << "a" << Newline << "b" |
| << "c" << Newline << "d"; |
| out << EndSeq; |
| ExpectEmit("[a,\nb, c,\nd]"); |
| } |
| |
| TEST_F(EmitterTest, NewlineInBlockMap) { |
| out << BeginMap; |
| out << Key << "a" << Value << "foo" << Newline; |
| out << Key << "b" << Newline << Value << "bar"; |
| out << LongKey << Key << "c" << Newline << Value << "car"; |
| out << EndMap; |
| ExpectEmit("a: foo\nb:\n bar\n? c\n\n: car"); |
| } |
| |
| TEST_F(EmitterTest, NewlineInFlowMap) { |
| out << Flow << BeginMap; |
| out << Key << "a" << Value << "foo" << Newline; |
| out << Key << "b" << Value << "bar"; |
| out << EndMap; |
| ExpectEmit("{a: foo,\nb: bar}"); |
| } |
| |
| TEST_F(EmitterTest, LotsOfNewlines) { |
| out << BeginSeq; |
| out << "a" << Newline; |
| out << BeginSeq; |
| out << "b" |
| << "c" << Newline; |
| out << EndSeq; |
| out << Newline; |
| out << BeginMap; |
| out << Newline << Key << "d" << Value << Newline << "e"; |
| out << LongKey << Key << "f" << Newline << Value << "foo"; |
| out << EndMap; |
| out << EndSeq; |
| ExpectEmit("- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo"); |
| } |
| |
| TEST_F(EmitterTest, Binary) { |
| out << Binary(reinterpret_cast<const unsigned char*>("Hello, World!"), 13); |
| ExpectEmit("!!binary \"SGVsbG8sIFdvcmxkIQ==\""); |
| } |
| |
| TEST_F(EmitterTest, LongBinary) { |
| out << Binary( |
| reinterpret_cast<const unsigned char*>( |
| "Man is distinguished, not only by his reason, but by this " |
| "singular passion from other animals, which is a lust of the " |
| "mind, that by a perseverance of delight in the continued and " |
| "indefatigable generation of knowledge, exceeds the short " |
| "vehemence of any carnal pleasure.\n"), |
| 270); |
| ExpectEmit( |
| "!!binary " |
| "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" |
| "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" |
| "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" |
| "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" |
| "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" |
| "4K\""); |
| } |
| |
| TEST_F(EmitterTest, EmptyBinary) { |
| out << Binary(reinterpret_cast<const unsigned char*>(""), 0); |
| ExpectEmit("!!binary \"\""); |
| } |
| |
| TEST_F(EmitterTest, ColonAtEndOfScalar) { |
| out << "a:"; |
| ExpectEmit("\"a:\""); |
| } |
| |
| TEST_F(EmitterTest, ColonAsScalar) { |
| out << BeginMap; |
| out << Key << "apple" << Value << ":"; |
| out << Key << "banana" << Value << ":"; |
| out << EndMap; |
| ExpectEmit("apple: \":\"\nbanana: \":\""); |
| } |
| |
| TEST_F(EmitterTest, ColonAtEndOfScalarInFlow) { |
| out << Flow << BeginMap << Key << "C:" << Value << "C:" << EndMap; |
| ExpectEmit("{\"C:\": \"C:\"}"); |
| } |
| |
| TEST_F(EmitterTest, GlobalBoolFormatting) { |
| out << BeginSeq; |
| out.SetBoolFormat(UpperCase); |
| out.SetBoolFormat(YesNoBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(TrueFalseBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(OnOffBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(LowerCase); |
| out.SetBoolFormat(YesNoBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(TrueFalseBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(OnOffBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(CamelCase); |
| out.SetBoolFormat(YesNoBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(TrueFalseBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(OnOffBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(ShortBool); |
| out.SetBoolFormat(UpperCase); |
| out.SetBoolFormat(YesNoBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(TrueFalseBool); |
| out << true; |
| out << false; |
| out.SetBoolFormat(OnOffBool); |
| out << true; |
| out << false; |
| out << EndSeq; |
| ExpectEmit( |
| "- YES\n- NO\n- TRUE\n- FALSE\n- ON\n- OFF\n" |
| "- yes\n- no\n- true\n- false\n- on\n- off\n" |
| "- Yes\n- No\n- True\n- False\n- On\n- Off\n" |
| "- Y\n- N\n- Y\n- N\n- Y\n- N"); |
| } |
| |
| TEST_F(EmitterTest, BoolFormatting) { |
| out << BeginSeq; |
| out << TrueFalseBool << UpperCase << true; |
| out << TrueFalseBool << CamelCase << true; |
| out << TrueFalseBool << LowerCase << true; |
| out << TrueFalseBool << UpperCase << false; |
| out << TrueFalseBool << CamelCase << false; |
| out << TrueFalseBool << LowerCase << false; |
| out << YesNoBool << UpperCase << true; |
| out << YesNoBool << CamelCase << true; |
| out << YesNoBool << LowerCase << true; |
| out << YesNoBool << UpperCase << false; |
| out << YesNoBool << CamelCase << false; |
| out << YesNoBool << LowerCase << false; |
| out << OnOffBool << UpperCase << true; |
| out << OnOffBool << CamelCase << true; |
| out << OnOffBool << LowerCase << true; |
| out << OnOffBool << UpperCase << false; |
| out << OnOffBool << CamelCase << false; |
| out << OnOffBool << LowerCase << false; |
| out << ShortBool << UpperCase << true; |
| out << ShortBool << CamelCase << true; |
| out << ShortBool << LowerCase << true; |
| out << ShortBool << UpperCase << false; |
| out << ShortBool << CamelCase << false; |
| out << ShortBool << LowerCase << false; |
| out << EndSeq; |
| ExpectEmit( |
| "- TRUE\n- True\n- true\n- FALSE\n- False\n- false\n" |
| "- YES\n- Yes\n- yes\n- NO\n- No\n- no\n" |
| "- ON\n- On\n- on\n- OFF\n- Off\n- off\n" |
| "- Y\n- Y\n- y\n- N\n- N\n- n"); |
| } |
| |
| TEST_F(EmitterTest, GlobalNullFormatting) { |
| out << Flow << BeginSeq; |
| out.SetNullFormat(LowerNull); |
| out << Null; |
| out.SetNullFormat(UpperNull); |
| out << Null; |
| out.SetNullFormat(CamelNull); |
| out << Null; |
| out.SetNullFormat(TildeNull); |
| out << Null; |
| out << EndSeq; |
| ExpectEmit("[null, NULL, Null, ~]"); |
| } |
| |
| TEST_F(EmitterTest, NullFormatting) { |
| out << Flow << BeginSeq; |
| out << LowerNull << Null; |
| out << UpperNull << Null; |
| out << CamelNull << Null; |
| out << TildeNull << Null; |
| out << EndSeq; |
| ExpectEmit("[null, NULL, Null, ~]"); |
| } |
| |
| TEST_F(EmitterTest, NullFormattingOnNode) { |
| Node n(Load("null")); |
| out << Flow << BeginSeq; |
| out.SetNullFormat(LowerNull); |
| out << n; |
| out.SetNullFormat(UpperNull); |
| out << n; |
| out.SetNullFormat(CamelNull); |
| out << n; |
| out.SetNullFormat(TildeNull); |
| out << n; |
| out << EndSeq; |
| ExpectEmit("[null, NULL, Null, ~]"); |
| } |
| |
| // TODO: Fix this test. |
| // TEST_F(EmitterTest, DocStartAndEnd) { |
| // out << BeginDoc; |
| // out << BeginSeq << 1 << 2 << 3 << EndSeq; |
| // out << BeginDoc; |
| // out << "Hi there!"; |
| // out << EndDoc; |
| // out << EndDoc; |
| // out << EndDoc; |
| // out << BeginDoc; |
| // out << VerbatimTag("foo") << "bar"; |
| // ExpectEmit( |
| // "---\n- 1\n- 2\n- 3\n---\nHi there!\n...\n...\n...\n---\n!<foo> bar"); |
| //} |
| |
| TEST_F(EmitterTest, ImplicitDocStart) { |
| out << "Hi"; |
| out << "Bye"; |
| out << "Oops"; |
| ExpectEmit("Hi\n---\nBye\n---\nOops"); |
| } |
| |
| TEST_F(EmitterTest, EmptyString) { |
| out << BeginMap; |
| out << Key << "key" << Value << ""; |
| out << EndMap; |
| ExpectEmit("key: \"\""); |
| } |
| |
| TEST_F(EmitterTest, SingleChar) { |
| out << BeginSeq; |
| out << 'a'; |
| out << ':'; |
| out << (char)0x10; |
| out << '\n'; |
| out << ' '; |
| out << '\t'; |
| out << EndSeq; |
| ExpectEmit("- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""); |
| } |
| |
| TEST_F(EmitterTest, DefaultPrecision) { |
| out << BeginSeq; |
| out << 1.3125f; |
| out << 1.23455810546875; |
| out << EndSeq; |
| ExpectEmit("- 1.3125\n- 1.23455810546875"); |
| } |
| |
| TEST_F(EmitterTest, SetPrecision) { |
| out << BeginSeq; |
| out << FloatPrecision(3) << 1.3125f; |
| out << DoublePrecision(6) << 1.23455810546875; |
| out << EndSeq; |
| ExpectEmit("- 1.31\n- 1.23456"); |
| } |
| |
| TEST_F(EmitterTest, DashInBlockContext) { |
| out << BeginMap; |
| out << Key << "key" << Value << "-"; |
| out << EndMap; |
| ExpectEmit("key: \"-\""); |
| } |
| |
| TEST_F(EmitterTest, HexAndOct) { |
| out << Flow << BeginSeq; |
| out << 31; |
| out << Hex << 31; |
| out << Oct << 31; |
| out << EndSeq; |
| ExpectEmit("[31, 0x1f, 037]"); |
| } |
| |
| TEST_F(EmitterTest, CompactMapWithNewline) { |
| out << Comment("Characteristics"); |
| out << BeginSeq; |
| out << BeginMap; |
| out << Key << "color" << Value << "blue"; |
| out << Key << "height" << Value << 120; |
| out << EndMap; |
| out << Newline << Newline; |
| out << Comment("Skills"); |
| out << BeginMap; |
| out << Key << "attack" << Value << 23; |
| out << Key << "intelligence" << Value << 56; |
| out << EndMap; |
| out << EndSeq; |
| |
| ExpectEmit( |
| "# Characteristics\n" |
| "- color: blue\n" |
| " height: 120\n" |
| "\n" |
| "# Skills\n" |
| "- attack: 23\n" |
| " intelligence: 56"); |
| } |
| |
| TEST_F(EmitterTest, ForceSingleQuotedToDouble) { |
| out << SingleQuoted << "Hello\nWorld"; |
| |
| ExpectEmit("\"Hello\\nWorld\""); |
| } |
| |
| TEST_F(EmitterTest, QuoteNull) { |
| out << "null"; |
| |
| ExpectEmit("\"null\""); |
| } |
| |
| TEST_F(EmitterTest, ValueOfDoubleQuote) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "foo" << YAML::Value << '"'; |
| out << YAML::EndMap; |
| |
| ExpectEmit("foo: \"\\\"\""); |
| } |
| |
| TEST_F(EmitterTest, ValueOfBackslash) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "foo" << YAML::Value << '\\'; |
| out << YAML::EndMap; |
| |
| ExpectEmit("foo: \"\\\\\""); |
| } |
| |
| TEST_F(EmitterTest, Infinity) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "foo" << YAML::Value |
| << std::numeric_limits<float>::infinity(); |
| out << YAML::Key << "bar" << YAML::Value |
| << std::numeric_limits<double>::infinity(); |
| out << YAML::EndMap; |
| |
| ExpectEmit( |
| "foo: .inf\n" |
| "bar: .inf"); |
| } |
| |
| TEST_F(EmitterTest, NegInfinity) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "foo" << YAML::Value |
| << -std::numeric_limits<float>::infinity(); |
| out << YAML::Key << "bar" << YAML::Value |
| << -std::numeric_limits<double>::infinity(); |
| out << YAML::EndMap; |
| |
| ExpectEmit( |
| "foo: -.inf\n" |
| "bar: -.inf"); |
| } |
| |
| TEST_F(EmitterTest, NaN) { |
| out << YAML::BeginMap; |
| out << YAML::Key << "foo" << YAML::Value |
| << std::numeric_limits<float>::quiet_NaN(); |
| out << YAML::Key << "bar" << YAML::Value |
| << std::numeric_limits<double>::quiet_NaN(); |
| out << YAML::EndMap; |
| |
| ExpectEmit( |
| "foo: .nan\n" |
| "bar: .nan"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLine) { |
| out << YAML::BeginMap; |
| |
| out << YAML::Key << "NodeA" << YAML::Value << YAML::BeginMap; |
| out << YAML::Key << "k" << YAML::Value << YAML::Flow << YAML::BeginSeq; |
| out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 0 << YAML::EndMap |
| << YAML::Newline; |
| out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 1 << YAML::EndMap |
| << YAML::Newline; |
| out << YAML::EndSeq; |
| out << YAML::EndMap; |
| |
| out << YAML::Key << "NodeB" << YAML::Value << YAML::BeginMap; |
| out << YAML::Key << "k" << YAML::Value << YAML::Flow << YAML::BeginSeq; |
| out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 0 << YAML::EndMap |
| << YAML::Newline; |
| out << YAML::BeginMap << YAML::Key << "i" << YAML::Value << 1 << YAML::EndMap |
| << YAML::Newline; |
| out << YAML::EndSeq; |
| out << YAML::EndMap; |
| |
| out << YAML::EndMap; |
| |
| ExpectEmit(R"(NodeA: |
| k: [{i: 0}, |
| {i: 1}, |
| ] |
| NodeB: |
| k: [{i: 0}, |
| {i: 1}, |
| ])"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases) { |
| out << BeginMap; |
| |
| out << Key << "Node" << Anchor("Node") << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << YAML::Newline; |
| out << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << YAML::Newline; |
| out << EndSeq << EndMap; |
| |
| out << Key << "NodeA" << Alias("Node"); |
| out << Key << "NodeB" << Alias("Node"); |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Node: &Node |
| k: [{i: 0}, |
| {i: 1}, |
| ] |
| NodeA: *Node |
| NodeB: *Node)"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases) { |
| out << BeginMap; |
| |
| out << Key << "Node" << Anchor("Node") << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << EndSeq << EndMap; |
| |
| out << Key << "NodeA" << Alias("Node"); |
| out << Key << "NodeB" << Alias("Node"); |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Node: &Node |
| k: [{i: 0}, {i: 1}] |
| NodeA: *Node |
| NodeB: *Node)"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases2) { |
| out << BeginMap; |
| |
| out << Key << "Seq" << Anchor("Seq") << Flow << BeginSeq; |
| out << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << YAML::Newline; |
| out << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << YAML::Newline; |
| out << EndSeq; |
| |
| out << Key << "NodeA" << Value << BeginMap; |
| out << Key << "k" << Value << Alias("Seq") << EndMap; |
| out << Key << "NodeB" << Value << BeginMap; |
| out << Key << "k" << Value << Alias("Seq") << EndMap; |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Seq: &Seq [{i: 0}, |
| {i: 1}, |
| ] |
| NodeA: |
| k: *Seq |
| NodeB: |
| k: *Seq)"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases2) { |
| out << BeginMap; |
| |
| out << Key << "Seq" << Anchor("Seq") << Value << Flow << BeginSeq; |
| out << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << EndSeq; |
| |
| out << Key << "NodeA" << Value << BeginMap; |
| out << Key << "k" << Value << Alias("Seq") << EndMap; |
| out << Key << "NodeB" << Value << BeginMap; |
| out << Key << "k" << Value << Alias("Seq") << EndMap; |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Seq: &Seq [{i: 0}, {i: 1}] |
| NodeA: |
| k: *Seq |
| NodeB: |
| k: *Seq)"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapWithNewLineUsingAliases3) { |
| out << BeginMap; |
| |
| out << Key << "Keys" << Value << Flow << BeginSeq; |
| out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap |
| << Newline; |
| out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap |
| << Newline; |
| out << EndSeq; |
| |
| out << Key << "NodeA" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Newline << Alias("k1") << Newline; |
| out << EndSeq << EndMap; |
| |
| out << Key << "NodeB" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Newline << Alias("k1") << Newline; |
| out << EndSeq << EndMap; |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Keys: [&k0 {i: 0}, |
| &k1 {i: 1}, |
| ] |
| NodeA: |
| k: [*k0, |
| *k1, |
| ] |
| NodeB: |
| k: [*k0, |
| *k1, |
| ])"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases3a) { |
| out << BeginMap; |
| |
| out << Key << "Keys" << Value << BeginSeq; |
| out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << EndSeq; |
| |
| out << Key << "NodeA" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Alias("k1"); |
| out << EndSeq << EndMap; |
| |
| out << Key << "NodeB" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Alias("k1"); |
| out << EndSeq << EndMap; |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Keys: |
| - &k0 |
| i: 0 |
| - &k1 |
| i: 1 |
| NodeA: |
| k: [*k0, *k1] |
| NodeB: |
| k: [*k0, *k1])"); |
| } |
| |
| TEST_F(EmitterTest, ComplexFlowSeqEmbeddingAMapUsingAliases3b) { |
| out << BeginMap; |
| |
| out << Key << "Keys" << Value << Flow << BeginSeq; |
| out << Anchor("k0") << BeginMap << Key << "i" << Value << 0 << EndMap; |
| out << Anchor("k1") << BeginMap << Key << "i" << Value << 1 << EndMap; |
| out << EndSeq; |
| |
| out << Key << "NodeA" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Alias("k1"); |
| out << EndSeq << EndMap; |
| |
| out << Key << "NodeB" << Value << BeginMap; |
| out << Key << "k" << Value << Flow << BeginSeq; |
| out << Alias("k0") << Alias("k1"); |
| out << EndSeq << EndMap; |
| |
| out << EndMap; |
| |
| ExpectEmit(R"(Keys: [&k0 {i: 0}, &k1 {i: 1}] |
| NodeA: |
| k: [*k0, *k1] |
| NodeB: |
| k: [*k0, *k1])"); |
| } |
| |
| TEST_F(EmitterTest, AnchorEncoding) { |
| Node node; |
| node["--- &$ [*$]1"] = 1; |
| out << node; |
| ExpectEmit("\"--- &$ [*$]1\": 1"); |
| Node reparsed = YAML::Load(out.c_str()); |
| EXPECT_EQ(reparsed["--- &$ [*$]1"].as<int>(), 1); |
| } |
| |
| class EmitterErrorTest : public ::testing::Test { |
| protected: |
| void ExpectEmitError(const std::string& expectedError) { |
| ASSERT_FALSE(out.good()) << "Emitter cleanly produced: " << out.c_str(); |
| EXPECT_EQ(expectedError, out.GetLastError()); |
| } |
| |
| Emitter out; |
| }; |
| |
| TEST_F(EmitterErrorTest, BadLocalTag) { |
| out << LocalTag("e!far") << "bar"; |
| |
| ExpectEmitError("invalid tag"); |
| } |
| |
| TEST_F(EmitterErrorTest, BadTagAndTag) { |
| out << VerbatimTag("!far") << VerbatimTag("!foo") << "bar"; |
| ExpectEmitError(ErrorMsg::INVALID_TAG); |
| } |
| |
| TEST_F(EmitterErrorTest, BadAnchorAndAnchor) { |
| out << Anchor("far") << Anchor("foo") << "bar"; |
| ExpectEmitError(ErrorMsg::INVALID_ANCHOR); |
| } |
| |
| TEST_F(EmitterErrorTest, BadEmptyAnchorOnGroup) { |
| out << BeginSeq << "bar" << Anchor("foo") << EndSeq; |
| ExpectEmitError(ErrorMsg::INVALID_ANCHOR); |
| } |
| |
| TEST_F(EmitterErrorTest, BadEmptyTagOnGroup) { |
| out << BeginSeq << "bar" << VerbatimTag("!foo") << EndSeq; |
| ExpectEmitError(ErrorMsg::INVALID_TAG); |
| } |
| |
| TEST_F(EmitterErrorTest, ExtraEndSeq) { |
| out << BeginSeq; |
| out << "Hello"; |
| out << "World"; |
| out << EndSeq; |
| out << EndSeq; |
| |
| ExpectEmitError(ErrorMsg::UNEXPECTED_END_SEQ); |
| } |
| |
| TEST_F(EmitterErrorTest, ExtraEndMap) { |
| out << BeginMap; |
| out << Key << "Hello" << Value << "World"; |
| out << EndMap; |
| out << EndMap; |
| |
| ExpectEmitError(ErrorMsg::UNEXPECTED_END_MAP); |
| } |
| |
| TEST_F(EmitterErrorTest, InvalidAnchor) { |
| out << BeginSeq; |
| out << Anchor("new\nline") << "Test"; |
| out << EndSeq; |
| |
| ExpectEmitError(ErrorMsg::INVALID_ANCHOR); |
| } |
| |
| TEST_F(EmitterErrorTest, InvalidAlias) { |
| out << BeginSeq; |
| out << Alias("new\nline"); |
| out << EndSeq; |
| |
| ExpectEmitError(ErrorMsg::INVALID_ALIAS); |
| } |
| |
| } // namespace |
| } // namespace YAML |