Files
rapidyaml/test/test_location.cpp
2025-12-28 19:17:22 +00:00

743 lines
23 KiB
C++

#ifndef RYML_SINGLE_HEADER
#include <c4/yml/std/std.hpp>
#include <c4/yml/yml.hpp>
#endif
#include "./test_lib/test_case.hpp"
#include <gtest/gtest.h>
namespace c4 {
namespace yml {
TEST(locations, default_is_no_location)
{
{
ParserOptions opts;
EXPECT_EQ(opts.locations(), false);
}
{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler);
EXPECT_EQ(parser.options().locations(), false);
}
{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, ParserOptions{});
EXPECT_EQ(parser.options().locations(), false);
}
{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, ParserOptions().locations(false));
EXPECT_EQ(parser.options().locations(), false);
}
{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, ParserOptions().locations(true));
EXPECT_EQ(parser.options().locations(), true);
}
}
TEST(locations, error_is_triggered_querying_with_locations_disabled)
{
bool parsed_ok = false;
ExpectError::check_error_basic([&]{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, ParserOptions().locations(false));
Tree t = parse_in_arena(&parser, "test", "foo: bar");
parsed_ok = true;
t["foo"].location(parser);
});
EXPECT_TRUE(parsed_ok);
}
#define _checkloc(node, line_, col_, str) \
{ \
const Location loc = node.location(parser); \
EXPECT_EQ(loc.name, "myfile.yml"); \
EXPECT_EQ(loc.line, line_); \
EXPECT_EQ(loc.col, col_); \
EXPECT_EQ(t.arena().sub(loc.offset, csubstr(str).len), csubstr(str)); \
}
TEST(locations, no_error_is_triggered_querying_with_locations)
{
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, ParserOptions().locations(true));
EXPECT_EQ(parser.options().locations(), true);
Tree t = parse_in_arena(&parser, "myfile.yml", "foo: bar");
_checkloc(t["foo"], 0, 0, "foo");
}
TEST(locations, docval)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", "docval");
_checkloc(t.rootref(), 0u, 0u, "docval");
t = parse_in_arena(&parser, "myfile.yml", "\n docval");
_checkloc(t.rootref(), 1u, 1u, "docval");
t = parse_in_arena(&parser, "myfile.yml", "\n\n docval");
_checkloc(t.rootref(), 2u, 1u, "docval");
}
TEST(locations, docval_null)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", "~");
_checkloc(t.rootref(), 0u, 0u, "~");
t = parse_in_arena(&parser, "myfile.yml", "");
_checkloc(t.rootref(), 0u, 0u, "");
t = parse_in_arena(&parser, "myfile.yml", R"(#
#
#
#
#
)");
_checkloc(t.rootref(), 0u, 0u, "");
}
TEST(locations, seq_block)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"(
- this
- is
- a
- seq
- - and
- this
- - as
- well
- - # this one works as well
# even with a comment in between
the scalar value is here
- and here's another value
-
- another val
- yet another val
)";
Tree t = parse_in_arena(&parser, "myfile.yml", yaml);
ConstNodeRef seq = t.rootref();
ASSERT_TRUE(seq.is_seq());
_checkloc(seq , 1u, 0u, "- ");
_checkloc(seq[0] , 1u, 2u, "this");
_checkloc(seq[1] , 2u, 2u, "is");
_checkloc(seq[2] , 3u, 2u, "a");
_checkloc(seq[3] , 4u, 2u, "seq");
_checkloc(seq[4] , 5u, 2u, "- ");
_checkloc(seq[4][0] , 5u, 4u, "and");
_checkloc(seq[4][1] , 6u, 4u, "this");
_checkloc(seq[4][2] , 7u, 4u, "- ");
_checkloc(seq[4][2][0], 7u, 6u, "as");
_checkloc(seq[4][2][1], 8u, 6u, "well");
_checkloc(seq[4][3] , 9u, 4u, "- # this one works as well");
_checkloc(seq[4][3][0], 11u, 6u, "the scalar value is here");
_checkloc(seq[4][3][1], 12u, 8u, "and here's another value");
_checkloc(seq[4][3][2], 14u, 6u, "- ");
_checkloc(seq[4][3][2][0], 14u, 8u, "another val");
_checkloc(seq[4][3][2][1], 15u, 8u, "yet another val");
}
TEST(locations, map_block)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"(
this: ~
is: ~
a: ~
map: ~
and:
this:
as: ~
well: ~
aswell: # this one works as well
# even with a comment in between
val: here
hah: here
)";
Tree t = parse_in_arena(&parser, "myfile.yml", yaml);
ConstNodeRef map = t.rootref();
ASSERT_TRUE(map.is_map());
_checkloc(map , 1u, 0u, "this:");
_checkloc(map["this"] , 1u, 0u, "this:");
_checkloc(map["is"] , 2u, 0u, "is:");
_checkloc(map["a"] , 3u, 0u, "a:");
_checkloc(map["map"] , 4u, 0u, "map:");
_checkloc(map["and"] , 5u, 0u, "and:");
_checkloc(map["and"]["this"] , 6u, 2u, "this:");
_checkloc(map["and"]["this"]["as"] , 7u, 4u, "as:");
_checkloc(map["and"]["this"]["well"] , 8u, 4u, "well:");
_checkloc(map["and"]["aswell"] , 9u, 2u, "aswell:");
_checkloc(map["and"]["aswell"]["val"] , 11u, 4u, "val:");
_checkloc(map["and"]["aswell"]["hah"] , 12u, 4u, "hah:");
}
TEST(locations, seq_block_null)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
const Tree t = parse_in_arena(&parser, "myfile.yml", R"(---
- ~
- ~
- notnull
- ~
- ~
---
- ~
- - ~
- - - ~
- - - - ~
- - - - - ~
- - - - ~
- - - ~
- - ~
- ~
---
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
)");
_checkloc(t.rootref() , 0u, 0u, "---");
_checkloc(t.docref(0) , 1u, 0u, "- ");
_checkloc(t.docref(0)[0], 1u, 2u, "~");
_checkloc(t.docref(0)[1], 2u, 2u, "~");
_checkloc(t.docref(0)[2], 3u, 2u, "notnull");
_checkloc(t.docref(0)[3], 4u, 2u, "~");
_checkloc(t.docref(0)[4], 5u, 2u, "~");
_checkloc(t.docref(1) , 7u, 0u, "- ");
_checkloc(t.docref(1)[0], 7u, 2u, "~");
_checkloc(t.docref(1)[1], 8u, 2u, "- ");
_checkloc(t.docref(1)[1][0], 8u, 4u, "~");
_checkloc(t.docref(1)[2], 9u, 2u, "- ");
_checkloc(t.docref(1)[2][0], 9u, 4u, "- ");
_checkloc(t.docref(1)[2][0][0], 9u, 6u, "~");
_checkloc(t.docref(1)[3], 10u, 2u, "- ");
_checkloc(t.docref(1)[3][0], 10u, 4u, "- ");
_checkloc(t.docref(1)[3][0][0], 10u, 6u, "- ");
_checkloc(t.docref(1)[3][0][0][0], 10u, 8u, "~");
_checkloc(t.docref(1)[4], 11u, 2u, "- ");
_checkloc(t.docref(1)[4][0], 11u, 4u, "- ");
_checkloc(t.docref(1)[4][0][0], 11u, 6u, "- ");
_checkloc(t.docref(1)[4][0][0][0], 11u, 8u, "- ");
_checkloc(t.docref(1)[4][0][0][0][0], 11u, 10u, "~");
_checkloc(t.docref(1)[5], 12u, 2u, "- ");
_checkloc(t.docref(1)[5][0], 12u, 4u, "- ");
_checkloc(t.docref(1)[5][0][0], 12u, 6u, "- ");
_checkloc(t.docref(1)[5][0][0][0], 12u, 8u, "~");
_checkloc(t.docref(1)[6], 13u, 2u, "- ");
_checkloc(t.docref(1)[6][0], 13u, 4u, "- ");
_checkloc(t.docref(1)[6][0][0], 13u, 6u, "~");
_checkloc(t.docref(1)[7], 14u, 2u, "- ");
_checkloc(t.docref(1)[7][0], 14u, 4u, "~");
_checkloc(t.docref(1)[8], 15u, 2u, "~");
_checkloc(t.docref(2) , 17u, 0u, "-");
_checkloc(t.docref(2)[0], 17u, 0u, "-");
_checkloc(t.docref(2)[1], 17u, 0u, "-");
_checkloc(t.docref(2)[2], 21u, 2u, "-");
_checkloc(t.docref(2)[3], 21u, 2u, "-");
_checkloc(t.docref(2)[3][0], 21u, 2u, "-");
_checkloc(t.docref(2)[3][1], 24u, 4u, "-");
_checkloc(t.docref(2)[3][2], 24u, 4u, "-");
_checkloc(t.docref(2)[3][2][0], 25u, 6u, "-");
_checkloc(t.docref(2)[3][2][0][0], 26u, 8u, "-");
_checkloc(t.docref(2)[3][2][0][0][0], 26u, 8u, "-");
_checkloc(t.docref(2)[3][2][0][0][1], 26u, 8u, "-");
_checkloc(t.docref(2)[3][2][1], 25u, 6u, "-");
_checkloc(t.docref(2)[3][3], 24u, 4u, "-"); // fix: this should be after the previous child
_checkloc(t.docref(2)[3][4], 21u, 2u, "-"); // fix: this should be after the previous child
_checkloc(t.docref(2)[3][5], 21u, 2u, "-"); // fix: this should be after the previous child
}
TEST(locations, map_block_null)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", R"(---
~: v
---
null: v
---
: v
)");
_checkloc(t.rootref() , 0u, 0u, "---");
_checkloc(t.docref(0) , 1u, 0u, "");
_checkloc(t.docref(0)[0], 1u, 0u, "~");
_checkloc(t.docref(1) , 3u, 0u, "null");
_checkloc(t.docref(1)[0], 3u, 0u, "null");
_checkloc(t.docref(2) , 5u, 1u, "");
_checkloc(t.docref(2)[0], 5u, 3u, "");
}
TEST(locations, empty_seq)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", R"(---
- []
- []
- notnull
- []
- []
---
- []
---
[]
---
key0: []
key1: []
key2: notnull
key3: []
key4: []
---
key: []
)");
_checkloc(t.rootref() , 0u, 0u, "---");
_checkloc(t.docref(0) , 1u, 0u, "- ");
_checkloc(t.docref(0)[0], 1u, 2u, "[]");
_checkloc(t.docref(0)[1], 2u, 2u, "[]");
_checkloc(t.docref(0)[2], 3u, 2u, "notnull");
_checkloc(t.docref(0)[3], 4u, 2u, "[]");
_checkloc(t.docref(0)[4], 5u, 2u, "[]");
_checkloc(t.docref(1) , 7u, 0u, "- ");
_checkloc(t.docref(1)[0], 7u, 2u, "[]");
_checkloc(t.docref(2) , 9u, 0u, "[]");
_checkloc(t.docref(3) , 11u, 0u, "key0"); // WTF
_checkloc(t.docref(3)["key0"], 11u, 0u, "key0");
_checkloc(t.docref(3)["key1"], 12u, 0u, "key1");
_checkloc(t.docref(3)["key2"], 13u, 0u, "key2");
_checkloc(t.docref(3)["key3"], 14u, 0u, "key3");
_checkloc(t.docref(3)["key4"], 15u, 0u, "key4");
}
TEST(locations, empty_map)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", R"(---
- {}
- {}
- notnull
- {}
- {}
---
- {}
---
{}
---
key0: {}
key1: {}
key2: notnull
key3: {}
key4: {}
---
key: {}
)");
_checkloc(t.rootref() , 0u, 0u, "---");
_checkloc(t.docref(0) , 1u, 0u, "- ");
_checkloc(t.docref(0)[0], 1u, 2u, "{}");
_checkloc(t.docref(0)[1], 2u, 2u, "{}");
_checkloc(t.docref(0)[2], 3u, 2u, "notnull");
_checkloc(t.docref(0)[3], 4u, 2u, "{}");
_checkloc(t.docref(0)[4], 5u, 2u, "{}");
_checkloc(t.docref(1) , 7u, 0u, "- ");
_checkloc(t.docref(1)[0], 7u, 2u, "{}");
_checkloc(t.docref(2) , 9u, 0u, "{}");
_checkloc(t.docref(3) , 11u, 0u, "key0"); // WTF
_checkloc(t.docref(3)["key0"], 11u, 0u, "key0");
_checkloc(t.docref(3)["key1"], 12u, 0u, "key1");
_checkloc(t.docref(3)["key2"], 13u, 0u, "key2");
_checkloc(t.docref(3)["key3"], 14u, 0u, "key3");
_checkloc(t.docref(3)["key4"], 15u, 0u, "key4");
}
TEST(locations, seq_flow)
{
Tree t;
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"([one,two,three,four,items])";
parse_in_arena(&parser, "myfile.yml", yaml, &t);
ConstNodeRef seq = t.rootref();
ASSERT_TRUE(seq.is_seq());
_checkloc(seq , 0u, 0u, "[");
_checkloc(seq[0], 0u, 1u, "one");
_checkloc(seq[1], 0u, 5u, "two");
_checkloc(seq[2], 0u, 9u, "three");
_checkloc(seq[3], 0u, 15u, "four");
_checkloc(seq[4], 0u, 20u, "items");
}
TEST(locations, map_flow)
{
Tree t;
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"({one: item,two: items,three: items,four: items})";
parse_in_arena(&parser, "myfile.yml", yaml, &t);
ConstNodeRef map = t.rootref();
ASSERT_TRUE(map.is_map());
_checkloc(map , 0u, 0u, "{");
_checkloc(map[0], 0u, 1u, "one:");
_checkloc(map[1], 0u, 11u, "two:");
_checkloc(map[2], 0u, 22u, "three:");
_checkloc(map[3], 0u, 35u, "four:");
}
TEST(locations, seq_flow_nested)
{
Tree t;
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"([
one,
two,
[woops, there, [ goes, master]],
five,
{wait: is, this: { really: a map? }, nope: [ a seq!, { had: you there, eehh: no. } ]},
yep,
it,
was
])";
parse_in_arena(&parser, "myfile.yml", yaml, &t);
ConstNodeRef seq = t.rootref();
ASSERT_TRUE(seq.is_seq());
_checkloc(seq , 0u, 0u, "[");
_checkloc(seq[0] , 1u, 2u, "one");
_checkloc(seq[1] , 2u, 2u, "two");
_checkloc(seq[2] , 3u, 2u, "[");
_checkloc(seq[2][0] , 3u, 3u, "woops");
_checkloc(seq[2][1] , 3u, 14u, "there");
_checkloc(seq[2][2] , 3u, 24u, "[");
_checkloc(seq[2][2][0] , 3u, 27u, "goes");
_checkloc(seq[2][2][1] , 3u, 37u, "master");
_checkloc(seq[3] , 4u, 2u, "five");
_checkloc(seq[4] , 5u, 2u, "{");
_checkloc(seq[4]["wait"] , 5u, 3u, "wait");
_checkloc(seq[4]["this"] , 5u, 15u, "this");
_checkloc(seq[4]["this"]["really"] , 5u, 27u, "really");
_checkloc(seq[4]["nope"] , 5u, 47u, "nope");
_checkloc(seq[4]["nope"][0] , 5u, 56u, "a seq!");
_checkloc(seq[4]["nope"][1] , 5u, 64u, "{");
_checkloc(seq[4]["nope"][1]["had"] , 5u, 66u, "had");
_checkloc(seq[4]["nope"][1]["eehh"], 5u, 83u, "eehh");
_checkloc(seq[5] , 6u, 2u, "yep");
_checkloc(seq[6] , 7u, 2u, "it");
_checkloc(seq[7] , 8u, 2u, "was");
}
TEST(locations, grow_array)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree t = parse_in_arena(&parser, "myfile.yml", "docval");
_checkloc(t.rootref(), 0u, 0u, "docval");
t = parse_in_arena(&parser, "myfile.yml", "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\ndocval");
_checkloc(t.rootref(), 47u, 0u, "docval");
}
// do a test with a buffer size up to 30 lines to ensure hitting
// the binary search path
TEST(locations, small_array)
{
Tree t;
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"(---
foo: yes
bar:
- 1
- 2
baz:
- 1_
- 2_
- 3_
)";
parse_in_arena(&parser, "myfile.yml", yaml, &t);
ConstNodeRef stream = t.rootref();
ConstNodeRef map = t.docref(0);
ASSERT_TRUE(map.is_map());
ASSERT_TRUE(map.is_doc());
_checkloc(stream , 0u, 0u, "---");
_checkloc(map , 1u, 0u, "foo");
_checkloc(map["foo"] , 1u, 0u, "foo");
_checkloc(map["bar"] , 2u, 0u, "bar");
_checkloc(map["bar"][0], 3u, 4u, "1");
_checkloc(map["bar"][1], 4u, 4u, "2");
_checkloc(map["baz"] , 5u, 0u, "baz");
_checkloc(map["baz"][0], 6u, 6u, "1_");
_checkloc(map["baz"][1], 7u, 6u, "2_");
_checkloc(map["baz"][2], 8u, 10u, "3_");
}
// do a test with a buffer of at least 30 lines to ensure hitting
// the binary search path
TEST(locations, large_array)
{
Tree t;
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
csubstr yaml = R"(---
foo1: definitely # 1
bar1:
- 1
- 2
baz1:
- 1_
- 2_
- 3_
foo2: definitely # 12
bar2:
- 1
- 2
baz2:
- 1_
- 2_
- 3_
foo3: definitely # 23
bar3:
- 1
- 2
baz3:
- 1_
- 2_
- 3_
foo4: definitely # 34
bar4:
- 1
- 2
baz4:
- 1_
- 2_
- 3_
foo5: definitely # 45
bar5:
- 1
- 2
baz5:
- 1_
- 2_
- 3_
foo6: definitely # 56
bar6:
- 1
- 2
baz6:
- 1_
- 2_
- 3_
)";
parse_in_arena(&parser, "myfile.yml", yaml, &t);
ConstNodeRef map = t.docref(0);
ASSERT_TRUE(map.is_map());
ASSERT_TRUE(map.is_doc());
_checkloc(t.rootref() , 0u, 0u, "---");
_checkloc(map , 1u, 0u, "foo1");
_checkloc(map["foo1"] , 0u+1u, 0u, "foo1");
_checkloc(map["bar1"] , 0u+2u, 0u, "bar1");
_checkloc(map["bar1"][0], 0u+3u, 4u, "1");
_checkloc(map["bar1"][1], 0u+4u, 4u, "2");
_checkloc(map["baz1"] , 0u+5u, 0u, "baz");
_checkloc(map["baz1"][0], 0u+6u, 6u, "1_");
_checkloc(map["baz1"][1], 0u+7u, 6u, "2_");
_checkloc(map["baz1"][2], 0u+8u, 10u, "3_");
//
_checkloc(map["foo2"] , 11u+1u, 0u, "foo2");
_checkloc(map["bar2"] , 11u+2u, 0u, "bar2");
_checkloc(map["bar2"][0], 11u+3u, 4u, "1");
_checkloc(map["bar2"][1], 11u+4u, 4u, "2");
_checkloc(map["baz2"] , 11u+5u, 0u, "baz2");
_checkloc(map["baz2"][0], 11u+6u, 6u, "1_");
_checkloc(map["baz2"][1], 11u+7u, 6u, "2_");
_checkloc(map["baz2"][2], 11u+8u, 10u, "3_");
//
_checkloc(map["foo3"] , 22u+1u, 0u, "foo3");
_checkloc(map["bar3"] , 22u+2u, 0u, "bar3");
_checkloc(map["bar3"][0], 22u+3u, 4u, "1");
_checkloc(map["bar3"][1], 22u+4u, 4u, "2");
_checkloc(map["baz3"] , 22u+5u, 0u, "baz3");
_checkloc(map["baz3"][0], 22u+6u, 6u, "1_");
_checkloc(map["baz3"][1], 22u+7u, 6u, "2_");
_checkloc(map["baz3"][2], 22u+8u, 10u, "3_");
//
_checkloc(map["foo4"] , 33u+1u, 0u, "foo4");
_checkloc(map["bar4"] , 33u+2u, 0u, "bar4");
_checkloc(map["bar4"][0], 33u+3u, 4u, "1");
_checkloc(map["bar4"][1], 33u+4u, 4u, "2");
_checkloc(map["baz4"] , 33u+5u, 0u, "baz4");
_checkloc(map["baz4"][0], 33u+6u, 6u, "1_");
_checkloc(map["baz4"][1], 33u+7u, 6u, "2_");
_checkloc(map["baz4"][2], 33u+8u, 10u, "3_");
//
_checkloc(map["foo5"] , 44u+1u, 0u, "foo5");
_checkloc(map["bar5"] , 44u+2u, 0u, "bar5");
_checkloc(map["bar5"][0], 44u+3u, 4u, "1");
_checkloc(map["bar5"][1], 44u+4u, 4u, "2");
_checkloc(map["baz5"] , 44u+5u, 0u, "baz5");
_checkloc(map["baz5"][0], 44u+6u, 6u, "1_");
_checkloc(map["baz5"][1], 44u+7u, 6u, "2_");
_checkloc(map["baz5"][2], 44u+8u, 10u, "3_");
//
_checkloc(map["foo6"] , 55u+1u, 0u, "foo6");
_checkloc(map["bar6"] , 55u+2u, 0u, "bar6");
_checkloc(map["bar6"][0], 55u+3u, 4u, "1");
_checkloc(map["bar6"][1], 55u+4u, 4u, "2");
_checkloc(map["baz6"] , 55u+5u, 0u, "baz6");
_checkloc(map["baz6"][0], 55u+6u, 6u, "1_");
_checkloc(map["baz6"][1], 55u+7u, 6u, "2_");
_checkloc(map["baz6"][2], 55u+8u, 10u, "3_");
}
TEST(locations, issue260_0)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree tree = parse_in_arena(&parser, "source.yml", R"(Body:
- Id: 1
Name: Apple
Script: |
Line One
Line Two
- Id: 2
Name: Cat
Script: |
Line One
Line Two
- Id: 3
Name: Dog
Script: |
Line One
Line Two)");
EXPECT_EQ(tree["Body"][2]["Name"].val(), "Dog");
EXPECT_EQ(tree["Body"][2]["Name"].location(parser).line, 12u);
}
TEST(locations, issue260_1)
{
ParserOptions opts = ParserOptions().locations(true);
Parser::handler_type evt_handler = {};
Parser parser(&evt_handler, opts);
Tree tree = parse_in_arena(&parser, "source.yml", R"(Body: # 0
- Id: 1 # line 1
Name: Apple
- Id: 2 # line 3
Name: Cat
Script: |
Line One
Line Two
- Id: 3 # line 8
Name: Cat2
Script: >
Line One
Line Two
- Id: 4 # line 13
Name: Cat3
Script: "
Line One
Line Two"
- Id: 5 # line 18
Name: Cat4
Script: '
Line One
Line Two'
- Id: 5 # line 23
Name: Cat5
Script:
Line One
Line Two
- Id: 6 # line 28
Name: Dog
Script: |
Line One
Line Two)");
EXPECT_EQ(tree["Body"][0].location(parser).line, 1u);
EXPECT_EQ(tree["Body"][1].location(parser).line, 3u);
EXPECT_EQ(tree["Body"][2].location(parser).line, 8u);
EXPECT_EQ(tree["Body"][3].location(parser).line, 13u);
EXPECT_EQ(tree["Body"][4].location(parser).line, 18u);
EXPECT_EQ(tree["Body"][5].location(parser).line, 23u);
EXPECT_EQ(tree["Body"][6].location(parser).line, 28u);
EXPECT_EQ(tree["Body"][0]["Id"].location(parser).line, 1u);
EXPECT_EQ(tree["Body"][1]["Id"].location(parser).line, 3u);
EXPECT_EQ(tree["Body"][2]["Id"].location(parser).line, 8u);
EXPECT_EQ(tree["Body"][3]["Id"].location(parser).line, 13u);
EXPECT_EQ(tree["Body"][4]["Id"].location(parser).line, 18u);
EXPECT_EQ(tree["Body"][5]["Id"].location(parser).line, 23u);
EXPECT_EQ(tree["Body"][6]["Id"].location(parser).line, 28u);
EXPECT_EQ(tree["Body"][0]["Name"].location(parser).line, 1u+1u);
EXPECT_EQ(tree["Body"][1]["Name"].location(parser).line, 3u+1u);
EXPECT_EQ(tree["Body"][2]["Name"].location(parser).line, 8u+1u);
EXPECT_EQ(tree["Body"][3]["Name"].location(parser).line, 13u+1u);
EXPECT_EQ(tree["Body"][4]["Name"].location(parser).line, 18u+1u);
EXPECT_EQ(tree["Body"][5]["Name"].location(parser).line, 23u+1u);
EXPECT_EQ(tree["Body"][6]["Name"].location(parser).line, 28u+1u);
}
// The other test executables are written to contain the declarative-style
// YmlTestCases. This executable does not have any but the build setup
// assumes it does, and links with the test lib, which requires an existing
// get_case() function. So this is here to act as placeholder until (if?)
// proper test cases are added here. This was detected in #47 (thanks
// @cburgard).
Case const* get_case(csubstr)
{
return nullptr;
}
} // namespace yml
} // namespace c4