#ifdef RYML_SINGLE_HEADER
#include "ryml_all.hpp"
#else
#include "c4/yml/event_handler_tree.hpp"
#include "c4/yml/parse_engine.hpp"
#include "c4/yml/parse.hpp"
#include "c4/yml/node.hpp"
#endif
#include <gtest/gtest.h>
#include "./test_lib/callbacks_tester.hpp"
#include "./test_lib/test_case.hpp"


RYML_DEFINE_TEST_MAIN()

namespace c4 {
namespace yml {

C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wold-style-cast")

// undefined below
#define testlc(lc, buf, offs, begins_with_, rem_, full_) \
    {                                                               \
        RYML_TRACE_FMT("offs={}", offs);                            \
        substr sub = buf.sub(offs);                                 \
        EXPECT_TRUE(sub.begins_with(begins_with_)) << buf.sub(offs); \
        lc.reset_with_next_line(buf, offs);                         \
        EXPECT_EQ(lc.rem, csubstr(rem_));                           \
        EXPECT_EQ(lc.full, csubstr(full_));                         \
    }

TEST(LineContents, basic)
{
    char buf_[] =
        "line 0\n"
        "line 1\n"
        "\n"
        "line 3\n"
        "      \n"
        "line 5\n"
        ;
    substr buf = buf_;
    LineContents lc;
    //
    testlc(lc, buf, 0, "line 0\n", "line 0", "line 0\n");
    testlc(lc, buf, 1, "ine 0\n", "ine 0", "ine 0\n");
    testlc(lc, buf, 5, "0\n", "0", "0\n");
    testlc(lc, buf, 6, "\nline 1", "", "\n");
    testlc(lc, buf, 7, "line 1", "line 1", "line 1\n");
    testlc(lc, buf, 12, "1", "1", "1\n");
    testlc(lc, buf, 13, "\n", "", "\n");
    testlc(lc, buf, 14, "\n", "", "\n");
    testlc(lc, buf, 15, "line 3\n", "line 3", "line 3\n");
    testlc(lc, buf, 20, "3\n", "3", "3\n");
    testlc(lc, buf, 21, "\n", "", "\n");
    testlc(lc, buf, 22, "      \n", "      ", "      \n");
    testlc(lc, buf, 28, "\n", "", "\n");
    testlc(lc, buf, 29, "line 5\n", "line 5", "line 5\n");
    testlc(lc, buf, 34, "5\n", "5", "5\n");
    testlc(lc, buf, 35, "\n", "", "\n");
    testlc(lc, buf, 36, "", "", "");
}


TEST(LineContents, with_carriage_return_1)
{
    char buf_[] =
        "line 0\r\n"
        "line 1\r\n"
        "\r\n"
        "line 3\r\n"
        "      \r\n"
        "line 5\r\n"
        ;
    substr buf = buf_;
    LineContents lc;
    //
    testlc(lc, buf,  0, "line 0\r\n", "line 0", "line 0\r\n");
    testlc(lc, buf,  1, "ine 0\r\n" , "ine 0" , "ine 0\r\n");
    testlc(lc, buf,  5, "0\r\n"     , "0"     , "0\r\n");
    testlc(lc, buf,  6, "\r\nline 1", ""      , "\r\n");
    testlc(lc, buf,  7, "\nline 1"  , ""      , "\n");
    testlc(lc, buf,  8, "line 1"    , "line 1", "line 1\r\n");
    testlc(lc, buf, 13, "1"         , "1"     , "1\r\n");
    testlc(lc, buf, 14, "\r\n"      , ""      , "\r\n");
    testlc(lc, buf, 15, "\n"        , ""      , "\n");
    testlc(lc, buf, 16, "\r\n"      , ""      , "\r\n");
    testlc(lc, buf, 17, "\n"        , ""      , "\n");
    testlc(lc, buf, 18, "line 3\r\n", "line 3", "line 3\r\n");
    testlc(lc, buf, 23, "3\r\n"     , "3"     , "3\r\n");
    testlc(lc, buf, 24, "\r\n"      , ""      , "\r\n");
    testlc(lc, buf, 25, "\n"        , ""      , "\n");
    testlc(lc, buf, 26, "      \r\n", "      ", "      \r\n");
    testlc(lc, buf, 32, "\r\n"      , ""      , "\r\n");
    testlc(lc, buf, 33, "\n"        , ""      , "\n");
    testlc(lc, buf, 34, "line 5\r\n", "line 5", "line 5\r\n");
    testlc(lc, buf, 39, "5\r\n"     , "5"     , "5\r\n");
    testlc(lc, buf, 40, "\r\n"      , ""      , "\r\n");
    testlc(lc, buf, 41, "\n"        , ""      , "\n");
    testlc(lc, buf, 42, ""          , ""      , "");
}


TEST(LineContents, with_carriage_return_2)
{
    char buf_[] =
        "line 0\r\r\n"
        "line 1\r\r\n"
        "\r\r\n"
        "line 3\r\r\n"
        "      \r\r\n"
        "line 5\r\r\n"
        ;
    substr buf = buf_;
    LineContents lc;
    //
    testlc(lc, buf,  0, "line 0\r\r\n", "line 0", "line 0\r\r\n");
    testlc(lc, buf,  1, "ine 0\r\r\n" , "ine 0" , "ine 0\r\r\n");
    testlc(lc, buf,  5, "0\r\r\n"     , "0"     , "0\r\r\n");
    testlc(lc, buf,  6, "\r\r\nline 1", ""      , "\r\r\n");
    testlc(lc, buf,  7, "\r\nline 1"  , ""      , "\r\n");
    testlc(lc, buf,  8, "\nline 1"    , ""      , "\n");
    testlc(lc, buf,  9, "line 1"      , "line 1", "line 1\r\r\n");
    testlc(lc, buf, 14, "1"           , "1"     , "1\r\r\n");
    testlc(lc, buf, 15, "\r\r\n"      , ""      , "\r\r\n");
    testlc(lc, buf, 16, "\r\n"        , ""      , "\r\n");
    testlc(lc, buf, 17, "\n"          , ""      , "\n");
    testlc(lc, buf, 18, "\r\r\n"      , ""      , "\r\r\n");
    testlc(lc, buf, 19, "\r\n"        , ""      , "\r\n");
    testlc(lc, buf, 20, "\n"          , ""      , "\n");
    testlc(lc, buf, 21, "line 3\r\r\n", "line 3", "line 3\r\r\n");
    testlc(lc, buf, 26, "3\r\r\n"     , "3"     , "3\r\r\n");
    testlc(lc, buf, 27, "\r\r\n"      , ""      , "\r\r\n");
    testlc(lc, buf, 28, "\r\n"        , ""      , "\r\n");
    testlc(lc, buf, 29, "\n"          , ""      , "\n");
    testlc(lc, buf, 30, "      \r\r\n", "      ", "      \r\r\n");
    testlc(lc, buf, 36, "\r\r\n"      , ""      , "\r\r\n");
    testlc(lc, buf, 37, "\r\n"        , ""      , "\r\n");
    testlc(lc, buf, 38, "\n"          , ""      , "\n");
    testlc(lc, buf, 39, "line 5\r\r\n", "line 5", "line 5\r\r\n");
    testlc(lc, buf, 44, "5\r\r\n"     , "5"     , "5\r\r\n");
    testlc(lc, buf, 45, "\r\r\n"      , ""      , "\r\r\n");
    testlc(lc, buf, 46, "\r\n"        , ""      , "\r\n");
    testlc(lc, buf, 47, "\n"          , ""      , "\n");
    testlc(lc, buf, 48, ""            , ""      , "");
}


TEST(LineContents, with_carriage_return_3)
{
    char buf_[] =
        "line 0\r\r\r\n"
        "line 1\r\r\r\n"
        "\r\r\r\n"
        "line 3\r\r\r\n"
        "      \r\r\r\n"
        "line 5\r\r\r\n"
        ;
    substr buf = buf_;
    LineContents lc;
    //
    testlc(lc, buf,  0, "line 0\r\r\r\n", "line 0", "line 0\r\r\r\n");
    testlc(lc, buf,  1, "ine 0\r\r\r\n" , "ine 0" , "ine 0\r\r\r\n");
    testlc(lc, buf,  5, "0\r\r\r\n"     , "0"     , "0\r\r\r\n");
    testlc(lc, buf,  6, "\r\r\r\nline 1", ""      , "\r\r\r\n");
    testlc(lc, buf,  7, "\r\r\nline 1"  , ""      , "\r\r\n");
    testlc(lc, buf,  8, "\r\nline 1"    , ""      , "\r\n");
    testlc(lc, buf,  9, "\nline 1"      , ""      , "\n");
    testlc(lc, buf, 10, "line 1"        , "line 1", "line 1\r\r\r\n");
    testlc(lc, buf, 15, "1"             , "1"     , "1\r\r\r\n");
    testlc(lc, buf, 16, "\r\r\r\n"      , ""      , "\r\r\r\n");
    testlc(lc, buf, 17, "\r\r\n"        , ""      , "\r\r\n");
    testlc(lc, buf, 18, "\r\n"          , ""      , "\r\n");
    testlc(lc, buf, 19, "\n"            , ""      , "\n");
    testlc(lc, buf, 20, "\r\r\r\n"      , ""      , "\r\r\r\n");
    testlc(lc, buf, 21, "\r\r\n"        , ""      , "\r\r\n");
    testlc(lc, buf, 22, "\r\n"          , ""      , "\r\n");
    testlc(lc, buf, 23, "\n"            , ""      , "\n");
    testlc(lc, buf, 24, "line 3\r\r\r\n", "line 3", "line 3\r\r\r\n");
    testlc(lc, buf, 29, "3\r\r\r\n"     , "3"     , "3\r\r\r\n");
    testlc(lc, buf, 30, "\r\r\r\n"      , ""      , "\r\r\r\n");
    testlc(lc, buf, 31, "\r\r\n"        , ""      , "\r\r\n");
    testlc(lc, buf, 32, "\r\n"          , ""      , "\r\n");
    testlc(lc, buf, 33, "\n"            , ""      , "\n");
    testlc(lc, buf, 34, "      \r\r\r\n", "      ", "      \r\r\r\n");
    testlc(lc, buf, 40, "\r\r\r\n"      , ""      , "\r\r\r\n");
    testlc(lc, buf, 41, "\r\r\n"        , ""      , "\r\r\n");
    testlc(lc, buf, 42, "\r\n"          , ""      , "\r\n");
    testlc(lc, buf, 43, "\n"            , ""      , "\n");
    testlc(lc, buf, 44, "line 5\r\r\r\n", "line 5", "line 5\r\r\r\n");
    testlc(lc, buf, 49, "5\r\r\r\n"     , "5"     , "5\r\r\r\n");
    testlc(lc, buf, 50, "\r\r\r\n"      , ""      , "\r\r\r\n");
    testlc(lc, buf, 51, "\r\r\n"        , ""      , "\r\r\n");
    testlc(lc, buf, 52, "\r\n"          , ""      , "\r\n");
    testlc(lc, buf, 53, "\n"            , ""      , "\n");
    testlc(lc, buf, 54, ""              , ""      , "");
}

#undef testlc


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

// TODO: add this as a method to csubstr
bool is_same(csubstr lhs, csubstr rhs)
{
    return lhs.str == rhs.str && lhs.len == rhs.len;
}

void mklarge(Parser *p, Callbacks const& cb)
{
    ASSERT_TRUE(p->m_evt_handler);
    Parser::handler_type *evt_handler = p->m_evt_handler;
    p->~Parser();
    if(&cb != &evt_handler->m_stack.m_callbacks)
        evt_handler->m_stack.m_callbacks = cb;
    new ((void*)p) Parser(evt_handler, p->options());
    p->reserve_stack(20); // cause an allocation
    p->reserve_locations(128); // cause an allocation
    EXPECT_GE(p->stack_capacity(), 20);
    EXPECT_GE(p->locations_capacity(), 128);
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

TEST(Parser, empty_ctor)
{
    Parser::handler_type evt_handler = {};
    EXPECT_EQ(evt_handler.m_stack.m_callbacks, get_callbacks());
    Parser parser(&evt_handler);
    EXPECT_EQ(parser.callbacks(), get_callbacks());
}

TEST(Parser, callbacks_ctor)
{
    CallbacksTester cbt;
    {
        Parser::handler_type evt_handler = {cbt.callbacks()};
        Parser parser(&evt_handler);
        EXPECT_EQ(parser.callbacks(), cbt.callbacks());
    }
    EXPECT_EQ(cbt.num_allocs, 0u);
    EXPECT_EQ(cbt.num_deallocs, 0u);
}

TEST(Parser, reserve_stack)
{
    CallbacksTester cbt("test", 30000/*Bytes*/);
    {
        Parser::handler_type evt_handler = {cbt.callbacks()};
        using Stack = detail::stack<EventHandlerTreeState>;
        Stack const& stack = evt_handler.m_stack;
        enum : id_type { sso_size = Stack::sso_size }; // NOLINT
        Parser parser(&evt_handler);
        for(id_type cap = 0; cap <= sso_size; ++cap)
        {
            SCOPED_TRACE(cap);
            parser.reserve_stack(cap);
            EXPECT_EQ(cbt.num_allocs, 0u);
            EXPECT_EQ(cbt.num_deallocs, 0u);
            EXPECT_EQ(stack.capacity(), sso_size);
        }
        for(id_type cap = sso_size + 1; cap <= 2u * sso_size; ++cap)
        {
            SCOPED_TRACE(cap);
            parser.reserve_stack(cap);
            EXPECT_GE(parser.stack_capacity(), cap);
            EXPECT_EQ(parser.stack_capacity(), sso_size * 2u);
            EXPECT_EQ(cbt.num_allocs, 1u);
            EXPECT_EQ(cbt.num_deallocs, 0u);
        }
        for(id_type cap = (2u * sso_size) + 1u; cap < 4u * sso_size; ++cap)
        {
            SCOPED_TRACE(cap);
            parser.reserve_stack(cap);
            EXPECT_GE(parser.stack_capacity(), cap);
            EXPECT_EQ(parser.stack_capacity(), sso_size * 4u);
            EXPECT_EQ(cbt.num_allocs, 2u);
            EXPECT_EQ(cbt.num_deallocs, 1u);
        }
        for(id_type cap = 0; cap < 4u * sso_size; ++cap)
        {
            SCOPED_TRACE(cap);
            parser.reserve_stack(cap);
            EXPECT_EQ(stack.capacity(), sso_size * 4u);
            EXPECT_EQ(cbt.num_allocs, 2u);
            EXPECT_EQ(cbt.num_deallocs, 1u);
        }
    }
    EXPECT_EQ(cbt.num_allocs, 2u);
    EXPECT_EQ(cbt.num_deallocs, 2u);
    cbt.check();
}

TEST(Parser, reserve_locations)
{
    CallbacksTester ts;
    {
        Parser::handler_type evt_handler = {ts.callbacks()};
        Parser parser(&evt_handler);
        EXPECT_EQ(parser.callbacks(), ts.callbacks());
        EXPECT_EQ(ts.num_allocs, 0u);
        EXPECT_EQ(ts.num_deallocs, 0u);
        parser.reserve_locations(128);
        EXPECT_GE(parser.locations_capacity(), 128);
        EXPECT_EQ(ts.num_allocs, 1u);
        EXPECT_EQ(ts.num_deallocs, 0u);
        EXPECT_EQ(ts.alloc_size, 128u * sizeof(size_t));
        EXPECT_EQ(ts.dealloc_size, 0u);
    }
    EXPECT_EQ(ts.num_allocs, 1u);
    EXPECT_EQ(ts.num_deallocs, 1u);
    EXPECT_EQ(ts.alloc_size, 128u * sizeof(size_t));
    EXPECT_EQ(ts.dealloc_size, 128u * sizeof(size_t));
}

TEST(Parser, copy_ctor_0)
{
    Parser::handler_type evt_handler = {};
    EXPECT_EQ(evt_handler.m_stack.m_callbacks, get_callbacks());
    Parser src(&evt_handler);
    mklarge(&src, evt_handler.m_stack.m_callbacks);
    EXPECT_EQ(src.callbacks(), get_callbacks());
    Parser dst(src);
    EXPECT_EQ(src.callbacks(), get_callbacks());
    EXPECT_EQ(dst.callbacks(), get_callbacks());
}

TEST(Parser, copy_ctor_1)
{
    CallbacksTester ts;
    {
        Parser::handler_type evt_handler = {ts.callbacks()};
        Parser src(&evt_handler);
        mklarge(&src, evt_handler.m_stack.m_callbacks);
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        Parser dst(src);
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_GT(ts.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
}

TEST(Parser, move_ctor_0)
{
    Parser::handler_type evt_handler = {};
    Parser src(&evt_handler);
    mklarge(&src, evt_handler.m_stack.m_callbacks);
    EXPECT_EQ(src.callbacks(), get_callbacks());
    Parser dst(std::move(src));
    //EXPECT_EQ(src.callbacks(), get_callbacks());
    EXPECT_EQ(dst.callbacks(), get_callbacks());
}
TEST(Parser, move_ctor_1)
{
    CallbacksTester ts;
    {
        Parser::handler_type evt_handler = {ts.callbacks()};
        Parser src(&evt_handler);
        mklarge(&src, evt_handler.m_stack.m_callbacks);
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        Parser dst(std::move(src));
        //ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_EQ(ts.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
}

TEST(Parser, copy_assign_same_callbacks)
{
    CallbacksTester ts;
    {
        Parser::handler_type evt_handler_src = {ts.callbacks()};
        Parser::handler_type evt_handler_dst = {ts.callbacks()};
        Parser src(&evt_handler_src);
        Parser dst(&evt_handler_dst);
        mklarge(&src, ts.callbacks());
        mklarge(&dst, ts.callbacks());
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        EXPECT_GT(ts.num_allocs, 0u);
        dst = src;
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_GT(ts.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
}

TEST(Parser, copy_assign_diff_callbacks)
{
    CallbacksTester ts("src");
    CallbacksTester td("dst");
    {
        Parser::handler_type evt_handler_src = {ts.callbacks()};
        Parser::handler_type evt_handler_dst = {td.callbacks()};
        Parser src(&evt_handler_src);
        Parser dst(&evt_handler_dst);
        mklarge(&src, ts.callbacks());
        mklarge(&dst, td.callbacks());
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), td.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        EXPECT_GT(td.num_allocs, 0u);
        dst = src;
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_GT(ts.num_allocs, nbefore);
        EXPECT_EQ(td.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
    EXPECT_EQ(td.num_allocs, td.num_deallocs);
    EXPECT_EQ(td.alloc_size, td.dealloc_size);
}

TEST(Parser, move_assign_same_callbacks)
{
    CallbacksTester ts;
    {
        Parser::handler_type evt_handler_src = {ts.callbacks()};
        Parser::handler_type evt_handler_dst = {ts.callbacks()};
        Parser src(&evt_handler_src);
        Parser dst(&evt_handler_dst);
        mklarge(&src, ts.callbacks());
        mklarge(&dst, ts.callbacks());
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        EXPECT_GT(ts.num_allocs, 0u);
        dst = std::move(src);
        //ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_EQ(ts.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
}

TEST(Parser, move_assign_diff_callbacks)
{
    CallbacksTester ts("src");
    CallbacksTester td("dst");
    {
        Parser::handler_type evt_handler_src = {ts.callbacks()};
        Parser::handler_type evt_handler_dst = {td.callbacks()};
        Parser src(&evt_handler_src);
        Parser dst(&evt_handler_dst);
        mklarge(&src, ts.callbacks());
        mklarge(&dst, td.callbacks());
        ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), td.callbacks());
        size_t nbefore = ts.num_allocs;
        EXPECT_GT(ts.num_allocs, 0u);
        EXPECT_GT(td.num_allocs, 0u);
        dst = std::move(src);
        //ASSERT_EQ(src.callbacks(), ts.callbacks());
        ASSERT_EQ(dst.callbacks(), ts.callbacks());
        EXPECT_EQ(ts.num_allocs, nbefore);
        EXPECT_EQ(ts.num_allocs, nbefore);
    }
    EXPECT_EQ(ts.num_allocs, ts.num_deallocs);
    EXPECT_EQ(ts.alloc_size, ts.dealloc_size);
    EXPECT_EQ(td.num_allocs, td.num_deallocs);
    EXPECT_EQ(td.alloc_size, td.dealloc_size);
}

TEST(Parser, new_tree_receives_callbacks)
{
    char src_[] = "{a: b}";
    substr src = src_;
    csubstr csrc = src_;
    {
        {
            Parser::handler_type evt_handler = {};
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), get_callbacks());
            Tree t = parse_in_arena(&parser, "file0", csrc);
            EXPECT_EQ(t.callbacks(), get_callbacks());
        }
        CallbacksTester cbt("test", 20000/*Bytes*/);
        {
            Parser::handler_type evt_handler = {cbt.callbacks()};
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), cbt.callbacks());
            Tree t = parse_in_arena(&parser, "file1", csrc);
            EXPECT_EQ(t.callbacks(), cbt.callbacks());
        }
        cbt.check();
    }
    {
        {
            Parser::handler_type evt_handler = {};
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), get_callbacks());
            Tree t = parse_in_place(&parser, "file", src);
            EXPECT_EQ(t.callbacks(), get_callbacks());
        }
        CallbacksTester cbt("test", 20000/*Bytes*/);
        {
            Parser::handler_type evt_handler = {cbt.callbacks()};
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), cbt.callbacks());
            Tree t = parse_in_place(&parser, "file", src);
            EXPECT_EQ(t.callbacks(), cbt.callbacks());
        }
        cbt.check();
    }
}

