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