123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- // __ _____ _____ _____
- // __| | __| | | | JSON for Modern C++ (supporting code)
- // | | |__ | | | | | | version 3.11.2
- // |_____|_____|_____|_|___| https://github.com/nlohmann/json
- //
- // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
- // SPDX-License-Identifier: MIT
- // cmake/test.cmake selects the C++ standard versions with which to build a
- // unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
- // When using macros that are only defined for particular versions of the standard
- // (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
- // version macro in a comment close by, like this:
- // JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
- #include "doctest_compatibility.h"
- #define JSON_TESTS_PRIVATE
- #include <nlohmann/json.hpp>
- using nlohmann::json;
- #if JSON_HAS_THREE_WAY_COMPARISON
- // this can be replaced with the doctest stl extension header in version 2.5
- namespace doctest
- {
- template<> struct StringMaker<std::partial_ordering>
- {
- static String convert(const std::partial_ordering& order)
- {
- if (order == std::partial_ordering::less)
- {
- return "std::partial_ordering::less";
- }
- if (order == std::partial_ordering::equivalent)
- {
- return "std::partial_ordering::equivalent";
- }
- if (order == std::partial_ordering::greater)
- {
- return "std::partial_ordering::greater";
- }
- if (order == std::partial_ordering::unordered)
- {
- return "std::partial_ordering::unordered";
- }
- return "{?}";
- }
- };
- } // namespace doctest
- #endif
- namespace
- {
- // helper function to check std::less<json::value_t>
- // see https://en.cppreference.com/w/cpp/utility/functional/less
- template <typename A, typename B, typename U = std::less<json::value_t>>
- bool f(A a, B b, U u = U())
- {
- return u(a, b);
- }
- } // namespace
- TEST_CASE("lexicographical comparison operators")
- {
- constexpr auto f_ = false;
- constexpr auto _t = true;
- constexpr auto nan = std::numeric_limits<json::number_float_t>::quiet_NaN();
- #if JSON_HAS_THREE_WAY_COMPARISON
- constexpr auto lt = std::partial_ordering::less;
- constexpr auto gt = std::partial_ordering::greater;
- constexpr auto eq = std::partial_ordering::equivalent;
- constexpr auto un = std::partial_ordering::unordered;
- #endif
- #if JSON_HAS_THREE_WAY_COMPARISON
- INFO("using 3-way comparison");
- #endif
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- INFO("using legacy comparison");
- #endif
- //REQUIRE(std::numeric_limits<json::number_float_t>::has_quiet_NaN);
- REQUIRE(std::isnan(nan));
- SECTION("types")
- {
- std::vector<json::value_t> j_types =
- {
- json::value_t::null,
- json::value_t::boolean,
- json::value_t::number_integer,
- json::value_t::number_unsigned,
- json::value_t::number_float,
- json::value_t::object,
- json::value_t::array,
- json::value_t::string,
- json::value_t::binary,
- json::value_t::discarded
- };
- std::vector<std::vector<bool>> expected_lt =
- {
- //0 1 2 3 4 5 6 7 8 9
- {f_, _t, _t, _t, _t, _t, _t, _t, _t, f_}, // 0
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, f_}, // 1
- {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 2
- {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 3
- {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 4
- {f_, f_, f_, f_, f_, f_, _t, _t, _t, f_}, // 5
- {f_, f_, f_, f_, f_, f_, f_, _t, _t, f_}, // 6
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, f_}, // 7
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
- };
- SECTION("comparison: less")
- {
- REQUIRE(expected_lt.size() == j_types.size());
- for (size_t i = 0; i < j_types.size(); ++i)
- {
- REQUIRE(expected_lt[i].size() == j_types.size());
- for (size_t j = 0; j < j_types.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- // check precomputed values
- #if JSON_HAS_THREE_WAY_COMPARISON
- // JSON_HAS_CPP_20 (do not remove; see note at top of file)
- CHECK((j_types[i] < j_types[j]) == expected_lt[i][j]);
- #else
- CHECK(operator<(j_types[i], j_types[j]) == expected_lt[i][j]);
- #endif
- CHECK(f(j_types[i], j_types[j]) == expected_lt[i][j]);
- }
- }
- }
- #if JSON_HAS_THREE_WAY_COMPARISON
- // JSON_HAS_CPP_20 (do not remove; see note at top of file)
- SECTION("comparison: 3-way")
- {
- std::vector<std::vector<std::partial_ordering>> expected =
- {
- //0 1 2 3 4 5 6 7 8 9
- {eq, lt, lt, lt, lt, lt, lt, lt, lt, un}, // 0
- {gt, eq, lt, lt, lt, lt, lt, lt, lt, un}, // 1
- {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 2
- {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 3
- {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 4
- {gt, gt, gt, gt, gt, eq, lt, lt, lt, un}, // 5
- {gt, gt, gt, gt, gt, gt, eq, lt, lt, un}, // 6
- {gt, gt, gt, gt, gt, gt, gt, eq, lt, un}, // 7
- {gt, gt, gt, gt, gt, gt, gt, gt, eq, un}, // 8
- {un, un, un, un, un, un, un, un, un, un}, // 9
- };
- // check expected partial_ordering against expected boolean
- REQUIRE(expected.size() == expected_lt.size());
- for (size_t i = 0; i < expected.size(); ++i)
- {
- REQUIRE(expected[i].size() == expected_lt[i].size());
- for (size_t j = 0; j < expected[i].size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
- }
- }
- // check 3-way comparison against expected partial_ordering
- REQUIRE(expected.size() == j_types.size());
- for (size_t i = 0; i < j_types.size(); ++i)
- {
- REQUIRE(expected[i].size() == j_types.size());
- for (size_t j = 0; j < j_types.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
- }
- }
- }
- #endif
- }
- SECTION("values")
- {
- json j_values =
- {
- nullptr, nullptr, // 0 1
- -17, 42, // 2 3
- 8u, 13u, // 4 5
- 3.14159, 23.42, // 6 7
- nan, nan, // 8 9
- "foo", "bar", // 10 11
- true, false, // 12 13
- {1, 2, 3}, {"one", "two", "three"}, // 14 15
- {{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}, // 16 17
- json::binary({1, 2, 3}), json::binary({1, 2, 4}), // 18 19
- json(json::value_t::discarded), json(json::value_t::discarded) // 20 21
- };
- std::vector<std::vector<bool>> expected_eq =
- {
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- {_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
- {_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
- {f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
- {f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
- {f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
- {f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
- {f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
- {f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_}, // 14
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_}, // 15
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_}, // 16
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_}, // 17
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_}, // 18
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 19
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
- };
- std::vector<std::vector<bool>> expected_lt =
- {
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 0
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 1
- {f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 2
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 3
- {f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 4
- {f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 5
- {f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 6
- {f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 7
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 8
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 9
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 10
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 11
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 12
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 13
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_}, // 14
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 15
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_}, // 16
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_}, // 17
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 18
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
- };
- SECTION("compares unordered")
- {
- std::vector<std::vector<bool>> expected =
- {
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 0
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 1
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 2
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 3
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 4
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 5
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 6
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 7
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 8
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 9
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 10
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 11
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 12
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 13
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 14
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 15
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 16
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 17
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 18
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 19
- {_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 20
- {_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 21
- };
- // check if two values compare unordered as expected
- REQUIRE(expected.size() == j_values.size());
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- REQUIRE(expected[i].size() == j_values.size());
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK(json::compares_unordered(j_values[i], j_values[j]) == expected[i][j]);
- }
- }
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- SECTION("compares unordered (inverse)")
- {
- std::vector<std::vector<bool>> expected =
- {
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
- {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
- {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 14
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 15
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 16
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 17
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 18
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
- {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
- };
- // check that two values compare unordered as expected (with legacy-mode enabled)
- REQUIRE(expected.size() == j_values.size());
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- REQUIRE(expected[i].size() == j_values.size());
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CAPTURE(j_values[i])
- CAPTURE(j_values[j])
- CHECK(json::compares_unordered(j_values[i], j_values[j], true) == expected[i][j]);
- }
- }
- }
- #endif
- SECTION("comparison: equal")
- {
- // check that two values compare equal
- REQUIRE(expected_eq.size() == j_values.size());
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- REQUIRE(expected_eq[i].size() == j_values.size());
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK((j_values[i] == j_values[j]) == expected_eq[i][j]);
- }
- }
- // compare with null pointer
- json j_null;
- CHECK(j_null == nullptr);
- CHECK(nullptr == j_null);
- }
- SECTION("comparison: not equal")
- {
- // check that two values compare unequal as expected
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- if (json::compares_unordered(j_values[i], j_values[j], true))
- {
- // if two values compare unordered,
- // check that the boolean comparison result is always false
- CHECK_FALSE(j_values[i] != j_values[j]);
- }
- else
- {
- // otherwise, check that they compare according to their definition
- // as the inverse of equal
- CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
- }
- }
- }
- // compare with null pointer
- const json j_null;
- CHECK((j_null != nullptr) == false);
- CHECK((nullptr != j_null) == false);
- CHECK((j_null != nullptr) == !(j_null == nullptr));
- CHECK((nullptr != j_null) == !(nullptr == j_null));
- }
- SECTION("comparison: less")
- {
- // check that two values compare less than as expected
- REQUIRE(expected_lt.size() == j_values.size());
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- REQUIRE(expected_lt[i].size() == j_values.size());
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK((j_values[i] < j_values[j]) == expected_lt[i][j]);
- }
- }
- }
- SECTION("comparison: less than or equal equal")
- {
- // check that two values compare less than or equal as expected
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- if (json::compares_unordered(j_values[i], j_values[j], true))
- {
- // if two values compare unordered,
- // check that the boolean comparison result is always false
- CHECK_FALSE(j_values[i] <= j_values[j]);
- }
- else
- {
- // otherwise, check that they compare according to their definition
- // as the inverse of less than with the operand order reversed
- CHECK((j_values[i] <= j_values[j]) == !(j_values[j] < j_values[i]));
- }
- }
- }
- }
- SECTION("comparison: greater than")
- {
- // check that two values compare greater than as expected
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- if (json::compares_unordered(j_values[i], j_values[j]))
- {
- // if two values compare unordered,
- // check that the boolean comparison result is always false
- CHECK_FALSE(j_values[i] > j_values[j]);
- }
- else
- {
- // otherwise, check that they compare according to their definition
- // as the inverse of less than or equal which is defined as
- // the inverse of less than with the operand order reversed
- CHECK((j_values[i] > j_values[j]) == !(j_values[i] <= j_values[j]));
- CHECK((j_values[i] > j_values[j]) == !!(j_values[j] < j_values[i]));
- }
- }
- }
- }
- SECTION("comparison: greater than or equal")
- {
- // check that two values compare greater than or equal as expected
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- if (json::compares_unordered(j_values[i], j_values[j], true))
- {
- // if two values compare unordered,
- // check that the boolean result is always false
- CHECK_FALSE(j_values[i] >= j_values[j]);
- }
- else
- {
- // otherwise, check that they compare according to their definition
- // as the inverse of less than
- CHECK((j_values[i] >= j_values[j]) == !(j_values[i] < j_values[j]));
- }
- }
- }
- }
- #if JSON_HAS_THREE_WAY_COMPARISON
- // JSON_HAS_CPP_20 (do not remove; see note at top of file)
- SECTION("comparison: 3-way")
- {
- std::vector<std::vector<std::partial_ordering>> expected =
- {
- //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
- {eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 0
- {eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 1
- {gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 2
- {gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 3
- {gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 4
- {gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 5
- {gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 6
- {gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 7
- {gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 8
- {gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 9
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 10
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 11
- {gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un}, // 12
- {gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un}, // 13
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un}, // 14
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un}, // 15
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un}, // 16
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un}, // 17
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un}, // 18
- {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un}, // 19
- {un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 20
- {un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 21
- };
- // check expected partial_ordering against expected booleans
- REQUIRE(expected.size() == expected_eq.size());
- REQUIRE(expected.size() == expected_lt.size());
- for (size_t i = 0; i < expected.size(); ++i)
- {
- REQUIRE(expected[i].size() == expected_eq[i].size());
- REQUIRE(expected[i].size() == expected_lt[i].size());
- for (size_t j = 0; j < expected[i].size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK(std::is_eq(expected[i][j]) == expected_eq[i][j]);
- CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
- if (std::is_gt(expected[i][j]))
- {
- CHECK((!expected_eq[i][j] && !expected_lt[i][j]));
- }
- }
- }
- // check that two values compare according to their expected ordering
- REQUIRE(expected.size() == j_values.size());
- for (size_t i = 0; i < j_values.size(); ++i)
- {
- REQUIRE(expected[i].size() == j_values.size());
- for (size_t j = 0; j < j_values.size(); ++j)
- {
- CAPTURE(i)
- CAPTURE(j)
- CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
- }
- }
- }
- #endif
- }
- #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
- SECTION("parser callback regression")
- {
- SECTION("filter specific element")
- {
- const auto* s_object = R"(
- {
- "foo": 2,
- "bar": {
- "baz": 1
- }
- }
- )";
- const auto* s_array = R"(
- [1,2,[3,4,5],4,5]
- )";
- json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
- {
- // filter all number(2) elements
- return j != json(2);
- });
- CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
- json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
- {
- return j != json(2);
- });
- CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
- }
- }
- #endif
- }
|