aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/ryml/test/test_parser.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2025-11-07 14:49:13 +0100
committerGitHub Enterprise <[email protected]>2025-11-07 14:49:13 +0100
commit24e43a913f29ac3b314354e8ce5175f135bcc64f (patch)
treeca442937ceeb63461012b33a4576e9835099f106 /thirdparty/ryml/test/test_parser.cpp
parentget oplog attachments (#622) (diff)
downloadzen-24e43a913f29ac3b314354e8ce5175f135bcc64f.tar.xz
zen-24e43a913f29ac3b314354e8ce5175f135bcc64f.zip
switch to xmake for package management (#611)
This change removes our dependency on vcpkg for package management, in favour of bringing some code in-tree in the `thirdparty` folder as well as using the xmake build-in package management feature. For the latter, all the package definitions are maintained in the zen repo itself, in the `repo` folder. It should now also be easier to build the project as it will no longer depend on having the right version of vcpkg installed, which has been a common problem for new people coming in to the codebase. Now you should only need xmake to build. * Bumps xmake requirement on github runners to 2.9.9 to resolve an issue where xmake on Windows invokes cmake with `v144` toolchain which does not exist * BLAKE3 is now in-tree at `thirdparty/blake3` * cpr is now in-tree at `thirdparty/cpr` * cxxopts is now in-tree at `thirdparty/cxxopts` * fmt is now in-tree at `thirdparty/fmt` * robin-map is now in-tree at `thirdparty/robin-map` * ryml is now in-tree at `thirdparty/ryml` * sol2 is now in-tree at `thirdparty/sol2` * spdlog is now in-tree at `thirdparty/spdlog` * utfcpp is now in-tree at `thirdparty/utfcpp` * xmake package repo definitions is in `repo` * implemented support for sanitizers. ASAN is supported on windows, TSAN, UBSAN, MSAN etc are supported on Linux/MacOS though I have not yet tested it extensively on MacOS * the zencore encryption implementation also now supports using mbedTLS which is used on MacOS, though for now we still use openssl on Linux * crashpad * bumps libcurl to 8.11.0 (from 8.8.0) which should address a rare build upload bug
Diffstat (limited to 'thirdparty/ryml/test/test_parser.cpp')
-rw-r--r--thirdparty/ryml/test/test_parser.cpp566
1 files changed, 566 insertions, 0 deletions
diff --git a/thirdparty/ryml/test/test_parser.cpp b/thirdparty/ryml/test/test_parser.cpp
new file mode 100644
index 000000000..3ef9ee145
--- /dev/null
+++ b/thirdparty/ryml/test/test_parser.cpp
@@ -0,0 +1,566 @@
+#ifdef RYML_SINGLE_HEADER
+#include "ryml_all.hpp"
+#else
+#include "c4/yml/parse.hpp"
+#endif
+#include <gtest/gtest.h>
+#include "./callbacks_tester.hpp"
+
+
+namespace c4 {
+namespace yml {
+
+// 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)
+{
+ p->~Parser();
+ new ((void*)p) Parser(cb);
+ p->reserve_stack(20); // cause an allocation
+ p->reserve_locations(128); // cause an allocation
+ p->reserve_filter_arena(128); // cause an allocation
+}
+
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+TEST(Parser, empty_ctor)
+{
+ Parser parser;
+ EXPECT_EQ(parser.callbacks(), get_callbacks());
+}
+
+TEST(Parser, callbacks_ctor)
+{
+ CallbacksTester cbt;
+ {
+ Parser parser(cbt.callbacks());
+ EXPECT_EQ(parser.callbacks(), cbt.callbacks());
+ }
+ EXPECT_EQ(cbt.num_allocs, 0u);
+ EXPECT_EQ(cbt.num_deallocs, 0u);
+}
+
+TEST(Parser, reserve_capacity)
+{
+ CallbacksTester cbt("test", 20000/*Bytes*/);
+ {
+ Parser parser(cbt.callbacks());
+ EXPECT_EQ(cbt.num_allocs, 0u);
+ EXPECT_EQ(cbt.num_deallocs, 0u);
+ parser.reserve_stack(18);
+ EXPECT_EQ(cbt.num_allocs, 1u);
+ EXPECT_EQ(cbt.num_deallocs, 0u);
+ parser.reserve_stack(24);
+ EXPECT_EQ(cbt.num_allocs, 2u);
+ EXPECT_EQ(cbt.num_deallocs, 1u);
+ parser.reserve_stack(28);
+ EXPECT_EQ(cbt.num_allocs, 3u);
+ EXPECT_EQ(cbt.num_deallocs, 2u);
+ }
+ EXPECT_EQ(cbt.num_allocs, 3u);
+ EXPECT_EQ(cbt.num_deallocs, 3u);
+ cbt.check();
+}
+
+TEST(Parser, reserve_locations)
+{
+ CallbacksTester ts;
+ {
+ Parser parser(ts.callbacks());
+ EXPECT_EQ(parser.callbacks(), ts.callbacks());
+ EXPECT_EQ(ts.num_allocs, 0u);
+ EXPECT_EQ(ts.num_deallocs, 0u);
+ parser.reserve_locations(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, reserve_filter_arena)
+{
+ size_t cap = 256u;
+ CallbacksTester ts;
+ {
+ Parser parser(ts.callbacks());
+ EXPECT_EQ(parser.filter_arena_capacity(), 0u);
+ EXPECT_EQ(parser.callbacks(), ts.callbacks());
+ EXPECT_EQ(ts.num_allocs, 0u);
+ EXPECT_EQ(ts.num_deallocs, 0u);
+ parser.reserve_filter_arena(cap);
+ EXPECT_EQ(ts.num_allocs, 1u);
+ EXPECT_EQ(ts.num_deallocs, 0u);
+ EXPECT_EQ(ts.alloc_size, cap);
+ EXPECT_EQ(ts.dealloc_size, 0u);
+ }
+ EXPECT_EQ(ts.num_allocs, 1u);
+ EXPECT_EQ(ts.num_deallocs, 1u);
+ EXPECT_EQ(ts.alloc_size, cap);
+ EXPECT_EQ(ts.dealloc_size, cap);
+}
+
+TEST(Parser, copy_ctor)
+{
+ {
+ Parser src;
+ mklarge(&src, get_callbacks());
+ EXPECT_EQ(src.callbacks(), get_callbacks());
+ Parser dst(src);
+ EXPECT_EQ(src.callbacks(), get_callbacks());
+ EXPECT_EQ(dst.callbacks(), get_callbacks());
+ }
+ {
+ CallbacksTester ts;
+ {
+ Parser src;
+ mklarge(&src, ts.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)
+{
+ {
+ Parser src;
+ mklarge(&src, get_callbacks());
+ EXPECT_EQ(src.callbacks(), get_callbacks());
+ Parser dst(std::move(src));
+ EXPECT_EQ(src.callbacks(), get_callbacks());
+ EXPECT_EQ(dst.callbacks(), get_callbacks());
+ }
+ {
+ CallbacksTester ts;
+ {
+ Parser src;
+ mklarge(&src, ts.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 src;
+ Parser 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 src;
+ Parser 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 src;
+ Parser 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 src;
+ Parser 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(td.num_allocs, nbefore); // dst frees with td
+ EXPECT_EQ(ts.num_allocs, nbefore); // dst moves from ts
+ }
+ 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 parser;
+ EXPECT_EQ(parser.callbacks(), get_callbacks());
+ Tree t = parser.parse_in_arena("file0", csrc);
+ EXPECT_EQ(t.callbacks(), get_callbacks());
+ }
+ CallbacksTester cbt("test", 20000/*Bytes*/);
+ {
+ Parser parser(cbt.callbacks());
+ EXPECT_EQ(parser.callbacks(), cbt.callbacks());
+ Tree t = parser.parse_in_arena("file1", csrc);
+ EXPECT_EQ(t.callbacks(), cbt.callbacks());
+ }
+ cbt.check();
+ }
+ {
+ {
+ Parser parser;
+ EXPECT_EQ(parser.callbacks(), get_callbacks());
+ Tree t = parser.parse_in_place("file", src);
+ EXPECT_EQ(t.callbacks(), get_callbacks());
+ }
+ CallbacksTester cbt("test", 20000/*Bytes*/);
+ {
+ Parser parser(cbt.callbacks());
+ EXPECT_EQ(parser.callbacks(), cbt.callbacks());
+ Tree t = parser.parse_in_place("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());
+ Parser parser(cbp.callbacks());
+ EXPECT_EQ(tree.callbacks(), cbt.callbacks());
+ EXPECT_EQ(parser.callbacks(), cbp.callbacks());
+ parser.parse_in_arena("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());
+ Parser parser(cbp.callbacks());
+ EXPECT_EQ(tree.callbacks(), cbt.callbacks());
+ EXPECT_EQ(parser.callbacks(), cbp.callbacks());
+ parser.parse_in_place("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 parser;
+ EXPECT_EQ(parser.filename(), csubstr{});
+ {
+ Tree tree = parser.parse_in_place("file0", src);
+ EXPECT_EQ(parser.filename(), "file0");
+ EXPECT_TRUE(is_same(parser.source(), src));
+ }
+ {
+ Tree tree = parser.parse_in_arena("file1", csrc);
+ EXPECT_EQ(parser.filename(), "file1");
+ EXPECT_TRUE(!is_same(parser.source(), src));
+ }
+ {
+ Tree tree = parser.parse_in_place("file2", src);
+ EXPECT_EQ(parser.filename(), "file2");
+ EXPECT_TRUE(is_same(parser.source(), src));
+ }
+ {
+ Tree tree = parser.parse_in_arena({}, csrc);
+ EXPECT_EQ(parser.filename(), csubstr{});
+ EXPECT_TRUE(!is_same(parser.source(), src));
+ }
+}
+
+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);
+ size_t e = tree.find_child(tree.root_id(), "e");
+ ASSERT_NE(e, (size_t)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);
+ size_t e = tree.find_child(tree.root_id(), "e");
+ ASSERT_NE(e, (size_t)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), (size_t)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), (size_t)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), (size_t)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), (size_t)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), (size_t)npos);
+ size_t e = tree.find_child(tree.root_id(), "e");
+ ASSERT_NE(e, (size_t)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), (size_t)npos);
+ EXPECT_NE(tree.arena().find(src2), (size_t)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), (size_t)npos);
+ size_t e = tree.find_child(tree.root_id(), "e");
+ ASSERT_NE(e, (size_t)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), (size_t)npos);
+ EXPECT_NE(tree.arena().find(src2), (size_t)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), (size_t)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), (size_t)npos);
+ EXPECT_NE(tree.arena().find(src2), (size_t)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), (size_t)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), (size_t)npos);
+ EXPECT_NE(tree.arena().find(src2), (size_t)npos);
+ }
+}
+
+TEST(parse_in_place, version_numbers)
+{
+ char src1_[] = "{a: 1.2.3}";
+ {
+ Tree tree = parse_in_place(src1_);
+ EXPECT_EQ(tree["a"].val(), "1.2.3");
+ }
+}
+
+} // 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;
+}
+} // namespace yml
+} // namespace c4