diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e885802..ac22d7c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,7 +2,7 @@ add_subdirectory(gtest-1.7.0) include_directories(gtest-1.7.0/include) file(GLOB test_headers [a-z_]*.h) -file(GLOB test_sources [a-z_]*.cpp) +file(GLOB test_sources [a-z_]*.cpp integration/[a-z_]*.cpp) file(GLOB test_core_sources core/[a-z]*.cpp) list(APPEND test_sources ${test_core_sources}) diff --git a/test/emittertests.cpp b/test/emittertests.cpp index f4f57df..cdf56ea 100644 --- a/test/emittertests.cpp +++ b/test/emittertests.cpp @@ -4,1063 +4,9 @@ #include "yaml-cpp/eventhandler.h" #include "yaml-cpp/yaml.h" // IWYU pragma: keep -namespace YAML { -class Exception; -struct Mark; -} // namespace YAML - namespace Test { namespace Emitter { -//////////////////////////////////////////////////////////////////////////////////////////////////////// -// correct emitting - -void SimpleScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << "Hello, World!"; - desiredOutput = "Hello, World!"; -} - -void SimpleSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "eggs"; - out << "bread"; - out << "milk"; - out << YAML::EndSeq; - - desiredOutput = "- eggs\n- bread\n- milk"; -} - -void SimpleFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginSeq; - out << "Larry"; - out << "Curly"; - out << "Moe"; - out << YAML::EndSeq; - - desiredOutput = "[Larry, Curly, Moe]"; -} - -void EmptyFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginSeq; - out << YAML::EndSeq; - - desiredOutput = "[]"; -} - -void NestedBlockSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "item 1"; - out << YAML::BeginSeq << "subitem 1" - << "subitem 2" << YAML::EndSeq; - out << YAML::EndSeq; - - desiredOutput = "- item 1\n-\n - subitem 1\n - subitem 2"; -} - -void NestedFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "one"; - out << YAML::Flow << YAML::BeginSeq << "two" - << "three" << YAML::EndSeq; - out << YAML::EndSeq; - - desiredOutput = "- one\n- [two, three]"; -} - -void SimpleMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Ryan Braun"; - out << YAML::Key << "position"; - out << YAML::Value << "3B"; - out << YAML::EndMap; - - desiredOutput = "name: Ryan Braun\nposition: 3B"; -} - -void SimpleFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "shape"; - out << YAML::Value << "square"; - out << YAML::Key << "color"; - out << YAML::Value << "blue"; - out << YAML::EndMap; - - desiredOutput = "{shape: square, color: blue}"; -} - -void MapAndList(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Barack Obama"; - out << YAML::Key << "children"; - out << YAML::Value << YAML::BeginSeq << "Sasha" - << "Malia" << YAML::EndSeq; - out << YAML::EndMap; - - desiredOutput = "name: Barack Obama\nchildren:\n - Sasha\n - Malia"; -} - -void ListAndMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "item 1"; - out << YAML::BeginMap; - out << YAML::Key << "pens" << YAML::Value << 8; - out << YAML::Key << "pencils" << YAML::Value << 14; - out << YAML::EndMap; - out << "item 2"; - out << YAML::EndSeq; - - desiredOutput = "- item 1\n- pens: 8\n pencils: 14\n- item 2"; -} - -void NestedBlockMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Fred"; - out << YAML::Key << "grades"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "algebra" << YAML::Value << "A"; - out << YAML::Key << "physics" << YAML::Value << "C+"; - out << YAML::Key << "literature" << YAML::Value << "B"; - out << YAML::EndMap; - out << YAML::EndMap; - - desiredOutput = - "name: Fred\ngrades:\n algebra: A\n physics: C+\n literature: B"; -} - -void NestedFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Fred"; - out << YAML::Key << "grades"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "algebra" << YAML::Value << "A"; - out << YAML::Key << "physics" << YAML::Value << "C+"; - out << YAML::Key << "literature" << YAML::Value << "B"; - out << YAML::EndMap; - out << YAML::EndMap; - - desiredOutput = - "{name: Fred, grades: {algebra: A, physics: C+, literature: B}}"; -} - -void MapListMix(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "name"; - out << YAML::Value << "Bob"; - out << YAML::Key << "position"; - out << YAML::Value; - out << YAML::Flow << YAML::BeginSeq << 2 << 4 << YAML::EndSeq; - out << YAML::Key << "invincible" << YAML::Value << YAML::OnOffBool << false; - out << YAML::EndMap; - - desiredOutput = "name: Bob\nposition: [2, 4]\ninvincible: off"; -} - -void SimpleLongKey(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::LongKey; - out << YAML::BeginMap; - out << YAML::Key << "height"; - out << YAML::Value << "5'9\""; - out << YAML::Key << "weight"; - out << YAML::Value << 145; - out << YAML::EndMap; - - desiredOutput = "? height\n: 5'9\"\n? weight\n: 145"; -} - -void SingleLongKey(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "age"; - out << YAML::Value << "24"; - out << YAML::LongKey << YAML::Key << "height"; - out << YAML::Value << "5'9\""; - out << YAML::Key << "weight"; - out << YAML::Value << 145; - out << YAML::EndMap; - - desiredOutput = "age: 24\n? height\n: 5'9\"\nweight: 145"; -} - -void ComplexLongKey(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::LongKey; - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; - out << YAML::Value << "monster"; - out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; - out << YAML::Value << "demon"; - out << YAML::EndMap; - - desiredOutput = "? - 1\n - 3\n: monster\n? [2, 0]\n: demon"; -} - -void AutoLongKey(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 3 << YAML::EndSeq; - out << YAML::Value << "monster"; - out << YAML::Key << YAML::Flow << YAML::BeginSeq << 2 << 0 << YAML::EndSeq; - out << YAML::Value << "demon"; - out << YAML::Key << "the origin"; - out << YAML::Value << "angel"; - out << YAML::EndMap; - - desiredOutput = "? - 1\n - 3\n: monster\n[2, 0]: demon\nthe origin: angel"; -} - -void ScalarFormat(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "simple scalar"; - out << YAML::SingleQuoted << "explicit single-quoted scalar"; - out << YAML::DoubleQuoted << "explicit double-quoted scalar"; - out << "auto-detected\ndouble-quoted scalar"; - out << "a non-\"auto-detected\" double-quoted scalar"; - out << YAML::Literal << "literal scalar\nthat may span\nmany, many\nlines " - "and have \"whatever\" crazy\tsymbols that we like"; - out << YAML::EndSeq; - - desiredOutput = - "- 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"; -} - -void AutoLongKeyScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << YAML::Literal << "multi-line\nscalar"; - out << YAML::Value << "and its value"; - out << YAML::EndMap; - - desiredOutput = "? |\n multi-line\n scalar\n: and its value"; -} - -void LongKeyFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow; - out << YAML::BeginMap; - out << YAML::Key << "simple key"; - out << YAML::Value << "and value"; - out << YAML::LongKey << YAML::Key << "long key"; - out << YAML::Value << "and its value"; - out << YAML::EndMap; - - desiredOutput = "{simple key: and value, ? long key: and its value}"; -} - -void BlockMapAsKey(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key; - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << "value"; - out << YAML::Key << "next key" << YAML::Value << "next value"; - out << YAML::EndMap; - out << YAML::Value; - out << "total value"; - out << YAML::EndMap; - - desiredOutput = "? key: value\n next key: next value\n: total value"; -} - -void AliasAndAnchor(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::Anchor("fred"); - out << YAML::BeginMap; - out << YAML::Key << "name" << YAML::Value << "Fred"; - out << YAML::Key << "age" << YAML::Value << 42; - out << YAML::EndMap; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "- &fred\n name: Fred\n age: 42\n- *fred"; -} - -void AliasAndAnchorWithNull(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::Anchor("fred") << YAML::Null; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "- &fred ~\n- *fred"; -} - -void AliasAndAnchorInFlow(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::Anchor("fred"); - out << YAML::BeginMap; - out << YAML::Key << "name" << YAML::Value << "Fred"; - out << YAML::Key << "age" << YAML::Value << 42; - out << YAML::EndMap; - out << YAML::Alias("fred"); - out << YAML::EndSeq; - - desiredOutput = "[&fred {name: Fred, age: 42}, *fred]"; -} - -void SimpleVerbatimTag(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::VerbatimTag("!foo") << "bar"; - - desiredOutput = "! bar"; -} - -void VerbatimTagInBlockSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << "bar"; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "- ! bar\n- baz"; -} - -void VerbatimTagInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << "bar"; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "[! bar, baz]"; -} - -void VerbatimTagInFlowSeqWithNull(YAML::Emitter& out, - std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << YAML::Null; - out << "baz"; - out << YAML::EndSeq; - - desiredOutput = "[! ~, baz]"; -} - -void VerbatimTagInBlockMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; - out << YAML::Value << YAML::VerbatimTag("!waz") << "baz"; - out << YAML::EndMap; - - desiredOutput = "! bar: ! baz"; -} - -void VerbatimTagInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << "bar"; - out << YAML::Value << "baz"; - out << YAML::EndMap; - - desiredOutput = "{! bar: baz}"; -} - -void VerbatimTagInFlowMapWithNull(YAML::Emitter& out, - std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << YAML::VerbatimTag("!foo") << YAML::Null; - out << YAML::Value << "baz"; - out << YAML::EndMap; - - desiredOutput = "{! ~: baz}"; -} - -void VerbatimTagWithEmptySeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; - - desiredOutput = "!\n[]"; -} - -void VerbatimTagWithEmptyMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; - - desiredOutput = "!\n{}"; -} - -void VerbatimTagWithEmptySeqAndMap(YAML::Emitter& out, - std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::VerbatimTag("!foo") << YAML::BeginSeq << YAML::EndSeq; - out << YAML::VerbatimTag("!bar") << YAML::BeginMap << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- !\n []\n- !\n {}"; -} - -void ByKindTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::DoubleQuoted << "12"; - out << "12"; - out << YAML::TagByKind << "12"; - out << YAML::EndSeq; - - desiredOutput = "- \"12\"\n- 12\n- ! 12"; -} - -void LocalTagWithScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::LocalTag("foo") << "bar"; - - desiredOutput = "!foo bar"; -} - -void BadLocalTag(YAML::Emitter& out, std::string& desiredError) { - out << YAML::LocalTag("e!far") << "bar"; - - desiredError = "invalid tag"; -} - -void ComplexDoc(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "receipt"; - out << YAML::Value << "Oz-Ware Purchase Invoice"; - out << YAML::Key << "date"; - out << YAML::Value << "2007-08-06"; - out << YAML::Key << "customer"; - out << YAML::Value; - out << YAML::BeginMap; - out << YAML::Key << "given"; - out << YAML::Value << "Dorothy"; - out << YAML::Key << "family"; - out << YAML::Value << "Gale"; - out << YAML::EndMap; - out << YAML::Key << "items"; - out << YAML::Value; - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "part_no"; - out << YAML::Value << "A4786"; - out << YAML::Key << "descrip"; - out << YAML::Value << "Water Bucket (Filled)"; - out << YAML::Key << "price"; - out << YAML::Value << 1.47; - out << YAML::Key << "quantity"; - out << YAML::Value << 4; - out << YAML::EndMap; - out << YAML::BeginMap; - out << YAML::Key << "part_no"; - out << YAML::Value << "E1628"; - out << YAML::Key << "descrip"; - out << YAML::Value << "High Heeled \"Ruby\" Slippers"; - out << YAML::Key << "price"; - out << YAML::Value << 100.27; - out << YAML::Key << "quantity"; - out << YAML::Value << 1; - out << YAML::EndMap; - out << YAML::EndSeq; - out << YAML::Key << "bill-to"; - out << YAML::Value << YAML::Anchor("id001"); - out << YAML::BeginMap; - out << YAML::Key << "street"; - out << YAML::Value << YAML::Literal << "123 Tornado Alley\nSuite 16"; - out << YAML::Key << "city"; - out << YAML::Value << "East Westville"; - out << YAML::Key << "state"; - out << YAML::Value << "KS"; - out << YAML::EndMap; - out << YAML::Key << "ship-to"; - out << YAML::Value << YAML::Alias("id001"); - out << YAML::EndMap; - - desiredOutput = - "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"; -} - -void STLContainers(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - std::vector 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 << YAML::Flow << primes; - std::map ages; - ages["Daniel"] = 26; - ages["Jesse"] = 24; - out << ages; - out << YAML::EndSeq; - - desiredOutput = "- [2, 3, 5, 7, 11, 13]\n- Daniel: 26\n Jesse: 24"; -} - -void SimpleComment(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "method"; - out << YAML::Value << "least squares" - << YAML::Comment("should we change this method?"); - out << YAML::EndMap; - - desiredOutput = "method: least squares # should we change this method?"; -} - -void MultiLineComment(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "item 1" << YAML::Comment( - "really really long\ncomment that couldn't " - "possibly\nfit on one line"); - out << "item 2"; - out << YAML::EndSeq; - - desiredOutput = - "- item 1 # really really long\n # comment that couldn't " - "possibly\n # fit on one line\n- item 2"; -} - -void ComplexComments(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::LongKey << YAML::Key << "long key" << YAML::Comment("long key"); - out << YAML::Value << "value"; - out << YAML::EndMap; - - desiredOutput = "? long key # long key\n: value"; -} - -void InitialComment(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Comment("A comment describing the purpose of the file."); - out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" - << YAML::EndMap; - - desiredOutput = "# A comment describing the purpose of the file.\nkey: value"; -} - -void InitialCommentWithDocIndicator(YAML::Emitter& out, - std::string& desiredOutput) { - out << YAML::BeginDoc - << YAML::Comment("A comment describing the purpose of the file."); - out << YAML::BeginMap << YAML::Key << "key" << YAML::Value << "value" - << YAML::EndMap; - - desiredOutput = - "---\n# A comment describing the purpose of the file.\nkey: value"; -} - -void CommentInFlowSeq(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq << "foo" << YAML::Comment("foo!") << "bar" - << YAML::EndSeq; - - desiredOutput = "[foo, # foo!\nbar]"; -} - -void CommentInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << "foo" << YAML::Value << "foo value"; - out << YAML::Key << "bar" << YAML::Value << "bar value" - << YAML::Comment("bar!"); - out << YAML::Key << "baz" << YAML::Value << "baz value" - << YAML::Comment("baz!"); - out << YAML::EndMap; - - desiredOutput = - "{foo: foo value, bar: bar value, # bar!\nbaz: baz value, # baz!\n}"; -} - -void Indentation(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Indent(4); - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value << YAML::BeginSeq << "a" - << "b" - << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = - "- key 1: value 1\n key 2:\n - a\n - b\n - " - " c"; -} - -void SimpleGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) { - out.SetIndent(4); - out.SetMapFormat(YAML::LongKey); - - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value << YAML::Flow << YAML::BeginSeq - << "a" - << "b" - << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- ? key 1\n : value 1\n ? key 2\n : [a, b, c]"; -} - -void ComplexGlobalSettings(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::Block; - out << YAML::BeginMap; - out << YAML::Key << "key 1" << YAML::Value << "value 1"; - out << YAML::Key << "key 2" << YAML::Value; - out.SetSeqFormat(YAML::Flow); - out << YAML::BeginSeq << "a" - << "b" - << "c" << YAML::EndSeq; - out << YAML::EndMap; - out << YAML::BeginMap; - out << YAML::Key << YAML::BeginSeq << 1 << 2 << YAML::EndSeq; - out << YAML::Value << YAML::BeginMap << YAML::Key << "a" << YAML::Value << "b" - << YAML::EndMap; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- key 1: value 1\n key 2: [a, b, c]\n- [1, 2]:\n a: b"; -} - -void Null(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::Null; - out << YAML::BeginMap; - out << YAML::Key << "null value" << YAML::Value << YAML::Null; - out << YAML::Key << YAML::Null << YAML::Value << "null key"; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = "- ~\n- null value: ~\n ~: null key"; -} - -void EscapedUnicode(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::EscapeNonAscii << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - - desiredOutput = "\"$ \\xa2 \\u20ac \\U00024b62\""; -} - -void Unicode(YAML::Emitter& out, std::string& desiredOutput) { - out << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - desiredOutput = "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; -} - -void DoubleQuotedUnicode(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::DoubleQuoted << "\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2"; - desiredOutput = "\"\x24 \xC2\xA2 \xE2\x82\xAC \xF0\xA4\xAD\xA2\""; -} - -struct Foo { - Foo() : x(0) {} - Foo(int x_, const std::string& bar_) : x(x_), bar(bar_) {} - - int x; - std::string bar; -}; - -YAML::Emitter& operator<<(YAML::Emitter& out, const Foo& foo) { - out << YAML::BeginMap; - out << YAML::Key << "x" << YAML::Value << foo.x; - out << YAML::Key << "bar" << YAML::Value << foo.bar; - out << YAML::EndMap; - return out; -} - -void UserType(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << Foo(5, "hello"); - out << Foo(3, "goodbye"); - out << YAML::EndSeq; - - desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; -} - -void UserTypeInContainer(YAML::Emitter& out, std::string& desiredOutput) { - std::vector fv; - fv.push_back(Foo(5, "hello")); - fv.push_back(Foo(3, "goodbye")); - out << fv; - - desiredOutput = "- x: 5\n bar: hello\n- x: 3\n bar: goodbye"; -} - -template -YAML::Emitter& operator<<(YAML::Emitter& out, const T* v) { - if (v) - out << *v; - else - out << YAML::Null; - return out; -} - -void PointerToInt(YAML::Emitter& out, std::string& desiredOutput) { - int foo = 5; - int* bar = &foo; - int* baz = 0; - out << YAML::BeginSeq; - out << bar << baz; - out << YAML::EndSeq; - - desiredOutput = "- 5\n- ~"; -} - -void PointerToUserType(YAML::Emitter& out, std::string& desiredOutput) { - Foo foo(5, "hello"); - Foo* bar = &foo; - Foo* baz = 0; - out << YAML::BeginSeq; - out << bar << baz; - out << YAML::EndSeq; - - desiredOutput = "- x: 5\n bar: hello\n- ~"; -} - -void NewlineAtEnd(YAML::Emitter& out, std::string& desiredOutput) { - out << "Hello" << YAML::Newline << YAML::Newline; - desiredOutput = "Hello\n\n"; -} - -void NewlineInBlockSequence(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "a" << YAML::Newline << "b" - << "c" << YAML::Newline << "d"; - out << YAML::EndSeq; - desiredOutput = "- a\n\n- b\n- c\n\n- d"; -} - -void NewlineInFlowSequence(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq; - out << "a" << YAML::Newline << "b" - << "c" << YAML::Newline << "d"; - out << YAML::EndSeq; - desiredOutput = "[a,\nb, c,\nd]"; -} - -void NewlineInBlockMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; - out << YAML::Key << "b" << YAML::Newline << YAML::Value << "bar"; - out << YAML::LongKey << YAML::Key << "c" << YAML::Newline << YAML::Value - << "car"; - out << YAML::EndMap; - desiredOutput = "a: foo\nb:\n bar\n? c\n\n: car"; -} - -void NewlineInFlowMap(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginMap; - out << YAML::Key << "a" << YAML::Value << "foo" << YAML::Newline; - out << YAML::Key << "b" << YAML::Value << "bar"; - out << YAML::EndMap; - desiredOutput = "{a: foo,\nb: bar}"; -} - -void LotsOfNewlines(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << "a" << YAML::Newline; - out << YAML::BeginSeq; - out << "b" - << "c" << YAML::Newline; - out << YAML::EndSeq; - out << YAML::Newline; - out << YAML::BeginMap; - out << YAML::Newline << YAML::Key << "d" << YAML::Value << YAML::Newline - << "e"; - out << YAML::LongKey << YAML::Key << "f" << YAML::Newline << YAML::Value - << "foo"; - out << YAML::EndMap; - out << YAML::EndSeq; - desiredOutput = - "- a\n\n-\n - b\n - c\n\n\n-\n d:\n e\n ? f\n\n : foo"; -} - -void Binary(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Binary(reinterpret_cast("Hello, World!"), - 13); - desiredOutput = "!!binary \"SGVsbG8sIFdvcmxkIQ==\""; -} - -void LongBinary(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Binary( - reinterpret_cast( - "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); - desiredOutput = - "!!binary " - "\"TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieS" - "B0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIG" - "x1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbi" - "B0aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZG" - "dlLCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS" - "4K\""; -} - -void EmptyBinary(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Binary(reinterpret_cast(""), 0); - desiredOutput = "!!binary \"\""; -} - -void ColonAtEndOfScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << "a:"; - desiredOutput = "\"a:\""; -} - -void ColonAsScalar(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "apple" << YAML::Value << ":"; - out << YAML::Key << "banana" << YAML::Value << ":"; - out << YAML::EndMap; - desiredOutput = "apple: \":\"\nbanana: \":\""; -} - -void ColonAtEndOfScalarInFlow(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginMap << YAML::Key << "C:" << YAML::Value - << "C:" << YAML::EndMap; - desiredOutput = "{\"C:\": \"C:\"}"; -} - -void BoolFormatting(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::TrueFalseBool << YAML::UpperCase << true; - out << YAML::TrueFalseBool << YAML::CamelCase << true; - out << YAML::TrueFalseBool << YAML::LowerCase << true; - out << YAML::TrueFalseBool << YAML::UpperCase << false; - out << YAML::TrueFalseBool << YAML::CamelCase << false; - out << YAML::TrueFalseBool << YAML::LowerCase << false; - out << YAML::YesNoBool << YAML::UpperCase << true; - out << YAML::YesNoBool << YAML::CamelCase << true; - out << YAML::YesNoBool << YAML::LowerCase << true; - out << YAML::YesNoBool << YAML::UpperCase << false; - out << YAML::YesNoBool << YAML::CamelCase << false; - out << YAML::YesNoBool << YAML::LowerCase << false; - out << YAML::OnOffBool << YAML::UpperCase << true; - out << YAML::OnOffBool << YAML::CamelCase << true; - out << YAML::OnOffBool << YAML::LowerCase << true; - out << YAML::OnOffBool << YAML::UpperCase << false; - out << YAML::OnOffBool << YAML::CamelCase << false; - out << YAML::OnOffBool << YAML::LowerCase << false; - out << YAML::ShortBool << YAML::UpperCase << true; - out << YAML::ShortBool << YAML::CamelCase << true; - out << YAML::ShortBool << YAML::LowerCase << true; - out << YAML::ShortBool << YAML::UpperCase << false; - out << YAML::ShortBool << YAML::CamelCase << false; - out << YAML::ShortBool << YAML::LowerCase << false; - out << YAML::EndSeq; - desiredOutput = - "- 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"; -} - -void DocStartAndEnd(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginDoc; - out << YAML::BeginSeq << 1 << 2 << 3 << YAML::EndSeq; - out << YAML::BeginDoc; - out << "Hi there!"; - out << YAML::EndDoc; - out << YAML::EndDoc; - out << YAML::EndDoc; - out << YAML::BeginDoc; - out << YAML::VerbatimTag("foo") << "bar"; - desiredOutput = - "---\n- 1\n- 2\n- 3\n---\nHi there!\n...\n...\n...\n---\n! bar"; -} - -void ImplicitDocStart(YAML::Emitter& out, std::string& desiredOutput) { - out << "Hi"; - out << "Bye"; - out << "Oops"; - desiredOutput = "Hi\n---\nBye\n---\nOops"; -} - -void EmptyString(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << ""; - out << YAML::EndMap; - desiredOutput = "key: \"\""; -} - -void SingleChar(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << 'a'; - out << ':'; - out << (char)0x10; - out << '\n'; - out << ' '; - out << '\t'; - out << YAML::EndSeq; - desiredOutput = "- a\n- \":\"\n- \"\\x10\"\n- \"\\n\"\n- \" \"\n- \"\\t\""; -} - -void DefaultPrecision(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << 1.234f; - out << 3.14159265358979; - out << YAML::EndSeq; - desiredOutput = "- 1.234\n- 3.14159265358979"; -} - -void SetPrecision(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginSeq; - out << YAML::FloatPrecision(3) << 1.234f; - out << YAML::DoublePrecision(6) << 3.14159265358979; - out << YAML::EndSeq; - desiredOutput = "- 1.23\n- 3.14159"; -} - -void DashInBlockContext(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::BeginMap; - out << YAML::Key << "key" << YAML::Value << "-"; - out << YAML::EndMap; - desiredOutput = "key: \"-\""; -} - -void HexAndOct(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Flow << YAML::BeginSeq; - out << 31; - out << YAML::Hex << 31; - out << YAML::Oct << 31; - out << YAML::EndSeq; - desiredOutput = "[31, 0x1f, 037]"; -} - -void CompactMapWithNewline(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::Comment("Characteristics"); - out << YAML::BeginSeq; - out << YAML::BeginMap; - out << YAML::Key << "color" << YAML::Value << "blue"; - out << YAML::Key << "height" << YAML::Value << 120; - out << YAML::EndMap; - out << YAML::Newline << YAML::Newline; - out << YAML::Comment("Skills"); - out << YAML::BeginMap; - out << YAML::Key << "attack" << YAML::Value << 23; - out << YAML::Key << "intelligence" << YAML::Value << 56; - out << YAML::EndMap; - out << YAML::EndSeq; - - desiredOutput = - "# Characteristics\n" - "- color: blue\n" - " height: 120\n" - "\n" - "# Skills\n" - "- attack: 23\n" - " intelligence: 56"; -} - -void ForceSingleQuotedToDouble(YAML::Emitter& out, std::string& desiredOutput) { - out << YAML::SingleQuoted << "Hello\nWorld"; - - desiredOutput = "\"Hello\\nWorld\""; -} - -//////////////////////////////////////////////////////////////////////////////// -// incorrect emitting - -void ExtraEndSeq(YAML::Emitter& out, std::string& desiredError) { - desiredError = YAML::ErrorMsg::UNEXPECTED_END_SEQ; - - out << YAML::BeginSeq; - out << "Hello"; - out << "World"; - out << YAML::EndSeq; - out << YAML::EndSeq; -} - -void ExtraEndMap(YAML::Emitter& out, std::string& desiredError) { - desiredError = YAML::ErrorMsg::UNEXPECTED_END_MAP; - - out << YAML::BeginMap; - out << YAML::Key << "Hello" << YAML::Value << "World"; - out << YAML::EndMap; - out << YAML::EndMap; -} - -void InvalidAnchor(YAML::Emitter& out, std::string& desiredError) { - desiredError = YAML::ErrorMsg::INVALID_ANCHOR; - - out << YAML::BeginSeq; - out << YAML::Anchor("new\nline") << "Test"; - out << YAML::EndSeq; -} - -void InvalidAlias(YAML::Emitter& out, std::string& desiredError) { - desiredError = YAML::ErrorMsg::INVALID_ALIAS; - - out << YAML::BeginSeq; - out << YAML::Alias("new\nline"); - out << YAML::EndSeq; -} -} - namespace { -class NullEventHandler : public YAML::EventHandler { - virtual void OnDocumentStart(const YAML::Mark&) {} - virtual void OnDocumentEnd() {} - - virtual void OnNull(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnAlias(const YAML::Mark&, YAML::anchor_t) {} - virtual void OnScalar(const YAML::Mark&, const std::string&, YAML::anchor_t, - const std::string&) {} - - virtual void OnSequenceStart(const YAML::Mark&, const std::string&, - YAML::anchor_t) {} - virtual void OnSequenceEnd() {} - - virtual void OnMapStart(const YAML::Mark&, const std::string&, - YAML::anchor_t) {} - virtual void OnMapEnd() {} -}; - -void RunEmitterTest(void (*test)(YAML::Emitter&, std::string&), - const std::string& name, int& passed, int& total) { - YAML::Emitter out; - std::string desiredOutput; - test(out, desiredOutput); - std::string output = out.c_str(); - std::string lastError = out.GetLastError(); - - if (output == desiredOutput) { - try { - std::stringstream stream(output); - YAML::Parser parser; - NullEventHandler handler; - parser.HandleNextDocument(handler); - passed++; - } - catch (const YAML::Exception& e) { - std::cout << "Emitter test failed: " << name << "\n"; - std::cout << "Parsing output error: " << e.what() << "\n"; - } - } else { - std::cout << "Emitter test failed: " << name << "\n"; - std::cout << "Output:\n"; - std::cout << output << "<<<\n"; - std::cout << "Desired output:\n"; - std::cout << desiredOutput << "<<<\n"; - if (!out.good()) - std::cout << "Emitter error: " << lastError << "\n"; - } - total++; -} - -void RunEmitterErrorTest(void (*test)(YAML::Emitter&, std::string&), - const std::string& name, int& passed, int& total) { - YAML::Emitter out; - std::string desiredError; - test(out, desiredError); - std::string lastError = out.GetLastError(); - if (!out.good() && lastError == desiredError) { - passed++; - } else { - std::cout << "Emitter test failed: " << name << "\n"; - if (out.good()) - std::cout << "No error detected\n"; - else - std::cout << "Detected error: " << lastError << "\n"; - std::cout << "Expected error: " << desiredError << "\n"; - } - total++; -} - void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name, int& passed, int& total) { YAML::Emitter out; @@ -1091,133 +37,13 @@ void RunGenEmitterTest(TEST (*test)(YAML::Emitter&), const std::string& name, total++; } } +} #include "genemittertests.h" bool RunEmitterTests() { int passed = 0; int total = 0; - RunEmitterTest(&Emitter::SimpleScalar, "simple scalar", passed, total); - RunEmitterTest(&Emitter::SimpleSeq, "simple seq", passed, total); - RunEmitterTest(&Emitter::SimpleFlowSeq, "simple flow seq", passed, total); - RunEmitterTest(&Emitter::EmptyFlowSeq, "empty flow seq", passed, total); - RunEmitterTest(&Emitter::NestedBlockSeq, "nested block seq", passed, total); - RunEmitterTest(&Emitter::NestedFlowSeq, "nested flow seq", passed, total); - RunEmitterTest(&Emitter::SimpleMap, "simple map", passed, total); - RunEmitterTest(&Emitter::SimpleFlowMap, "simple flow map", passed, total); - RunEmitterTest(&Emitter::MapAndList, "map and list", passed, total); - RunEmitterTest(&Emitter::ListAndMap, "list and map", passed, total); - RunEmitterTest(&Emitter::NestedBlockMap, "nested block map", passed, total); - RunEmitterTest(&Emitter::NestedFlowMap, "nested flow map", passed, total); - RunEmitterTest(&Emitter::MapListMix, "map list mix", passed, total); - RunEmitterTest(&Emitter::SimpleLongKey, "simple long key", passed, total); - RunEmitterTest(&Emitter::SingleLongKey, "single long key", passed, total); - RunEmitterTest(&Emitter::ComplexLongKey, "complex long key", passed, total); - RunEmitterTest(&Emitter::AutoLongKey, "auto long key", passed, total); - RunEmitterTest(&Emitter::ScalarFormat, "scalar format", passed, total); - RunEmitterTest(&Emitter::AutoLongKeyScalar, "auto long key scalar", passed, - total); - RunEmitterTest(&Emitter::LongKeyFlowMap, "long key flow map", passed, total); - RunEmitterTest(&Emitter::BlockMapAsKey, "block map as key", passed, total); - RunEmitterTest(&Emitter::AliasAndAnchor, "alias and anchor", passed, total); - RunEmitterTest(&Emitter::AliasAndAnchorWithNull, "alias and anchor with null", - passed, total); - RunEmitterTest(&Emitter::AliasAndAnchorInFlow, "alias and anchor in flow", - passed, total); - RunEmitterTest(&Emitter::SimpleVerbatimTag, "simple verbatim tag", passed, - total); - RunEmitterTest(&Emitter::VerbatimTagInBlockSeq, "verbatim tag in block seq", - passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowSeq, "verbatim tag in flow seq", - passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowSeqWithNull, - "verbatim tag in flow seq with null", passed, total); - RunEmitterTest(&Emitter::VerbatimTagInBlockMap, "verbatim tag in block map", - passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowMap, "verbatim tag in flow map", - passed, total); - RunEmitterTest(&Emitter::VerbatimTagInFlowMapWithNull, - "verbatim tag in flow map with null", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptySeq, - "verbatim tag with empty seq", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptyMap, - "verbatim tag with empty map", passed, total); - RunEmitterTest(&Emitter::VerbatimTagWithEmptySeqAndMap, - "verbatim tag with empty seq and map", passed, total); - RunEmitterTest(&Emitter::ByKindTagWithScalar, "by-kind tag with scalar", - passed, total); - RunEmitterTest(&Emitter::LocalTagWithScalar, "local tag with scalar", passed, - total); - RunEmitterTest(&Emitter::ComplexDoc, "complex doc", passed, total); - RunEmitterTest(&Emitter::STLContainers, "STL containers", passed, total); - RunEmitterTest(&Emitter::SimpleComment, "simple comment", passed, total); - RunEmitterTest(&Emitter::MultiLineComment, "multi-line comment", passed, - total); - RunEmitterTest(&Emitter::ComplexComments, "complex comments", passed, total); - RunEmitterTest(&Emitter::InitialComment, "initial comment", passed, total); - RunEmitterTest(&Emitter::InitialCommentWithDocIndicator, - "initial comment with doc indicator", passed, total); - RunEmitterTest(&Emitter::CommentInFlowSeq, "comment in flow seq", passed, - total); - RunEmitterTest(&Emitter::CommentInFlowMap, "comment in flow map", passed, - total); - RunEmitterTest(&Emitter::Indentation, "indentation", passed, total); - RunEmitterTest(&Emitter::SimpleGlobalSettings, "simple global settings", - passed, total); - RunEmitterTest(&Emitter::ComplexGlobalSettings, "complex global settings", - passed, total); - RunEmitterTest(&Emitter::Null, "null", passed, total); - RunEmitterTest(&Emitter::EscapedUnicode, "escaped unicode", passed, total); - RunEmitterTest(&Emitter::Unicode, "unicode", passed, total); - RunEmitterTest(&Emitter::DoubleQuotedUnicode, "double quoted unicode", passed, - total); - RunEmitterTest(&Emitter::UserType, "user type", passed, total); - RunEmitterTest(&Emitter::UserTypeInContainer, "user type in container", - passed, total); - RunEmitterTest(&Emitter::PointerToInt, "pointer to int", passed, total); - RunEmitterTest(&Emitter::PointerToUserType, "pointer to user type", passed, - total); - RunEmitterTest(&Emitter::NewlineAtEnd, "newline at end", passed, total); - RunEmitterTest(&Emitter::NewlineInBlockSequence, "newline in block sequence", - passed, total); - RunEmitterTest(&Emitter::NewlineInFlowSequence, "newline in flow sequence", - passed, total); - RunEmitterTest(&Emitter::NewlineInBlockMap, "newline in block map", passed, - total); - RunEmitterTest(&Emitter::NewlineInFlowMap, "newline in flow map", passed, - total); - RunEmitterTest(&Emitter::LotsOfNewlines, "lots of newlines", passed, total); - RunEmitterTest(&Emitter::Binary, "binary", passed, total); - RunEmitterTest(&Emitter::LongBinary, "long binary", passed, total); - RunEmitterTest(&Emitter::EmptyBinary, "empty binary", passed, total); - RunEmitterTest(&Emitter::ColonAtEndOfScalar, "colon at end of scalar", passed, - total); - RunEmitterTest(&Emitter::ColonAsScalar, "colon as scalar", passed, total); - RunEmitterTest(&Emitter::ColonAtEndOfScalarInFlow, - "colon at end of scalar in flow", passed, total); - RunEmitterTest(&Emitter::BoolFormatting, "bool formatting", passed, total); - RunEmitterTest(&Emitter::DocStartAndEnd, "doc start and end", passed, total); - RunEmitterTest(&Emitter::ImplicitDocStart, "implicit doc start", passed, - total); - RunEmitterTest(&Emitter::EmptyString, "empty string", passed, total); - RunEmitterTest(&Emitter::SingleChar, "single char", passed, total); - RunEmitterTest(&Emitter::DefaultPrecision, "default precision", passed, - total); - RunEmitterTest(&Emitter::SetPrecision, "set precision", passed, total); - RunEmitterTest(&Emitter::DashInBlockContext, "dash in block context", passed, - total); - RunEmitterTest(&Emitter::HexAndOct, "hex and oct", passed, total); - RunEmitterTest(&Emitter::CompactMapWithNewline, "compact map with newline", - passed, total); - RunEmitterTest(&Emitter::ForceSingleQuotedToDouble, - "force single quoted to double", passed, total); - - RunEmitterErrorTest(&Emitter::ExtraEndSeq, "extra EndSeq", passed, total); - RunEmitterErrorTest(&Emitter::ExtraEndMap, "extra EndMap", passed, total); - RunEmitterErrorTest(&Emitter::InvalidAnchor, "invalid anchor", passed, total); - RunEmitterErrorTest(&Emitter::InvalidAlias, "invalid alias", passed, total); - RunEmitterErrorTest(&Emitter::BadLocalTag, "bad local tag", passed, total); - RunGenEmitterTests(passed, total); std::cout << "Emitter tests: " << passed << "/" << total << " passed\n"; diff --git a/test/integration/emitter_test.cpp b/test/integration/emitter_test.cpp new file mode 100644 index 0000000..6508d81 --- /dev/null +++ b/test/integration/emitter_test.cpp @@ -0,0 +1,1007 @@ +#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) {} + virtual void OnSequenceEnd() {} + + virtual void OnMapStart(const Mark&, const std::string&, anchor_t) {} + 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, 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, 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) { + out << BeginMap; + out << Key << "age"; + out << Value << "24"; + out << LongKey << Key << "height"; + out << Value << "5'9\""; + out << Key << "weight"; + out << Value << 145; + out << EndMap; + + ExpectEmit("age: 24\n? height\n: 5'9\"\nweight: 145"); +} + +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, 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, 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, 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("! bar"); +} + +TEST_F(EmitterTest, VerbatimTagInBlockSeq) { + out << BeginSeq; + out << VerbatimTag("!foo") << "bar"; + out << "baz"; + out << EndSeq; + + ExpectEmit("- ! bar\n- baz"); +} + +TEST_F(EmitterTest, VerbatimTagInFlowSeq) { + out << Flow << BeginSeq; + out << VerbatimTag("!foo") << "bar"; + out << "baz"; + out << EndSeq; + + ExpectEmit("[! bar, baz]"); +} + +TEST_F(EmitterTest, VerbatimTagInFlowSeqWithNull) { + out << Flow << BeginSeq; + out << VerbatimTag("!foo") << Null; + out << "baz"; + out << EndSeq; + + ExpectEmit("[! ~, baz]"); +} + +TEST_F(EmitterTest, VerbatimTagInBlockMap) { + out << BeginMap; + out << Key << VerbatimTag("!foo") << "bar"; + out << Value << VerbatimTag("!waz") << "baz"; + out << EndMap; + + ExpectEmit("! bar: ! baz"); +} + +TEST_F(EmitterTest, VerbatimTagInFlowMap) { + out << Flow << BeginMap; + out << Key << VerbatimTag("!foo") << "bar"; + out << Value << "baz"; + out << EndMap; + + ExpectEmit("{! bar: baz}"); +} + +TEST_F(EmitterTest, VerbatimTagInFlowMapWithNull) { + out << Flow << BeginMap; + out << Key << VerbatimTag("!foo") << Null; + out << Value << "baz"; + out << EndMap; + + ExpectEmit("{! ~: baz}"); +} + +TEST_F(EmitterTest, VerbatimTagWithEmptySeq) { + out << VerbatimTag("!foo") << BeginSeq << EndSeq; + + ExpectEmit("!\n[]"); +} + +TEST_F(EmitterTest, VerbatimTagWithEmptyMap) { + out << VerbatimTag("!bar") << BeginMap << EndMap; + + ExpectEmit("!\n{}"); +} + +TEST_F(EmitterTest, VerbatimTagWithEmptySeqAndMap) { + out << BeginSeq; + out << VerbatimTag("!foo") << BeginSeq << EndSeq; + out << VerbatimTag("!bar") << BeginMap << EndMap; + out << EndSeq; + + ExpectEmit("- !\n []\n- !\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, 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 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 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, 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, 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, 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\""); +} + +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, UserTypeInContainer) { + std::vector 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 +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("Hello, World!"), 13); + ExpectEmit("!!binary \"SGVsbG8sIFdvcmxkIQ==\""); +} + +TEST_F(EmitterTest, LongBinary) { + out << Binary( + reinterpret_cast( + "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(""), 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, 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"); +} + +// 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! 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.234f; + out << 3.14159265358979; + out << EndSeq; + ExpectEmit("- 1.234\n- 3.14159265358979"); +} + +TEST_F(EmitterTest, SetPrecision) { + out << BeginSeq; + out << FloatPrecision(3) << 1.234f; + out << DoublePrecision(6) << 3.14159265358979; + out << EndSeq; + ExpectEmit("- 1.23\n- 3.14159"); +} + +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\""); +} + +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, 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); +} +} +}