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_null_val.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_null_val.cpp')
| -rw-r--r-- | thirdparty/ryml/test/test_null_val.cpp | 519 |
1 files changed, 519 insertions, 0 deletions
diff --git a/thirdparty/ryml/test/test_null_val.cpp b/thirdparty/ryml/test/test_null_val.cpp new file mode 100644 index 000000000..4bdd6d419 --- /dev/null +++ b/thirdparty/ryml/test/test_null_val.cpp @@ -0,0 +1,519 @@ +#include "./test_group.hpp" +#include "c4/error.hpp" + +namespace c4 { +namespace yml { + +C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") + +csubstr getafter(csubstr yaml, csubstr pattern) +{ + size_t pos = yaml.find(pattern); + RYML_ASSERT(pos != npos); + RYML_ASSERT(yaml.sub(pos).begins_with(pattern)); + return yaml.sub(pos + pattern.len); +} + +#define _check_null_pointing_at(expr_, which, pattern, arena) \ + do \ + { \ + csubstr expr = expr_.which(); \ + if(expr.empty()) \ + { \ + EXPECT_EQ(expr, nullptr); \ + EXPECT_EQ(expr.len, 0u); \ + EXPECT_EQ(expr.str, nullptr); \ + } \ + EXPECT_TRUE(expr_.which##_is_null()); \ + } while(0) + + +TEST(null_val, simple) +{ + Tree tree = parse_in_arena("{foo: , bar: '', baz: [,,,], bat: [ , , , ], two: [,,], one: [,], empty: []}"); + _check_null_pointing_at(tree["foo"], val, " ,", tree.arena()); + ASSERT_EQ(tree["baz"].num_children(), 3u); + _check_null_pointing_at(tree["baz"][0], val, "[,,,]", tree.arena()); + _check_null_pointing_at(tree["baz"][1], val, ",,,]", tree.arena()); + _check_null_pointing_at(tree["baz"][2], val, ",,]", tree.arena()); + ASSERT_EQ(tree["bat"].num_children(), 3u); + _check_null_pointing_at(tree["bat"][0], val, " , , , ]", tree.arena()); + _check_null_pointing_at(tree["bat"][1], val, " , , ]", tree.arena()); + _check_null_pointing_at(tree["bat"][2], val, " , ]", tree.arena()); + ASSERT_EQ(tree["two"].num_children(), 2u); + _check_null_pointing_at(tree["two"][0], val, "[,,]", tree.arena()); + _check_null_pointing_at(tree["two"][1], val, ",,]", tree.arena()); + ASSERT_EQ(tree["one"].num_children(), 1u); + _check_null_pointing_at(tree["one"][0], val, "[,]", tree.arena()); + ASSERT_EQ(tree["empty"].num_children(), 0u); +} + +TEST(null_val, block_seq) +{ + csubstr yaml = R"( +# nospace +- +- +- +# onespace +- +- +- +# null +- null +- null +- null +- ~ +)"; + ASSERT_EQ(yaml.count('\r'), 0u); + Tree tree = parse_in_arena(yaml); + ASSERT_EQ(tree.rootref().num_children(), 10u); + // FIXME: empty vals in block seqs are pointing at the next item! + _check_null_pointing_at(tree[0], val, after("nospace\n-\n"), tree.arena()); + _check_null_pointing_at(tree[1], val, after("nospace\n-\n-\n"), tree.arena()); + _check_null_pointing_at(tree[2], val, after("nospace\n-\n-\n-\n# onespace\n"), tree.arena()); + _check_null_pointing_at(tree[3], val, after("onespace\n- \n"), tree.arena()); + _check_null_pointing_at(tree[4], val, after("onespace\n- \n- \n"), tree.arena()); + _check_null_pointing_at(tree[5], val, after("onespace\n- \n- \n- \n# null\n"), tree.arena()); + // but explicitly null vals are ok: + _check_null_pointing_at(tree[6], val, "null\n- null\n- null\n- ~\n", tree.arena()); + _check_null_pointing_at(tree[7], val, "null\n- null\n- ~", tree.arena()); + _check_null_pointing_at(tree[8], val, "null\n- ~\n", tree.arena()); + _check_null_pointing_at(tree[9], val, "~\n", tree.arena()); +} + +TEST(null_val, block_map) +{ + csubstr yaml = R"( +# nospace +val0: +val1: +val2: +# onespace +val3: +val4: +val5: +# null +val6: null +val7: null +val8: null +val9: ~ +)"; + ASSERT_EQ(yaml.count('\r'), 0u); + Tree tree = parse_in_arena(yaml); + ASSERT_EQ(tree.rootref().num_children(), 10u); + // FIXME: empty vals in block seqs are pointing at the next item! + _check_null_pointing_at(tree["val0"], val, after("val0:"), tree.arena()); + _check_null_pointing_at(tree["val1"], val, after("val1:"), tree.arena()); + _check_null_pointing_at(tree["val2"], val, after("val2:\n# onespace"), tree.arena()); + _check_null_pointing_at(tree["val3"], val, after("val3: "), tree.arena()); + _check_null_pointing_at(tree["val4"], val, after("val4: "), tree.arena()); + _check_null_pointing_at(tree["val5"], val, after("val5: \n# null"), tree.arena()); + // but explicitly null vals are ok: + _check_null_pointing_at(tree["val6"], val, "null\nval7:", tree.arena()); + _check_null_pointing_at(tree["val7"], val, "null\nval8:", tree.arena()); + _check_null_pointing_at(tree["val8"], val, "null\nval9:", tree.arena()); + _check_null_pointing_at(tree["val9"], val, "~\n", tree.arena()); +} + + +TEST(null_val, issue103) +{ + C4_SUPPRESS_WARNING_GCC_WITH_PUSH("-Wuseless-cast") + Tree tree; + + tree = parse_in_arena(R"({null: null})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "null"); + EXPECT_EQ(tree.val(1), "null"); + EXPECT_TRUE(tree.key_is_null(1)); + EXPECT_TRUE(tree.val_is_null(1)); + EXPECT_TRUE(tree[0].key_is_null()); + EXPECT_TRUE(tree[0].val_is_null()); + _check_null_pointing_at(tree[0], key, "null:", tree.arena()); + _check_null_pointing_at(tree[0], val, "null}", tree.arena()); + + tree = parse_in_arena(R"({Null: Null})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "Null"); + EXPECT_EQ(tree.val(1), "Null"); + EXPECT_TRUE(tree.key_is_null(1)); + EXPECT_TRUE(tree.val_is_null(1)); + EXPECT_TRUE(tree[0].key_is_null()); + EXPECT_TRUE(tree[0].val_is_null()); + _check_null_pointing_at(tree[0], key, "Null:", tree.arena()); + _check_null_pointing_at(tree[0], val, "Null}", tree.arena()); + + tree = parse_in_arena(R"({NULL: NULL})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "NULL"); + EXPECT_EQ(tree.val(1), "NULL"); + EXPECT_TRUE(tree.key_is_null(1)); + EXPECT_TRUE(tree.val_is_null(1)); + EXPECT_TRUE(tree[0].key_is_null()); + EXPECT_TRUE(tree[0].val_is_null()); + _check_null_pointing_at(tree[0], key, "NULL:", tree.arena()); + _check_null_pointing_at(tree[0], val, "NULL}", tree.arena()); + + tree = parse_in_arena(R"({ : })"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), nullptr); + EXPECT_EQ(tree.val(1), nullptr); + EXPECT_TRUE(tree.key_is_null(1)); + EXPECT_TRUE(tree.val_is_null(1)); + EXPECT_TRUE(tree[0].key_is_null()); + EXPECT_TRUE(tree[0].val_is_null()); + _check_null_pointing_at(tree[0], key, ": }", tree.arena()); + _check_null_pointing_at(tree[0], val, " }", tree.arena()); + + tree = parse_in_arena(R"({~: ~})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "~"); + EXPECT_EQ(tree.val(1), "~"); + EXPECT_TRUE(tree.key_is_null(1)); + EXPECT_TRUE(tree.val_is_null(1)); + EXPECT_TRUE(tree[0].key_is_null()); + EXPECT_TRUE(tree[0].val_is_null()); + _check_null_pointing_at(tree[0], key, "~:", tree.arena()); + _check_null_pointing_at(tree[0], val, "~}", tree.arena()); + + tree = parse_in_arena(R"({"~": "~"})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "~"); + EXPECT_EQ(tree.val(1), "~"); + EXPECT_NE(tree.key(1), nullptr); + EXPECT_NE(tree.val(1), nullptr); + EXPECT_FALSE(tree.key_is_null(1)); + EXPECT_FALSE(tree.val_is_null(1)); + EXPECT_FALSE(tree[0].key_is_null()); + EXPECT_FALSE(tree[0].val_is_null()); + + tree = parse_in_arena(R"({"null": "null"})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "null"); + EXPECT_EQ(tree.val(1), "null"); + EXPECT_NE(tree.key(1), nullptr); + EXPECT_NE(tree.val(1), nullptr); + EXPECT_FALSE(tree[0].key_is_null()); + EXPECT_FALSE(tree[0].val_is_null()); + + tree = parse_in_arena(R"({"Null": "Null"})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "Null"); + EXPECT_EQ(tree.val(1), "Null"); + EXPECT_NE(tree.key(1), nullptr); + EXPECT_NE(tree.val(1), nullptr); + EXPECT_FALSE(tree.key_is_null(1)); + EXPECT_FALSE(tree.val_is_null(1)); + EXPECT_FALSE(tree[0].key_is_null()); + EXPECT_FALSE(tree[0].val_is_null()); + + tree = parse_in_arena(R"({"NULL": "NULL"})"); + ASSERT_EQ(tree.size(), 2u); + EXPECT_EQ(tree.root_id(), 0u); + EXPECT_EQ(tree.first_child(0), 1u); + EXPECT_TRUE(tree.type(1).is_keyval()); + EXPECT_EQ(tree.key(1), "NULL"); + EXPECT_EQ(tree.val(1), "NULL"); + EXPECT_NE(tree.key(1), nullptr); + EXPECT_NE(tree.val(1), nullptr); + EXPECT_FALSE(tree.key_is_null(1)); + EXPECT_FALSE(tree.val_is_null(1)); + EXPECT_FALSE(tree[0].key_is_null()); + EXPECT_FALSE(tree[0].val_is_null()); + + C4_SUPPRESS_WARNING_GCC_POP +} + + +TEST(null_val, null_key) +{ + auto tree = parse_in_arena(R"({null: null})"); + + ASSERT_EQ(tree.size(), 2u); + _check_null_pointing_at(tree[0], key, "null: ", tree.arena()); + _check_null_pointing_at(tree[0], val, "null}", tree.arena()); +} + + +TEST(null_val, readme_example) +{ + csubstr yaml = R"( +seq: + - ~ + - null + - + - + # a comment + - +map: + val0: ~ + val1: null + val2: + val3: + # a comment + val4: +)"; + Parser p; + Tree t = p.parse_in_arena("file.yml", yaml); + // as expected: (len is null, str is pointing at the value where the node starts) + EXPECT_EQ(t["seq"][0].val(), "~"); + EXPECT_EQ(t["seq"][1].val(), "null"); + EXPECT_EQ(t["seq"][2].val(), nullptr); + EXPECT_EQ(t["seq"][3].val(), nullptr); + EXPECT_EQ(t["seq"][4].val(), nullptr); + EXPECT_EQ(t["map"][0].val(), "~"); + EXPECT_EQ(t["map"][1].val(), "null"); + EXPECT_EQ(t["map"][2].val(), nullptr); + EXPECT_EQ(t["map"][3].val(), nullptr); + EXPECT_EQ(t["map"][4].val(), nullptr); + // standard null values point at the expected location: + EXPECT_EQ(csubstr(t["seq"][0].val().str, 1), csubstr("~")); + EXPECT_EQ(csubstr(t["seq"][1].val().str, 4), csubstr("null")); + EXPECT_EQ(csubstr(t["map"]["val0"].val().str, 1), csubstr("~")); + EXPECT_EQ(csubstr(t["map"]["val1"].val().str, 4), csubstr("null")); +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +CASE_GROUP(NULL_VAL) +{ + +ADD_CASE_TO_GROUP("all null", +R"( +- +- # with space +- null +- Null +- NULL +- ~ +- null: null +- Null: Null +- NULL: NULL +- ~: ~ +- ~: null +- null: ~ +)", +L{ +N(VAL, nullptr), +N(VAL, nullptr), +N(VAL, "null"), +N(VAL, "Null"), +N(VAL, "NULL"), +N(VAL, "~"), +N(MAP, L{N(KEYVAL, "null", "null")}), +N(MAP, L{N(KEYVAL, "Null", "Null")}), +N(MAP, L{N(KEYVAL, "NULL", "NULL")}), +N(MAP, L{N(KEYVAL, "~", "~")}), +N(MAP, L{N(KEYVAL, "~", "null")}), +N(MAP, L{N(KEYVAL, "null", "~")}), +}); + +ADD_CASE_TO_GROUP("null map vals, expl", +R"({foo: , bar: , baz: } +)", +L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} +); + +ADD_CASE_TO_GROUP("null map vals, impl", +R"( +foo: +bar: +baz: +)", +L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} +); + +ADD_CASE_TO_GROUP("null seq vals, impl", +R"(- +- +- +)", +L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)} +); + +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 1", +R"( +foo: + - + - + - +bar: +baz: +)", +L{N("foo", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)}), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)} +); + +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 2", +R"( +foo: +bar: + - + - + - +baz: +)", +L{N(KEYVAL, "foo", nullptr), N("bar", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)}), N(KEYVAL, "baz", nullptr)} +); + +ADD_CASE_TO_GROUP("null seq vals in map, impl, mixed 3", +R"( +foo: +bar: +baz: + - + - + - +)", +L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N("baz", L{N(VAL, nullptr), N(VAL, nullptr), N(VAL, nullptr)})} +); + +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 1", +R"( +- foo: + bar: + baz: +- +- +)", +L{N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)}), N(VAL, nullptr), N(VAL, nullptr)} +); + +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 2", +R"( +- +- foo: + bar: + baz: +- +)", +L{N(VAL, nullptr), N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)}), N(VAL, nullptr)} +); + +ADD_CASE_TO_GROUP("null map vals in seq, impl, mixed 3", +R"( +- +- +- foo: + bar: + baz: +)", +L{N(VAL, nullptr), N(VAL, nullptr), N(L{N(KEYVAL, "foo", nullptr), N(KEYVAL, "bar", nullptr), N(KEYVAL, "baz", nullptr)})} +); + +ADD_CASE_TO_GROUP("issue84.1", +R"( +fixed case: + foo: a + bar: +your case: + foo: a + bar: '' +whatever: baz +)", +L{ +N("fixed case", L{N("foo", "a"), N(KEYVAL, "bar", nullptr)}), +N("your case", L{N("foo", "a"), N(QV, "bar", "")}), +N("whatever", "baz"), +}); + +ADD_CASE_TO_GROUP("issue84.2", +R"( +version: 0 +type: xml +param_root: + objects: + System: {SameGroupActorName: '', IsGetItemSelf: false} + General: + Speed: 1.0 + Life: 100 + IsLifeInfinite: false + ElectricalDischarge: 1.0 + IsBurnOutBorn: false + BurnOutBornName: + IsBurnOutBornIdent: false + ChangeDropTableName: '' +)", +L{ +N("version", "0"), +N("type", "xml"), +N("param_root", L{ + N("objects", L{ + N("System", L{ + N(QV, "SameGroupActorName", ""), + N("IsGetItemSelf", "false") + }), + N("General", L{ + N("Speed", "1.0"), + N("Life", "100"), + N("IsLifeInfinite", "false"), + N("ElectricalDischarge", "1.0"), + N("IsBurnOutBorn", "false"), + N(KEYVAL, "BurnOutBornName", nullptr), + N("IsBurnOutBornIdent", "false"), + N(QV, "ChangeDropTableName", ""), + }), + }) +}), +}); + +ADD_CASE_TO_GROUP("issue84.3", +R"( +version: 10 +type: test +param_root: + objects: + TestContent: + Str64_empty: '' + Str64_empty2: + Str64_empty3: '' + lists: {} +)", +L{ +N("version", "10"), +N("type", "test"), +N("param_root", L{ + N("objects", L{ + N("TestContent", L{ + N(QV, "Str64_empty", ""), + N(KEYVAL, "Str64_empty2", nullptr), + N(QV, "Str64_empty3", ""), + }), + }), + N(KEYMAP, "lists", L{}) +}), +}); + +} + +} // namespace yml +} // namespace c4 + +C4_SUPPRESS_WARNING_GCC_POP |