TEST(Parser, existing_tree_overwrites_parser_callbacks)
{
    char src_[] = "{a: b}";
    substr src = src_;
    csubstr csrc = src_;
    {
        CallbacksTester cbp("parser");
        CallbacksTester cbt("tree");
        {
            Tree tree(cbt.callbacks());
            EXPECT_EQ(tree.callbacks(), cbt.callbacks());
            Parser::handler_type evt_handler(cbp.callbacks());
            EXPECT_EQ(evt_handler.m_stack.m_callbacks, cbp.callbacks());
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), cbp.callbacks());
            parse_in_arena(&parser, "file", csrc, &tree);
            EXPECT_EQ(tree.callbacks(), cbt.callbacks());
            EXPECT_EQ(parser.callbacks(), cbp.callbacks());
        }
        cbp.check();
        cbt.check();
    }
    {
        CallbacksTester cbp("parser");
        CallbacksTester cbt("tree");
        {
            Tree tree(cbt.callbacks());
            EXPECT_EQ(tree.callbacks(), cbt.callbacks());
            Parser::handler_type evt_handler(cbp.callbacks());
            Parser parser(&evt_handler);
            EXPECT_EQ(parser.callbacks(), cbp.callbacks());
            parse_in_place(&parser, "file", src, &tree);
            EXPECT_EQ(tree.callbacks(), cbt.callbacks());
            EXPECT_EQ(parser.callbacks(), cbp.callbacks());
        }
        cbp.check();
        cbt.check();
    }
}

