1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3 // |  |  |__   |  |  | | | |  version 3.11.2
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
7 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
8 // SPDX-License-Identifier: MIT
9 
10 #include "doctest_compatibility.h"
11 
12 #include <nlohmann/json.hpp>
13 using nlohmann::json;
14 
15 TEST_CASE("modifiers")
16 {
17     SECTION("clear()")
18     {
19         SECTION("boolean")
20         {
21             json j = true;
22             json k = j;
23 
24             j.clear();
25             CHECK(j == json(json::value_t::boolean));
26             CHECK(j == json(k.type()));
27         }
28 
29         SECTION("string")
30         {
31             json j = "hello world";
32             json k = j;
33 
34             j.clear();
35             CHECK(j == json(json::value_t::string));
36             CHECK(j == json(k.type()));
37         }
38 
39         SECTION("array")
40         {
41             SECTION("empty array")
42             {
43                 json j = json::array();
44                 json k = j;
45 
46                 j.clear();
47                 CHECK(j.empty());
48                 CHECK(j == json(json::value_t::array));
49                 CHECK(j == json(k.type()));
50             }
51 
52             SECTION("filled array")
53             {
54                 json j = {1, 2, 3};
55                 json k = j;
56 
57                 j.clear();
58                 CHECK(j.empty());
59                 CHECK(j == json(json::value_t::array));
60                 CHECK(j == json(k.type()));
61             }
62         }
63 
64         SECTION("object")
65         {
66             SECTION("empty object")
67             {
68                 json j = json::object();
69                 json k = j;
70 
71                 j.clear();
72                 CHECK(j.empty());
73                 CHECK(j == json(json::value_t::object));
74                 CHECK(j == json(k.type()));
75             }
76 
77             SECTION("filled object")
78             {
79                 json j = {{"one", 1}, {"two", 2}, {"three", 3}};
80                 json k = j;
81 
82                 j.clear();
83                 CHECK(j.empty());
84                 CHECK(j == json(json::value_t::object));
85                 CHECK(j == json(k.type()));
86             }
87         }
88 
89         SECTION("binary")
90         {
91             SECTION("empty binary")
92             {
93                 json j = json::binary({});
94                 json k = j;
95 
96                 j.clear();
97                 CHECK(!j.empty());
98                 CHECK(j == json(json::value_t::binary));
99                 CHECK(j == json(k.type()));
100             }
101 
102             SECTION("filled binary")
103             {
104                 json j = json::binary({1, 2, 3, 4, 5});
105                 json k = j;
106 
107                 j.clear();
108                 CHECK(!j.empty());
109                 CHECK(j == json(json::value_t::binary));
110                 CHECK(j == json(k.type()));
111             }
112         }
113 
114         SECTION("number (integer)")
115         {
116             json j = 23;
117             json k = j;
118 
119             j.clear();
120             CHECK(j == json(json::value_t::number_integer));
121             CHECK(j == json(k.type()));
122         }
123 
124         SECTION("number (unsigned)")
125         {
126             json j = 23u;
127             json k = j;
128 
129             j.clear();
130             CHECK(j == json(json::value_t::number_integer));
131             CHECK(j == json(k.type()));
132         }
133 
134         SECTION("number (float)")
135         {
136             json j = 23.42;
137             json k = j;
138 
139             j.clear();
140             CHECK(j == json(json::value_t::number_float));
141             CHECK(j == json(k.type()));
142         }
143 
144         SECTION("null")
145         {
146             json j = nullptr;
147             json k = j;
148 
149             j.clear();
150             CHECK(j == json(json::value_t::null));
151             CHECK(j == json(k.type()));
152         }
153     }
154 
155     SECTION("push_back()")
156     {
157         SECTION("to array")
158         {
159             SECTION("json&&")
160             {
161                 SECTION("null")
162                 {
163                     json j;
164                     j.push_back(1);
165                     j.push_back(2);
166                     CHECK(j.type() == json::value_t::array);
167                     CHECK(j == json({1, 2}));
168                 }
169 
170                 SECTION("array")
171                 {
172                     json j = {1, 2, 3};
173                     j.push_back("Hello");
174                     CHECK(j.type() == json::value_t::array);
175                     CHECK(j == json({1, 2, 3, "Hello"}));
176                 }
177 
178                 SECTION("other type")
179                 {
180                     json j = 1;
181                     CHECK_THROWS_WITH_AS(j.push_back("Hello"), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
182                 }
183             }
184 
185             SECTION("const json&")
186             {
187                 SECTION("null")
188                 {
189                     json j;
190                     json k(1);
191                     j.push_back(k);
192                     j.push_back(k);
193                     CHECK(j.type() == json::value_t::array);
194                     CHECK(j == json({1, 1}));
195                 }
196 
197                 SECTION("array")
198                 {
199                     json j = {1, 2, 3};
200                     json k("Hello");
201                     j.push_back(k);
202                     CHECK(j.type() == json::value_t::array);
203                     CHECK(j == json({1, 2, 3, "Hello"}));
204                 }
205 
206                 SECTION("other type")
207                 {
208                     json j = 1;
209                     json k("Hello");
210                     CHECK_THROWS_WITH_AS(j.push_back(k), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
211                 }
212             }
213         }
214 
215         SECTION("to object")
216         {
217             SECTION("null")
218             {
219                 json j;
220                 j.push_back(json::object_t::value_type({"one", 1}));
221                 j.push_back(json::object_t::value_type({"two", 2}));
222                 CHECK(j.type() == json::value_t::object);
223                 CHECK(j.size() == 2);
224                 CHECK(j["one"] == json(1));
225                 CHECK(j["two"] == json(2));
226             }
227 
228             SECTION("object")
229             {
230                 json j(json::value_t::object);
231                 j.push_back(json::object_t::value_type({"one", 1}));
232                 j.push_back(json::object_t::value_type({"two", 2}));
233                 CHECK(j.size() == 2);
234                 CHECK(j["one"] == json(1));
235                 CHECK(j["two"] == json(2));
236             }
237 
238             SECTION("other type")
239             {
240                 json j = 1;
241                 json k("Hello");
242                 CHECK_THROWS_WITH_AS(j.push_back(json::object_t::value_type({"one", 1})), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
243             }
244         }
245 
246         SECTION("with initializer_list")
247         {
248             SECTION("null")
249             {
250                 json j;
251                 j.push_back({"foo", "bar"});
252                 CHECK(j == json::array({{"foo", "bar"}}));
253 
254                 json k;
255                 k.push_back({1, 2, 3});
256                 CHECK(k == json::array({{1, 2, 3}}));
257             }
258 
259             SECTION("array")
260             {
261                 json j = {1, 2, 3};
262                 j.push_back({"foo", "bar"});
263                 CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
264 
265                 json k = {1, 2, 3};
266                 k.push_back({1, 2, 3});
267                 CHECK(k == json({1, 2, 3, {1, 2, 3}}));
268             }
269 
270             SECTION("object")
271             {
272                 json j = {{"key1", 1}};
273                 j.push_back({"key2", "bar"});
274                 CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
275 
276                 // invalid values (no string/val pair)
277                 CHECK_THROWS_WITH_AS(j.push_back({1}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
278                 CHECK_THROWS_WITH_AS(j.push_back({1, 2}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
279                 CHECK_THROWS_WITH_AS(j.push_back({1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
280             }
281         }
282     }
283 
284     SECTION("emplace_back()")
285     {
286         SECTION("to array")
287         {
288             SECTION("null")
289             {
290                 json j;
291                 auto& x1 = j.emplace_back(1);
292                 CHECK(x1 == 1);
293                 auto& x2 = j.emplace_back(2);
294                 CHECK(x2 == 2);
295                 CHECK(j.type() == json::value_t::array);
296                 CHECK(j == json({1, 2}));
297             }
298 
299             SECTION("array")
300             {
301                 json j = {1, 2, 3};
302                 auto& x = j.emplace_back("Hello");
303                 CHECK(x == "Hello");
304                 CHECK(j.type() == json::value_t::array);
305                 CHECK(j == json({1, 2, 3, "Hello"}));
306             }
307 
308             SECTION("multiple values")
309             {
310                 json j;
311                 auto& x = j.emplace_back(3, "foo");
312                 CHECK(x == json({"foo", "foo", "foo"}));
313                 CHECK(j.type() == json::value_t::array);
314                 CHECK(j == json({{"foo", "foo", "foo"}}));
315             }
316         }
317 
318         SECTION("other type")
319         {
320             json j = 1;
321             CHECK_THROWS_WITH_AS(j.emplace_back("Hello"), "[json.exception.type_error.311] cannot use emplace_back() with number", json::type_error&);
322         }
323     }
324 
325     SECTION("emplace()")
326     {
327         SECTION("to object")
328         {
329             SECTION("null")
330             {
331                 // start with a null value
332                 json j;
333 
334                 // add a new key
335                 auto res1 = j.emplace("foo", "bar");
336                 CHECK(res1.second == true);
337                 CHECK(*res1.first == "bar");
338 
339                 // the null value is changed to an object
340                 CHECK(j.type() == json::value_t::object);
341 
342                 // add a new key
343                 auto res2 = j.emplace("baz", "bam");
344                 CHECK(res2.second == true);
345                 CHECK(*res2.first == "bam");
346 
347                 // we try to insert at given key - no change
348                 auto res3 = j.emplace("baz", "bad");
349                 CHECK(res3.second == false);
350                 CHECK(*res3.first == "bam");
351 
352                 // the final object
353                 CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
354             }
355 
356             SECTION("object")
357             {
358                 // start with an object
359                 json j = {{"foo", "bar"}};
360 
361                 // add a new key
362                 auto res1 = j.emplace("baz", "bam");
363                 CHECK(res1.second == true);
364                 CHECK(*res1.first == "bam");
365 
366                 // add an existing key
367                 auto res2 = j.emplace("foo", "bad");
368                 CHECK(res2.second == false);
369                 CHECK(*res2.first == "bar");
370 
371                 // check final object
372                 CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
373             }
374         }
375 
376         SECTION("other type")
377         {
378             json j = 1;
379             CHECK_THROWS_WITH_AS(j.emplace("foo", "bar"), "[json.exception.type_error.311] cannot use emplace() with number", json::type_error&);
380         }
381     }
382 
383     SECTION("operator+=")
384     {
385         SECTION("to array")
386         {
387             SECTION("json&&")
388             {
389                 SECTION("null")
390                 {
391                     json j;
392                     j += 1;
393                     j += 2;
394                     CHECK(j.type() == json::value_t::array);
395                     CHECK(j == json({1, 2}));
396                 }
397 
398                 SECTION("array")
399                 {
400                     json j = {1, 2, 3};
401                     j += "Hello";
402                     CHECK(j.type() == json::value_t::array);
403                     CHECK(j == json({1, 2, 3, "Hello"}));
404                 }
405 
406                 SECTION("other type")
407                 {
408                     json j = 1;
409                     CHECK_THROWS_WITH_AS(j += "Hello", "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
410                 }
411             }
412 
413             SECTION("const json&")
414             {
415                 SECTION("null")
416                 {
417                     json j;
418                     json k(1);
419                     j += k;
420                     j += k;
421                     CHECK(j.type() == json::value_t::array);
422                     CHECK(j == json({1, 1}));
423                 }
424 
425                 SECTION("array")
426                 {
427                     json j = {1, 2, 3};
428                     json k("Hello");
429                     j += k;
430                     CHECK(j.type() == json::value_t::array);
431                     CHECK(j == json({1, 2, 3, "Hello"}));
432                 }
433 
434                 SECTION("other type")
435                 {
436                     json j = 1;
437                     json k("Hello");
438                     CHECK_THROWS_WITH_AS(j += k, "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
439                 }
440             }
441         }
442 
443         SECTION("to object")
444         {
445             SECTION("null")
446             {
447                 json j;
448                 j += json::object_t::value_type({"one", 1});
449                 j += json::object_t::value_type({"two", 2});
450                 CHECK(j.type() == json::value_t::object);
451                 CHECK(j.size() == 2);
452                 CHECK(j["one"] == json(1));
453                 CHECK(j["two"] == json(2));
454             }
455 
456             SECTION("object")
457             {
458                 json j(json::value_t::object);
459                 j += json::object_t::value_type({"one", 1});
460                 j += json::object_t::value_type({"two", 2});
461                 CHECK(j.size() == 2);
462                 CHECK(j["one"] == json(1));
463                 CHECK(j["two"] == json(2));
464             }
465 
466             SECTION("other type")
467             {
468                 json j = 1;
469                 json k("Hello");
470                 CHECK_THROWS_WITH_AS(j += json::object_t::value_type({"one", 1}), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
471             }
472         }
473 
474         SECTION("with initializer_list")
475         {
476             SECTION("null")
477             {
478                 json j;
479                 j += {"foo", "bar"};
480                 CHECK(j == json::array({{"foo", "bar"}}));
481 
482                 json k;
483                 k += {1, 2, 3};
484                 CHECK(k == json::array({{1, 2, 3}}));
485             }
486 
487             SECTION("array")
488             {
489                 json j = {1, 2, 3};
490                 j += {"foo", "bar"};
491                 CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
492 
493                 json k = {1, 2, 3};
494                 k += {1, 2, 3};
495                 CHECK(k == json({1, 2, 3, {1, 2, 3}}));
496             }
497 
498             SECTION("object")
499             {
500                 json j = {{"key1", 1}};
501                 j += {"key2", "bar"};
502                 CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
503 
504                 json k = {{"key1", 1}};
505                 CHECK_THROWS_WITH_AS((k += {1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
506             }
507         }
508     }
509 
510     SECTION("insert()")
511     {
512         json j_array = {1, 2, 3, 4};
513         json j_value = 5;
514 
515         SECTION("value at position")
516         {
517             SECTION("insert before begin()")
518             {
519                 auto it = j_array.insert(j_array.begin(), j_value);
520                 CHECK(j_array.size() == 5);
521                 CHECK(*it == j_value);
522                 CHECK(j_array.begin() == it);
523                 CHECK(j_array == json({5, 1, 2, 3, 4}));
524             }
525 
526             SECTION("insert in the middle")
527             {
528                 auto it = j_array.insert(j_array.begin() + 2, j_value);
529                 CHECK(j_array.size() == 5);
530                 CHECK(*it == j_value);
531                 CHECK((it - j_array.begin()) == 2);
532                 CHECK(j_array == json({1, 2, 5, 3, 4}));
533             }
534 
535             SECTION("insert before end()")
536             {
537                 auto it = j_array.insert(j_array.end(), j_value);
538                 CHECK(j_array.size() == 5);
539                 CHECK(*it == j_value);
540                 CHECK((j_array.end() - it) == 1);
541                 CHECK(j_array == json({1, 2, 3, 4, 5}));
542             }
543         }
544 
545         SECTION("rvalue at position")
546         {
547             SECTION("insert before begin()")
548             {
549                 auto it = j_array.insert(j_array.begin(), 5);
550                 CHECK(j_array.size() == 5);
551                 CHECK(*it == j_value);
552                 CHECK(j_array.begin() == it);
553                 CHECK(j_array == json({5, 1, 2, 3, 4}));
554             }
555 
556             SECTION("insert in the middle")
557             {
558                 auto it = j_array.insert(j_array.begin() + 2, 5);
559                 CHECK(j_array.size() == 5);
560                 CHECK(*it == j_value);
561                 CHECK((it - j_array.begin()) == 2);
562                 CHECK(j_array == json({1, 2, 5, 3, 4}));
563             }
564 
565             SECTION("insert before end()")
566             {
567                 auto it = j_array.insert(j_array.end(), 5);
568                 CHECK(j_array.size() == 5);
569                 CHECK(*it == j_value);
570                 CHECK((j_array.end() - it) == 1);
571                 CHECK(j_array == json({1, 2, 3, 4, 5}));
572             }
573         }
574 
575         SECTION("copies at position")
576         {
577             SECTION("insert before begin()")
578             {
579                 auto it = j_array.insert(j_array.begin(), 3, 5);
580                 CHECK(j_array.size() == 7);
581                 CHECK(*it == j_value);
582                 CHECK(j_array.begin() == it);
583                 CHECK(j_array == json({5, 5, 5, 1, 2, 3, 4}));
584             }
585 
586             SECTION("insert in the middle")
587             {
588                 auto it = j_array.insert(j_array.begin() + 2, 3, 5);
589                 CHECK(j_array.size() == 7);
590                 CHECK(*it == j_value);
591                 CHECK((it - j_array.begin()) == 2);
592                 CHECK(j_array == json({1, 2, 5, 5, 5, 3, 4}));
593             }
594 
595             SECTION("insert before end()")
596             {
597                 auto it = j_array.insert(j_array.end(), 3, 5);
598                 CHECK(j_array.size() == 7);
599                 CHECK(*it == j_value);
600                 CHECK((j_array.end() - it) == 3);
601                 CHECK(j_array == json({1, 2, 3, 4, 5, 5, 5}));
602             }
603 
604             SECTION("insert nothing (count = 0)")
605             {
606                 auto it = j_array.insert(j_array.end(), 0, 5);
607                 CHECK(j_array.size() == 4);
608                 // the returned iterator points to the first inserted element;
609                 // there were 4 elements, so it should point to the 5th
610                 CHECK(it == j_array.begin() + 4);
611                 CHECK(j_array == json({1, 2, 3, 4}));
612             }
613         }
614 
615         SECTION("range for array")
616         {
617             json j_other_array = {"first", "second"};
618 
619             SECTION("proper usage")
620             {
621                 auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.end());
622                 CHECK(j_array.size() == 6);
623                 CHECK(*it == *j_other_array.begin());
624                 CHECK((j_array.end() - it) == 2);
625                 CHECK(j_array == json({1, 2, 3, 4, "first", "second"}));
626             }
627 
628             SECTION("empty range")
629             {
630                 auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.begin());
631                 CHECK(j_array.size() == 4);
632                 CHECK(it == j_array.end());
633                 CHECK(j_array == json({1, 2, 3, 4}));
634             }
635 
636             SECTION("invalid iterators")
637             {
638                 json j_other_array2 = {"first", "second"};
639 
640                 CHECK_THROWS_WITH_AS(j_array.insert(j_array.end(), j_array.begin(), j_array.end()), "[json.exception.invalid_iterator.211] passed iterators may not belong to container",
641                                      json::invalid_iterator&);
642                 CHECK_THROWS_WITH_AS(j_array.insert(j_array.end(), j_other_array.begin(), j_other_array2.end()), "[json.exception.invalid_iterator.210] iterators do not fit",
643                                      json::invalid_iterator&);
644             }
645         }
646 
647         SECTION("range for object")
648         {
649             json j_object1 = {{"one", "eins"}, {"two", "zwei"}};
650             json j_object2 = {{"eleven", "elf"}, {"seventeen", "siebzehn"}};
651 
652             SECTION("proper usage")
653             {
654                 j_object1.insert(j_object2.begin(), j_object2.end());
655                 CHECK(j_object1.size() == 4);
656             }
657 
658             SECTION("empty range")
659             {
660                 j_object1.insert(j_object2.begin(), j_object2.begin());
661                 CHECK(j_object1.size() == 2);
662             }
663 
664             SECTION("invalid iterators")
665             {
666                 json j_other_array2 = {"first", "second"};
667 
668                 CHECK_THROWS_WITH_AS(j_array.insert(j_object2.begin(), j_object2.end()), "[json.exception.type_error.309] cannot use insert() with array", json::type_error&);
669                 CHECK_THROWS_WITH_AS(j_object1.insert(j_object1.begin(), j_object2.end()), "[json.exception.invalid_iterator.210] iterators do not fit", json::invalid_iterator&);
670                 CHECK_THROWS_WITH_AS(j_object1.insert(j_array.begin(), j_array.end()), "[json.exception.invalid_iterator.202] iterators first and last must point to objects", json::invalid_iterator&);
671             }
672         }
673 
674         SECTION("initializer list at position")
675         {
676             SECTION("insert before begin()")
677             {
678                 auto it = j_array.insert(j_array.begin(), {7, 8, 9});
679                 CHECK(j_array.size() == 7);
680                 CHECK(*it == json(7));
681                 CHECK(j_array.begin() == it);
682                 CHECK(j_array == json({7, 8, 9, 1, 2, 3, 4}));
683             }
684 
685             SECTION("insert in the middle")
686             {
687                 auto it = j_array.insert(j_array.begin() + 2, {7, 8, 9});
688                 CHECK(j_array.size() == 7);
689                 CHECK(*it == json(7));
690                 CHECK((it - j_array.begin()) == 2);
691                 CHECK(j_array == json({1, 2, 7, 8, 9, 3, 4}));
692             }
693 
694             SECTION("insert before end()")
695             {
696                 auto it = j_array.insert(j_array.end(), {7, 8, 9});
697                 CHECK(j_array.size() == 7);
698                 CHECK(*it == json(7));
699                 CHECK((j_array.end() - it) == 3);
700                 CHECK(j_array == json({1, 2, 3, 4, 7, 8, 9}));
701             }
702         }
703 
704         SECTION("invalid iterator")
705         {
706             // pass iterator to a different array
707             json j_another_array = {1, 2};
708             json j_yet_another_array = {"first", "second"};
709             CHECK_THROWS_WITH_AS(j_array.insert(j_another_array.end(), 10), "[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
710             CHECK_THROWS_WITH_AS(j_array.insert(j_another_array.end(), j_value), "[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
711             CHECK_THROWS_WITH_AS(j_array.insert(j_another_array.end(), 10, 11), "[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
712             CHECK_THROWS_WITH_AS(j_array.insert(j_another_array.end(), j_yet_another_array.begin(), j_yet_another_array.end()), "[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
713             CHECK_THROWS_WITH_AS(j_array.insert(j_another_array.end(), {1, 2, 3, 4}), "[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
714         }
715 
716         SECTION("non-array type")
717         {
718             // call insert on a non-array type
719             json j_nonarray = 3;
720             json j_yet_another_array = {"first", "second"};
721             CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), 10), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
722             CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), j_value), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
723             CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), 10, 11), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
724             CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), j_yet_another_array.begin(), j_yet_another_array.end()), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
725             CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), {1, 2, 3, 4}), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
726         }
727     }
728 
729     SECTION("update()")
730     {
731         SECTION("non-recursive (default)")
732         {
733             json j_object1 = {{"one", "eins"}, {"two", "zwei"}};
734             json j_object2 = {{"three", "drei"}, {"two", "zwo"}};
735             json j_array = {1, 2, 3, 4};
736 
737             SECTION("const reference")
738             {
739                 SECTION("proper usage")
740                 {
741                     j_object1.update(j_object2);
742                     CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwo"}, {"three", "drei"}}));
743 
744                     json j_null;
745                     j_null.update(j_object2);
746                     CHECK(j_null == j_object2);
747                 }
748 
749                 SECTION("wrong types")
750                 {
751                     CHECK_THROWS_WITH_AS(j_array.update(j_object1), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
752 
753                     CHECK_THROWS_WITH_AS(j_object1.update(j_array), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
754                 }
755             }
756 
757             SECTION("iterator range")
758             {
759                 SECTION("proper usage")
760                 {
761                     j_object1.update(j_object2.begin(), j_object2.end());
762                     CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwo"}, {"three", "drei"}}));
763 
764                     json j_null;
765                     j_null.update(j_object2.begin(), j_object2.end());
766                     CHECK(j_null == j_object2);
767                 }
768 
769                 SECTION("empty range")
770                 {
771                     j_object1.update(j_object2.begin(), j_object2.begin());
772                     CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwei"}}));
773                 }
774 
775                 SECTION("invalid iterators")
776                 {
777                     json j_other_array2 = {"first", "second"};
778 
779                     CHECK_THROWS_WITH_AS(j_array.update(j_object2.begin(), j_object2.end()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
780                     CHECK_THROWS_WITH_AS(j_object1.update(j_object1.begin(), j_object2.end()), "[json.exception.invalid_iterator.210] iterators do not fit", json::invalid_iterator&);
781                     CHECK_THROWS_WITH_AS(j_object1.update(j_array.begin(), j_array.end()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
782                 }
783             }
784         }
785 
786         SECTION("recursive")
787         {
788             SECTION("const reference")
789             {
790                 SECTION("extend object")
791                 {
792                     json j1 = {{"string", "s"}, {"numbers", {{"one", 1}}}};
793                     json j2 = {{"string", "t"}, {"numbers", {{"two", 2}}}};
794                     j1.update(j2, true);
795                     CHECK(j1 == json({{"string", "t"}, {"numbers", {{"one", 1}, {"two", 2}}}}));
796                 }
797 
798                 SECTION("replace object")
799                 {
800                     json j1 = {{"string", "s"}, {"numbers", {{"one", 1}}}};
801                     json j2 = {{"string", "t"}, {"numbers", 1}};
802                     j1.update(j2, true);
803                     CHECK(j1 == json({{"string", "t"}, {"numbers", 1}}));
804                 }
805             }
806         }
807     }
808 
809     SECTION("swap()")
810     {
811         SECTION("json")
812         {
813             SECTION("member swap")
814             {
815                 json j("hello world");
816                 json k(42.23);
817 
818                 j.swap(k);
819 
820                 CHECK(j == json(42.23));
821                 CHECK(k == json("hello world"));
822             }
823 
824             SECTION("nonmember swap")
825             {
826                 json j("hello world");
827                 json k(42.23);
828 
829                 using std::swap;
830                 swap(j, k);
831 
832                 CHECK(j == json(42.23));
833                 CHECK(k == json("hello world"));
834             }
835         }
836 
837         SECTION("array_t")
838         {
839             SECTION("array_t type")
840             {
841                 json j = {1, 2, 3, 4};
842                 json::array_t a = {"foo", "bar", "baz"};
843 
844                 j.swap(a);
845 
846                 CHECK(j == json({"foo", "bar", "baz"}));
847 
848                 j.swap(a);
849 
850                 CHECK(j == json({1, 2, 3, 4}));
851             }
852 
853             SECTION("non-array_t type")
854             {
855                 json j = 17;
856                 json::array_t a = {"foo", "bar", "baz"};
857 
858                 CHECK_THROWS_WITH_AS(j.swap(a), "[json.exception.type_error.310] cannot use swap(array_t&) with number", json::type_error&);
859             }
860         }
861 
862         SECTION("object_t")
863         {
864             SECTION("object_t type")
865             {
866                 json j = {{"one", 1}, {"two", 2}};
867                 json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
868 
869                 j.swap(o);
870 
871                 CHECK(j == json({{"cow", "Kuh"}, {"chicken", "Huhn"}}));
872 
873                 j.swap(o);
874 
875                 CHECK(j == json({{"one", 1}, {"two", 2}}));
876             }
877 
878             SECTION("non-object_t type")
879             {
880                 json j = 17;
881                 json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
882 
883                 CHECK_THROWS_WITH_AS(j.swap(o), "[json.exception.type_error.310] cannot use swap(object_t&) with number", json::type_error&);
884             }
885         }
886 
887         SECTION("string_t")
888         {
889             SECTION("string_t type")
890             {
891                 json j = "Hello world";
892                 json::string_t s = "Hallo Welt";
893 
894                 j.swap(s);
895 
896                 CHECK(j == json("Hallo Welt"));
897 
898                 j.swap(s);
899 
900                 CHECK(j == json("Hello world"));
901             }
902 
903             SECTION("non-string_t type")
904             {
905                 json j = 17;
906                 json::string_t s = "Hallo Welt";
907 
908                 CHECK_THROWS_WITH_AS(j.swap(s), "[json.exception.type_error.310] cannot use swap(string_t&) with number", json::type_error&);
909             }
910         }
911 
912         SECTION("binary_t")
913         {
914             SECTION("binary_t type")
915             {
916                 json j = json::binary({1, 2, 3, 4});
917                 json::binary_t s = {{5, 6, 7, 8}};
918 
919                 j.swap(s);
920 
921                 CHECK(j == json::binary({5, 6, 7, 8}));
922 
923                 j.swap(s);
924 
925                 CHECK(j == json::binary({1, 2, 3, 4}));
926             }
927 
928             SECTION("binary_t::container_type type")
929             {
930                 json j = json::binary({1, 2, 3, 4});
931                 std::vector<std::uint8_t> s = {{5, 6, 7, 8}};
932 
933                 j.swap(s);
934 
935                 CHECK(j == json::binary({5, 6, 7, 8}));
936 
937                 j.swap(s);
938 
939                 CHECK(j == json::binary({1, 2, 3, 4}));
940             }
941 
942             SECTION("non-binary_t type")
943             {
944                 json j = 17;
945                 json::binary_t s1 = {{1, 2, 3, 4}};
946                 std::vector<std::uint8_t> s2 = {{5, 6, 7, 8}};
947 
948                 CHECK_THROWS_WITH_AS(j.swap(s1), "[json.exception.type_error.310] cannot use swap(binary_t&) with number", json::type_error);
949                 CHECK_THROWS_WITH_AS(j.swap(s2), "[json.exception.type_error.310] cannot use swap(binary_t::container_type&) with number", json::type_error);
950             }
951         }
952     }
953 }
954