1 // __ _____ _____ _____
2 // __| | __| | | | JSON for Modern C++ (supporting code)
3 // | | |__ | | | | | | version 3.11.2
4 // |_____|_____|_____|_|___| https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8
9 // cmake/test.cmake selects the C++ standard versions with which to build a
10 // unit test based on the presence of JSON_HAS_CPP_<VERSION> macros.
11 // When using macros that are only defined for particular versions of the standard
12 // (e.g., JSON_HAS_FILESYSTEM for C++17 and up), please mention the corresponding
13 // version macro in a comment close by, like this:
14 // JSON_HAS_CPP_<VERSION> (do not remove; see note at top of file)
15
16 #include "doctest_compatibility.h"
17
18 #define JSON_TESTS_PRIVATE
19 #include <nlohmann/json.hpp>
20 using nlohmann::json;
21
22 #if JSON_HAS_THREE_WAY_COMPARISON
23 // this can be replaced with the doctest stl extension header in version 2.5
24 namespace doctest
25 {
26 template<> struct StringMaker<std::partial_ordering>
27 {
convertdoctest::StringMaker28 static String convert(const std::partial_ordering& order)
29 {
30 if (order == std::partial_ordering::less)
31 {
32 return "std::partial_ordering::less";
33 }
34 if (order == std::partial_ordering::equivalent)
35 {
36 return "std::partial_ordering::equivalent";
37 }
38 if (order == std::partial_ordering::greater)
39 {
40 return "std::partial_ordering::greater";
41 }
42 if (order == std::partial_ordering::unordered)
43 {
44 return "std::partial_ordering::unordered";
45 }
46 return "{?}";
47 }
48 };
49 } // namespace doctest
50 #endif
51
52 namespace
53 {
54 // helper function to check std::less<json::value_t>
55 // see https://en.cppreference.com/w/cpp/utility/functional/less
56 template <typename A, typename B, typename U = std::less<json::value_t>>
f(A a,B b,U u=U ())57 bool f(A a, B b, U u = U())
58 {
59 return u(a, b);
60 }
61 } // namespace
62
63 TEST_CASE("lexicographical comparison operators")
64 {
65 constexpr auto f_ = false;
66 constexpr auto _t = true;
67 constexpr auto nan = std::numeric_limits<json::number_float_t>::quiet_NaN();
68 #if JSON_HAS_THREE_WAY_COMPARISON
69 constexpr auto lt = std::partial_ordering::less;
70 constexpr auto gt = std::partial_ordering::greater;
71 constexpr auto eq = std::partial_ordering::equivalent;
72 constexpr auto un = std::partial_ordering::unordered;
73 #endif
74
75 #if JSON_HAS_THREE_WAY_COMPARISON
76 INFO("using 3-way comparison");
77 #endif
78
79 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
80 INFO("using legacy comparison");
81 #endif
82
83 //REQUIRE(std::numeric_limits<json::number_float_t>::has_quiet_NaN);
84 REQUIRE(std::isnan(nan));
85
86 SECTION("types")
87 {
88 std::vector<json::value_t> j_types =
89 {
90 json::value_t::null,
91 json::value_t::boolean,
92 json::value_t::number_integer,
93 json::value_t::number_unsigned,
94 json::value_t::number_float,
95 json::value_t::object,
96 json::value_t::array,
97 json::value_t::string,
98 json::value_t::binary,
99 json::value_t::discarded
100 };
101
102 std::vector<std::vector<bool>> expected_lt =
103 {
104 //0 1 2 3 4 5 6 7 8 9
105 {f_, _t, _t, _t, _t, _t, _t, _t, _t, f_}, // 0
106 {f_, f_, _t, _t, _t, _t, _t, _t, _t, f_}, // 1
107 {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 2
108 {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 3
109 {f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 4
110 {f_, f_, f_, f_, f_, f_, _t, _t, _t, f_}, // 5
111 {f_, f_, f_, f_, f_, f_, f_, _t, _t, f_}, // 6
112 {f_, f_, f_, f_, f_, f_, f_, f_, _t, f_}, // 7
113 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
114 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
115 };
116
117 SECTION("comparison: less")
118 {
119 REQUIRE(expected_lt.size() == j_types.size());
120 for (size_t i = 0; i < j_types.size(); ++i)
121 {
122 REQUIRE(expected_lt[i].size() == j_types.size());
123 for (size_t j = 0; j < j_types.size(); ++j)
124 {
125 CAPTURE(i)
126 CAPTURE(j)
127 // check precomputed values
128 #if JSON_HAS_THREE_WAY_COMPARISON
129 // JSON_HAS_CPP_20 (do not remove; see note at top of file)
130 CHECK((j_types[i] < j_types[j]) == expected_lt[i][j]);
131 #else
132 CHECK(operator<(j_types[i], j_types[j]) == expected_lt[i][j]);
133 #endif
134 CHECK(f(j_types[i], j_types[j]) == expected_lt[i][j]);
135 }
136 }
137 }
138 #if JSON_HAS_THREE_WAY_COMPARISON
139 // JSON_HAS_CPP_20 (do not remove; see note at top of file)
140 SECTION("comparison: 3-way")
141 {
142 std::vector<std::vector<std::partial_ordering>> expected =
143 {
144 //0 1 2 3 4 5 6 7 8 9
145 {eq, lt, lt, lt, lt, lt, lt, lt, lt, un}, // 0
146 {gt, eq, lt, lt, lt, lt, lt, lt, lt, un}, // 1
147 {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 2
148 {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 3
149 {gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 4
150 {gt, gt, gt, gt, gt, eq, lt, lt, lt, un}, // 5
151 {gt, gt, gt, gt, gt, gt, eq, lt, lt, un}, // 6
152 {gt, gt, gt, gt, gt, gt, gt, eq, lt, un}, // 7
153 {gt, gt, gt, gt, gt, gt, gt, gt, eq, un}, // 8
154 {un, un, un, un, un, un, un, un, un, un}, // 9
155 };
156
157 // check expected partial_ordering against expected boolean
158 REQUIRE(expected.size() == expected_lt.size());
159 for (size_t i = 0; i < expected.size(); ++i)
160 {
161 REQUIRE(expected[i].size() == expected_lt[i].size());
162 for (size_t j = 0; j < expected[i].size(); ++j)
163 {
164 CAPTURE(i)
165 CAPTURE(j)
166 CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
167 }
168 }
169
170 // check 3-way comparison against expected partial_ordering
171 REQUIRE(expected.size() == j_types.size());
172 for (size_t i = 0; i < j_types.size(); ++i)
173 {
174 REQUIRE(expected[i].size() == j_types.size());
175 for (size_t j = 0; j < j_types.size(); ++j)
176 {
177 CAPTURE(i)
178 CAPTURE(j)
179 CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
180 }
181 }
182 }
183 #endif
184 }
185
186 SECTION("values")
187 {
188 json j_values =
189 {
190 nullptr, nullptr, // 0 1
191 -17, 42, // 2 3
192 8u, 13u, // 4 5
193 3.14159, 23.42, // 6 7
194 nan, nan, // 8 9
195 "foo", "bar", // 10 11
196 true, false, // 12 13
197 {1, 2, 3}, {"one", "two", "three"}, // 14 15
198 {{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}, // 16 17
199 json::binary({1, 2, 3}), json::binary({1, 2, 4}), // 18 19
200 json(json::value_t::discarded), json(json::value_t::discarded) // 20 21
201 };
202
203 std::vector<std::vector<bool>> expected_eq =
204 {
205 //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
206 {_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
207 {_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
208 {f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
209 {f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
210 {f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
211 {f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
212 {f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
213 {f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
214 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
215 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
216 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
217 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
218 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
219 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
220 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_}, // 14
221 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_}, // 15
222 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_}, // 16
223 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_}, // 17
224 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_}, // 18
225 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 19
226 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
227 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
228 };
229
230 std::vector<std::vector<bool>> expected_lt =
231 {
232 //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
233 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 0
234 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 1
235 {f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 2
236 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 3
237 {f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 4
238 {f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 5
239 {f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 6
240 {f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 7
241 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 8
242 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 9
243 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 10
244 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 11
245 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 12
246 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 13
247 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_}, // 14
248 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 15
249 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_}, // 16
250 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_}, // 17
251 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 18
252 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
253 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
254 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
255 };
256
257 SECTION("compares unordered")
258 {
259 std::vector<std::vector<bool>> expected =
260 {
261 //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
262 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 0
263 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 1
264 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 2
265 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 3
266 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 4
267 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 5
268 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 6
269 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 7
270 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 8
271 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 9
272 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 10
273 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 11
274 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 12
275 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 13
276 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 14
277 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 15
278 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 16
279 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 17
280 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 18
281 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 19
282 {_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 20
283 {_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 21
284 };
285
286 // check if two values compare unordered as expected
287 REQUIRE(expected.size() == j_values.size());
288 for (size_t i = 0; i < j_values.size(); ++i)
289 {
290 REQUIRE(expected[i].size() == j_values.size());
291 for (size_t j = 0; j < j_values.size(); ++j)
292 {
293 CAPTURE(i)
294 CAPTURE(j)
295 CHECK(json::compares_unordered(j_values[i], j_values[j]) == expected[i][j]);
296 }
297 }
298 }
299
300 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
301 SECTION("compares unordered (inverse)")
302 {
303 std::vector<std::vector<bool>> expected =
304 {
305 //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
306 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
307 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
308 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
309 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
310 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
311 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
312 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
313 {f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
314 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
315 {f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
316 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
317 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
318 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
319 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
320 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 14
321 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 15
322 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 16
323 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 17
324 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 18
325 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
326 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
327 {f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
328 };
329
330 // check that two values compare unordered as expected (with legacy-mode enabled)
331 REQUIRE(expected.size() == j_values.size());
332 for (size_t i = 0; i < j_values.size(); ++i)
333 {
334 REQUIRE(expected[i].size() == j_values.size());
335 for (size_t j = 0; j < j_values.size(); ++j)
336 {
337 CAPTURE(i)
338 CAPTURE(j)
339 CAPTURE(j_values[i])
340 CAPTURE(j_values[j])
341 CHECK(json::compares_unordered(j_values[i], j_values[j], true) == expected[i][j]);
342 }
343 }
344 }
345 #endif
346
347 SECTION("comparison: equal")
348 {
349 // check that two values compare equal
350 REQUIRE(expected_eq.size() == j_values.size());
351 for (size_t i = 0; i < j_values.size(); ++i)
352 {
353 REQUIRE(expected_eq[i].size() == j_values.size());
354 for (size_t j = 0; j < j_values.size(); ++j)
355 {
356 CAPTURE(i)
357 CAPTURE(j)
358 CHECK((j_values[i] == j_values[j]) == expected_eq[i][j]);
359 }
360 }
361
362 // compare with null pointer
363 json j_null;
364 CHECK(j_null == nullptr);
365 CHECK(nullptr == j_null);
366 }
367
368 SECTION("comparison: not equal")
369 {
370 // check that two values compare unequal as expected
371 for (size_t i = 0; i < j_values.size(); ++i)
372 {
373 for (size_t j = 0; j < j_values.size(); ++j)
374 {
375 CAPTURE(i)
376 CAPTURE(j)
377
378 if (json::compares_unordered(j_values[i], j_values[j], true))
379 {
380 // if two values compare unordered,
381 // check that the boolean comparison result is always false
382 CHECK_FALSE(j_values[i] != j_values[j]);
383 }
384 else
385 {
386 // otherwise, check that they compare according to their definition
387 // as the inverse of equal
388 CHECK((j_values[i] != j_values[j]) == !(j_values[i] == j_values[j]));
389 }
390 }
391 }
392
393 // compare with null pointer
394 json j_null;
395 CHECK((j_null != nullptr) == false);
396 CHECK((nullptr != j_null) == false);
397 CHECK((j_null != nullptr) == !(j_null == nullptr));
398 CHECK((nullptr != j_null) == !(nullptr == j_null));
399 }
400
401 SECTION("comparison: less")
402 {
403 // check that two values compare less than as expected
404 REQUIRE(expected_lt.size() == j_values.size());
405 for (size_t i = 0; i < j_values.size(); ++i)
406 {
407 REQUIRE(expected_lt[i].size() == j_values.size());
408 for (size_t j = 0; j < j_values.size(); ++j)
409 {
410 CAPTURE(i)
411 CAPTURE(j)
412 CHECK((j_values[i] < j_values[j]) == expected_lt[i][j]);
413 }
414 }
415 }
416
417 SECTION("comparison: less than or equal equal")
418 {
419 // check that two values compare less than or equal as expected
420 for (size_t i = 0; i < j_values.size(); ++i)
421 {
422 for (size_t j = 0; j < j_values.size(); ++j)
423 {
424 CAPTURE(i)
425 CAPTURE(j)
426 if (json::compares_unordered(j_values[i], j_values[j], true))
427 {
428 // if two values compare unordered,
429 // check that the boolean comparison result is always false
430 CHECK_FALSE(j_values[i] <= j_values[j]);
431 }
432 else
433 {
434 // otherwise, check that they compare according to their definition
435 // as the inverse of less than with the operand order reversed
436 CHECK((j_values[i] <= j_values[j]) == !(j_values[j] < j_values[i]));
437 }
438 }
439 }
440 }
441
442 SECTION("comparison: greater than")
443 {
444 // check that two values compare greater than as expected
445 for (size_t i = 0; i < j_values.size(); ++i)
446 {
447 for (size_t j = 0; j < j_values.size(); ++j)
448 {
449 CAPTURE(i)
450 CAPTURE(j)
451 if (json::compares_unordered(j_values[i], j_values[j]))
452 {
453 // if two values compare unordered,
454 // check that the boolean comparison result is always false
455 CHECK_FALSE(j_values[i] > j_values[j]);
456 }
457 else
458 {
459 // otherwise, check that they compare according to their definition
460 // as the inverse of less than or equal which is defined as
461 // the inverse of less than with the operand order reversed
462 CHECK((j_values[i] > j_values[j]) == !(j_values[i] <= j_values[j]));
463 CHECK((j_values[i] > j_values[j]) == !!(j_values[j] < j_values[i]));
464 }
465 }
466 }
467 }
468
469 SECTION("comparison: greater than or equal")
470 {
471 // check that two values compare greater than or equal as expected
472 for (size_t i = 0; i < j_values.size(); ++i)
473 {
474 for (size_t j = 0; j < j_values.size(); ++j)
475 {
476 CAPTURE(i)
477 CAPTURE(j)
478 if (json::compares_unordered(j_values[i], j_values[j], true))
479 {
480 // if two values compare unordered,
481 // check that the boolean result is always false
482 CHECK_FALSE(j_values[i] >= j_values[j]);
483 }
484 else
485 {
486 // otherwise, check that they compare according to their definition
487 // as the inverse of less than
488 CHECK((j_values[i] >= j_values[j]) == !(j_values[i] < j_values[j]));
489 }
490 }
491 }
492 }
493
494 #if JSON_HAS_THREE_WAY_COMPARISON
495 // JSON_HAS_CPP_20 (do not remove; see note at top of file)
496 SECTION("comparison: 3-way")
497 {
498 std::vector<std::vector<std::partial_ordering>> expected =
499 {
500 //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
501 {eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 0
502 {eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 1
503 {gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 2
504 {gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 3
505 {gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 4
506 {gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 5
507 {gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 6
508 {gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 7
509 {gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 8
510 {gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 9
511 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 10
512 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 11
513 {gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un}, // 12
514 {gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un}, // 13
515 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un}, // 14
516 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un}, // 15
517 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un}, // 16
518 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un}, // 17
519 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un}, // 18
520 {gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un}, // 19
521 {un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 20
522 {un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 21
523 };
524
525 // check expected partial_ordering against expected booleans
526 REQUIRE(expected.size() == expected_eq.size());
527 REQUIRE(expected.size() == expected_lt.size());
528 for (size_t i = 0; i < expected.size(); ++i)
529 {
530 REQUIRE(expected[i].size() == expected_eq[i].size());
531 REQUIRE(expected[i].size() == expected_lt[i].size());
532 for (size_t j = 0; j < expected[i].size(); ++j)
533 {
534 CAPTURE(i)
535 CAPTURE(j)
536 CHECK(std::is_eq(expected[i][j]) == expected_eq[i][j]);
537 CHECK(std::is_lt(expected[i][j]) == expected_lt[i][j]);
538 if (std::is_gt(expected[i][j]))
539 {
540 CHECK((!expected_eq[i][j] && !expected_lt[i][j]));
541 }
542 }
543 }
544
545 // check that two values compare according to their expected ordering
546 REQUIRE(expected.size() == j_values.size());
547 for (size_t i = 0; i < j_values.size(); ++i)
548 {
549 REQUIRE(expected[i].size() == j_values.size());
550 for (size_t j = 0; j < j_values.size(); ++j)
551 {
552 CAPTURE(i)
553 CAPTURE(j)
554 CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
555 }
556 }
557 }
558 #endif
559 }
560
561 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
562 SECTION("parser callback regression")
563 {
564 SECTION("filter specific element")
565 {
566 const auto* s_object = R"(
567 {
568 "foo": 2,
569 "bar": {
570 "baz": 1
571 }
572 }
573 )";
574 const auto* s_array = R"(
575 [1,2,[3,4,5],4,5]
576 )";
577
578 json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
__anon7c97999e0202(int , json::parse_event_t , const json & j) 579 {
580 // filter all number(2) elements
581 return j != json(2);
582 });
583
584 CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
585
586 json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
__anon7c97999e0302(int , json::parse_event_t , const json & j) 587 {
588 return j != json(2);
589 });
590
591 CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
592 }
593 }
594 #endif
595 }
596