TEST(Parser, filename_and_buffer_are_stored)
{
    char src_[] = "{a: b}";
    substr src = src_;
    csubstr csrc = src_;
    Parser::handler_type evt_handler = {};
    Parser parser(&evt_handler);
    EXPECT_NE(parser.m_evt_handler, nullptr);
    EXPECT_EQ(parser.m_evt_handler->m_curr, nullptr);
    EXPECT_EQ(parser.filename().str, nullptr);
    EXPECT_EQ(parser.filename().len, 0);
    EXPECT_EQ(parser.source().str, nullptr);
    EXPECT_EQ(parser.source().len, 0);
    {
        Tree tree = parse_in_place(&parser, "file0", src);
        EXPECT_EQ(parser.filename(), "file0");
        EXPECT_NE(parser.m_evt_handler, nullptr);
        EXPECT_NE(parser.m_evt_handler->m_curr, nullptr);
        EXPECT_EQ(parser.source().str, src.str);
        EXPECT_EQ(parser.source().len, src.len);
    }
    {
        Tree tree = parse_in_arena(&parser, "file1", csrc);
        EXPECT_EQ(parser.filename(), "file1");
        EXPECT_TRUE(!is_same(parser.source(), src));
    }
    {
        Tree tree = parse_in_place(&parser, "file2", src);
        EXPECT_EQ(parser.filename(), "file2");
        EXPECT_TRUE(is_same(parser.source(), src));
    }
    {
        Tree tree = parse_in_arena(&parser, csrc);
        EXPECT_EQ(parser.filename(), csubstr{});
        EXPECT_TRUE(!is_same(parser.source(), src));
    }
}

