• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2      __ _____ _____ _____
3   __|  |   __|     |   | |  JSON for Modern C++ (test suite)
4  |  |  |__   |  |  | | | |  version 3.9.1
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-2019 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)
__anon6eb5060e0102(const json & value) 45              {
46                  return value.size() > 0;
47              }));
48              CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
__anon6eb5060e0202(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)
__anon6eb5060e0302(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)
__anon6eb5060e0402(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)
__anon6eb5060e0502(const json & value) 69              {
70                  return value.size() == 0;
71              }));
72              CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
__anon6eb5060e0602(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)
__anon6eb5060e0702(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)
__anon6eb5060e0802(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)
__anon6eb5060e0902(const json & value) 119              {
120                  return (value.is_number());
121              }) == 3);
122              CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
__anon6eb5060e0a02(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)
__anon6eb5060e0b02(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)
__anon6eb5060e0c02(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)
__anon6eb5060e0d02(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)
__anon6eb5060e0e02(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)
__anon6eb5060e0f02(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)
__anon6eb5060e1002(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  }
321