• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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