TEST(Parser, estimate_tree_capacity)
{
    EXPECT_EQ(2, estimate_tree_capacity(R"([])"));
    EXPECT_EQ(2, estimate_tree_capacity(R"([a])"));
    EXPECT_EQ(3, estimate_tree_capacity(R"([a, b])"));
    EXPECT_EQ(4, estimate_tree_capacity(R"([a, b, c])"));
    EXPECT_EQ(5, estimate_tree_capacity(R"([a, b, c, d])"));
    EXPECT_EQ(2, estimate_tree_capacity(R"({})"));
    EXPECT_EQ(2, estimate_tree_capacity(R"({a: 0})"));
    EXPECT_EQ(3, estimate_tree_capacity(R"({a: 0, b: 1})"));
    EXPECT_EQ(4, estimate_tree_capacity(R"({a: 0, b: 1, c: 2})"));
    EXPECT_EQ(5, estimate_tree_capacity(R"({a: 0, b: 1, c: 2, d: 3})"));
    EXPECT_EQ(9, estimate_tree_capacity(R"(- {a: 0, b: 1, c: 2, d: 3}
- a
- b
- c
)"));
}

TEST(Parser, alloc_arena)
{
    Tree tree;
    Parser::handler_type evt_handler = {};
    Parser parser(&evt_handler);
    evt_handler.reset(&tree, tree.root_id());
    evt_handler.start_parse("filename", substr{});
    substr bufa = evt_handler.alloc_arena(64);
    bufa.fill('a');
    csubstr prev = bufa;
    csubstr prev_arena = tree.arena();
    substr bufb = parser._alloc_arena(64, &bufa);
    csubstr curr_arena = tree.arena();
    EXPECT_NE(prev_arena.str, curr_arena.str);
    EXPECT_NE(prev.str, bufa.str);
    EXPECT_EQ(bufa.first_not_of('a'), npos);
    (void)bufb;
}

TEST(parse_in_place, overloads)
{
    char src1_[] = "{a: b}";
    char src2_[] = "{c: d, e: {}}";
    {
        Tree tree = parse_in_place(src1_);
        EXPECT_EQ(tree["a"].val(), "b");
    }
    {
        Tree tree = parse_in_place("src1", src1_);
        EXPECT_EQ(tree["a"].val(), "b");
    }
    {
        Tree tree;
        parse_in_place(src1_, &tree);
        EXPECT_EQ(tree["a"].val(), "b");
    }
    {
        Tree tree;
        parse_in_place("src1", src1_, &tree);
        EXPECT_EQ(tree["a"].val(), "b");
    }
    {
        Tree tree = parse_in_place(src2_);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        id_type e = tree.find_child(tree.root_id(), "e");
        ASSERT_NE(e, (id_type)NONE);
        parse_in_place(src1_, &tree, e);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
    }
    {
        Tree tree = parse_in_place("src2", src2_);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        id_type e = tree.find_child(tree.root_id(), "e");
        ASSERT_NE(e, (id_type)NONE);
        parse_in_place("src1", src1_, &tree, e);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
    }
    {
        Tree tree = parse_in_place(src2_);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        parse_in_place(src1_, tree["e"]);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
    }
    {
        Tree tree = parse_in_place("src2", src2_);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        parse_in_place("src1", src1_, tree["e"]);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
    }
}

TEST(parse_in_arena, overloads)
{
    csubstr src1 = "{a: b}";
    csubstr src2 = "{c: d, e: {}}";
    {
        Tree tree = parse_in_arena(src1);
        EXPECT_EQ(tree["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
    }
    {
        Tree tree = parse_in_arena("src1", src1);
        EXPECT_EQ(tree["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
    }
    {
        Tree tree;
        parse_in_arena(src1, &tree);
        EXPECT_EQ(tree["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
    }
    {
        Tree tree;
        parse_in_arena("src1", src1, &tree);
        EXPECT_EQ(tree["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
    }
    {
        Tree tree = parse_in_arena(src2);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src2), npos);
        id_type e = tree.find_child(tree.root_id(), "e");
        ASSERT_NE(e, (id_type)NONE);
        parse_in_arena(src1, &tree, e);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
        EXPECT_NE(tree.arena().find(src2), npos);
    }
    {
        Tree tree = parse_in_arena("src2", src2);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src2), npos);
        id_type e = tree.find_child(tree.root_id(), "e");
        ASSERT_NE(e, (id_type)NONE);
        parse_in_arena("src1", src1, &tree, e);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
        EXPECT_NE(tree.arena().find(src2), npos);
    }
    {
        Tree tree = parse_in_arena(src2);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src2), npos);
        parse_in_arena(src1, tree["e"]);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
        EXPECT_NE(tree.arena().find(src2), npos);
    }
    {
        Tree tree = parse_in_arena("src2", src2);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].is_map(), true);
        EXPECT_EQ(tree["e"].has_children(), false);
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src2), npos);
        parse_in_arena("src1", src1, tree["e"]);
        EXPECT_EQ(tree["c"].val(), "d");
        EXPECT_EQ(tree["e"].has_children(), true);
        EXPECT_EQ(tree["e"]["a"].val(), "b");
        EXPECT_FALSE(tree.arena().empty());
        EXPECT_NE(tree.arena().find(src1), npos);
        EXPECT_NE(tree.arena().find(src2), npos);
    }
}

