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>
13using nlohmann::json;
14
15TEST_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