mirror of https://github.com/jbeder/yaml-cpp.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1754 lines
42 KiB
C++
1754 lines
42 KiB
C++
#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 << 1999926.4338;
|
|
out << 9999926.4338;
|
|
out << EndSeq;
|
|
|
|
ExpectEmit("- 3.14\n- 54\n- 2.4e+06\n- 2e+06\n- 1e+07");
|
|
}
|
|
|
|
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
|