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