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_serialize.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_serialize.cpp')
| -rw-r--r-- | thirdparty/ryml/test/test_serialize.cpp | 499 |
1 files changed, 499 insertions, 0 deletions
diff --git a/thirdparty/ryml/test/test_serialize.cpp b/thirdparty/ryml/test/test_serialize.cpp new file mode 100644 index 000000000..979de7c79 --- /dev/null +++ b/thirdparty/ryml/test/test_serialize.cpp @@ -0,0 +1,499 @@ +#ifndef RYML_SINGLE_HEADER +#include "c4/yml/std/std.hpp" +#include "c4/yml/parse.hpp" +#include "c4/yml/emit.hpp" +#include <c4/format.hpp> +#include <c4/yml/detail/checks.hpp> +#include <c4/yml/detail/print.hpp> +#endif + +#include "./test_case.hpp" + +#include <gtest/gtest.h> + +#if defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable: 4389) // signed/unsigned mismatch +#elif defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdollar-in-identifier-extension" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +#endif + +namespace foo { + +template<class T> +struct vec2 +{ + T x, y; +}; +template<class T> +struct vec3 +{ + T x, y, z; +}; +template<class T> +struct vec4 +{ + T x, y, z, w; +}; + +template<class T> size_t to_chars(c4::substr buf, vec2<T> v) { return c4::format(buf, "({},{})", v.x, v.y); } +template<class T> size_t to_chars(c4::substr buf, vec3<T> v) { return c4::format(buf, "({},{},{})", v.x, v.y, v.z); } +template<class T> size_t to_chars(c4::substr buf, vec4<T> v) { return c4::format(buf, "({},{},{},{})", v.x, v.y, v.z, v.w); } + +template<class T> bool from_chars(c4::csubstr buf, vec2<T> *v) { size_t ret = c4::unformat(buf, "({},{})", v->x, v->y); return ret != c4::yml::npos; } +template<class T> bool from_chars(c4::csubstr buf, vec3<T> *v) { size_t ret = c4::unformat(buf, "({},{},{})", v->x, v->y, v->z); return ret != c4::yml::npos; } +template<class T> bool from_chars(c4::csubstr buf, vec4<T> *v) { size_t ret = c4::unformat(buf, "({},{},{},{})", v->x, v->y, v->z, v->w); return ret != c4::yml::npos; } + +TEST(serialize, type_as_str) +{ + c4::yml::Tree t; + + auto r = t.rootref(); + r |= c4::yml::MAP; + + vec2<int> v2in{10, 11}; + vec2<int> v2out{1, 2}; + r["v2"] << v2in; + r["v2"] >> v2out; + EXPECT_EQ(v2in.x, v2out.x); + EXPECT_EQ(v2in.y, v2out.y); + + vec3<int> v3in{100, 101, 102}; + vec3<int> v3out{1, 2, 3}; + r["v3"] << v3in; + r["v3"] >> v3out; + EXPECT_EQ(v3in.x, v3out.x); + EXPECT_EQ(v3in.y, v3out.y); + EXPECT_EQ(v3in.z, v3out.z); + + vec4<int> v4in{1000, 1001, 1002, 1003}; + vec4<int> v4out{1, 2, 3, 4}; + r["v4"] << v4in; + r["v4"] >> v4out; + EXPECT_EQ(v4in.x, v4out.x); + EXPECT_EQ(v4in.y, v4out.y); + EXPECT_EQ(v4in.z, v4out.z); + EXPECT_EQ(v4in.w, v4out.w); + + char buf[256]; + c4::csubstr ret = c4::yml::emit_yaml(t, buf); + EXPECT_EQ(ret, R"(v2: '(10,11)' +v3: '(100,101,102)' +v4: '(1000,1001,1002,1003)' +)"); +} +} // namespace foo + + +namespace c4 { +namespace yml { + +//------------------------------------------- +template<class Container, class... Args> +void do_test_serialize(Args&& ...args) +{ + using namespace c4::yml; + Container s(std::forward<Args>(args)...); + Container out; + + Tree t; + NodeRef n(&t); + + n << s; + //print_tree(t); + emit_yaml(t); + c4::yml::check_invariants(t); + n >> out; + EXPECT_EQ(s, out); +} + + +TEST(serialize, std_vector_int) +{ + using T = int; + using L = std::initializer_list<T>; + do_test_serialize<std::vector<T>>(L{1, 2, 3, 4, 5}); +} +TEST(serialize, std_vector_bool) +{ + using T = bool; + using L = std::initializer_list<T>; + do_test_serialize<std::vector<T>>(L{true, false, true, false, true, true}); +} +TEST(serialize, std_vector_string) +{ + using T = std::string; + using L = std::initializer_list<T>; + do_test_serialize<std::vector<T>>(L{"0asdadk0", "1sdfkjdfgu1", "2fdfdjkhdfgkjhdfi2", "3e987dfgnfdg83", "4'd0fgºçdfg«4"}); +} +TEST(serialize, std_vector_std_vector_int) +{ + using T = std::vector<int>; + using L = std::initializer_list<T>; + do_test_serialize<std::vector<T>>(L{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 0}}); +} + + +TEST(serialize, std_map__int_int) +{ + using M = std::map<int, int>; + using L = std::initializer_list<typename M::value_type>; + do_test_serialize<M>(L{{10, 0}, {11, 1}, {22, 2}, {10001, 1000}, {20002, 2000}, {30003, 3000}}); +} +TEST(serialize, std_map__std_string_int) +{ + using M = std::map<std::string, int>; + using L = std::initializer_list<typename M::value_type>; + do_test_serialize<M>(L{{"asdsdf", 0}, {"dfgdfgdfg", 1}, {"dfgjdfgkjh", 2}}); +} +TEST(serialize, std_map__string_vectori) +{ + using M = std::map<std::string, std::vector<int>>; + using L = std::initializer_list<typename M::value_type>; + do_test_serialize<M>(L{{"asdsdf", {0, 1, 2, 3}}, {"dfgdfgdfg", {4, 5, 6, 7}}, {"dfgjdfgkjh", {8, 9, 10, 11}}}); +} +TEST(serialize, std_vector__map_string_int) +{ + using V = std::vector< std::map<std::string, int>>; + using M = typename V::value_type; + using L = std::initializer_list<M>; + do_test_serialize<V>(L{ + M{{"asdasf", 0}, {"dfgkjhdfg", 1}, {"fghffg", 2}, {"r5656kjnh9b'dfgwg+*", 3}}, + M{{"asdasf", 10}, {"dfgkjhdfg", 11}, {"fghffg", 12}, {"r5656kjnh9b'dfgwg+*", 13}}, + M{{"asdasf", 20}, {"dfgkjhdfg", 21}, {"fghffg", 22}, {"r5656kjnh9b'dfgwg+*", 23}}, + M{{"asdasf", 30}, {"dfgkjhdfg", 31}, {"fghffg", 32}, {"r5656kjnh9b'dfgwg+*", 33}}, + }); +} + + +TEST(serialize, bool) +{ + Tree t = parse_in_arena("{a: 0, b: false, c: 1, d: true}"); + bool v, w; + t["a"] >> v; + EXPECT_EQ(v, false); + t["b"] >> v; + EXPECT_EQ(v, false); + t["c"] >> v; + EXPECT_EQ(v, true); + t["d"] >> v; + EXPECT_EQ(v, true); + + t["e"] << true; + EXPECT_EQ(t["e"].val(), "1"); + t["e"] >> w; + EXPECT_EQ(w, true); + + t["e"] << false; + EXPECT_EQ(t["e"].val(), "0"); + t["e"] >> w; + EXPECT_EQ(w, false); + + t["e"] << fmt::boolalpha(true); + EXPECT_EQ(t["e"].val(), "true"); + t["e"] >> w; + EXPECT_EQ(w, true); + + t["e"] << fmt::boolalpha(false); + EXPECT_EQ(t["e"].val(), "false"); + t["e"] >> w; + EXPECT_EQ(w, false); +} + +TEST(serialize, nan) +{ + Tree t = parse_in_arena(R"( +good: + - .nan + - .nan + - .NaN + - .NAN + - nan + - + .nan +set: + - nothing + - nothing +})"); + t["set"][0] << std::numeric_limits<float>::quiet_NaN(); + t["set"][1] << std::numeric_limits<double>::quiet_NaN(); + EXPECT_EQ(t["set"][0].val(), ".nan"); + EXPECT_EQ(t["set"][1].val(), ".nan"); + EXPECT_EQ(t["good"][0].val(), ".nan"); + EXPECT_EQ(t["good"][1].val(), ".nan"); + EXPECT_EQ(t["good"][2].val(), ".NaN"); + EXPECT_EQ(t["good"][3].val(), ".NAN"); + EXPECT_EQ(t["good"][4].val(), "nan"); + EXPECT_EQ(t["good"][5].val(), ".nan"); + float f; + double d; + f = 0.f; + d = 0.; + t["good"][0] >> f; + t["good"][0] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); + f = 0.f; + d = 0.; + t["good"][1] >> f; + t["good"][1] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); + f = 0.f; + d = 0.; + t["good"][2] >> f; + t["good"][2] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); + f = 0.f; + d = 0.; + t["good"][3] >> f; + t["good"][3] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); + f = 0.f; + d = 0.; + t["good"][4] >> f; + t["good"][4] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); + f = 0.f; + d = 0.; + t["good"][5] >> f; + t["good"][5] >> d; + EXPECT_TRUE(std::isnan(f)); + EXPECT_TRUE(std::isnan(d)); +} + +TEST(serialize, inf) +{ + C4_SUPPRESS_WARNING_GCC_CLANG_WITH_PUSH("-Wfloat-equal"); + Tree t = parse_in_arena(R"( +good: + - .inf + - .inf + - .Inf + - .INF + - inf + - infinity + - + .inf +set: + - nothing + - nothing +})"); + float finf = std::numeric_limits<float>::infinity(); + double dinf = std::numeric_limits<double>::infinity(); + t["set"][0] << finf; + t["set"][1] << dinf; + EXPECT_EQ(t["set"][0].val(), ".inf"); + EXPECT_EQ(t["set"][1].val(), ".inf"); + EXPECT_EQ(t["good"][0].val(), ".inf"); + EXPECT_EQ(t["good"][1].val(), ".inf"); + EXPECT_EQ(t["good"][2].val(), ".Inf"); + EXPECT_EQ(t["good"][3].val(), ".INF"); + EXPECT_EQ(t["good"][4].val(), "inf"); + EXPECT_EQ(t["good"][5].val(), "infinity"); + EXPECT_EQ(t["good"][6].val(), ".inf"); + float f; + double d; + f = 0.f; + d = 0.; + t["good"][0] >> f; + t["good"][0] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][1] >> f; + t["good"][1] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][2] >> f; + t["good"][2] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][3] >> f; + t["good"][3] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][4] >> f; + t["good"][4] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][5] >> f; + t["good"][5] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + f = 0.f; + d = 0.; + t["good"][6] >> f; + t["good"][6] >> d; + EXPECT_TRUE(f == finf); + EXPECT_TRUE(d == dinf); + + t = parse_in_arena(R"( +good: + - -.inf + - -.inf + - -.Inf + - -.INF + - -inf + - -infinity + - + -.inf +set: + - nothing + - nothing +})"); + t["set"][0] << -finf; + t["set"][1] << -dinf; + EXPECT_EQ(t["set"][0].val(), "-.inf"); + EXPECT_EQ(t["set"][1].val(), "-.inf"); + EXPECT_EQ(t["good"][0].val(), "-.inf"); + EXPECT_EQ(t["good"][1].val(), "-.inf"); + EXPECT_EQ(t["good"][2].val(), "-.Inf"); + EXPECT_EQ(t["good"][3].val(), "-.INF"); + EXPECT_EQ(t["good"][4].val(), "-inf"); + EXPECT_EQ(t["good"][5].val(), "-infinity"); + EXPECT_EQ(t["good"][6].val(), "-.inf"); + f = 0.f; + d = 0.; + t["good"][0] >> f; + t["good"][0] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][1] >> f; + t["good"][1] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][2] >> f; + t["good"][2] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][3] >> f; + t["good"][3] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][4] >> f; + t["good"][4] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][5] >> f; + t["good"][5] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + f = 0.f; + d = 0.; + t["good"][6] >> f; + t["good"][6] >> d; + EXPECT_TRUE(f == -finf); + EXPECT_TRUE(d == -dinf); + C4_SUPPRESS_WARNING_GCC_CLANG_POP +} + +TEST(serialize, std_string) +{ + auto t = parse_in_arena("{foo: bar}"); + std::string s; + EXPECT_NE(s, "bar"); + t["foo"] >> s; + EXPECT_EQ(s, "bar"); +} + +TEST(serialize, anchor_and_ref_round_trip) +{ + const char yaml[] = R"(anchor_objects: + - &id001 + name: id001 + - &id002 + name: id002 + - name: id003 + - &id004 + name: id004 +references: + reference_key: *id001 + reference_list: + - *id002 + - *id004 +)"; + + Tree t = parse_in_arena(yaml); + std::string cmpbuf; + emitrs_yaml(t, &cmpbuf); + EXPECT_EQ(cmpbuf, yaml); +} + +TEST(serialize, create_anchor_ref_trip) +{ + const char expected_yaml[] = R"(anchor_objects: + - &id001 + name: a_name +reference_list: + - *id001 +)"; + + Tree tree; + auto root_id = tree.root_id(); + tree.to_map(root_id); + + auto anchor_list_id = tree.append_child(root_id); + tree.to_seq(anchor_list_id, "anchor_objects"); + + auto anchor_map0 = tree.append_child(anchor_list_id); + tree.to_map(anchor_map0); + tree.set_val_anchor(anchor_map0, "id001"); + + auto anchor_elem0 = tree.append_child(anchor_map0); + tree.to_keyval(anchor_elem0, "name", "a_name"); + + auto ref_list_id = tree.append_child(root_id); + tree.to_seq(ref_list_id, "reference_list"); + + auto elem0_id = tree.append_child(ref_list_id); + tree.set_val_ref(elem0_id, "id001"); + + std::string cmpbuf; + emitrs_yaml(tree, &cmpbuf); + EXPECT_EQ(cmpbuf, expected_yaml); +} + + +//------------------------------------------- +// this is needed to use the test case library +Case const* get_case(csubstr /*name*/) +{ + return nullptr; +} + +} // namespace yml +} // namespace c4 + +#if defined(_MSC_VER) +# pragma warning(pop) +#elif defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif |