diff options
| author | Stefan Boberg <[email protected]> | 2025-11-07 14:49:13 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2025-11-07 14:49:13 +0100 |
| commit | 24e43a913f29ac3b314354e8ce5175f135bcc64f (patch) | |
| tree | ca442937ceeb63461012b33a4576e9835099f106 /thirdparty/ryml/test/test_parser.cpp | |
| parent | get oplog attachments (#622) (diff) | |
| download | zen-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.cpp | 566 |
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 |