TEST(Parser, error_without_handler)
{
    ExpectError::check_error_basic([]{
        Parser parser{nullptr};
    });
}

TEST(parse_in_place, error_without_handler)
{
    ExpectError::check_error_basic([]{
        EventHandlerTree evth;
        Parser parser{&evth};
        parser.m_evt_handler = nullptr;
        char yaml[] = "{foo: bar}";
        Tree t = parse_in_place(&parser, yaml);
    });
}

TEST(parse_in_arena, error_without_handler)
{
    ExpectError::check_error_basic([]{
        EventHandlerTree evth;
        Parser parser{&evth};
        parser.m_evt_handler = nullptr;
        const char yaml[] = "{foo: bar}";
        Tree t = parse_in_arena(&parser, yaml);
    });
}

TEST(parse_flow_ml, respects_parser_options)
{
    std::string yaml = R"({
  foo: 0,
  bar: 1,
  map: {
    hell: yeah
  },
  seq: [
    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");
        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(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]}");
        });
    }
}


//-----------------------------------------------------------------------------

class ParseOverloadYamlTest : public testing::Test
{
protected:

    Tree ref;
    std::string yaml_ = "{this: is, a: [yaml, example]}";
    substr yaml = to_substr(yaml_);
    csubstr cyaml = to_csubstr(yaml_);
    csubstr filename = "example.yml";

    EventHandlerTree evt_handler;
    Parser parser = {&evt_handler};

    void SetUp() override
    {
        NodeRef root = ref.rootref();
        root |= MAP;
        root |= FLOW_SL;
        NodeRef keyval = root.append_child();
        NodeRef keyseq = root.append_child();
        keyval << key("this") << "is";
        keyseq << key("a");
        keyseq |= SEQ;
        keyseq.append_child() << "yaml";
        keyseq.append_child() << "example";
    }

    void check_tree(Tree const& actual, csubstr expected_arena)
    {
        ASSERT_TRUE(actual.rootref().is_map());
        ASSERT_TRUE(actual["a"].is_seq());
        EXPECT_EQ(actual["this"].key(), "this");
        EXPECT_EQ(actual["this"].val(), "is");
        EXPECT_EQ(actual["a"].key(), "a");
        EXPECT_EQ(actual["a"][0].val(), "yaml");
        EXPECT_EQ(actual["a"][1].val(), "example");
        EXPECT_TRUE(actual["this"].key().is_sub(expected_arena));
        EXPECT_TRUE(actual["this"].val().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"].key().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"][0].val().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"][1].val().is_sub(expected_arena));
        if(expected_arena.str != actual.arena().str)
        {
            EXPECT_TRUE(actual.arena().empty());
        }
    }
};

