mirror of
https://github.com/biojppm/rapidyaml.git
synced 2026-01-18 21:41:18 +01:00
1807 lines
50 KiB
C++
1807 lines
50 KiB
C++
#include "./test_lib/test_group.hpp"
|
|
#include "./test_lib/test_group.def.hpp"
|
|
|
|
namespace c4 {
|
|
namespace yml {
|
|
|
|
TEST(anchors, circular)
|
|
{
|
|
Tree t = parse_in_arena(R"(&x
|
|
- *x
|
|
)");
|
|
ASSERT_TRUE(t.rootref().has_val_anchor());
|
|
ASSERT_TRUE(t[0].is_val_ref());
|
|
EXPECT_EQ(t.rootref().val_anchor(), "x");
|
|
EXPECT_EQ(t[0].val_ref(), "x");
|
|
}
|
|
|
|
TEST(anchors, node_scalar_set_ref_when_empty)
|
|
{
|
|
{
|
|
NodeScalar ns;
|
|
ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/false);
|
|
EXPECT_EQ(ns.scalar, "foo");
|
|
EXPECT_EQ(ns.anchor, "foo");
|
|
}
|
|
{
|
|
NodeScalar ns;
|
|
ns.set_ref_maybe_replacing_scalar("*foo", /*has_scalar*/false);
|
|
EXPECT_EQ(ns.scalar, "*foo");
|
|
EXPECT_EQ(ns.anchor, "foo");
|
|
}
|
|
}
|
|
|
|
TEST(anchors, node_scalar_set_ref_when_non_empty)
|
|
{
|
|
{
|
|
NodeScalar ns;
|
|
ns.scalar = "whatever";
|
|
ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/true);
|
|
EXPECT_EQ(ns.scalar, "foo");
|
|
EXPECT_EQ(ns.anchor, "foo");
|
|
}
|
|
{
|
|
NodeScalar ns;
|
|
ns.scalar = "whatever";
|
|
ns.set_ref_maybe_replacing_scalar("*foo", /*has_scalar*/true);
|
|
EXPECT_EQ(ns.scalar, "*foo");
|
|
EXPECT_EQ(ns.anchor, "foo");
|
|
ns.set_ref_maybe_replacing_scalar("foo", /*has_scalar*/true);
|
|
EXPECT_EQ(ns.scalar, "*foo"); // keep the previous as it is well formed
|
|
EXPECT_EQ(ns.anchor, "foo");
|
|
ns.set_ref_maybe_replacing_scalar("bar", /*has_scalar*/true);
|
|
EXPECT_EQ(ns.scalar, "bar"); // replace previous as it is not well formed
|
|
EXPECT_EQ(ns.anchor, "bar");
|
|
}
|
|
}
|
|
|
|
TEST(anchors, no_ambiguity_when_key_scalars_begin_with_star)
|
|
{
|
|
Tree t = parse_in_arena("{foo: &foo: 1, *foo: : 2, '*foo:': 3}");
|
|
EXPECT_TRUE(t[1].is_key_ref());
|
|
EXPECT_FALSE(t[2].is_key_ref());
|
|
EXPECT_FALSE(t[1].is_key_quoted());
|
|
EXPECT_TRUE(t[2].is_key_quoted());
|
|
EXPECT_EQ(t[1].key(), "*foo:");
|
|
EXPECT_EQ(t[1].key_ref(), "foo:");
|
|
EXPECT_EQ(t[2].key(), "*foo:");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({foo: &foo: 1,*foo: : 2,'*foo:': 3})");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({foo: 1,1: 2,'*foo:': 3})");
|
|
}
|
|
|
|
TEST(anchors, no_ambiguity_when_val_scalars_begin_with_star)
|
|
{
|
|
Tree t = parse_in_arena("{foo: &foo: 1, ref: *foo:, quo: '*foo:'}");
|
|
EXPECT_TRUE(t["ref"].is_val_ref());
|
|
EXPECT_FALSE(t["quo"].is_val_ref());
|
|
EXPECT_FALSE(t["ref"].is_val_quoted());
|
|
EXPECT_TRUE(t["quo"].is_val_quoted());
|
|
EXPECT_EQ(t["ref"].val_ref(), "foo:");
|
|
EXPECT_EQ(t["ref"].val(), "*foo:");
|
|
EXPECT_EQ(t["quo"].val(), "*foo:");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({foo: &foo: 1,ref: *foo:,quo: '*foo:'})");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({foo: 1,ref: 1,quo: '*foo:'})");
|
|
}
|
|
|
|
TEST(anchors, no_ambiguity_with_inheritance)
|
|
{
|
|
Tree t = parse_in_arena(R"({
|
|
foo: &foo {a: 1, b: 2},
|
|
bar: {<<: *foo},
|
|
sq: {'<<': haha},
|
|
dq: {"<<": hehe}
|
|
})");
|
|
_c4dbg_tree("parsed tree", t);
|
|
EXPECT_TRUE(t["bar"].has_child("<<"));
|
|
EXPECT_FALSE(t["bar"]["<<"].is_key_ref());
|
|
EXPECT_TRUE(t["bar"]["<<"].is_val_ref());
|
|
EXPECT_TRUE(t["sq"]["<<"].is_key_quoted());
|
|
EXPECT_TRUE(t["dq"]["<<"].is_key_quoted());
|
|
EXPECT_FALSE(t["sq"]["<<"].is_key_ref());
|
|
EXPECT_FALSE(t["dq"]["<<"].is_key_ref());
|
|
EXPECT_EQ(t["sq"]["<<"].key(), "<<");
|
|
EXPECT_EQ(t["dq"]["<<"].key(), "<<");
|
|
EXPECT_EQ(t["bar"]["<<"].key(), "<<");
|
|
EXPECT_EQ(t["bar"]["<<"].val(), "*foo");
|
|
//EXPECT_EQ(t["bar"]["<<"].key_ref(), "<<"); // not a ref!
|
|
EXPECT_EQ(t["bar"]["<<"].val_ref(), "foo");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({
|
|
foo: &foo {a: 1,b: 2},
|
|
bar: {<<: *foo},
|
|
sq: {'<<': haha},
|
|
dq: {"<<": hehe}
|
|
}
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({
|
|
foo: {a: 1,b: 2},
|
|
bar: {a: 1,b: 2},
|
|
sq: {'<<': haha},
|
|
dq: {"<<": hehe}
|
|
}
|
|
)");
|
|
}
|
|
|
|
TEST(anchors, programatic_key_ref)
|
|
{
|
|
Tree t = parse_in_arena("{}");
|
|
t._rem_flags(t.root_id(), CONTAINER_STYLE);
|
|
t._add_flags(t.root_id(), BLOCK);
|
|
NodeRef r = t.rootref();
|
|
r["kanchor"] = "2";
|
|
r["kanchor"].set_key_anchor("kanchor");
|
|
r["vanchor"] = "3";
|
|
r["vanchor"].set_val_anchor("vanchor");
|
|
r["*kanchor"] = "4";
|
|
r["*vanchor"] = "5";
|
|
NodeRef ch = r.append_child();
|
|
ch.set_key_ref("kanchor");
|
|
ch.set_val("6");
|
|
ch = r.append_child();
|
|
ch.set_key_ref("vanchor");
|
|
ch.set_val("7");
|
|
_c4dbg_tree(t);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(&kanchor kanchor: 2
|
|
vanchor: &vanchor 3
|
|
'*kanchor': 4
|
|
'*vanchor': 5
|
|
*kanchor : 6
|
|
*vanchor : 7
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(kanchor: 2
|
|
vanchor: 3
|
|
'*kanchor': 4
|
|
'*vanchor': 5
|
|
kanchor: 6
|
|
3: 7
|
|
)");
|
|
}
|
|
|
|
TEST(anchors, programatic_val_ref)
|
|
{
|
|
Tree t = parse_in_arena("{}");
|
|
t._rem_flags(t.root_id(), CONTAINER_STYLE);
|
|
t._add_flags(t.root_id(), BLOCK);
|
|
t["kanchor"] = "2";
|
|
t["kanchor"].set_key_anchor("kanchor");
|
|
t["vanchor"] = "3";
|
|
t["vanchor"].set_val_anchor("vanchor");
|
|
t["kref"].set_val_ref("kanchor");
|
|
t["vref"].set_val_ref("vanchor");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(&kanchor kanchor: 2
|
|
vanchor: &vanchor 3
|
|
kref: *kanchor
|
|
vref: *vanchor
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(kanchor: 2
|
|
vanchor: 3
|
|
kref: kanchor
|
|
vref: 3
|
|
)");
|
|
}
|
|
|
|
TEST(anchors, programatic_inheritance)
|
|
{
|
|
Tree t = parse_in_arena(R"(orig: &orig {foo: bar, baz: bat}
|
|
copy: {}
|
|
notcopy: {}
|
|
notref: {}
|
|
)");
|
|
_c4dbg_tree(t);
|
|
t["copy"]["<<"].set_val_ref("orig");
|
|
t["notcopy"]["test"].set_val_ref("orig");
|
|
t["notcopy"]["<<"].set_val_ref("orig");
|
|
t["notref"]["<<"] = "*orig";
|
|
_c4dbg_tree(t);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(orig: &orig {foo: bar,baz: bat}
|
|
copy: {<<: *orig}
|
|
notcopy: {test: *orig,<<: *orig}
|
|
notref: {<<: '*orig'}
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(orig: {foo: bar,baz: bat}
|
|
copy: {foo: bar,baz: bat}
|
|
notcopy: {test: {foo: bar,baz: bat},foo: bar,baz: bat}
|
|
notref: {<<: '*orig'}
|
|
)");
|
|
}
|
|
|
|
TEST(anchors, programatic_multiple_inheritance)
|
|
{
|
|
Tree t = parse_in_arena(R"(orig1: &orig1 {foo: bar}
|
|
orig2: &orig2 {baz: bat}
|
|
orig3: &orig3 {and: more}
|
|
copy: {}
|
|
)");
|
|
NodeRef seq = t["copy"]["<<"];
|
|
seq |= SEQ;
|
|
seq.append_child().set_val_ref("orig1");
|
|
seq.append_child().set_val_ref("orig2");
|
|
seq.append_child().set_val_ref("orig3");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(orig1: &orig1 {foo: bar}
|
|
orig2: &orig2 {baz: bat}
|
|
orig3: &orig3 {and: more}
|
|
copy: {<<: [*orig1,*orig2,*orig3]}
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(orig1: {foo: bar}
|
|
orig2: {baz: bat}
|
|
orig3: {and: more}
|
|
copy: {foo: bar,baz: bat,and: more}
|
|
)");
|
|
}
|
|
|
|
TEST(anchors, set_anchor_leading_ampersand_is_optional)
|
|
{
|
|
Tree t = parse_in_arena("{without: 0, with: 1}");
|
|
|
|
t["without"].set_key_anchor("without");
|
|
t["with"].set_key_anchor("&with");
|
|
EXPECT_EQ(t["without"].key_anchor(), "without");
|
|
EXPECT_EQ(t["with"].key_anchor(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({&without without: 0,&with with: 1})");
|
|
|
|
t["without"].set_val_anchor("without");
|
|
t["with"].set_val_anchor("&with");
|
|
EXPECT_EQ(t["without"].val_anchor(), "without");
|
|
EXPECT_EQ(t["with"].val_anchor(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({&without without: &without 0,&with with: &with 1})");
|
|
}
|
|
|
|
TEST(anchors, set_ref_leading_star_is_optional)
|
|
{
|
|
Tree t = parse_in_arena("{}");
|
|
|
|
t["*without"] = "0";
|
|
t["*with"] = "1";
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({'*without': 0,'*with': 1})");
|
|
|
|
t["*without"].set_key_ref("without");
|
|
t["*with"].set_key_ref("*with");
|
|
EXPECT_EQ(t["*without"].key_ref(), "without");
|
|
EXPECT_EQ(t["*with"].key_ref(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({*without : 0,*with : 1})");
|
|
|
|
t["*without"].set_val_ref("without");
|
|
t["*with"].set_val_ref("*with");
|
|
EXPECT_EQ(t["*without"].val_ref(), "without");
|
|
EXPECT_EQ(t["*with"].val_ref(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({*without : *without,*with : *with})");
|
|
}
|
|
|
|
TEST(anchors, set_key_ref_also_sets_the_key_when_none_exists)
|
|
{
|
|
Tree t = parse_in_arena("{}");
|
|
NodeRef root = t.rootref();
|
|
NodeRef without = root.append_child();
|
|
NodeRef with = root.append_child();
|
|
ASSERT_FALSE(without.has_key());
|
|
ASSERT_FALSE(with.has_key());
|
|
without.set_key_ref("without");
|
|
with.set_key_ref("*with");
|
|
without.set_val("0");
|
|
with.set_val("1");
|
|
ASSERT_TRUE(without.has_key());
|
|
ASSERT_TRUE(with.has_key());
|
|
EXPECT_EQ(without.key(), "without");
|
|
EXPECT_EQ(with.key(), "*with");
|
|
EXPECT_EQ(without.key_ref(), "without");
|
|
EXPECT_EQ(with.key_ref(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({*without : 0,*with : 1})");
|
|
}
|
|
|
|
TEST(anchors, set_val_ref_also_sets_the_val_when_none_exists)
|
|
{
|
|
Tree t = parse_in_arena("{}");
|
|
NodeRef root = t.rootref();
|
|
NodeRef without = root.append_child();
|
|
NodeRef with = root.append_child();
|
|
without.set_key("without");
|
|
with.set_key("with");
|
|
ASSERT_FALSE(without.has_val());
|
|
ASSERT_FALSE(with.has_val());
|
|
without.set_val_ref("without");
|
|
with.set_val_ref("*with");
|
|
ASSERT_TRUE(without.has_val());
|
|
ASSERT_TRUE(with.has_val());
|
|
EXPECT_EQ(without.val(), "without");
|
|
EXPECT_EQ(with.val(), "*with");
|
|
EXPECT_EQ(without.val_ref(), "without");
|
|
EXPECT_EQ(with.val_ref(), "with");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({without: *without,with: *with})");
|
|
}
|
|
|
|
TEST(anchors, set_key_ref_replaces_existing_key)
|
|
{
|
|
Tree t = parse_in_arena("{*foo : bar}");
|
|
NodeRef root = t.rootref();
|
|
EXPECT_TRUE(root.has_child("*foo"));
|
|
root["*foo"].set_key_ref("notfoo");
|
|
EXPECT_FALSE(root.has_child("*foo"));
|
|
EXPECT_FALSE(root.has_child("*notfoo"));
|
|
EXPECT_TRUE(root.has_child("notfoo"));
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), "{*notfoo : bar}");
|
|
}
|
|
|
|
TEST(anchors, set_val_ref_replaces_existing_key)
|
|
{
|
|
Tree t = parse_in_arena("{foo : *bar}");
|
|
NodeRef root = t.rootref();
|
|
root["foo"].set_val_ref("notbar");
|
|
EXPECT_EQ(root["foo"].val(), "notbar");
|
|
root["foo"].set_val_ref("*notfoo");
|
|
EXPECT_EQ(root["foo"].val(), "*notfoo");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), "{foo: *notfoo}");
|
|
}
|
|
|
|
|
|
TEST(anchors, github529)
|
|
{
|
|
csubstr unresolved = R"(
|
|
dimensions: 3
|
|
type: EXPRESSION
|
|
variables:
|
|
"<<":
|
|
- biomes/abstract/carving/carving_land.yml:carving.sampler.variables
|
|
carvingMaxHeight: 40
|
|
expression: $biomes/abstract/carving/carving_land.yml:carving.sampler.expression
|
|
samplers: $biomes/abstract/carving/carving_land.yml:carving.sampler.samplers
|
|
<<: not a reference
|
|
tpl: &anchor
|
|
it: works
|
|
<<: *anchor
|
|
)";
|
|
Tree tree = parse_in_arena(unresolved);
|
|
//print_tree(tree);
|
|
EXPECT_FALSE(tree["variables"]["<<"].is_val_ref());
|
|
EXPECT_TRUE(tree["variables"]["<<"].is_key_quoted());
|
|
EXPECT_EQ(tree[5].key(), "<<");
|
|
EXPECT_FALSE(tree[5].is_val_ref());
|
|
EXPECT_FALSE(tree[5].is_key_quoted());
|
|
EXPECT_EQ(tree[7].key(), "<<");
|
|
EXPECT_TRUE(tree[7].is_val_ref());
|
|
EXPECT_FALSE(tree[7].is_key_quoted());
|
|
tree.resolve();
|
|
EXPECT_EQ(tree["variables"]["<<"][0].val(), "biomes/abstract/carving/carving_land.yml:carving.sampler.variables");
|
|
EXPECT_EQ(tree["<<"].val(), "not a reference");
|
|
EXPECT_EQ(tree["it"].val(), "works");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
Tree github566_make_map(NodeType_e root_style)
|
|
{
|
|
Tree tree;
|
|
NodeRef root = tree.rootref();
|
|
root |= MAP|root_style;
|
|
root.set_val_anchor("ref0");
|
|
root["a"] = "1";
|
|
NodeRef self = root["self"];
|
|
self.set_val("*ref0");
|
|
self.set_val_ref("ref0");
|
|
return tree;
|
|
}
|
|
|
|
Tree github566_make_seq(NodeType_e root_style)
|
|
{
|
|
Tree tree;
|
|
NodeRef root = tree.rootref();
|
|
root |= SEQ|root_style;
|
|
root.set_val_anchor("ref0");
|
|
root[0] = "1";
|
|
root[1].set_val("*ref0");
|
|
root[1].set_val_ref("ref0");
|
|
return tree;
|
|
}
|
|
|
|
void github566_cmp(type_bits mask, Tree const& orig, std::string const& expected)
|
|
{
|
|
const Tree parsed = parse_in_arena(to_csubstr(expected));
|
|
test_compare(orig, parsed, "orig", "parsed", mask);
|
|
EXPECT_EQ(expected, emitrs_yaml<std::string>(parsed));
|
|
EXPECT_EQ(expected, emitrs_yaml<std::string>(orig));
|
|
}
|
|
|
|
TEST(anchors, github566_map_NOSTYLE)
|
|
{
|
|
const Tree orig = github566_make_map(NOTYPE);
|
|
github566_cmp(_TYMASK, orig, R"(&ref0
|
|
a: 1
|
|
self: *ref0
|
|
)");
|
|
}
|
|
TEST(anchors, github566_map_BLOCK)
|
|
{
|
|
const Tree orig = github566_make_map(BLOCK);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0
|
|
a: 1
|
|
self: *ref0
|
|
)");
|
|
}
|
|
TEST(anchors, github566_map_FLOW_ML)
|
|
{
|
|
const Tree orig = github566_make_map(FLOW_ML);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0 {
|
|
a: 1,
|
|
self: *ref0
|
|
}
|
|
)");
|
|
}
|
|
TEST(anchors, github566_map_FLOW_SL)
|
|
{
|
|
const Tree orig = github566_make_map(FLOW_SL);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0 {a: 1,self: *ref0})");
|
|
}
|
|
|
|
|
|
TEST(anchors, github566_seq_NOSTYLE)
|
|
{
|
|
const Tree orig = github566_make_seq(NOTYPE);
|
|
github566_cmp(_TYMASK, orig, R"(&ref0
|
|
- 1
|
|
- *ref0
|
|
)");
|
|
}
|
|
TEST(anchors, github566_seq_BLOCK)
|
|
{
|
|
const Tree orig = github566_make_seq(BLOCK);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0
|
|
- 1
|
|
- *ref0
|
|
)");
|
|
}
|
|
TEST(anchors, github566_seq_FLOW_ML)
|
|
{
|
|
const Tree orig = github566_make_seq(FLOW_ML);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0 [
|
|
1,
|
|
*ref0
|
|
]
|
|
)");
|
|
}
|
|
TEST(anchors, github566_seq_FLOW_SL)
|
|
{
|
|
const Tree orig = github566_make_seq(FLOW_SL);
|
|
github566_cmp(0xffffffff, orig, R"(&ref0 [1,*ref0])");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TEST(weird_anchor_cases_from_suite, 2SXE)
|
|
{
|
|
Tree t = parse_in_arena(R"(&a: key: &a value
|
|
foo:
|
|
*a:
|
|
)");
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(key: value
|
|
foo: key
|
|
)");
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// SIMPLE_ANCHOR/YmlTestCase.parse_using_ryml/0
|
|
|
|
C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast")
|
|
|
|
/** verify that the reference class is working correctly (yay, testing the tests) */
|
|
TEST(CaseNode, anchors)
|
|
{
|
|
const NodeType mask = KEYREF|KEYANCH|VALREF|VALANCH;
|
|
|
|
{
|
|
auto n = N("*vref", AR(KEYREF, "vref"), "c");
|
|
EXPECT_EQ(n.key, "*vref");
|
|
EXPECT_EQ(n.val, "c");
|
|
EXPECT_EQ((type_bits)(n.type & mask), (type_bits)KEYREF);
|
|
EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)KEYREF);
|
|
EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ(n.key_anchor.str, "vref");
|
|
EXPECT_EQ(n.val_anchor.str, "");
|
|
}
|
|
|
|
{
|
|
TestCaseNode n("<<", "*base", AR(VALANCH, "base"));
|
|
EXPECT_EQ(n.key, "<<");
|
|
EXPECT_EQ(n.val, "*base");
|
|
EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH);
|
|
EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH);
|
|
EXPECT_EQ(n.key_anchor.str, "");
|
|
EXPECT_EQ(n.val_anchor.str, "base");
|
|
}
|
|
|
|
{
|
|
TestCaseNode n("base", L{N("name", "Everyone has same name")}, AR(VALANCH, "base"));
|
|
EXPECT_EQ(n.key, "base");
|
|
EXPECT_EQ(n.val, "");
|
|
EXPECT_NE(n.type.is_seq(), true);
|
|
EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH);
|
|
EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH);
|
|
EXPECT_EQ(n.key_anchor.str, "");
|
|
EXPECT_EQ(n.val_anchor.str, "base");
|
|
}
|
|
|
|
{
|
|
L l{N("<<", "*base", AR(VALREF, "base"))};
|
|
TestCaseNode const& base = *l.begin();
|
|
EXPECT_EQ(base.key, "<<");
|
|
EXPECT_EQ(base.val, "*base");
|
|
EXPECT_EQ(base.type.is_keyval(), true);
|
|
EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF);
|
|
EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF);
|
|
EXPECT_EQ(base.key_anchor.str, "");
|
|
EXPECT_EQ(base.val_anchor.str, "base");
|
|
}
|
|
|
|
{
|
|
L l{N("<<", "*base", AR(VALREF, "base")), N("age", "10")};
|
|
TestCaseNode const& base = *l.begin();
|
|
TestCaseNode const& age = *(&base + 1);
|
|
EXPECT_EQ(base.key, "<<");
|
|
EXPECT_EQ(base.val, "*base");
|
|
EXPECT_EQ(base.type.is_keyval(), true);
|
|
EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF);
|
|
EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF);
|
|
EXPECT_EQ(base.key_anchor.str, "");
|
|
EXPECT_EQ(base.val_anchor.str, "base");
|
|
|
|
EXPECT_EQ(age.key, "age");
|
|
EXPECT_EQ(age.val, "10");
|
|
EXPECT_EQ(age.type.is_keyval(), true);
|
|
EXPECT_EQ((type_bits)(age.type & mask), (type_bits)0);
|
|
EXPECT_EQ((type_bits)age.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)age.val_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ(age.key_anchor.str, "");
|
|
EXPECT_EQ(age.val_anchor.str, "");
|
|
}
|
|
|
|
{
|
|
TestCaseNode n("foo", L{N("<<", "*base", AR(VALREF, "base")), N("age", "10")}, AR(VALANCH, "foo"));
|
|
EXPECT_EQ(n.key, "foo");
|
|
EXPECT_EQ(n.val, "");
|
|
EXPECT_EQ(n.type.has_key(), true);
|
|
EXPECT_EQ(n.type.is_map(), true);
|
|
EXPECT_EQ((type_bits)(n.type & mask), (type_bits)VALANCH);
|
|
EXPECT_EQ((type_bits)n.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)n.val_anchor.type, (type_bits)VALANCH);
|
|
EXPECT_EQ(n.key_anchor.str, "");
|
|
EXPECT_EQ(n.val_anchor.str, "foo");
|
|
|
|
TestCaseNode const& base = n.children[0];
|
|
EXPECT_EQ(base.key, "<<");
|
|
EXPECT_EQ(base.val, "*base");
|
|
EXPECT_EQ(base.type.has_key() && base.type.has_val(), true);
|
|
EXPECT_EQ((type_bits)(base.type & mask), (type_bits)VALREF);
|
|
EXPECT_EQ((type_bits)base.key_anchor.type, (type_bits)NOTYPE);
|
|
EXPECT_EQ((type_bits)base.val_anchor.type, (type_bits)VALREF);
|
|
EXPECT_EQ(base.key_anchor.str, "");
|
|
EXPECT_EQ(base.val_anchor.str, "base");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
TEST(simple_anchor, resolve_works_on_an_empty_tree)
|
|
{
|
|
Tree t(0);
|
|
t.resolve();
|
|
EXPECT_TRUE(t.empty());
|
|
}
|
|
|
|
TEST(simple_anchor, resolve_works_on_a_tree_without_refs)
|
|
{
|
|
Tree t = parse_in_arena("[a, b, c, d, e, f]");
|
|
size_t size_before = t.size();
|
|
t.resolve();
|
|
EXPECT_EQ(t.size(), size_before);
|
|
}
|
|
|
|
TEST(simple_anchor, resolve_works_on_keyrefvalref)
|
|
{
|
|
Tree t = parse_in_arena("{&a a: &b b, *b : *a}");
|
|
EXPECT_EQ(t["a"].has_key_anchor(), true);
|
|
EXPECT_EQ(t["a"].has_val_anchor(), true);
|
|
EXPECT_EQ(t["a"].key_anchor(), "a");
|
|
EXPECT_EQ(t["a"].val_anchor(), "b");
|
|
EXPECT_EQ(t["*b"].is_key_ref(), true);
|
|
EXPECT_EQ(t["*b"].is_val_ref(), true);
|
|
EXPECT_EQ(t["*b"].key_ref(), "b");
|
|
EXPECT_EQ(t["*b"].val_ref(), "a");
|
|
_c4dbg_tree(t);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({&a a: &b b,*b : *a})");
|
|
t.resolve();
|
|
EXPECT_EQ(t["a"].val(), "b");
|
|
EXPECT_EQ(t["b"].val(), "a");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"({a: b,b: a})");
|
|
}
|
|
|
|
TEST(simple_anchor, anchors_of_first_child_key_implicit)
|
|
{
|
|
csubstr yaml = R"(&anchor0
|
|
&anchor4 top4:
|
|
key4: scalar4
|
|
top5: &anchor5
|
|
key5: scalar5
|
|
top6:
|
|
&anchor6 key6: scalar6
|
|
top61:
|
|
&anchor61 key61:
|
|
scalar61
|
|
top62:
|
|
&anchor62
|
|
key62:
|
|
scalar62
|
|
)";
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(t.rootref().has_val_anchor(), true);
|
|
EXPECT_EQ(t.rootref().val_anchor(), "anchor0");
|
|
EXPECT_EQ(t["top4"].has_key_anchor(), true);
|
|
EXPECT_EQ(t["top4"].has_val_anchor(), false);
|
|
EXPECT_EQ(t["top4"].key_anchor(), "anchor4");
|
|
EXPECT_EQ(t["top4"]["key4"].val(), "scalar4");
|
|
EXPECT_EQ(t["top4"]["key4"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top5"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top5"].has_val_anchor(), true);
|
|
EXPECT_EQ(t["top5"].val_anchor(), "anchor5");
|
|
EXPECT_EQ(t["top5"]["key5"].val(), "scalar5");
|
|
EXPECT_EQ(t["top5"]["key5"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top6"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top6"].has_val_anchor(), false);
|
|
EXPECT_EQ(t["top6"]["key6"].val(), "scalar6");
|
|
ASSERT_EQ(t["top6"]["key6"].has_key_anchor(), true);
|
|
EXPECT_EQ(t["top6"]["key6"].key_anchor(), "anchor6");
|
|
EXPECT_EQ(t["top61"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top61"].has_val_anchor(), false);
|
|
EXPECT_EQ(t["top61"]["key61"].val(), "scalar61");
|
|
ASSERT_EQ(t["top61"]["key61"].has_key_anchor(), true);
|
|
EXPECT_EQ(t["top61"]["key61"].key_anchor(), "anchor61");
|
|
EXPECT_EQ(t["top62"].has_key_anchor(), false);
|
|
EXPECT_EQ(t["top62"].has_val_anchor(), true);
|
|
EXPECT_EQ(t["top62"].val_anchor(), "anchor62");
|
|
EXPECT_EQ(t["top62"]["key62"].val(), "scalar62");
|
|
ASSERT_EQ(t["top62"]["key62"].has_key_anchor(), false);
|
|
}
|
|
|
|
TEST(simple_anchor, merge_seqs)
|
|
{
|
|
const Tree src = parse_in_arena(R"([0, 1])");
|
|
{
|
|
Tree dst = parse_in_arena(R"([2, 3])");
|
|
dst.duplicate_children_no_rep(&src, 0, 0, NONE);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[0,1,2,3]");
|
|
}
|
|
{
|
|
Tree dst = parse_in_arena(R"([2, 3])");
|
|
dst.duplicate_children_no_rep(&src, 0, 0, 1);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[2,0,1,3]");
|
|
}
|
|
{
|
|
Tree dst = parse_in_arena(R"([2, 3])");
|
|
dst.duplicate_children_no_rep(&src, 0, 0, 2);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(dst), "[2,3,0,1]");
|
|
}
|
|
}
|
|
|
|
TEST(simple_anchor, issue_400)
|
|
{
|
|
csubstr yaml = R"(
|
|
a: &a
|
|
x: 1
|
|
b: &b
|
|
ref: *a
|
|
c:
|
|
ref: *b
|
|
)";
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
t.resolve();
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(a:
|
|
x: 1
|
|
b:
|
|
ref:
|
|
x: 1
|
|
c:
|
|
ref:
|
|
ref:
|
|
x: 1
|
|
)");
|
|
}
|
|
}
|
|
|
|
TEST(simple_anchor, billion_laughs)
|
|
{
|
|
// https://en.wikipedia.org/wiki/Billion_laughs_attack
|
|
csubstr yaml = R"(a: &a ["lol","lol"]
|
|
b: &b [*a,*a]
|
|
c: &c [*b,*b]
|
|
)";
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), yaml);
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
t.resolve(true);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(a: ["lol","lol"]
|
|
b: [["lol","lol"],["lol","lol"]]
|
|
c: [[["lol","lol"],["lol","lol"]],[["lol","lol"],["lol","lol"]]]
|
|
)");
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
t.resolve(false);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(a: &a ["lol","lol"]
|
|
b: &b [&a ["lol","lol"],&a ["lol","lol"]]
|
|
c: &c [&b [&a ["lol","lol"],&a ["lol","lol"]],&b [&a ["lol","lol"],&a ["lol","lol"]]]
|
|
)");
|
|
}
|
|
}
|
|
|
|
TEST(simple_anchor, resolve_nested)
|
|
{
|
|
csubstr yaml = R"(a: &a
|
|
b:
|
|
<<: *a
|
|
)";
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), yaml);
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
ExpectError::check_error_basic(&t, [&]{
|
|
t.resolve(true);
|
|
});
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
ExpectError::check_error_basic(&t, [&]{
|
|
t.resolve(false);
|
|
});
|
|
}
|
|
}
|
|
|
|
TEST(simple_anchor, resolve_nested_2)
|
|
{
|
|
csubstr yaml = R"(a0: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a1: &a1
|
|
ref: *a0
|
|
a2: &a2
|
|
ref: *a1
|
|
a3: &a3
|
|
ref: *a2
|
|
a4: &a4
|
|
ref: *a3
|
|
a5: &a5
|
|
ref: *a4
|
|
)";
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), yaml);
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
t.resolve(true);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(a0:
|
|
b0:
|
|
c0: v0
|
|
a1:
|
|
ref:
|
|
b0:
|
|
c0: v0
|
|
a2:
|
|
ref:
|
|
ref:
|
|
b0:
|
|
c0: v0
|
|
a3:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
b0:
|
|
c0: v0
|
|
a4:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
b0:
|
|
c0: v0
|
|
a5:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
ref:
|
|
b0:
|
|
c0: v0
|
|
)");
|
|
}
|
|
{
|
|
Tree t = parse_in_arena(yaml);
|
|
t.resolve(false);
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(a0: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a1: &a1
|
|
ref: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a2: &a2
|
|
ref: &a1
|
|
ref: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a3: &a3
|
|
ref: &a2
|
|
ref: &a1
|
|
ref: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a4: &a4
|
|
ref: &a3
|
|
ref: &a2
|
|
ref: &a1
|
|
ref: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
a5: &a5
|
|
ref: &a4
|
|
ref: &a3
|
|
ref: &a2
|
|
ref: &a1
|
|
ref: &a0
|
|
b0: &b0
|
|
c0: &c0 v0
|
|
)");
|
|
}
|
|
}
|
|
|
|
TEST(simple_anchor, issue_484_0)
|
|
{
|
|
csubstr yaml = R"(
|
|
base_1: &base_1
|
|
a: 10
|
|
b: 10
|
|
base_2: &base_2
|
|
b: 20
|
|
k1:
|
|
!!merge <<: *base_1
|
|
!!merge <<: *base_2
|
|
k2:
|
|
!!merge <<: *base_2
|
|
!!merge <<: *base_1
|
|
)";
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(t["k1"][0].val(), "*base_1");
|
|
EXPECT_EQ(t["k1"][1].val(), "*base_2");
|
|
EXPECT_EQ(t["k2"][0].val(), "*base_2");
|
|
EXPECT_EQ(t["k2"][1].val(), "*base_1");
|
|
t.resolve();
|
|
EXPECT_EQ(t["k1"]["a"].val(), "10");
|
|
EXPECT_EQ(t["k1"]["b"].val(), "20");
|
|
EXPECT_EQ(t["k2"]["a"].val(), "10");
|
|
EXPECT_EQ(t["k2"]["b"].val(), "10");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(base_1:
|
|
a: 10
|
|
b: 10
|
|
base_2:
|
|
b: 20
|
|
k1:
|
|
a: 10
|
|
b: 20
|
|
k2:
|
|
a: 10
|
|
b: 10
|
|
)");
|
|
}
|
|
|
|
TEST(simple_anchor, issue_484_1)
|
|
{
|
|
csubstr yaml = R"(
|
|
base_1: &base_1
|
|
a: 10
|
|
b: 10
|
|
base_2: &base_2
|
|
a: 30
|
|
k1:
|
|
<<: *base_1
|
|
<<: *base_2
|
|
k2:
|
|
<<: *base_2
|
|
<<: *base_1
|
|
)";
|
|
Tree t = parse_in_arena(yaml);
|
|
EXPECT_EQ(t["k1"][0].val(), "*base_1");
|
|
EXPECT_EQ(t["k1"][1].val(), "*base_2");
|
|
EXPECT_EQ(t["k2"][0].val(), "*base_2");
|
|
EXPECT_EQ(t["k2"][1].val(), "*base_1");
|
|
t.resolve();
|
|
EXPECT_EQ(t["k1"]["a"].val(), "30");
|
|
EXPECT_EQ(t["k1"]["b"].val(), "10");
|
|
EXPECT_EQ(t["k2"]["a"].val(), "10");
|
|
EXPECT_EQ(t["k2"]["b"].val(), "10");
|
|
EXPECT_EQ(emitrs_yaml<std::string>(t), R"(base_1:
|
|
a: 10
|
|
b: 10
|
|
base_2:
|
|
a: 30
|
|
k1:
|
|
b: 10
|
|
a: 30
|
|
k2:
|
|
a: 10
|
|
b: 10
|
|
)");
|
|
}
|
|
|
|
|
|
TEST(simple_anchor, key_anchor_error_json)
|
|
{
|
|
Tree tree = parse_in_arena("{&k key: val}");
|
|
EXPECT_EQ(emitrs_json<std::string>(tree), "{\"key\": \"val\"}");
|
|
ExpectError::check_error_visit(&tree, [&]{
|
|
emitrs_json<std::string>(tree, EmitOptions{}.json_error_flags(EmitOptions::JSON_ERR_ON_ANCHOR));
|
|
});
|
|
}
|
|
|
|
TEST(simple_anchor, val_anchor_error_json)
|
|
{
|
|
Tree tree = parse_in_arena("{key: &v val}");
|
|
EXPECT_EQ(emitrs_json<std::string>(tree), "{\"key\": \"val\"}");
|
|
ExpectError::check_error_visit(&tree, [&]{
|
|
emitrs_json<std::string>(tree, EmitOptions{}.json_error_flags(EmitOptions::JSON_ERR_ON_ANCHOR));
|
|
});
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
CASE_GROUP(SIMPLE_ANCHOR)
|
|
{
|
|
|
|
ADD_CASE_TO_GROUP("anchor colon ambiguity 1",
|
|
R"({*foo : bar})",
|
|
N(MFS, L{N(KEY|VP, "*foo", AR(KEYREF, "foo"), "bar")})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor colon ambiguity 2", EXPECT_PARSE_ERROR,
|
|
R"({*foo: bar})",
|
|
Location(1, 8)
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("merge example, unresolved",
|
|
R"(# https://yaml.org/type/merge.html
|
|
- &CENTER { x: 1, y: 2 }
|
|
- &LEFT { x: 0, y: 2 }
|
|
- &BIG { r: 10 }
|
|
- &SMALL { r: 1 }
|
|
|
|
# All the following maps are equal:
|
|
|
|
- # Explicit keys
|
|
x: 1
|
|
y: 2
|
|
r: 10
|
|
label: center/big
|
|
|
|
- # Merge one map
|
|
<< : *CENTER
|
|
r: 10
|
|
label: center/big
|
|
|
|
- # Merge multiple maps
|
|
<< : [ *CENTER, *BIG ]
|
|
label: center/big
|
|
|
|
- # Override
|
|
<< : [ *BIG, *LEFT, *SMALL ]
|
|
x: 1
|
|
label: center/big
|
|
)",
|
|
N(SB, L{
|
|
N(MFS, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2")}, AR(VALANCH, "CENTER")),
|
|
N(MFS, L{N(KP|VP, "x", "0" ), N(KP|VP, "y", "2")}, AR(VALANCH, "LEFT" )),
|
|
N(MFS, L{N(KP|VP, "r", "10")}, AR(VALANCH, "BIG" )),
|
|
N(MFS, L{N(KP|VP, "r", "1" )}, AR(VALANCH, "SMALL" )),
|
|
N(MB, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2"), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|VAL, "<<", "*CENTER", AR(VALREF, "*CENTER")), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|SFS, "<<", L{N(VAL, "*CENTER", AR(VALREF, "*CENTER")), N(VAL, "*BIG", AR(VALREF, "*BIG"))}), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|SFS, "<<", L{N(VAL, "*BIG", AR(VALREF, "*BIG")), N(VAL, "*LEFT", AR(VALREF, "*LEFT")), N(VAL, "*SMALL", AR(VALREF, "*SMALL"))}), N(KP|VP, "x", "1"), N(KP|VP, "label", "center/big")}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("merge example, resolved", RESOLVE_REFS,
|
|
R"(# https://yaml.org/type/merge.html
|
|
- &CENTER { x: 1, y: 2 }
|
|
- &LEFT { x: 0, y: 2 }
|
|
- &BIG { r: 10 }
|
|
- &SMALL { r: 1 }
|
|
|
|
# All the following maps are equal:
|
|
|
|
- # Explicit keys
|
|
x: 1
|
|
y: 2
|
|
r: 10
|
|
label: center/big
|
|
|
|
- # Merge one map
|
|
<< : *CENTER
|
|
r: 10
|
|
label: center/big
|
|
|
|
- # Merge multiple maps
|
|
<< : [ *CENTER, *BIG ]
|
|
label: center/big
|
|
|
|
- # Override
|
|
<< : [ *SMALL, *LEFT, *BIG ]
|
|
x: 1
|
|
label: center/big
|
|
)",
|
|
N(SB, L{
|
|
N(MFS, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2")}),
|
|
N(MFS, L{N(KP|VP, "x", "0" ), N(KP|VP, "y", "2")}),
|
|
N(MFS, L{N(KP|VP, "r", "10") }),
|
|
N(MFS, L{N(KP|VP, "r", "1" ) }),
|
|
N(MB, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2"), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2"), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2"), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
N(MB, L{N(KP|VP, "x", "1" ), N(KP|VP, "y", "2"), N(KP|VP, "r", "10"), N(KP|VP, "label", "center/big")}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("simple anchor 1, implicit, unresolved",
|
|
R"(
|
|
anchored_content: &anchor_name This string will appear as the value of two keys.
|
|
other_anchor: *anchor_name
|
|
anchors_in_seqs:
|
|
- &anchor_in_seq this value appears in both elements of the sequence
|
|
- *anchor_in_seq
|
|
base: &base
|
|
name: Everyone has same name
|
|
foo: &foo
|
|
<<: *base
|
|
age: 10
|
|
bar: &bar
|
|
<<: *base
|
|
age: 20
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "anchored_content", "This string will appear as the value of two keys.", AR(VALANCH, "anchor_name")),
|
|
N(KP|VAL, "other_anchor", "*anchor_name", AR(VALREF, "anchor_name")),
|
|
N(KP|SB, "anchors_in_seqs", L{
|
|
N(VP, "this value appears in both elements of the sequence", AR(VALANCH, "anchor_in_seq")),
|
|
N(VAL, "*anchor_in_seq", AR(VALREF, "anchor_in_seq")),
|
|
}),
|
|
N(KP|MB, "base", L{N(KP|VP, "name", "Everyone has same name")}, AR(VALANCH, "base")),
|
|
N(KP|MB, "foo", L{N(KP|VAL, "<<", "*base", AR(VALREF, "base")), N(KP|VP, "age", "10")}, AR(VALANCH, "foo")),
|
|
N(KP|MB, "bar", L{N(KP|VAL, "<<", "*base", AR(VALREF, "base")), N(KP|VP, "age", "20")}, AR(VALANCH, "bar")),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("simple anchor 1, explicit, unresolved",
|
|
R"({
|
|
anchored_content: &anchor_name This string will appear as the value of two keys.,
|
|
other_anchor: *anchor_name,
|
|
anchors_in_seqs: [
|
|
&anchor_in_seq this value appears in both elements of the sequence,
|
|
*anchor_in_seq
|
|
],
|
|
base: &base {
|
|
name: Everyone has same name
|
|
},
|
|
foo: &foo {
|
|
<<: *base,
|
|
age: 10
|
|
},
|
|
bar: &bar {
|
|
<<: *base,
|
|
age: 20
|
|
}
|
|
})",
|
|
N(MFM, L{
|
|
N(KP|VP, "anchored_content", "This string will appear as the value of two keys.", AR(VALANCH, "anchor_name")),
|
|
N(KP|VAL, "other_anchor", "*anchor_name", AR(VALREF, "anchor_name")),
|
|
N(KP|SFM, "anchors_in_seqs", L{
|
|
N(VP, "this value appears in both elements of the sequence", AR(VALANCH, "anchor_in_seq")),
|
|
N(VAL, "*anchor_in_seq", AR(VALREF, "anchor_in_seq")),
|
|
}),
|
|
N(KP|MFM, "base", L{N(KP|VP, "name", "Everyone has same name")}, AR(VALANCH, "base")),
|
|
N(KP|MFM, "foo", L{N(KP|VAL, "<<", "*base", AR(VALREF, "base")), N(KP|VP, "age", "10")}, AR(VALANCH, "foo")),
|
|
N(KP|MFM, "bar", L{N(KP|VAL, "<<", "*base", AR(VALREF, "base")), N(KP|VP, "age", "20")}, AR(VALANCH, "bar")),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("simple anchor 1, implicit, resolved", RESOLVE_REFS,
|
|
R"(
|
|
anchored_content: &anchor_name This string will appear as the value of two keys.
|
|
other_anchor: *anchor_name
|
|
anchors_in_seqs:
|
|
- &anchor_in_seq this value appears in both elements of the sequence
|
|
- *anchor_in_seq
|
|
base: &base
|
|
name: Everyone has same name
|
|
foo: &foo
|
|
<<: *base
|
|
age: 10
|
|
bar: &bar
|
|
<<: *base
|
|
age: 20
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "anchored_content", "This string will appear as the value of two keys."),
|
|
N(KP|VP, "other_anchor", "This string will appear as the value of two keys."),
|
|
N(KP|SB, "anchors_in_seqs", L{
|
|
N(VP, "this value appears in both elements of the sequence"),
|
|
N(VP, "this value appears in both elements of the sequence"),
|
|
}),
|
|
N(KP|MB, "base", L{N(KP|VP, "name", "Everyone has same name")}),
|
|
N(KP|MB, "foo", L{N(KP|VP, "name", "Everyone has same name"), N(KP|VP, "age", "10")}),
|
|
N(KP|MB, "bar", L{N(KP|VP, "name", "Everyone has same name"), N(KP|VP, "age", "20")}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("simple anchor 1, explicit, resolved", RESOLVE_REFS,
|
|
R"({
|
|
anchored_content: &anchor_name This string will appear as the value of two keys.,
|
|
other_anchor: *anchor_name,
|
|
anchors_in_seqs: [
|
|
&anchor_in_seq this value appears in both elements of the sequence,
|
|
*anchor_in_seq
|
|
],
|
|
base: &base {
|
|
name: Everyone has same name
|
|
},
|
|
foo: &foo {
|
|
<<: *base,
|
|
age: 10
|
|
},
|
|
bar: &bar {
|
|
<<: *base,
|
|
age: 20
|
|
}
|
|
})",
|
|
N(MFM, L{
|
|
N(KP|VP, "anchored_content", "This string will appear as the value of two keys."),
|
|
N(KP|VP, "other_anchor", "This string will appear as the value of two keys."),
|
|
N(KP|SFM, "anchors_in_seqs", L{
|
|
N(VP, "this value appears in both elements of the sequence"),
|
|
N(VP, "this value appears in both elements of the sequence"),
|
|
}),
|
|
N(KP|MFM, "base", L{N(KP|VP, "name", "Everyone has same name")}),
|
|
N(KP|MFM, "foo", L{N(KP|VP, "name", "Everyone has same name"), N(KP|VP, "age", "10")}),
|
|
N(KP|MFM, "bar", L{N(KP|VP, "name", "Everyone has same name"), N(KP|VP, "age", "20")}),
|
|
})
|
|
);
|
|
|
|
|
|
ADD_CASE_TO_GROUP("anchor example 2, unresolved",
|
|
R"(
|
|
receipt: Oz-Ware Purchase Invoice
|
|
date: 2012-08-06
|
|
customer:
|
|
first_name: Dorothy
|
|
family_name: Gale
|
|
items:
|
|
- part_no: A4786
|
|
descrip: Water Bucket (Filled)
|
|
price: 1.47
|
|
quantity: 4
|
|
- part_no: E1628
|
|
descrip: High Heeled "Ruby" Slippers
|
|
size: 8
|
|
price: 133.7
|
|
quantity: 1
|
|
bill-to: &id001
|
|
street: |
|
|
123 Tornado Alley
|
|
Suite 16
|
|
city: East Centerville
|
|
state: KS
|
|
ship-to: *id001
|
|
specialDelivery: >
|
|
Follow the Yellow Brick
|
|
Road to the Emerald City.
|
|
Pay no attention to the
|
|
man behind the curtain.
|
|
)",
|
|
N(MB, L{
|
|
N{KP|VP, "receipt", "Oz-Ware Purchase Invoice"},
|
|
N{KP|VP, "date", "2012-08-06"},
|
|
N{KP|MB, "customer", L{N{KP|VP, "first_name", "Dorothy"}, N{KP|VP, "family_name", "Gale"}}},
|
|
N{KP|SB, "items", L{
|
|
N{MB, L{N{KP|VP, "part_no", "A4786"},
|
|
N{KP|VP, "descrip", "Water Bucket (Filled)"},
|
|
N{KP|VP, "price", "1.47"},
|
|
N{KP|VP, "quantity", "4"},}},
|
|
N{MB, L{N{KP|VP, "part_no", "E1628"},
|
|
N{KP|VP, "descrip", "High Heeled \"Ruby\" Slippers"},
|
|
N{KP|VP, "size", "8"},
|
|
N{KP|VP, "price", "133.7"},
|
|
N{KP|VP, "quantity", "1"},}}}},
|
|
N{KP|MB, "bill-to", L{
|
|
N{KP|VL, "street", "123 Tornado Alley\nSuite 16\n"},
|
|
N{KP|VP, "city", "East Centerville"},
|
|
N{KP|VP, "state", "KS"},}, AR(VALANCH, "id001")},
|
|
N{KP|VAL, "ship-to", "*id001", AR(VALREF, "id001")},
|
|
N{KP|VF, "specialDelivery", "Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.\n"}
|
|
})
|
|
);
|
|
|
|
|
|
ADD_CASE_TO_GROUP("anchor example 2, resolved", RESOLVE_REFS,
|
|
R"(
|
|
receipt: Oz-Ware Purchase Invoice
|
|
date: 2012-08-06
|
|
customer:
|
|
first_name: Dorothy
|
|
family_name: Gale
|
|
items:
|
|
- part_no: A4786
|
|
descrip: Water Bucket (Filled)
|
|
price: 1.47
|
|
quantity: 4
|
|
- part_no: E1628
|
|
descrip: High Heeled "Ruby" Slippers
|
|
size: 8
|
|
price: 133.7
|
|
quantity: 1
|
|
bill-to: &id001
|
|
street: |
|
|
123 Tornado Alley
|
|
Suite 16
|
|
city: East Centerville
|
|
state: KS
|
|
ship-to: *id001
|
|
specialDelivery: >
|
|
Follow the Yellow Brick
|
|
Road to the Emerald City.
|
|
Pay no attention to the
|
|
man behind the curtain.
|
|
)",
|
|
N(MB, L{
|
|
N{KP|VP, "receipt", "Oz-Ware Purchase Invoice"},
|
|
N{KP|VP, "date", "2012-08-06"},
|
|
N{KP|MB, "customer", L{
|
|
N{KP|VP, "first_name", "Dorothy"},
|
|
N{KP|VP, "family_name", "Gale"}
|
|
}},
|
|
N{KP|SB, "items", L{
|
|
N{MB, L{
|
|
N{KP|VP, "part_no", "A4786"},
|
|
N{KP|VP, "descrip", "Water Bucket (Filled)"},
|
|
N{KP|VP, "price", "1.47"},
|
|
N{KP|VP, "quantity", "4"},
|
|
}},
|
|
N{MB, L{
|
|
N{KP|VP, "part_no", "E1628"},
|
|
N{KP|VP, "descrip", "High Heeled \"Ruby\" Slippers"},
|
|
N{KP|VP, "size", "8"},
|
|
N{KP|VP, "price", "133.7"},
|
|
N{KP|VP, "quantity", "1"},
|
|
}}
|
|
}},
|
|
N{KP|MB, "bill-to", L{
|
|
N{KP|VL, "street", "123 Tornado Alley\nSuite 16\n"},
|
|
N{KP|VP, "city", "East Centerville"},
|
|
N{KP|VP, "state", "KS"},
|
|
}},
|
|
N{KP|MB, "ship-to", L{
|
|
N{KP|VL, "street", "123 Tornado Alley\nSuite 16\n"},
|
|
N{KP|VP, "city", "East Centerville"},
|
|
N{KP|VP, "state", "KS"},
|
|
}},
|
|
N{KP|VF, "specialDelivery", "Follow the Yellow Brick Road to the Emerald City. Pay no attention to the man behind the curtain.\n"}
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor example 3, unresolved",
|
|
R"(
|
|
- step: &id001 # defines anchor label &id001
|
|
instrument: Lasik 2000
|
|
pulseEnergy: 5.4
|
|
pulseDuration: 12
|
|
repetition: 1000
|
|
spotSize: 1mm
|
|
- step: &id002
|
|
instrument: Lasik 2000
|
|
pulseEnergy: 5.0
|
|
pulseDuration: 10
|
|
repetition: 500
|
|
spotSize: 2mm
|
|
- step: *id001 # refers to the first step (with anchor &id001)
|
|
- step: *id002 # refers to the second step
|
|
- step:
|
|
<<: *id001
|
|
spotSize: 2mm # redefines just this key, refers rest from &id001
|
|
- step: *id002
|
|
)",
|
|
N(SB, L{
|
|
N(MB, L{
|
|
N(KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.4"},
|
|
N{KP|VP, "pulseDuration", "12"},
|
|
N{KP|VP, "repetition", "1000"},
|
|
N{KP|VP, "spotSize", "1mm"},
|
|
}, AR(VALANCH, "id001")),
|
|
}),
|
|
N(MB, L{
|
|
N(KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.0"},
|
|
N{KP|VP, "pulseDuration", "10"},
|
|
N{KP|VP, "repetition", "500"},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}, AR(VALANCH, "id002")),
|
|
}),
|
|
N(MB, L{
|
|
N{KP|VAL, "step", "*id001", AR(VALREF, "id001")},
|
|
}),
|
|
N(MB, L{
|
|
N{KP|VAL, "step", "*id002", AR(VALREF, "id002")},
|
|
}),
|
|
N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VAL, "<<", "*id001", AR(VALREF, "id002")},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}},
|
|
}),
|
|
N(MB, L{
|
|
N{KP|VAL, "step", "*id002", AR(VALREF, "id002")},
|
|
}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor example 3, resolved", RESOLVE_REFS,
|
|
R"(
|
|
- step: &id001 # defines anchor label &id001
|
|
instrument: Lasik 2000
|
|
pulseEnergy: 5.4
|
|
pulseDuration: 12
|
|
repetition: 1000
|
|
spotSize: 1mm
|
|
- step: &id002
|
|
instrument: Lasik 2000
|
|
pulseEnergy: 5.0
|
|
pulseDuration: 10
|
|
repetition: 500
|
|
spotSize: 2mm
|
|
- step: *id001 # refers to the first step (with anchor &id001)
|
|
- step: *id002 # refers to the second step
|
|
- step:
|
|
<<: *id001
|
|
spotSize: 2mm # redefines just this key, refers rest from &id001
|
|
- step: *id002
|
|
)",
|
|
N(SB, L{
|
|
N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.4"},
|
|
N{KP|VP, "pulseDuration", "12"},
|
|
N{KP|VP, "repetition", "1000"},
|
|
N{KP|VP, "spotSize", "1mm"},
|
|
}},
|
|
}), N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.0"},
|
|
N{KP|VP, "pulseDuration", "10"},
|
|
N{KP|VP, "repetition", "500"},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}},
|
|
}), N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.4"},
|
|
N{KP|VP, "pulseDuration", "12"},
|
|
N{KP|VP, "repetition", "1000"},
|
|
N{KP|VP, "spotSize", "1mm"},
|
|
}},
|
|
}), N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.0"},
|
|
N{KP|VP, "pulseDuration", "10"},
|
|
N{KP|VP, "repetition", "500"},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}},
|
|
}), N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.4"},
|
|
N{KP|VP, "pulseDuration", "12"},
|
|
N{KP|VP, "repetition", "1000"},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}},
|
|
}), N(MB, L{
|
|
N{KP|MB, "step", L{
|
|
N{KP|VP, "instrument", "Lasik 2000"},
|
|
N{KP|VP, "pulseEnergy", "5.0"},
|
|
N{KP|VP, "pulseDuration", "10"},
|
|
N{KP|VP, "repetition", "500"},
|
|
N{KP|VP, "spotSize", "2mm"},
|
|
}},
|
|
}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("tagged doc with anchors 9KAX",
|
|
R"(
|
|
---
|
|
&a1
|
|
!!str
|
|
scalar1
|
|
--- &a1 !!str scalar1
|
|
---
|
|
!!str
|
|
&a1
|
|
scalar1
|
|
--- !!str &a1 scalar1
|
|
---
|
|
!!str
|
|
&a2
|
|
scalar2
|
|
--- &a2 !!str scalar2
|
|
---
|
|
&a3
|
|
!!str scalar3
|
|
--- &a3 !!str scalar3
|
|
---
|
|
&a4 !!map
|
|
&a5 !!str key5: value4
|
|
--- &a4 !!map
|
|
&a5 !!str key5: value4
|
|
---
|
|
a6: 1
|
|
&anchor6 b6: 2
|
|
---
|
|
!!map
|
|
&a8 !!str key8: value7
|
|
--- !!map
|
|
&a8 !!str key8: value7
|
|
---
|
|
!!map
|
|
!!str &a10 key10: value9
|
|
--- !!map
|
|
&a10 !!str key10: value9
|
|
---
|
|
!!str &a11
|
|
value11
|
|
--- &a11 !!str value11
|
|
)",
|
|
N(STREAM, L{
|
|
N(DOC|VP, TS("!!str", "scalar1"), AR(VALANCH, "a1")),
|
|
N(DOC|VP, TS("!!str", "scalar1"), AR(VALANCH, "a1")),
|
|
N(DOC|VP, TS("!!str", "scalar1"), AR(VALANCH, "a1")),
|
|
N(DOC|VP, TS("!!str", "scalar1"), AR(VALANCH, "a1")),
|
|
N(DOC|VP, TS("!!str", "scalar2"), AR(VALANCH, "a2")),
|
|
N(DOC|VP, TS("!!str", "scalar2"), AR(VALANCH, "a2")),
|
|
N(DOC|VP, TS("!!str", "scalar3"), AR(VALANCH, "a3")),
|
|
N(DOC|VP, TS("!!str", "scalar3"), AR(VALANCH, "a3")),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key5"), AR(KEYANCH, "a5"), "value4")}), AR(VALANCH, "a4")),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key5"), AR(KEYANCH, "a5"), "value4")}), AR(VALANCH, "a4")),
|
|
N(DOC|MB, L{N(KP|VP, "a6", "1"), N(KP|VP, "b6", AR(KEYANCH, "anchor6"), "2")}),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key8"), AR(KEYANCH, "a8"), "value7")})),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key8"), AR(KEYANCH, "a8"), "value7")})),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key10"), AR(KEYANCH, "a10"), "value9")})),
|
|
N(DOC|MB, TL("!!map", L{N(KP|VP, TS("!!str", "key10"), AR(KEYANCH, "a10"), "value9")})),
|
|
N(DOC|VP, TS("!!str", "value11"), AR(VALANCH, "a11")),
|
|
N(DOC|VP, TS("!!str", "value11"), AR(VALANCH, "a11")),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("github131 1, unresolved",
|
|
R"(
|
|
a: &vref b
|
|
*vref : c
|
|
&kref aa: bb
|
|
aaa: &kvref bbb
|
|
foo:
|
|
*kref : cc
|
|
*kvref : dd
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "a", "b", AR(VALANCH, "vref")),
|
|
N(KEY|VP, "*vref", AR(KEYREF, "vref"), "c"),
|
|
N(KP|VP, "aa", AR(KEYANCH, "kref"), "bb"),
|
|
N(KP|VP, "aaa", "bbb", AR(VALANCH, "kvref")),
|
|
N(KP|MB, "foo", L{
|
|
N(KEY|VP, "*kref", AR(KEYREF, "kref"), "cc"),
|
|
N(KEY|VP, "*kvref", AR(KEYREF, "kvref"), "dd"),
|
|
})
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("github131 1, resolved", RESOLVE_REFS,
|
|
R"(
|
|
a: &vref b
|
|
*vref : c
|
|
&kref aa: bb
|
|
aaa: &kvref bbb
|
|
foo:
|
|
*kref : cc
|
|
*kvref : dd
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "a", "b"),
|
|
N(KP|VP, "b", "c"),
|
|
N(KP|VP, "aa", "bb"),
|
|
N(KP|VP, "aaa", "bbb"),
|
|
N(KP|MB, "foo", L{N(KP|VP, "aa", "cc"), N(KP|VP, "bbb", "dd")})
|
|
})
|
|
);
|
|
|
|
|
|
ADD_CASE_TO_GROUP("anchors+refs on key+val, unresolved",
|
|
R"({&a0 a0: &b0 b0, *b0 : *a0})",
|
|
N(MFS, L{
|
|
N(KP|VP, "a0", AR(KEYANCH, "a0"), "b0", AR(VALANCH, "b0")),
|
|
N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchors+refs on key+val, resolved", RESOLVE_REFS,
|
|
R"({&a0 a0: &b0 b0, *b0 : *a0})",
|
|
N(MFS, L{
|
|
N(KP|VP, "a0", "b0"),
|
|
N(KP|VP, "b0", "a0"),
|
|
})
|
|
);
|
|
|
|
|
|
ADD_CASE_TO_GROUP("ambiguous anchor, unresolved",
|
|
R"(&rootanchor
|
|
&a0 a0: &b0 b0
|
|
*b0 : *a0
|
|
map1:
|
|
&a1 a1: &b1 b1 # &a1 must be a KEY anchor on a1, not a VAL anchor on map1
|
|
*b1 : *a1
|
|
map2:
|
|
*b0 : *a0 # ensure the anchor is enough to establish the indentation
|
|
&a2 a2: &b2 b2
|
|
*b2 : *a2
|
|
map3: &a3 # &a3 must be a VAL anchor on map3, not a KEY anchor on a3
|
|
a3: &b3 b3
|
|
*b3 : *b0
|
|
map4: *a0
|
|
map5:
|
|
&map5
|
|
&a5 a5: &b5 b5
|
|
*b5 : *a5
|
|
map6:
|
|
&map6
|
|
a6: &b6 b6
|
|
*b6 : *b6
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "a0", AR(KEYANCH, "a0"), "b0", AR(VALANCH, "b0")),
|
|
N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")),
|
|
N(KP|MB, "map1", L{N(KP|VP, "a1", AR(KEYANCH, "a1"), "b1", AR(VALANCH, "b1")), N(AR(KEYREF, "*b1"), AR(VALREF, "*a1")),}),
|
|
N(KP|MB, "map2", L{N(AR(KEYREF, "*b0"), AR(VALREF, "*a0")), N(KP|VP, "a2", AR(KEYANCH, "a2"), "b2", AR(VALANCH, "b2")), N(AR(KEYREF, "*b2"), AR(VALREF, "*a2")),}),
|
|
N(KP|MB, "map3", L{N(KP|VP, "a3", "b3", AR(VALANCH, "b3")), N(AR(KEYREF, "*b3"), AR(VALREF, "*b0")),}, AR(VALANCH, "a3")),
|
|
N(KP|VAL, "map4", "*a0", AR(VALREF, "a0")),
|
|
N(KP|MB, "map5", L{N(KP|VP, "a5", AR(KEYANCH, "a5"), "b5", AR(VALANCH, "b5")), N(AR(KEYREF, "*b5"), AR(VALREF, "*a5")),}, AR(VALANCH, "map5")),
|
|
N(KP|MB, "map6", L{N(KP|VP, "a6", "b6", AR(VALANCH, "b6")), N(AR(KEYREF, "*b6"), AR(VALREF, "*b6")),}, AR(VALANCH, "map6")),
|
|
}, AR(VALANCH, "rootanchor"))
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("ambiguous anchor, resolved", RESOLVE_REFS,
|
|
R"(
|
|
&a0 a0: &b0 b0
|
|
*b0 : *a0
|
|
map1:
|
|
&a1 a1: &b1 b1 # &a1 must be a KEY anchor on a1, not a VAL anchor on map1
|
|
*b1 : *a1
|
|
map2:
|
|
*b0 : *a0 # ensure the anchor is enough to establish the indentation
|
|
&a2 a2: &b2 b2
|
|
*b2 : *a2
|
|
map3: &a3 # &a3 must be a VAL anchor on map3, not a KEY anchor on a3
|
|
a3: &b3 b3
|
|
*b3 : *b0
|
|
map4: *a0
|
|
map5:
|
|
&map5
|
|
&a5 a5: &b5 b5
|
|
*b5 : *a5
|
|
map6:
|
|
&map6
|
|
a6: &b6 b6
|
|
*b6 : *b6
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "a0", "b0"), N(KP|VP, "b0", "a0"),
|
|
N(KP|MB, "map1", L{N(KP|VP, "a1", "b1"), N(KP|VP, "b1", "a1"),}),
|
|
N(KP|MB, "map2", L{N(KP|VP, "b0", "a0"), N(KP|VP, "a2", "b2"), N(KP|VP, "b2", "a2"),}),
|
|
N(KP|MB, "map3", L{N(KP|VP, "a3", "b3"), N(KP|VP, "b3", "b0"),}),
|
|
N(KP|VP, "map4", "a0"),
|
|
N(KP|MB, "map5", L{N(KP|VP, "a5", "b5"), N(KP|VP, "b5", "a5"),}),
|
|
N(KP|MB, "map6", L{N(KP|VP, "a6", "b6"), N(KP|VP, "b6", "b6"),}),
|
|
})
|
|
);
|
|
|
|
|
|
ADD_CASE_TO_GROUP("ambiguous anchor in seq, unresolved",
|
|
R"(
|
|
&seq
|
|
- &a0
|
|
&a1 k1: v1
|
|
&a2 k2: v2
|
|
&a3 k3: v3
|
|
- &a4 k4: v4
|
|
&a5 k5: v5
|
|
&a6 k6: v6
|
|
- &a7
|
|
&a8 k8: v8
|
|
- &a9
|
|
k10: v10
|
|
- *a1 : w1
|
|
*a2 : w2
|
|
*a3 : w3
|
|
*a4 : w4
|
|
*a5 : w5
|
|
*a6 : w6
|
|
*a8 : w8
|
|
- *a0
|
|
- *a7
|
|
- *a9
|
|
)",
|
|
N(SB, L{
|
|
N(MB, L{N(KP|VP, "k1", AR(KEYANCH, "a1"), "v1"), N(KP|VP, "k2", AR(KEYANCH, "a2"), "v2"), N(KP|VP, "k3", AR(KEYANCH, "a3"), "v3")}, AR(VALANCH, "a0")),
|
|
N(MB, L{N(KP|VP, "k4", AR(KEYANCH, "a4"), "v4"), N(KP|VP, "k5", AR(KEYANCH, "a5"), "v5"), N(KP|VP, "k6", AR(KEYANCH, "a6"), "v6")}),
|
|
N(MB, L{N(KP|VP, "k8", AR(KEYANCH, "a8"), "v8")}, AR(VALANCH, "a7")),
|
|
N(MB, L{N(KP|VP, "k10", "v10")}, AR(VALANCH, "a9")),
|
|
N(MB, L{
|
|
N(KEY|VP, "*a1", AR(KEYREF, "*a1"), "w1"),
|
|
N(KEY|VP, "*a2", AR(KEYREF, "*a2"), "w2"),
|
|
N(KEY|VP, "*a3", AR(KEYREF, "*a3"), "w3"),
|
|
N(KEY|VP, "*a4", AR(KEYREF, "*a4"), "w4"),
|
|
N(KEY|VP, "*a5", AR(KEYREF, "*a5"), "w5"),
|
|
N(KEY|VP, "*a6", AR(KEYREF, "*a6"), "w6"),
|
|
N(KEY|VP, "*a8", AR(KEYREF, "*a8"), "w8"),
|
|
}),
|
|
N(VAL, "*a0", AR(VALREF, "*a0")),
|
|
N(VAL, "*a7", AR(VALREF, "*a7")),
|
|
N(VAL, "*a9", AR(VALREF, "*a9")),
|
|
}, AR(VALANCH, "seq"))
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("ambiguous anchor in seq, resolved", RESOLVE_REFS,
|
|
R"(
|
|
&seq
|
|
- &a0
|
|
&a1 k1: v1
|
|
&a2 k2: v2
|
|
&a3 k3: v3
|
|
- &a4 k4: v4
|
|
&a5 k5: v5
|
|
&a6 k6: v6
|
|
- &a7
|
|
&a8 k8: v8
|
|
- &a9
|
|
k10 : v10
|
|
- *a1 : w1
|
|
*a2 : w2
|
|
*a3 : w3
|
|
*a4 : w4
|
|
*a5 : w5
|
|
*a6 : w6
|
|
*a8 : w8
|
|
- *a0
|
|
- *a7
|
|
- *a9
|
|
)",
|
|
N(SB, L{
|
|
N(MB, L{N(KP|VP, "k1", "v1"), N(KP|VP, "k2", "v2"), N(KP|VP, "k3", "v3")}),
|
|
N(MB, L{N(KP|VP, "k4", "v4"), N(KP|VP, "k5", "v5"), N(KP|VP, "k6", "v6")}),
|
|
N(MB, L{N(KP|VP, "k8", "v8")}),
|
|
N(MB, L{N(KP|VP, "k10", "v10")}),
|
|
N(MB, L{
|
|
N(KP|VP, "k1", "w1"),
|
|
N(KP|VP, "k2", "w2"),
|
|
N(KP|VP, "k3", "w3"),
|
|
N(KP|VP, "k4", "w4"),
|
|
N(KP|VP, "k5", "w5"),
|
|
N(KP|VP, "k6", "w6"),
|
|
N(KP|VP, "k8", "w8"),
|
|
}),
|
|
N(MB, L{N(KP|VP, "k1", "v1"), N(KP|VP, "k2", "v2"), N(KP|VP, "k3", "v3")}),
|
|
N(MB, L{N(KP|VP, "k8", "v8")}),
|
|
N(MB, L{N(KP|VP, "k10", "v10")}),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor after complex key without value ZWK4",
|
|
R"(
|
|
a: 1
|
|
? b
|
|
&anchor c: 3
|
|
)",
|
|
N(MB, L{
|
|
N(KP|VP, "a", "1"), N(KP|VN, "b", {}), N(KP|VP, "c", AR(KEYANCH, "anchor"), "3")
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor mixed with tag HMQ5, unresolved",
|
|
R"(
|
|
!!str &a1 "foo":
|
|
!!str bar
|
|
&a2 baz : *a1
|
|
)",
|
|
N(MB, L{
|
|
N(KD|VP, TS("!!str", "foo"), AR(KEYANCH, "a1"), TS("!!str", "bar")),
|
|
N(KP|VAL, "baz", AR(KEYANCH, "a2"), "*a1", AR(VALREF, "*a1")),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("anchor mixed with tag HMQ5, resolved", RESOLVE_REFS,
|
|
R"(
|
|
!!str &a1 "foo":
|
|
!!str bar
|
|
&a2 baz : *a1
|
|
)",
|
|
N(MB, L{
|
|
N(KD|VP, TS("!!str", "foo"), TS("!!str", "bar")),
|
|
N(KP|VD, "baz", "foo"),
|
|
})
|
|
);
|
|
|
|
ADD_CASE_TO_GROUP("github 484, resolved", RESOLVE_REFS,
|
|
R"(
|
|
base_1: &base_1
|
|
a: 10
|
|
b: 10
|
|
base_2: &base_2
|
|
b: 20
|
|
k1:
|
|
!!merge <<: *base_1
|
|
!!merge <<: *base_2
|
|
k2:
|
|
!!merge <<: *base_2
|
|
!!merge <<: *base_1
|
|
)",
|
|
N(MB, L{
|
|
N(KP|MB, "base_1", L{N(KP|VP, "a", "10"), N(KP|VP, "b", "10")}),
|
|
N(KP|MB, "base_2", L{/* */N(KP|VP, "b", "20")}),
|
|
N(KP|MB, "k1", L{N(KP|VP, "a", "10"), N(KP|VP, "b", "20")}),
|
|
N(KP|MB, "k2", L{N(KP|VP, "a", "10"), N(KP|VP, "b", "10")}),
|
|
})
|
|
);
|
|
|
|
}
|
|
|
|
|
|
C4_SUPPRESS_WARNING_GCC_POP
|
|
|
|
} // namespace yml
|
|
} // namespace c4
|