Emitter: improve coverage

This commit is contained in:
Joao Paulo Magalhaes
2025-10-21 02:29:52 +01:00
parent 07d02b925e
commit 9a77f9d7ae
7 changed files with 90 additions and 16 deletions

View File

@@ -4560,7 +4560,6 @@ void sample_style_flow_ml_indent()
{
// we will be using this helper throughout this function
auto tostr = [](ryml::ConstNodeRef n, ryml::EmitOptions opts) {
std::cout << "~~~" << ryml::emitrs_yaml<std::string>(n, opts) << "~~~\n";
return ryml::emitrs_yaml<std::string>(n, opts);
};
ryml::csubstr yaml = "{map: {seq: [0, 1, 2, 3, [40, 41]]}}";
@@ -4669,16 +4668,18 @@ void sample_style_flow_ml_filter()
{
const ryml::Tree tree = ryml::parse_in_arena(yaml);
CHECK(tree["map"].is_flow_ml()); // etc
// emitted yaml is exactly equal to parsed yaml:
CHECK(ryml::emitrs_yaml<std::string>(tree) == yaml);
}
// if you prefer to shorten the emitted yaml, you can set the
// parser to use singleline flow (FLOW_SL):
// parser to set singleline flow (FLOW_SL) on all flow containers:
{
const ryml::ParserOptions opts = ryml::ParserOptions{}.detect_flow_ml(false);
const ryml::Tree tree = ryml::parse_in_arena(yaml, opts);
CHECK(tree["map"].is_flow_sl()); // etc
// notice how this is smaller
CHECK(ryml::emitrs_yaml<std::string>(tree) == R"({map: {seq: [0,1,2,3,[40,41]]}})");
// notice how this is smaller now:
CHECK(ryml::emitrs_yaml<std::string>(tree) ==
R"({map: {seq: [0,1,2,3,[40,41]]}})");
}
// you can also keep FLOW_ML, but control its indentation:
// (see more details in @ref sample_style_flow_ml_indent())
@@ -4686,7 +4687,8 @@ void sample_style_flow_ml_filter()
const ryml::EmitOptions noindent = ryml::EmitOptions{}.indent_flow_ml(false);
const ryml::Tree tree = ryml::parse_in_arena(yaml);
CHECK(tree["map"].is_flow_ml()); // etc
CHECK(ryml::emitrs_yaml<std::string>(tree, noindent) == R"({
CHECK(ryml::emitrs_yaml<std::string>(tree, noindent) ==
R"({
map: {
seq: [
0,

View File

@@ -133,7 +133,7 @@ inline C4_NO_INLINE id_type print_node(Tree const& p, id_type node, int level, i
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline void print_node(ConstNodeRef const& p, int level=0, bool print_address=false)
inline void print_node(ConstNodeRef const& p, int level=0, bool print_address=false) // LCOV_EXCL_LINE
{
print_node(*p.tree(), p.id(), level, 0, true, print_address); // LCOV_EXCL_LINE
}

View File

@@ -127,7 +127,7 @@ ryml_add_test_case_group(scalar_dquoted)
ryml_add_test_case_group(scalar_literal)
ryml_add_test_case_group(scalar_folded)
ryml_add_test_case_group(scalar_plain)
ryml_add_test_case_group(tag_property)
ryml_add_test_case_group(tag)
ryml_add_test_case_group(explicit_key)
ryml_add_test_case_group(map_nestedx2)
ryml_add_test_case_group(seq_nestedx2)

View File

@@ -859,6 +859,25 @@ k2:
}
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));
});
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

View File

@@ -232,6 +232,32 @@ TEST(emit_nested, basic)
)");
}
TEST(emit_block_seq, ambiguous_plain_emitted_as_squo)
{
Tree t;
NodeRef r = t.rootref();
r |= SEQ|BLOCK;
r[0] = ": odd";
r[0] |= VAL_PLAIN;
r[1] = ":\todd";
r[1] |= VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), "- ': odd'\n- ':\todd'\n");
}
TEST(emit_block_map, ambiguous_plain_emitted_as_squo)
{
Tree t;
NodeRef r = t.rootref();
r |= MAP|BLOCK;
r[0].set_key(": odd");
r[0] = ": odd";
r[0] |= KEY_PLAIN|VAL_PLAIN;
r[1].set_key(":\todd");
r[1] = ":\todd";
r[1] |= KEY_PLAIN|VAL_PLAIN;
EXPECT_EQ(emitrs_yaml<std::string>(t), "': odd': ': odd'\n':\todd': ':\todd'\n");
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

View File

@@ -616,32 +616,41 @@ TEST(parse_in_arena, error_without_handler)
TEST(parse_flow_ml, respects_parser_options)
{
csubstr yaml = R"({
std::string yaml = R"({
foo: 0,
bar: 1,
map: {
hell: yeah
},
seq: [
hell, yeah
hell,
yeah
]
})";
}
)";
const ParserOptions defaults = ParserOptions{};
const ParserOptions flow_ml = ParserOptions{}.detect_flow_ml(true);
const ParserOptions no_flow_ml = ParserOptions{}.detect_flow_ml(false);
{
SCOPED_TRACE("default behavior: detect flow_ml");
test_check_emit_check_with_parser(yaml, defaults, [](const Tree& t, Parser const&){
EXPECT_TRUE(t.rootref().is_flow_ml());
EXPECT_TRUE(t["map"].is_flow_ml());
EXPECT_TRUE(t["seq"].is_flow_ml());
});
for(ParserOptions opts : {defaults, flow_ml})
{
test_check_emit_check_with_parser(to_csubstr(yaml), opts, [&](const Tree& t, Parser const&){
EXPECT_TRUE(t.rootref().is_flow_ml());
EXPECT_TRUE(t["map"].is_flow_ml());
EXPECT_TRUE(t["seq"].is_flow_ml());
EXPECT_EQ(emitrs_yaml<std::string>(t), yaml);
});
}
}
{
SCOPED_TRACE("custom behavior: do not detect flow_ml");
test_check_emit_check_with_parser(yaml, no_flow_ml, [](const Tree& t, Parser const&){
test_check_emit_check_with_parser(to_csubstr(yaml), no_flow_ml, [](const Tree& t, Parser const&){
EXPECT_FALSE(t.rootref().is_flow_ml());
EXPECT_FALSE(t["map"].is_flow_ml());
EXPECT_FALSE(t["seq"].is_flow_ml());
EXPECT_EQ(emitrs_yaml<std::string>(t),
"{foo: 0,bar: 1,map: {hell: yeah},seq: [hell,yeah]}");
});
}
}

View File

@@ -1070,6 +1070,24 @@ TEST(tags, ys0)
});
}
TEST(tags, key_tag_error_json)
{
Tree tree = parse_in_arena("{!!str 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_TAG));
});
}
TEST(tags, val_tag_error_json)
{
Tree tree = parse_in_arena("{key: !!str 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_TAG));
});
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------