TEST_F(ParseOverloadYamlTest, in_place_noparser_1_1)
{
    const Tree actual = parse_in_place(yaml);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_1_2)
{
    const Tree actual = parse_in_place(filename, yaml);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_2_1)
{
    Tree actual;
    parse_in_place(yaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_2_2)
{
    Tree actual;
    parse_in_place(filename, yaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_3_1)
{
    Tree actual;
    parse_in_place(yaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_3_2)
{
    Tree actual;
    parse_in_place(filename, yaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_4_1)
{
    Tree actual;
    parse_in_place(yaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_noparser_4_2)
{
    Tree actual;
    parse_in_place(filename, yaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}

TEST_F(ParseOverloadYamlTest, in_place_parser_1_1)
{
    const Tree actual = parse_in_place(&parser, yaml);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_1_2)
{
    const Tree actual = parse_in_place(&parser, filename, yaml);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_2_1)
{
    Tree actual;
    parse_in_place(&parser, yaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_2_2)
{
    Tree actual;
    parse_in_place(&parser, filename, yaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_3_1)
{
    Tree actual;
    parse_in_place(&parser, yaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_3_2)
{
    Tree actual;
    parse_in_place(&parser, filename, yaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_4_1)
{
    Tree actual;
    parse_in_place(&parser, yaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}
TEST_F(ParseOverloadYamlTest, in_place_parser_4_2)
{
    Tree actual;
    parse_in_place(&parser, filename, yaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, yaml);
}

TEST_F(ParseOverloadYamlTest, in_arena_noparser_1_1)
{
    const Tree actual = parse_in_arena(cyaml);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_1_2)
{
    const Tree actual = parse_in_arena(filename, cyaml);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_2_1)
{
    Tree actual;
    parse_in_arena(cyaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_2_2)
{
    Tree actual;
    parse_in_arena(filename, cyaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_3_1)
{
    Tree actual;
    parse_in_arena(cyaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_3_2)
{
    Tree actual;
    parse_in_arena(filename, cyaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
// workaround for optimizer problem in armv4 and armv5 with -O3: when
// the calling the parser overloads that take a NodeRef, the compiler
// optimizes the tree away
static C4_NO_INLINE void ensure_compiler_knows_tree_was_changed(Tree *t)
{
    C4_DONT_OPTIMIZE(*t);
    print_tree(*t); // this was also needed (?)
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_4_1)
{
    Tree actual;
    parse_in_arena(cyaml, actual.rootref());
    ensure_compiler_knows_tree_was_changed(&actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_noparser_4_2)
{
    Tree actual;
    parse_in_arena(filename, cyaml, actual.rootref());
    ensure_compiler_knows_tree_was_changed(&actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}

TEST_F(ParseOverloadYamlTest, in_arena_parser_1_1)
{
    const Tree actual = parse_in_arena(&parser, cyaml);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_1_2)
{
    const Tree actual = parse_in_arena(&parser, filename, cyaml);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_2_1)
{
    Tree actual;
    parse_in_arena(&parser, cyaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_2_2)
{
    Tree actual;
    parse_in_arena(&parser, filename, cyaml, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_3_1)
{
    Tree actual;
    parse_in_arena(&parser, cyaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_3_2)
{
    Tree actual;
    parse_in_arena(&parser, filename, cyaml, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_4_1)
{
    Tree actual;
    parse_in_arena(&parser, cyaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadYamlTest, in_arena_parser_4_2)
{
    Tree actual;
    parse_in_arena(&parser, filename, cyaml, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}


//-----------------------------------------------------------------------------

class ParseOverloadJsonTest : public testing::Test
{
protected:

    Tree ref;
    std::string json_ = "{\"this\": \"is\", \"a\": [\"json\", \"example\"]}";
    substr json = to_substr(json_);
    csubstr cjson = to_csubstr(json_);
    csubstr filename = "example.yml";

    EventHandlerTree evt_handler;
    Parser parser = {&evt_handler};

    void SetUp() override
    {
        NodeRef root = ref.rootref();
        root |= MAP;
        root |= FLOW_SL;
        NodeRef keyval = root.append_child();
        NodeRef keyseq = root.append_child();
        keyval << key("this") << "is";
        keyseq << key("a");
        keyseq |= SEQ;
        keyseq.append_child() << "json";
        keyseq.append_child() << "example";
    }

    void check_tree(Tree const& actual, csubstr expected_arena)
    {
        ASSERT_TRUE(actual.rootref().is_map());
        ASSERT_TRUE(actual["a"].is_seq());
        EXPECT_EQ(actual["this"].key(), "this");
        EXPECT_EQ(actual["this"].val(), "is");
        EXPECT_EQ(actual["a"].key(), "a");
        EXPECT_EQ(actual["a"][0].val(), "json");
        EXPECT_EQ(actual["a"][1].val(), "example");
        EXPECT_TRUE(actual["this"].key().is_sub(expected_arena));
        EXPECT_TRUE(actual["this"].val().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"].key().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"][0].val().is_sub(expected_arena));
        EXPECT_TRUE(actual["a"][1].val().is_sub(expected_arena));
        if(expected_arena.str != actual.arena().str)
        {
            EXPECT_TRUE(actual.arena().empty());
        }
    }
};

TEST_F(ParseOverloadJsonTest, in_place_noparser_1_1)
{
    const Tree actual = parse_json_in_place(json);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_1_2)
{
    const Tree actual = parse_json_in_place(filename, json);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_2_1)
{
    Tree actual;
    parse_json_in_place(json, &actual);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_2_2)
{
    Tree actual;
    parse_json_in_place(filename, json, &actual);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_3_1)
{
    Tree actual;
    parse_json_in_place(json, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_3_2)
{
    Tree actual;
    parse_json_in_place(filename, json, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_4_1)
{
    Tree actual;
    parse_json_in_place(json, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_noparser_4_2)
{
    Tree actual;
    parse_json_in_place(filename, json, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, json);
}

TEST_F(ParseOverloadJsonTest, in_place_parser_1_1)
{
    const Tree actual = parse_json_in_place(&parser, json);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_1_2)
{
    const Tree actual = parse_json_in_place(&parser, filename, json);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_2_1)
{
    Tree actual;
    parse_json_in_place(&parser, json, &actual);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_2_2)
{
    Tree actual;
    parse_json_in_place(&parser, filename, json, &actual);
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_3_1)
{
    Tree actual;
    parse_json_in_place(&parser, json, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_3_2)
{
    Tree actual;
    parse_json_in_place(&parser, filename, json, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_4_1)
{
    Tree actual;
    parse_json_in_place(&parser, json, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, json);
}
TEST_F(ParseOverloadJsonTest, in_place_parser_4_2)
{
    Tree actual;
    parse_json_in_place(&parser, filename, json, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, json);
}

TEST_F(ParseOverloadJsonTest, in_arena_noparser_1_1)
{
    const Tree actual = parse_json_in_arena(cjson);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_1_2)
{
    const Tree actual = parse_json_in_arena(filename, cjson);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_2_1)
{
    Tree actual;
    parse_json_in_arena(cjson, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_2_2)
{
    Tree actual;
    parse_json_in_arena(filename, cjson, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_3_1)
{
    Tree actual;
    parse_json_in_arena(cjson, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_3_2)
{
    Tree actual;
    parse_json_in_arena(filename, cjson, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_4_1)
{
    Tree actual;
    parse_json_in_arena(cjson, actual.rootref());
    ensure_compiler_knows_tree_was_changed(&actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_noparser_4_2)
{
    Tree actual;
    parse_json_in_arena(filename, cjson, actual.rootref());
    ensure_compiler_knows_tree_was_changed(&actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}

TEST_F(ParseOverloadJsonTest, in_arena_parser_1_1)
{
    const Tree actual = parse_json_in_arena(&parser, cjson);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_1_2)
{
    const Tree actual = parse_json_in_arena(&parser, filename, cjson);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_2_1)
{
    Tree actual;
    parse_json_in_arena(&parser, cjson, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_2_2)
{
    Tree actual;
    parse_json_in_arena(&parser, filename, cjson, &actual);
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_3_1)
{
    Tree actual;
    parse_json_in_arena(&parser, cjson, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_3_2)
{
    Tree actual;
    parse_json_in_arena(&parser, filename, cjson, &actual, actual.root_id());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_4_1)
{
    Tree actual;
    parse_json_in_arena(&parser, cjson, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}
TEST_F(ParseOverloadJsonTest, in_arena_parser_4_2)
{
    Tree actual;
    parse_json_in_arena(&parser, filename, cjson, actual.rootref());
    test_compare(actual, ref);
    check_tree(actual, actual.arena());
}


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

class ParseToNodeTest : public testing::Test
{
protected:

    EventHandlerTree evt_handler;
    Parser parser = {&evt_handler};

    std::string val_plain = "this is a plain val";
    std::string val_plain_anchor = "&anchor this is a plain val";
    std::string val_plain_tag = "!!str this is a plain val";

    std::string val_squo = "'this is a squo val'";
    std::string val_squo_anchor = "&anchor 'this is a squo val'";
    std::string val_squo_tag = "!!str 'this is a squo val'";

    std::string val_dquo = "\"this is a dquo val\"";
    std::string val_dquo_anchor = "&anchor \"this is a dquo val\"";
    std::string val_dquo_tag = "!!str \"this is a dquo val\"";

    std::string val_literal = "|-\n this is a literal val";
    std::string val_literal_anchor = "&anchor |-\n this is a literal val";
    std::string val_literal_tag = "!!str |-\n this is a literal val";

    std::string val_folded = ">-\n this is a folded val";
    std::string val_folded_anchor = "&anchor >-\n this is a folded val";
    std::string val_folded_tag = "!!str >-\n this is a folded val";

    std::string val_ref = "*ref";

    std::string seq_flow = "  [seq, flow, yes, it is]";
    std::string seq_flow_anchor = "  &anchor [seq, flow, yes, it is]";
    std::string seq_flow_tag = "  !!seq [seq, flow, yes, it is]";

    std::string seq_blck = "- seq\n- block\n- yes\n- it is";
    std::string seq_blck_anchor = "&anchor\n- seq\n- block\n- yes\n- it is";
    std::string seq_blck_tag = "!!seq\n- seq\n- block\n- yes\n- it is";

    std::string map_flow = "  {map: flow, yes: it is}";
    std::string map_flow_anchor = "  &anchor {map: flow, yes: it is}";
    std::string map_flow_tag = "  !!map {map: flow, yes: it is}";

    std::string map_blck_keyless = ": block\nyes: it is";
    std::string map_blck_plain = "map: block\nyes: it is";
    std::string map_blck_squo = "'map': block\nyes: it is";
    std::string map_blck_dquo = "\"map\": block\nyes: it is";
    std::string map_blck_literal = "? |-\n  map\n: block\nyes: it is";
    std::string map_blck_folded = "? >-\n  map\n: block\nyes: it is";
    std::string map_blck_anchor = "&anchor\nmap: block\nyes: it is";
    std::string map_blck_tag = "!!map\nmap: block\nyes: it is";
    std::string map_blck_ref = "*map : block\nyes: it is";

    std::string empty = "";
    std::string whitespace = "     ";

    Tree dst_empty;
    Tree dst_val;
    Tree dst_map_flow;
    Tree dst_map_blck;
    Tree dst_seq_flow;
    Tree dst_seq_blck;

    void SetUp() override
    {
        dst_val.rootref().set_val("val");
        dst_map_flow.rootref() |= MAP|FLOW_SL;
        dst_map_blck.rootref() |= MAP|BLOCK;
        dst_seq_flow.rootref() |= SEQ|FLOW_SL;
        dst_seq_blck.rootref() |= SEQ|BLOCK;
    }

};


//-----------------------------------------------------------------------------

class ParseToSeqFlowTest : public ParseToNodeTest {};



TEST_F(ParseToSeqFlowTest, empty__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    parse_in_arena(to_csubstr(empty), dst);
    EXPECT_TRUE(dst.empty());
}

TEST_F(ParseToSeqFlowTest, empty__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(empty), dst);
    EXPECT_FALSE(dst.has_val());
}


TEST_F(ParseToSeqFlowTest, whitespace__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    parse_in_arena(to_csubstr(whitespace), dst);
    EXPECT_TRUE(dst.empty());
}

TEST_F(ParseToSeqFlowTest, whitespace__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(whitespace), dst);
    EXPECT_FALSE(dst.has_val());
}


TEST_F(ParseToSeqFlowTest, val_plain__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_plain__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_plain), dst);
    const Tree expected = parse_in_arena("[this is a plain val]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, val_squo__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_squo__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_squo), dst);
    const Tree expected = parse_in_arena("[this is a squo val]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, val_dquo__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_dquo__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_dquo), dst);
    const Tree expected = parse_in_arena("[this is a dquo val]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, val_literal__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_literal_anchor__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_literal), dst);
    const Tree expected = parse_in_arena("[this is a literal val]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, val_folded__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_folded__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_folded), dst);
    const Tree expected = parse_in_arena("[this is a folded val]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, val_ref__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_ref), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, val_ref__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(val_ref), dst);
    const Tree expected = parse_in_arena("[*ref]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, seq_flow__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    parse_in_arena(to_csubstr(seq_flow), dst);
    const Tree expected = parse_in_arena("[seq, flow, yes, it is]");
    _c4dbg_tree("actual", dst_seq_flow);
    _c4dbg_tree("expected", expected);
    test_compare(dst_seq_flow, expected);
}

TEST_F(ParseToSeqFlowTest, seq_flow__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(seq_flow), dst);
    const Tree expected = parse_in_arena("- [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, seq_blck__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    parse_in_arena(to_csubstr(seq_blck), dst);
    const Tree expected = parse_in_arena("[seq, block, yes, it is]");
    _c4dbg_tree("actual", dst_seq_flow);
    _c4dbg_tree("expected", expected);
    test_compare(dst_seq_flow, expected);
}

TEST_F(ParseToSeqFlowTest, seq_blck__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(seq_blck), dst);
    const Tree expected = parse_in_arena("- [seq, block, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_flow__to__seq_flow__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_flow), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_flow__to__seq_flow__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_flow), dst);
    const Tree expected = parse_in_arena("- {map: flow, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_blck_plain__to__seq_blck__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_blck_plain), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_blck_plain__to__seq_blck__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_blck_plain), dst);
    const Tree expected = parse_in_arena("- {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_blck_squo__to__seq_blck__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_blck_squo), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_blck_squo__to__seq_blck__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_blck_squo), dst);
    const Tree expected = parse_in_arena("- {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_blck_dquo__to__seq_blck__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_blck_dquo), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_blck_dquo__to__seq_blck__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_blck_dquo), dst);
    const Tree expected = parse_in_arena("- {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_blck_literal__to__seq_blck__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_blck_literal), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_blck_literal__to__seq_blck__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_blck_literal), dst);
    const Tree expected = parse_in_arena("- {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}


TEST_F(ParseToSeqFlowTest, map_blck_folded__to__seq_blck__root)
{
    NodeRef dst = dst_seq_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_blck_folded), dst);
    });
    _c4dbg_tree("actual", dst_seq_flow);
}

TEST_F(ParseToSeqFlowTest, map_blck_folded__to__seq_blck__new_child)
{
    NodeRef dst = dst_seq_flow.rootref().append_child();
    parse_in_arena(to_csubstr(map_blck_folded), dst);
    const Tree expected = parse_in_arena("- {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_seq_flow);
    test_compare(dst_seq_flow, expected);
}



//-----------------------------------------------------------------------------

class ParseToMapFlowTest : public ParseToNodeTest {};


TEST_F(ParseToMapFlowTest, empty__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(empty), dst);
    EXPECT_TRUE(dst.empty());
}

TEST_F(ParseToMapFlowTest, empty__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(empty), dst);
    EXPECT_FALSE(dst.has_val());
}


TEST_F(ParseToMapFlowTest, whitespace__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(whitespace), dst);
    EXPECT_TRUE(dst.empty());
}

TEST_F(ParseToMapFlowTest, whitespace__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(whitespace), dst);
    EXPECT_FALSE(dst.has_val());
}


TEST_F(ParseToMapFlowTest, val_plain__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_plain__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain), dst);
    const Tree expected = parse_in_arena("dst: this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_plain_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_plain_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_plain_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_plain_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_squo__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_squo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo), dst);
    const Tree expected = parse_in_arena("dst: this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_squo_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_squo_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_squo_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_squo_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_dquo__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_dquo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo), dst);
    const Tree expected = parse_in_arena("dst: this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_dquo_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_dquo_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_dquo_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_dquo_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_literal__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_literal__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal), dst);
    const Tree expected = parse_in_arena("dst: this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_literal_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_literal_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_literal_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_literal_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_folded__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_folded__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded), dst);
    const Tree expected = parse_in_arena("dst: this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_folded_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_folded_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_folded_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_folded_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, val_ref__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_ref), dst);
    });
    _c4dbg_tree("actual", dst_map_flow);
}

TEST_F(ParseToMapFlowTest, val_ref_to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_ref), dst);
    const Tree expected = parse_in_arena("dst: *ref");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, seq_flow__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow), dst);
    });
}

TEST_F(ParseToMapFlowTest, seq_flow__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow), dst);
    const Tree expected = parse_in_arena("dst: [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, seq_flow_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow_anchor), dst);
    });
}

TEST_F(ParseToMapFlowTest, seq_flow_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, seq_flow_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow_tag), dst);
    });
}

TEST_F(ParseToMapFlowTest, seq_flow_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow_tag), dst);
    const Tree expected = parse_in_arena("dst: !!seq [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, seq_blck__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_blck), dst);
    });
}

TEST_F(ParseToMapFlowTest, seq_blck__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_blck), dst);
    const Tree expected = parse_in_arena("dst: [seq, block, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_flow__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_flow), dst);
    const Tree expected = parse_in_arena("{map: flow, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_flow__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow), dst);
    const Tree expected = parse_in_arena("{dst: {map: flow, yes: it is}}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_flow__to__map_flow__new_child_no_key)
{
    NodeRef dst = dst_map_flow.rootref().append_child();
    ExpectError::check_error_basic(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_flow), dst);
    });
}


TEST_F(ParseToMapFlowTest, map_flow_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_flow_anchor), dst);
    const Tree expected = parse_in_arena("&anchor\nmap: flow\nyes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_flow_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor\n  map: flow\n  yes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_flow_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_flow_tag), dst);
    const Tree expected = parse_in_arena("!!map\nmap: flow\nyes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_flow_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow_tag), dst);
    const Tree expected = parse_in_arena("dst: !!map\n  map: flow\n  yes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_keyless__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_keyless), dst);
    const Tree expected = parse_in_arena("{ : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_keyless__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_keyless), dst);
    const Tree expected = parse_in_arena("dst : { : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_plain__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_plain), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_plain__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_plain), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_squo__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_squo), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_squo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_squo), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_dquo__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_dquo), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_dquo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_dquo), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_literal__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_literal), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_literal__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_literal), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_folded__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_folded), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_folded__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_folded), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_anchor), dst);
    const Tree expected = parse_in_arena("&anchor {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_tag), dst);
    const Tree expected = parse_in_arena("!!map {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_tag), dst);
    const Tree expected = parse_in_arena("dst: !!map {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}


TEST_F(ParseToMapFlowTest, map_block_ref__to__map_flow__root)
{
    NodeRef dst = dst_map_flow.rootref();
    parse_in_arena(to_csubstr(map_blck_ref), dst);
    const Tree expected = parse_in_arena("{*map : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}

TEST_F(ParseToMapFlowTest, map_block_ref__to__map_flow__new_child)
{
    NodeRef dst = dst_map_flow.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_ref), dst);
    const Tree expected = parse_in_arena("dst: {*map : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_flow);
    test_compare(dst_map_flow, expected);
}



//-----------------------------------------------------------------------------

class ParseToMapBlockTest : public ParseToNodeTest {};


TEST_F(ParseToMapBlockTest, val_plain__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_plain__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain), dst);
    const Tree expected = parse_in_arena("dst: this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_plain_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_plain_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_plain_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_plain_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_plain_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_plain_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a plain val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_squo__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_squo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo), dst);
    const Tree expected = parse_in_arena("dst: this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_squo_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_squo_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_squo_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_squo_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_squo_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_squo_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a squo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_dquo__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_dquo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo), dst);
    const Tree expected = parse_in_arena("dst: this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_dquo_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_dquo_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_dquo_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_dquo_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_dquo_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_dquo_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a dquo val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_literal__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_literal__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal), dst);
    const Tree expected = parse_in_arena("dst: this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_literal_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_literal_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_literal_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_literal_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_literal_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_literal_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a literal val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_folded__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_folded__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded), dst);
    const Tree expected = parse_in_arena("dst: this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_folded_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded_anchor), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_folded_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_folded_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_folded_tag), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_folded_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_folded_tag), dst);
    const Tree expected = parse_in_arena("dst: !!str this is a folded val");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, val_ref__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(val_ref), dst);
    });
    _c4dbg_tree("actual", dst_map_blck);
}

TEST_F(ParseToMapBlockTest, val_ref_to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(val_ref), dst);
    const Tree expected = parse_in_arena("dst: *ref");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, seq_flow__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow), dst);
    });
}

TEST_F(ParseToMapBlockTest, seq_flow__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow), dst);
    const Tree expected = parse_in_arena("dst: [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, seq_flow_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow_anchor), dst);
    });
}

TEST_F(ParseToMapBlockTest, seq_flow_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, seq_flow_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_flow_tag), dst);
    });
}

TEST_F(ParseToMapBlockTest, seq_flow_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_flow_tag), dst);
    const Tree expected = parse_in_arena("dst: !!seq [seq, flow, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, seq_blck__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    ExpectError::check_error_parse(dst.tree(), [&]{
        parse_in_arena(to_csubstr(seq_blck), dst);
    });
}

TEST_F(ParseToMapBlockTest, seq_blck__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(seq_blck), dst);
    const Tree expected = parse_in_arena("dst: [seq, block, yes, it is]");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_flow__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_flow), dst);
    const Tree expected = parse_in_arena("map: flow\nyes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_flow__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow), dst);
    const Tree expected = parse_in_arena("dst:\n  map: flow\n  yes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_flow__to__map_flow__new_child_no_key)
{
    NodeRef dst = dst_map_blck.rootref().append_child();
    ExpectError::check_error_basic(dst.tree(), [&]{
        parse_in_arena(to_csubstr(map_flow), dst);
    });
}


TEST_F(ParseToMapBlockTest, map_flow_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_flow_anchor), dst);
    const Tree expected = parse_in_arena("&anchor\nmap: flow\nyes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_flow_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor\n  map: flow\n  yes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_flow_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_flow_tag), dst);
    const Tree expected = parse_in_arena("!!map\nmap: flow\nyes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_flow_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_flow_tag), dst);
    const Tree expected = parse_in_arena("dst: !!map\n  map: flow\n  yes: it is\n");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_keyless__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_keyless), dst);
    const Tree expected = parse_in_arena("{ : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_keyless__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_keyless), dst);
    const Tree expected = parse_in_arena("dst : { : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_plain__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_plain), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_plain__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_plain), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_squo__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_squo), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_squo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_squo), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_dquo__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_dquo), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_dquo__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_dquo), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_literal__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_literal), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_literal__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_literal), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_folded__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_folded), dst);
    const Tree expected = parse_in_arena("{map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_folded__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_folded), dst);
    const Tree expected = parse_in_arena("dst: {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_anchor__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_anchor), dst);
    const Tree expected = parse_in_arena("&anchor {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_anchor__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_anchor), dst);
    const Tree expected = parse_in_arena("dst: &anchor {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_tag__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_tag), dst);
    const Tree expected = parse_in_arena("!!map {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_tag__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_tag), dst);
    const Tree expected = parse_in_arena("dst: !!map {map: block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}


TEST_F(ParseToMapBlockTest, map_block_ref__to__map_flow__root)
{
    NodeRef dst = dst_map_blck.rootref();
    parse_in_arena(to_csubstr(map_blck_ref), dst);
    const Tree expected = parse_in_arena("{*map : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}

TEST_F(ParseToMapBlockTest, map_block_ref__to__map_flow__new_child)
{
    NodeRef dst = dst_map_blck.rootref().append_child({KEY, "dst"});
    parse_in_arena(to_csubstr(map_blck_ref), dst);
    const Tree expected = parse_in_arena("dst: {*map : block, yes: it is}");
    _c4dbg_tree("expected", expected);
    _c4dbg_tree("actual", dst_map_blck);
    test_compare(dst_map_blck, expected);
}




} // namespace yml
} // namespace c4


//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------

// this is needed to use the test case library

#ifndef RYML_SINGLE_HEADER
#include "c4/substr.hpp"
#endif

namespace c4 {
namespace yml {
struct Case;
Case const* get_case(csubstr /*name*/)
{
    return nullptr;
}

C4_SUPPRESS_WARNING_GCC_CLANG_POP

} // namespace yml
} // namespace c4
