summaryrefslogtreecommitdiff
path: root/json4cpp/tests/src/unit-modifiers.cpp
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:42:50 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:42:50 +0300
commit5fad10f89c485cfdc7b99011f07609f8871160d4 (patch)
tree1860b39753b652dfe54d3cbbc80c875f40198d1f /json4cpp/tests/src/unit-modifiers.cpp
parent292baed7ac0cf84263263966ed32ed113cae857f (diff)
parent9a737481aed085fd289f82dff1fa8c3c66627a7e (diff)
downloadProject-Tick-5fad10f89c485cfdc7b99011f07609f8871160d4.tar.gz
Project-Tick-5fad10f89c485cfdc7b99011f07609f8871160d4.zip
Add 'json4cpp/' from commit '9a737481aed085fd289f82dff1fa8c3c66627a7e'
git-subtree-dir: json4cpp git-subtree-mainline: 292baed7ac0cf84263263966ed32ed113cae857f git-subtree-split: 9a737481aed085fd289f82dff1fa8c3c66627a7e
Diffstat (limited to 'json4cpp/tests/src/unit-modifiers.cpp')
-rw-r--r--json4cpp/tests/src/unit-modifiers.cpp952
1 files changed, 952 insertions, 0 deletions
diff --git a/json4cpp/tests/src/unit-modifiers.cpp b/json4cpp/tests/src/unit-modifiers.cpp
new file mode 100644
index 0000000000..18185ec00b
--- /dev/null
+++ b/json4cpp/tests/src/unit-modifiers.cpp
@@ -0,0 +1,952 @@
+// __ _____ _____ _____
+// __| | __| | | | JSON for Modern C++ (supporting code)
+// | | |__ | | | | | | version 3.12.0
+// |_____|_____|_____|_|___| https://github.com/nlohmann/json
+//
+// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
+// SPDX-License-Identifier: MIT
+
+#include "doctest_compatibility.h"
+
+#include <nlohmann/json.hpp>
+using nlohmann::json;
+
+TEST_CASE("modifiers")
+{
+ SECTION("clear()")
+ {
+ SECTION("boolean")
+ {
+ json j = true;
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::boolean));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("string")
+ {
+ json j = "hello world";
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::string));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("array")
+ {
+ SECTION("empty array")
+ {
+ json j = json::array();
+ json const k = j;
+
+ j.clear();
+ CHECK(j.empty());
+ CHECK(j == json(json::value_t::array));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("filled array")
+ {
+ json j = {1, 2, 3};
+ json const k = j;
+
+ j.clear();
+ CHECK(j.empty());
+ CHECK(j == json(json::value_t::array));
+ CHECK(j == json(k.type()));
+ }
+ }
+
+ SECTION("object")
+ {
+ SECTION("empty object")
+ {
+ json j = json::object();
+ json const k = j;
+
+ j.clear();
+ CHECK(j.empty());
+ CHECK(j == json(json::value_t::object));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("filled object")
+ {
+ json j = {{"one", 1}, {"two", 2}, {"three", 3}};
+ json const k = j;
+
+ j.clear();
+ CHECK(j.empty());
+ CHECK(j == json(json::value_t::object));
+ CHECK(j == json(k.type()));
+ }
+ }
+
+ SECTION("binary")
+ {
+ SECTION("empty binary")
+ {
+ json j = json::binary({});
+ json const k = j;
+
+ j.clear();
+ CHECK(!j.empty());
+ CHECK(j == json(json::value_t::binary));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("filled binary")
+ {
+ json j = json::binary({1, 2, 3, 4, 5});
+ json const k = j;
+
+ j.clear();
+ CHECK(!j.empty());
+ CHECK(j == json(json::value_t::binary));
+ CHECK(j == json(k.type()));
+ }
+ }
+
+ SECTION("number (integer)")
+ {
+ json j = 23;
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::number_integer));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("number (unsigned)")
+ {
+ json j = 23u;
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::number_integer));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("number (float)")
+ {
+ json j = 23.42;
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::number_float));
+ CHECK(j == json(k.type()));
+ }
+
+ SECTION("null")
+ {
+ json j = nullptr;
+ json const k = j;
+
+ j.clear();
+ CHECK(j == json(json::value_t::null));
+ CHECK(j == json(k.type()));
+ }
+ }
+
+ SECTION("push_back()")
+ {
+ SECTION("to array")
+ {
+ SECTION("json&&")
+ {
+ SECTION("null")
+ {
+ json j;
+ j.push_back(1);
+ j.push_back(2);
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ j.push_back("Hello");
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2, 3, "Hello"}));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ CHECK_THROWS_WITH_AS(j.push_back("Hello"), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
+ }
+ }
+
+ SECTION("const json&")
+ {
+ SECTION("null")
+ {
+ json j;
+ json const k(1);
+ j.push_back(k);
+ j.push_back(k);
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 1}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ json const k("Hello");
+ j.push_back(k);
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2, 3, "Hello"}));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ json const k("Hello");
+ CHECK_THROWS_WITH_AS(j.push_back(k), "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
+ }
+ }
+ }
+
+ SECTION("to object")
+ {
+ SECTION("null")
+ {
+ json j;
+ j.push_back(json::object_t::value_type({"one", 1}));
+ j.push_back(json::object_t::value_type({"two", 2}));
+ CHECK(j.type() == json::value_t::object);
+ CHECK(j.size() == 2);
+ CHECK(j["one"] == json(1));
+ CHECK(j["two"] == json(2));
+ }
+
+ SECTION("object")
+ {
+ json j(json::value_t::object);
+ j.push_back(json::object_t::value_type({"one", 1}));
+ j.push_back(json::object_t::value_type({"two", 2}));
+ CHECK(j.size() == 2);
+ CHECK(j["one"] == json(1));
+ CHECK(j["two"] == json(2));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ json const k("Hello");
+ 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&);
+ }
+ }
+
+ SECTION("with initializer_list")
+ {
+ SECTION("null")
+ {
+ json j;
+ j.push_back({"foo", "bar"});
+ CHECK(j == json::array({{"foo", "bar"}}));
+
+ json k;
+ k.push_back({1, 2, 3});
+ CHECK(k == json::array({{1, 2, 3}}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ j.push_back({"foo", "bar"});
+ CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
+
+ json k = {1, 2, 3};
+ k.push_back({1, 2, 3});
+ CHECK(k == json({1, 2, 3, {1, 2, 3}}));
+ }
+
+ SECTION("object")
+ {
+ json j = {{"key1", 1}};
+ j.push_back({"key2", "bar"});
+ CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
+
+ // invalid values (no string/val pair)
+ CHECK_THROWS_WITH_AS(j.push_back({1}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
+ CHECK_THROWS_WITH_AS(j.push_back({1, 2}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
+ 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&);
+ }
+ }
+ }
+
+ SECTION("emplace_back()")
+ {
+ SECTION("to array")
+ {
+ SECTION("null")
+ {
+ json j;
+ auto& x1 = j.emplace_back(1);
+ CHECK(x1 == 1);
+ auto& x2 = j.emplace_back(2);
+ CHECK(x2 == 2);
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ auto& x = j.emplace_back("Hello");
+ CHECK(x == "Hello");
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2, 3, "Hello"}));
+ }
+
+ SECTION("multiple values")
+ {
+ json j;
+ auto& x = j.emplace_back(3, "foo");
+ CHECK(x == json({"foo", "foo", "foo"}));
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({{"foo", "foo", "foo"}}));
+ }
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ CHECK_THROWS_WITH_AS(j.emplace_back("Hello"), "[json.exception.type_error.311] cannot use emplace_back() with number", json::type_error&);
+ }
+ }
+
+ SECTION("emplace()")
+ {
+ SECTION("to object")
+ {
+ SECTION("null")
+ {
+ // start with a null value
+ json j;
+
+ // add a new key
+ auto res1 = j.emplace("foo", "bar");
+ CHECK(res1.second == true);
+ CHECK(*res1.first == "bar");
+
+ // the null value is changed to an object
+ CHECK(j.type() == json::value_t::object);
+
+ // add a new key
+ auto res2 = j.emplace("baz", "bam");
+ CHECK(res2.second == true);
+ CHECK(*res2.first == "bam");
+
+ // we try to insert at given key - no change
+ auto res3 = j.emplace("baz", "bad");
+ CHECK(res3.second == false);
+ CHECK(*res3.first == "bam");
+
+ // the final object
+ CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
+ }
+
+ SECTION("object")
+ {
+ // start with an object
+ json j = {{"foo", "bar"}};
+
+ // add a new key
+ auto res1 = j.emplace("baz", "bam");
+ CHECK(res1.second == true);
+ CHECK(*res1.first == "bam");
+
+ // add an existing key
+ auto res2 = j.emplace("foo", "bad");
+ CHECK(res2.second == false);
+ CHECK(*res2.first == "bar");
+
+ // check final object
+ CHECK(j == json({{"baz", "bam"}, {"foo", "bar"}}));
+ }
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ CHECK_THROWS_WITH_AS(j.emplace("foo", "bar"), "[json.exception.type_error.311] cannot use emplace() with number", json::type_error&);
+ }
+ }
+
+ SECTION("operator+=")
+ {
+ SECTION("to array")
+ {
+ SECTION("json&&")
+ {
+ SECTION("null")
+ {
+ json j;
+ j += 1;
+ j += 2;
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ j += "Hello";
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2, 3, "Hello"}));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ CHECK_THROWS_WITH_AS(j += "Hello", "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
+ }
+ }
+
+ SECTION("const json&")
+ {
+ SECTION("null")
+ {
+ json j;
+ json const k(1);
+ j += k;
+ j += k;
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 1}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ json const k("Hello");
+ j += k;
+ CHECK(j.type() == json::value_t::array);
+ CHECK(j == json({1, 2, 3, "Hello"}));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ json const k("Hello");
+ CHECK_THROWS_WITH_AS(j += k, "[json.exception.type_error.308] cannot use push_back() with number", json::type_error&);
+ }
+ }
+ }
+
+ SECTION("to object")
+ {
+ SECTION("null")
+ {
+ json j;
+ j += json::object_t::value_type({"one", 1});
+ j += json::object_t::value_type({"two", 2});
+ CHECK(j.type() == json::value_t::object);
+ CHECK(j.size() == 2);
+ CHECK(j["one"] == json(1));
+ CHECK(j["two"] == json(2));
+ }
+
+ SECTION("object")
+ {
+ json j(json::value_t::object);
+ j += json::object_t::value_type({"one", 1});
+ j += json::object_t::value_type({"two", 2});
+ CHECK(j.size() == 2);
+ CHECK(j["one"] == json(1));
+ CHECK(j["two"] == json(2));
+ }
+
+ SECTION("other type")
+ {
+ json j = 1;
+ json const k("Hello");
+ 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&);
+ }
+ }
+
+ SECTION("with initializer_list")
+ {
+ SECTION("null")
+ {
+ json j;
+ j += {"foo", "bar"};
+ CHECK(j == json::array({{"foo", "bar"}}));
+
+ json k;
+ k += {1, 2, 3};
+ CHECK(k == json::array({{1, 2, 3}}));
+ }
+
+ SECTION("array")
+ {
+ json j = {1, 2, 3};
+ j += {"foo", "bar"};
+ CHECK(j == json({1, 2, 3, {"foo", "bar"}}));
+
+ json k = {1, 2, 3};
+ k += {1, 2, 3};
+ CHECK(k == json({1, 2, 3, {1, 2, 3}}));
+ }
+
+ SECTION("object")
+ {
+ json j = {{"key1", 1}};
+ j += {"key2", "bar"};
+ CHECK(j == json({{"key1", 1}, {"key2", "bar"}}));
+
+ json k = {{"key1", 1}};
+ CHECK_THROWS_WITH_AS((k += {1, 2, 3, 4}), "[json.exception.type_error.308] cannot use push_back() with object", json::type_error&);
+ }
+ }
+ }
+
+ SECTION("insert()")
+ {
+ json j_array = {1, 2, 3, 4};
+ json j_value = 5;
+
+ SECTION("value at position")
+ {
+ SECTION("insert before begin()")
+ {
+ auto it = j_array.insert(j_array.begin(), j_value);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK(j_array.begin() == it);
+ CHECK(j_array == json({5, 1, 2, 3, 4}));
+ }
+
+ SECTION("insert in the middle")
+ {
+ auto it = j_array.insert(j_array.begin() + 2, j_value);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK((it - j_array.begin()) == 2);
+ CHECK(j_array == json({1, 2, 5, 3, 4}));
+ }
+
+ SECTION("insert before end()")
+ {
+ auto it = j_array.insert(j_array.end(), j_value);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK((j_array.end() - it) == 1);
+ CHECK(j_array == json({1, 2, 3, 4, 5}));
+ }
+ }
+
+ SECTION("rvalue at position")
+ {
+ SECTION("insert before begin()")
+ {
+ auto it = j_array.insert(j_array.begin(), 5);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK(j_array.begin() == it);
+ CHECK(j_array == json({5, 1, 2, 3, 4}));
+ }
+
+ SECTION("insert in the middle")
+ {
+ auto it = j_array.insert(j_array.begin() + 2, 5);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK((it - j_array.begin()) == 2);
+ CHECK(j_array == json({1, 2, 5, 3, 4}));
+ }
+
+ SECTION("insert before end()")
+ {
+ auto it = j_array.insert(j_array.end(), 5);
+ CHECK(j_array.size() == 5);
+ CHECK(*it == j_value);
+ CHECK((j_array.end() - it) == 1);
+ CHECK(j_array == json({1, 2, 3, 4, 5}));
+ }
+ }
+
+ SECTION("copies at position")
+ {
+ SECTION("insert before begin()")
+ {
+ auto it = j_array.insert(j_array.begin(), 3, 5);
+ CHECK(j_array.size() == 7);
+ CHECK(*it == j_value);
+ CHECK(j_array.begin() == it);
+ CHECK(j_array == json({5, 5, 5, 1, 2, 3, 4}));
+ }
+
+ SECTION("insert in the middle")
+ {
+ auto it = j_array.insert(j_array.begin() + 2, 3, 5);
+ CHECK(j_array.size() == 7);
+ CHECK(*it == j_value);
+ CHECK((it - j_array.begin()) == 2);
+ CHECK(j_array == json({1, 2, 5, 5, 5, 3, 4}));
+ }
+
+ SECTION("insert before end()")
+ {
+ auto it = j_array.insert(j_array.end(), 3, 5);
+ CHECK(j_array.size() == 7);
+ CHECK(*it == j_value);
+ CHECK((j_array.end() - it) == 3);
+ CHECK(j_array == json({1, 2, 3, 4, 5, 5, 5}));
+ }
+
+ SECTION("insert nothing (count = 0)")
+ {
+ auto it = j_array.insert(j_array.end(), 0, 5);
+ CHECK(j_array.size() == 4);
+ // the returned iterator points to the first inserted element;
+ // there were 4 elements, so it should point to the 5th
+ CHECK(it == j_array.begin() + 4);
+ CHECK(j_array == json({1, 2, 3, 4}));
+ }
+ }
+
+ SECTION("range for array")
+ {
+ json j_other_array = {"first", "second"};
+
+ SECTION("proper usage")
+ {
+ auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.end());
+ CHECK(j_array.size() == 6);
+ CHECK(*it == *j_other_array.begin());
+ CHECK((j_array.end() - it) == 2);
+ CHECK(j_array == json({1, 2, 3, 4, "first", "second"}));
+ }
+
+ SECTION("empty range")
+ {
+ auto it = j_array.insert(j_array.end(), j_other_array.begin(), j_other_array.begin());
+ CHECK(j_array.size() == 4);
+ CHECK(it == j_array.end());
+ CHECK(j_array == json({1, 2, 3, 4}));
+ }
+
+ SECTION("invalid iterators")
+ {
+ json j_other_array2 = {"first", "second"};
+
+ 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",
+ json::invalid_iterator&);
+ 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",
+ json::invalid_iterator&);
+ }
+ }
+
+ SECTION("range for object")
+ {
+ json j_object1 = {{"one", "eins"}, {"two", "zwei"}};
+ json j_object2 = {{"eleven", "elf"}, {"seventeen", "siebzehn"}};
+
+ SECTION("proper usage")
+ {
+ j_object1.insert(j_object2.begin(), j_object2.end());
+ CHECK(j_object1.size() == 4);
+ }
+
+ SECTION("empty range")
+ {
+ j_object1.insert(j_object2.begin(), j_object2.begin());
+ CHECK(j_object1.size() == 2);
+ }
+
+ SECTION("invalid iterators")
+ {
+ json const j_other_array2 = {"first", "second"};
+
+ 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&);
+ 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&);
+ 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&);
+ }
+ }
+
+ SECTION("initializer list at position")
+ {
+ SECTION("insert before begin()")
+ {
+ auto it = j_array.insert(j_array.begin(), {7, 8, 9});
+ CHECK(j_array.size() == 7);
+ CHECK(*it == json(7));
+ CHECK(j_array.begin() == it);
+ CHECK(j_array == json({7, 8, 9, 1, 2, 3, 4}));
+ }
+
+ SECTION("insert in the middle")
+ {
+ auto it = j_array.insert(j_array.begin() + 2, {7, 8, 9});
+ CHECK(j_array.size() == 7);
+ CHECK(*it == json(7));
+ CHECK((it - j_array.begin()) == 2);
+ CHECK(j_array == json({1, 2, 7, 8, 9, 3, 4}));
+ }
+
+ SECTION("insert before end()")
+ {
+ auto it = j_array.insert(j_array.end(), {7, 8, 9});
+ CHECK(j_array.size() == 7);
+ CHECK(*it == json(7));
+ CHECK((j_array.end() - it) == 3);
+ CHECK(j_array == json({1, 2, 3, 4, 7, 8, 9}));
+ }
+ }
+
+ SECTION("invalid iterator")
+ {
+ // pass iterator to a different array
+ json j_another_array = {1, 2};
+ json j_yet_another_array = {"first", "second"};
+ 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&);
+ 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&);
+ 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&);
+ 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&);
+ 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&);
+ }
+
+ SECTION("non-array type")
+ {
+ // call insert on a non-array type
+ json j_nonarray = 3;
+ json j_yet_another_array = {"first", "second"};
+ CHECK_THROWS_WITH_AS(j_nonarray.insert(j_nonarray.end(), 10), "[json.exception.type_error.309] cannot use insert() with number", json::type_error&);
+ 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&);
+ 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&);
+ 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&);
+ 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&);
+ }
+ }
+
+ SECTION("update()")
+ {
+ SECTION("non-recursive (default)")
+ {
+ json j_object1 = {{"one", "eins"}, {"two", "zwei"}};
+ json j_object2 = {{"three", "drei"}, {"two", "zwo"}};
+ json j_array = {1, 2, 3, 4};
+
+ SECTION("const reference")
+ {
+ SECTION("proper usage")
+ {
+ j_object1.update(j_object2);
+ CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwo"}, {"three", "drei"}}));
+
+ json j_null;
+ j_null.update(j_object2);
+ CHECK(j_null == j_object2);
+ }
+
+ SECTION("wrong types")
+ {
+ CHECK_THROWS_WITH_AS(j_array.update(j_object1), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
+
+ CHECK_THROWS_WITH_AS(j_object1.update(j_array), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
+ }
+ }
+
+ SECTION("iterator range")
+ {
+ SECTION("proper usage")
+ {
+ j_object1.update(j_object2.begin(), j_object2.end());
+ CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwo"}, {"three", "drei"}}));
+
+ json j_null;
+ j_null.update(j_object2.begin(), j_object2.end());
+ CHECK(j_null == j_object2);
+ }
+
+ SECTION("empty range")
+ {
+ j_object1.update(j_object2.begin(), j_object2.begin());
+ CHECK(j_object1 == json({{"one", "eins"}, {"two", "zwei"}}));
+ }
+
+ SECTION("invalid iterators")
+ {
+ json const j_other_array2 = {"first", "second"};
+
+ 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&);
+ 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&);
+ 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&);
+ }
+ }
+ }
+
+ SECTION("recursive")
+ {
+ SECTION("const reference")
+ {
+ SECTION("extend object")
+ {
+ json j1 = {{"string", "s"}, {"numbers", {{"one", 1}}}};
+ json const j2 = {{"string", "t"}, {"numbers", {{"two", 2}}}};
+ j1.update(j2, true);
+ CHECK(j1 == json({{"string", "t"}, {"numbers", {{"one", 1}, {"two", 2}}}}));
+ }
+
+ SECTION("replace object")
+ {
+ json j1 = {{"string", "s"}, {"numbers", {{"one", 1}}}};
+ json const j2 = {{"string", "t"}, {"numbers", 1}};
+ j1.update(j2, true);
+ CHECK(j1 == json({{"string", "t"}, {"numbers", 1}}));
+ }
+ }
+ }
+ }
+
+ SECTION("swap()")
+ {
+ SECTION("json")
+ {
+ SECTION("member swap")
+ {
+ json j("hello world");
+ json k(42.23);
+
+ j.swap(k);
+
+ CHECK(j == json(42.23));
+ CHECK(k == json("hello world"));
+ }
+
+ SECTION("nonmember swap")
+ {
+ json j("hello world");
+ json k(42.23);
+
+ using std::swap;
+ swap(j, k);
+
+ CHECK(j == json(42.23));
+ CHECK(k == json("hello world"));
+ }
+ }
+
+ SECTION("array_t")
+ {
+ SECTION("array_t type")
+ {
+ json j = {1, 2, 3, 4};
+ json::array_t a = {"foo", "bar", "baz"};
+
+ j.swap(a);
+
+ CHECK(j == json({"foo", "bar", "baz"}));
+
+ j.swap(a);
+
+ CHECK(j == json({1, 2, 3, 4}));
+ }
+
+ SECTION("non-array_t type")
+ {
+ json j = 17;
+ json::array_t a = {"foo", "bar", "baz"};
+
+ CHECK_THROWS_WITH_AS(j.swap(a), "[json.exception.type_error.310] cannot use swap(array_t&) with number", json::type_error&);
+ }
+ }
+
+ SECTION("object_t")
+ {
+ SECTION("object_t type")
+ {
+ json j = {{"one", 1}, {"two", 2}};
+ json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
+
+ j.swap(o);
+
+ CHECK(j == json({{"cow", "Kuh"}, {"chicken", "Huhn"}}));
+
+ j.swap(o);
+
+ CHECK(j == json({{"one", 1}, {"two", 2}}));
+ }
+
+ SECTION("non-object_t type")
+ {
+ json j = 17;
+ json::object_t o = {{"cow", "Kuh"}, {"chicken", "Huhn"}};
+
+ CHECK_THROWS_WITH_AS(j.swap(o), "[json.exception.type_error.310] cannot use swap(object_t&) with number", json::type_error&);
+ }
+ }
+
+ SECTION("string_t")
+ {
+ SECTION("string_t type")
+ {
+ json j = "Hello world";
+ json::string_t s = "Hallo Welt";
+
+ j.swap(s);
+
+ CHECK(j == json("Hallo Welt"));
+
+ j.swap(s);
+
+ CHECK(j == json("Hello world"));
+ }
+
+ SECTION("non-string_t type")
+ {
+ json j = 17;
+ json::string_t s = "Hallo Welt";
+
+ CHECK_THROWS_WITH_AS(j.swap(s), "[json.exception.type_error.310] cannot use swap(string_t&) with number", json::type_error&);
+ }
+ }
+
+ SECTION("binary_t")
+ {
+ SECTION("binary_t type")
+ {
+ json j = json::binary({1, 2, 3, 4});
+ json::binary_t s = {{5, 6, 7, 8}};
+
+ j.swap(s);
+
+ CHECK(j == json::binary({5, 6, 7, 8}));
+
+ j.swap(s);
+
+ CHECK(j == json::binary({1, 2, 3, 4}));
+ }
+
+ SECTION("binary_t::container_type type")
+ {
+ json j = json::binary({1, 2, 3, 4});
+ std::vector<std::uint8_t> s = {{5, 6, 7, 8}};
+
+ j.swap(s);
+
+ CHECK(j == json::binary({5, 6, 7, 8}));
+
+ j.swap(s);
+
+ CHECK(j == json::binary({1, 2, 3, 4}));
+ }
+
+ SECTION("non-binary_t type")
+ {
+ json j = 17;
+ json::binary_t s1 = {{1, 2, 3, 4}};
+ std::vector<std::uint8_t> s2 = {{5, 6, 7, 8}};
+
+ CHECK_THROWS_WITH_AS(j.swap(s1), "[json.exception.type_error.310] cannot use swap(binary_t&) with number", json::type_error);
+ CHECK_THROWS_WITH_AS(j.swap(s2), "[json.exception.type_error.310] cannot use swap(binary_t::container_type&) with number", json::type_error);
+ }
+ }
+ }
+}