You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1751 lines
42 KiB

#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, EmptyFlowSeqInMap) {
out << BeginMap;
out << Key << Flow << BeginSeq << EndSeq;
out << Value << 1;
out << Key << 2;
out << Value << Flow << BeginSeq << EndSeq;
out << EndMap;
ExpectEmit("[]: 1\n2: []");
}
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