]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
1 | /* |
2 | __ _____ _____ _____ | |
3 | __| | __| | | | JSON for Modern C++ (test suite) | |
4 | | | |__ | | | | | | version 3.10.5 | |
5 | |_____|_____|_____|_|___| https://github.com/nlohmann/json | |
6 | ||
7 | Licensed under the MIT License <http://opensource.org/licenses/MIT>. | |
8 | SPDX-License-Identifier: MIT | |
9 | Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>. | |
10 | ||
11 | Permission is hereby granted, free of charge, to any person obtaining a copy | |
12 | of this software and associated documentation files (the "Software"), to deal | |
13 | in the Software without restriction, including without limitation the rights | |
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
15 | copies of the Software, and to permit persons to whom the Software is | |
16 | furnished to do so, subject to the following conditions: | |
17 | ||
18 | The above copyright notice and this permission notice shall be included in all | |
19 | copies or substantial portions of the Software. | |
20 | ||
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
27 | SOFTWARE. | |
28 | */ | |
29 | ||
30 | #include "doctest_compatibility.h" | |
31 | ||
32 | #include <nlohmann/json.hpp> | |
33 | using nlohmann::json; | |
34 | ||
35 | TEST_CASE("algorithms") | |
36 | { | |
37 | json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"}; | |
38 | json j_object = {{"one", 1}, {"two", 2}}; | |
39 | ||
40 | SECTION("non-modifying sequence operations") | |
41 | { | |
42 | SECTION("std::all_of") | |
43 | { | |
44 | CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value) | |
45 | { | |
46 | return !value.empty(); | |
47 | })); | |
48 | CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value) | |
49 | { | |
50 | return value.type() == json::value_t::number_integer; | |
51 | })); | |
52 | } | |
53 | ||
54 | SECTION("std::any_of") | |
55 | { | |
56 | CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value) | |
57 | { | |
58 | return value.is_string() && value.get<std::string>() == "foo"; | |
59 | })); | |
60 | CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value) | |
61 | { | |
62 | return value.get<int>() > 1; | |
63 | })); | |
64 | } | |
65 | ||
66 | SECTION("std::none_of") | |
67 | { | |
68 | CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value) | |
69 | { | |
70 | return value.empty(); | |
71 | })); | |
72 | CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value) | |
73 | { | |
74 | return value.get<int>() <= 0; | |
75 | })); | |
76 | } | |
77 | ||
78 | SECTION("std::for_each") | |
79 | { | |
80 | SECTION("reading") | |
81 | { | |
82 | int sum = 0; | |
83 | ||
84 | std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value) | |
85 | { | |
86 | if (value.is_number()) | |
87 | { | |
88 | sum += static_cast<int>(value); | |
89 | } | |
90 | }); | |
91 | ||
92 | CHECK(sum == 45); | |
93 | } | |
94 | ||
95 | SECTION("writing") | |
96 | { | |
97 | auto add17 = [](json & value) | |
98 | { | |
99 | if (value.is_array()) | |
100 | { | |
101 | value.push_back(17); | |
102 | } | |
103 | }; | |
104 | ||
105 | std::for_each(j_array.begin(), j_array.end(), add17); | |
106 | ||
107 | CHECK(j_array[6] == json({1, 2, 3, 17})); | |
108 | } | |
109 | } | |
110 | ||
111 | SECTION("std::count") | |
112 | { | |
113 | CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1); | |
114 | } | |
115 | ||
116 | SECTION("std::count_if") | |
117 | { | |
118 | CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value) | |
119 | { | |
120 | return (value.is_number()); | |
121 | }) == 3); | |
122 | CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&) | |
123 | { | |
124 | return true; | |
125 | }) == 9); | |
126 | } | |
127 | ||
128 | SECTION("std::mismatch") | |
129 | { | |
130 | json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"}; | |
131 | auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin()); | |
132 | CHECK(*res.first == json({{"one", 1}, {"two", 2}})); | |
133 | CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}})); | |
134 | } | |
135 | ||
136 | SECTION("std::equal") | |
137 | { | |
138 | SECTION("using operator==") | |
139 | { | |
140 | CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin())); | |
141 | CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin())); | |
142 | CHECK(!std::equal(j_array.begin(), j_array.end(), j_object.begin())); | |
143 | } | |
144 | ||
145 | SECTION("using user-defined comparison") | |
146 | { | |
147 | // compare objects only by size of its elements | |
148 | json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"}; | |
149 | CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin())); | |
150 | CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(), | |
151 | [](const json & a, const json & b) | |
152 | { | |
153 | return (a.size() == b.size()); | |
154 | })); | |
155 | } | |
156 | } | |
157 | ||
158 | SECTION("std::find") | |
159 | { | |
160 | auto it = std::find(j_array.begin(), j_array.end(), json(false)); | |
161 | CHECK(std::distance(j_array.begin(), it) == 5); | |
162 | } | |
163 | ||
164 | SECTION("std::find_if") | |
165 | { | |
166 | auto it = std::find_if(j_array.begin(), j_array.end(), | |
167 | [](const json & value) | |
168 | { | |
169 | return value.is_boolean(); | |
170 | }); | |
171 | CHECK(std::distance(j_array.begin(), it) == 4); | |
172 | } | |
173 | ||
174 | SECTION("std::find_if_not") | |
175 | { | |
176 | auto it = std::find_if_not(j_array.begin(), j_array.end(), | |
177 | [](const json & value) | |
178 | { | |
179 | return value.is_number(); | |
180 | }); | |
181 | CHECK(std::distance(j_array.begin(), it) == 3); | |
182 | } | |
183 | ||
184 | SECTION("std::adjacent_find") | |
185 | { | |
186 | CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end()); | |
187 | CHECK(std::adjacent_find(j_array.begin(), j_array.end(), | |
188 | [](const json & v1, const json & v2) | |
189 | { | |
190 | return v1.type() == v2.type(); | |
191 | }) == j_array.begin()); | |
192 | } | |
193 | } | |
194 | ||
195 | SECTION("modifying sequence operations") | |
196 | { | |
197 | SECTION("std::reverse") | |
198 | { | |
199 | std::reverse(j_array.begin(), j_array.end()); | |
200 | CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13})); | |
201 | } | |
202 | ||
203 | SECTION("std::rotate") | |
204 | { | |
205 | std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end()); | |
206 | CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13})); | |
207 | } | |
208 | ||
209 | SECTION("std::partition") | |
210 | { | |
211 | auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v) | |
212 | { | |
213 | return v.is_string(); | |
214 | }); | |
215 | CHECK(std::distance(j_array.begin(), it) == 2); | |
216 | CHECK(!it[2].is_string()); | |
217 | } | |
218 | } | |
219 | ||
220 | SECTION("sorting operations") | |
221 | { | |
222 | SECTION("std::sort") | |
223 | { | |
224 | SECTION("with standard comparison") | |
225 | { | |
226 | json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr}; | |
227 | std::sort(j.begin(), j.end()); | |
228 | CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"})); | |
229 | } | |
230 | ||
231 | SECTION("with user-defined comparison") | |
232 | { | |
233 | json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr}; | |
234 | std::sort(j.begin(), j.end(), [](const json & a, const json & b) | |
235 | { | |
236 | return a.size() < b.size(); | |
237 | }); | |
238 | CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}})); | |
239 | } | |
240 | ||
241 | SECTION("sorting an object") | |
242 | { | |
243 | json j({{"one", 1}, {"two", 2}}); | |
244 | CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&); | |
245 | CHECK_THROWS_WITH(std::sort(j.begin(), j.end()), | |
246 | "[json.exception.invalid_iterator.209] cannot use offsets with object iterators"); | |
247 | } | |
248 | } | |
249 | ||
250 | SECTION("std::partial_sort") | |
251 | { | |
252 | json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr}; | |
253 | std::partial_sort(j.begin(), j.begin() + 4, j.end()); | |
254 | CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13})); | |
255 | } | |
256 | } | |
257 | ||
258 | SECTION("set operations") | |
259 | { | |
260 | SECTION("std::merge") | |
261 | { | |
262 | { | |
263 | json j1 = {2, 4, 6, 8}; | |
264 | json j2 = {1, 2, 3, 5, 7}; | |
265 | json j3; | |
266 | ||
267 | std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); | |
268 | CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8})); | |
269 | } | |
270 | } | |
271 | ||
272 | SECTION("std::set_difference") | |
273 | { | |
274 | json j1 = {1, 2, 3, 4, 5, 6, 7, 8}; | |
275 | json j2 = {1, 2, 3, 5, 7}; | |
276 | json j3; | |
277 | ||
278 | std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); | |
279 | CHECK(j3 == json({4, 6, 8})); | |
280 | } | |
281 | ||
282 | SECTION("std::set_intersection") | |
283 | { | |
284 | json j1 = {1, 2, 3, 4, 5, 6, 7, 8}; | |
285 | json j2 = {1, 2, 3, 5, 7}; | |
286 | json j3; | |
287 | ||
288 | std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); | |
289 | CHECK(j3 == json({1, 2, 3, 5, 7})); | |
290 | } | |
291 | ||
292 | SECTION("std::set_union") | |
293 | { | |
294 | json j1 = {2, 4, 6, 8}; | |
295 | json j2 = {1, 2, 3, 5, 7}; | |
296 | json j3; | |
297 | ||
298 | std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); | |
299 | CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8})); | |
300 | } | |
301 | ||
302 | SECTION("std::set_symmetric_difference") | |
303 | { | |
304 | json j1 = {2, 4, 6, 8}; | |
305 | json j2 = {1, 2, 3, 5, 7}; | |
306 | json j3; | |
307 | ||
308 | std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3)); | |
309 | CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8})); | |
310 | } | |
311 | } | |
312 | ||
313 | SECTION("heap operations") | |
314 | { | |
315 | std::make_heap(j_array.begin(), j_array.end()); | |
316 | CHECK(std::is_heap(j_array.begin(), j_array.end())); | |
317 | std::sort_heap(j_array.begin(), j_array.end()); | |
318 | CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"})); | |
319 | } | |
320 | } |