json/test/src/unit-constructor1.cpp

1536 lines
51 KiB
C++

/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++ (test suite)
| | |__ | | | | | | version 3.6.1
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
SPDX-License-Identifier: MIT
Copyright (c) 2013-2019 Niels Lohmann <http://nlohmann.me>.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#include "doctest_compatibility.h"
DOCTEST_GCC_SUPPRESS_WARNING("-Wfloat-equal")
#define private public
#include <nlohmann/json.hpp>
using nlohmann::json;
#undef private
#include <deque>
#include <forward_list>
#include <fstream>
#include <list>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <valarray>
TEST_CASE("constructors")
{
SECTION("create an empty value with a given type")
{
SECTION("null")
{
auto t = json::value_t::null;
json j(t);
CHECK(j.type() == t);
}
SECTION("discarded")
{
auto t = json::value_t::discarded;
json j(t);
CHECK(j.type() == t);
}
SECTION("object")
{
auto t = json::value_t::object;
json j(t);
CHECK(j.type() == t);
}
SECTION("array")
{
auto t = json::value_t::array;
json j(t);
CHECK(j.type() == t);
}
SECTION("boolean")
{
auto t = json::value_t::boolean;
json j(t);
CHECK(j.type() == t);
CHECK(j == false);
}
SECTION("string")
{
auto t = json::value_t::string;
json j(t);
CHECK(j.type() == t);
CHECK(j == "");
}
SECTION("number_integer")
{
auto t = json::value_t::number_integer;
json j(t);
CHECK(j.type() == t);
CHECK(j == 0);
}
SECTION("number_unsigned")
{
auto t = json::value_t::number_unsigned;
json j(t);
CHECK(j.type() == t);
CHECK(j == 0);
}
SECTION("number_float")
{
auto t = json::value_t::number_float;
json j(t);
CHECK(j.type() == t);
CHECK(j == 0.0);
}
}
SECTION("create a null object (implicitly)")
{
SECTION("no parameter")
{
json j{};
CHECK(j.type() == json::value_t::null);
}
}
SECTION("create a null object (explicitly)")
{
SECTION("parameter")
{
json j(nullptr);
CHECK(j.type() == json::value_t::null);
}
}
SECTION("create an object (explicit)")
{
SECTION("empty object")
{
json::object_t o;
json j(o);
CHECK(j.type() == json::value_t::object);
}
SECTION("filled object")
{
json::object_t o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
}
}
SECTION("create an object (implicit)")
{
// reference object
json::object_t o_reference {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j_reference(o_reference);
SECTION("std::map<json::string_t, json>")
{
std::map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
SECTION("std::map<std::string, std::string> #600")
{
std::map<std::string, std::string> m;
m["a"] = "b";
m["c"] = "d";
m["e"] = "f";
json j(m);
CHECK((j.get<decltype(m)>() == m));
}
SECTION("std::map<const char*, json>")
{
std::map<const char*, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
SECTION("std::multimap<json::string_t, json>")
{
std::multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
SECTION("std::unordered_map<json::string_t, json>")
{
std::unordered_map<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
SECTION("std::unordered_multimap<json::string_t, json>")
{
std::unordered_multimap<json::string_t, json> o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
json j(o);
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
SECTION("associative container literal")
{
json j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
CHECK(j.type() == json::value_t::object);
CHECK(j == j_reference);
}
}
SECTION("create an array (explicit)")
{
SECTION("empty array")
{
json::array_t a;
json j(a);
CHECK(j.type() == json::value_t::array);
}
SECTION("filled array")
{
json::array_t a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
}
}
SECTION("create an array (implicit)")
{
// reference array
json::array_t a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j_reference(a_reference);
SECTION("std::list<json>")
{
std::list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
SECTION("std::pair")
{
std::pair<float, std::string> p{1.0f, "string"};
json j(p);
CHECK(j.type() == json::value_t::array);
CHECK(j.get<decltype(p)>() == p);
REQUIRE(j.size() == 2);
CHECK(j[0] == std::get<0>(p));
CHECK(j[1] == std::get<1>(p));
}
SECTION("std::pair with discarded values")
{
json j{1, 2.0, "string"};
const auto p = j.get<std::pair<int, float>>();
CHECK(p.first == j[0]);
CHECK(p.second == j[1]);
}
SECTION("std::tuple")
{
const auto t = std::make_tuple(1.0, std::string{"string"}, 42, std::vector<int> {0, 1});
json j(t);
CHECK(j.type() == json::value_t::array);
REQUIRE(j.size() == 4);
CHECK(j.get<decltype(t)>() == t);
CHECK(j[0] == std::get<0>(t));
CHECK(j[1] == std::get<1>(t));
CHECK(j[2] == std::get<2>(t));
CHECK(j[3][0] == 0);
CHECK(j[3][1] == 1);
}
SECTION("std::tuple with discarded values")
{
json j{1, 2.0, "string", 42};
const auto t = j.get<std::tuple<int, float, std::string>>();
CHECK(std::get<0>(t) == j[0]);
CHECK(std::get<1>(t) == j[1]);
CHECK(std::get<2>(t) == j[2]);
}
SECTION("std::pair/tuple/array failures")
{
json j{1};
CHECK_THROWS_AS((j.get<std::pair<int, int>>()), json::out_of_range&);
CHECK_THROWS_WITH((j.get<std::pair<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range");
CHECK_THROWS_AS((j.get<std::tuple<int, int>>()), json::out_of_range&);
CHECK_THROWS_WITH((j.get<std::tuple<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range");
CHECK_THROWS_AS((j.get<std::array<int, 3>>()), json::out_of_range&);
CHECK_THROWS_WITH((j.get<std::array<int, 3>>()), "[json.exception.out_of_range.401] array index 1 is out of range");
}
SECTION("std::forward_list<json>")
{
std::forward_list<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
SECTION("std::array<json, 6>")
{
std::array<json, 6> a {{json(1), json(1u), json(2.2), json(false), json("string"), json()}};
json j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
const auto a2 = j.get<std::array<json, 6>>();
CHECK(a2 == a);
}
SECTION("std::valarray<int>")
{
std::valarray<int> va = {1, 2, 3, 4, 5};
json j(va);
CHECK(j.type() == json::value_t::array);
CHECK(j == json({1, 2, 3, 4, 5}));
std::valarray<int> jva = j;
CHECK(jva.size() == va.size());
for (size_t i = 0; i < jva.size(); ++i)
{
CHECK(va[i] == jva[i]);
}
}
SECTION("std::valarray<double>")
{
std::valarray<double> va = {1.2, 2.3, 3.4, 4.5, 5.6};
json j(va);
CHECK(j.type() == json::value_t::array);
CHECK(j == json({1.2, 2.3, 3.4, 4.5, 5.6}));
std::valarray<double> jva = j;
CHECK(jva.size() == va.size());
for (size_t i = 0; i < jva.size(); ++i)
{
CHECK(va[i] == jva[i]);
}
}
SECTION("std::vector<json>")
{
std::vector<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
SECTION("std::deque<json>")
{
std::deque<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
SECTION("std::set<json>")
{
std::set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
// we cannot really check for equality here
}
SECTION("std::unordered_set<json>")
{
std::unordered_set<json> a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
json j(a);
CHECK(j.type() == json::value_t::array);
// we cannot really check for equality here
}
SECTION("sequence container literal")
{
json j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
CHECK(j.type() == json::value_t::array);
CHECK(j == j_reference);
}
}
SECTION("create a string (explicit)")
{
SECTION("empty string")
{
json::string_t s;
json j(s);
CHECK(j.type() == json::value_t::string);
}
SECTION("filled string")
{
json::string_t s {"Hello world"};
json j(s);
CHECK(j.type() == json::value_t::string);
}
}
SECTION("create a string (implicit)")
{
// reference string
json::string_t s_reference {"Hello world"};
json j_reference(s_reference);
SECTION("std::string")
{
std::string s {"Hello world"};
json j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
}
SECTION("char[]")
{
char s[] {"Hello world"};
json j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
}
SECTION("const char*")
{
const char* s {"Hello world"};
json j(s);
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
}
SECTION("string literal")
{
json j("Hello world");
CHECK(j.type() == json::value_t::string);
CHECK(j == j_reference);
}
}
SECTION("create a boolean (explicit)")
{
SECTION("empty boolean")
{
json::boolean_t b{};
json j(b);
CHECK(j.type() == json::value_t::boolean);
}
SECTION("filled boolean (true)")
{
json j(true);
CHECK(j.type() == json::value_t::boolean);
}
SECTION("filled boolean (false)")
{
json j(false);
CHECK(j.type() == json::value_t::boolean);
}
}
SECTION("create an integer number (explicit)")
{
SECTION("uninitialized value")
{
json::number_integer_t n{};
json j(n);
CHECK(j.type() == json::value_t::number_integer);
}
SECTION("initialized value")
{
json::number_integer_t n(42);
json j(n);
CHECK(j.type() == json::value_t::number_integer);
}
}
SECTION("create an integer number (implicit)")
{
// reference objects
json::number_integer_t n_reference = 42;
json j_reference(n_reference);
json::number_unsigned_t n_unsigned_reference = 42;
json j_unsigned_reference(n_unsigned_reference);
SECTION("short")
{
short n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("unsigned short")
{
unsigned short n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("int")
{
int n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("unsigned int")
{
unsigned int n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("long")
{
long n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("unsigned long")
{
unsigned long n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("long long")
{
long long n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("unsigned long long")
{
unsigned long long n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("int8_t")
{
int8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int16_t")
{
int16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int32_t")
{
int32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int64_t")
{
int64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_fast8_t")
{
int_fast8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_fast16_t")
{
int_fast16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_fast32_t")
{
int_fast32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_fast64_t")
{
int_fast64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_least8_t")
{
int_least8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_least16_t")
{
int_least16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_least32_t")
{
int_least32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("int_least64_t")
{
int_least64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("uint8_t")
{
uint8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint16_t")
{
uint16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint32_t")
{
uint32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint64_t")
{
uint64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_fast8_t")
{
uint_fast8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_fast16_t")
{
uint_fast16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_fast32_t")
{
uint_fast32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_fast64_t")
{
uint_fast64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_least8_t")
{
uint_least8_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_least16_t")
{
uint_least16_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_least32_t")
{
uint_least32_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("uint_least64_t")
{
uint_least64_t n = 42;
json j(n);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("integer literal without suffix")
{
json j(42);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("integer literal with u suffix")
{
json j(42u);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("integer literal with l suffix")
{
json j(42l);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("integer literal with ul suffix")
{
json j(42ul);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
SECTION("integer literal with ll suffix")
{
json j(42ll);
CHECK(j.type() == json::value_t::number_integer);
CHECK(j == j_reference);
}
SECTION("integer literal with ull suffix")
{
json j(42ull);
CHECK(j.type() == json::value_t::number_unsigned);
CHECK(j == j_unsigned_reference);
}
}
SECTION("create a floating-point number (explicit)")
{
SECTION("uninitialized value")
{
json::number_float_t n{};
json j(n);
CHECK(j.type() == json::value_t::number_float);
}
SECTION("initialized value")
{
json::number_float_t n(42.23);
json j(n);
CHECK(j.type() == json::value_t::number_float);
}
SECTION("infinity")
{
// infinity is stored properly, but serialized to null
json::number_float_t n(std::numeric_limits<json::number_float_t>::infinity());
json j(n);
CHECK(j.type() == json::value_t::number_float);
// check round trip of infinity
json::number_float_t d = j;
CHECK(d == n);
// check that inf is serialized to null
CHECK(j.dump() == "null");
}
}
SECTION("create a floating-point number (implicit)")
{
// reference object
json::number_float_t n_reference = 42.23;
json j_reference(n_reference);
SECTION("float")
{
float n = 42.23f;
json j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
SECTION("double")
{
double n = 42.23;
json j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
SECTION("long double")
{
long double n = 42.23l;
json j(n);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
SECTION("floating-point literal without suffix")
{
json j(42.23);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
SECTION("integer literal with f suffix")
{
json j(42.23f);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
SECTION("integer literal with l suffix")
{
json j(42.23l);
CHECK(j.type() == json::value_t::number_float);
CHECK(j.m_value.number_float == Approx(j_reference.m_value.number_float));
}
}
SECTION("create a container (array or object) from an initializer list")
{
SECTION("empty initializer list")
{
SECTION("explicit")
{
json j(json::initializer_list_t {});
CHECK(j.type() == json::value_t::object);
}
SECTION("implicit")
{
json j {};
CHECK(j.type() == json::value_t::null);
}
}
SECTION("one element")
{
SECTION("array")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(json::array_t())});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {json::array_t()};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("object")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(json::object_t())});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {json::object_t()};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("string")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json("Hello world")});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {"Hello world"};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("boolean")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(true)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {true};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("number (integer)")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(1)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {1};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("number (unsigned)")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(1u)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {1u};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("number (floating-point)")
{
SECTION("explicit")
{
json j(json::initializer_list_t {json(42.23)});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {42.23};
CHECK(j.type() == json::value_t::array);
}
}
}
SECTION("more elements")
{
SECTION("explicit")
{
json j(json::initializer_list_t {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()});
CHECK(j.type() == json::value_t::array);
}
SECTION("implicit")
{
json j {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
CHECK(j.type() == json::value_t::array);
}
}
SECTION("implicit type deduction")
{
SECTION("object")
{
json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} };
CHECK(j.type() == json::value_t::object);
}
SECTION("array")
{
json j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 };
CHECK(j.type() == json::value_t::array);
}
}
SECTION("explicit type deduction")
{
SECTION("empty object")
{
json j = json::object();
CHECK(j.type() == json::value_t::object);
}
SECTION("object")
{
json j = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
CHECK(j.type() == json::value_t::object);
}
SECTION("object with error")
{
CHECK_THROWS_AS(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
json::type_error&);
CHECK_THROWS_WITH(json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }),
"[json.exception.type_error.301] cannot create object from initializer list");
}
SECTION("empty array")
{
json j = json::array();
CHECK(j.type() == json::value_t::array);
}
SECTION("array")
{
json j = json::array({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
CHECK(j.type() == json::value_t::array);
}
}
SECTION("move from initializer_list")
{
SECTION("string")
{
// This should break through any short string optimization in std::string
std::string source(1024, '!');
const char* source_addr = source.data();
SECTION("constructor with implicit types (array)")
{
json j = {std::move(source)};
CHECK(j[0].get_ref<std::string const&>().data() == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json j = {{"key", std::move(source)}};
CHECK(j["key"].get_ref<std::string const&>().data() == source_addr);
}
SECTION("constructor with implicit types (object key)")
{
json j = {{std::move(source), 42}};
CHECK(j.get_ref<json::object_t&>().begin()->first.data() == source_addr);
}
}
SECTION("array")
{
json::array_t source = {1, 2, 3};
const json* source_addr = source.data();
SECTION("constructor with implicit types (array)")
{
json j {std::move(source)};
CHECK(j[0].get_ref<json::array_t const&>().data() == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json j {{"key", std::move(source)}};
CHECK(j["key"].get_ref<json::array_t const&>().data() == source_addr);
}
SECTION("assignment with implicit types (array)")
{
json j = {std::move(source)};
CHECK(j[0].get_ref<json::array_t const&>().data() == source_addr);
}
SECTION("assignment with implicit types (object)")
{
json j = {{"key", std::move(source)}};
CHECK(j["key"].get_ref<json::array_t const&>().data() == source_addr);
}
}
SECTION("object")
{
json::object_t source = {{"hello", "world"}};
const json* source_addr = &source.at("hello");
SECTION("constructor with implicit types (array)")
{
json j {std::move(source)};
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json j {{"key", std::move(source)}};
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("assignment with implicit types (array)")
{
json j = {std::move(source)};
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
SECTION("assignment with implicit types (object)")
{
json j = {{"key", std::move(source)}};
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
}
}
SECTION("json")
{
json source {1, 2, 3};
const json* source_addr = &source[0];
SECTION("constructor with implicit types (array)")
{
json j {std::move(source), {}};
CHECK(&j[0][0] == source_addr);
}
SECTION("constructor with implicit types (object)")
{
json j {{"key", std::move(source)}};
CHECK(&j["key"][0] == source_addr);
}
SECTION("assignment with implicit types (array)")
{
json j = {std::move(source), {}};
CHECK(&j[0][0] == source_addr);
}
SECTION("assignment with implicit types (object)")
{
json j = {{"key", std::move(source)}};
CHECK(&j["key"][0] == source_addr);
}
}
}
}
SECTION("create an array of n copies of a given value")
{
SECTION("cnt = 0")
{
json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json arr(0, v);
CHECK(arr.size() == 0);
}
SECTION("cnt = 1")
{
json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json arr(1, v);
CHECK(arr.size() == 1);
for (auto& x : arr)
{
CHECK(x == v);
}
}
SECTION("cnt = 3")
{
json v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
json arr(3, v);
CHECK(arr.size() == 3);
for (auto& x : arr)
{
CHECK(x == v);
}
}
}
SECTION("create a JSON container from an iterator range")
{
SECTION("object")
{
SECTION("json(begin(), end())")
{
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json j_new(jobject.begin(), jobject.end());
CHECK(j_new == jobject);
}
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json j_new(jobject.cbegin(), jobject.cend());
CHECK(j_new == jobject);
}
}
SECTION("json(begin(), begin())")
{
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json j_new(jobject.begin(), jobject.begin());
CHECK(j_new == json::object());
}
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
json j_new(jobject.cbegin(), jobject.cbegin());
CHECK(j_new == json::object());
}
}
SECTION("construct from subrange")
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json j_new(jobject.find("b"), jobject.find("e"));
CHECK(j_new == json({{"b", 1}, {"c", 17u}, {"d", false}}));
}
SECTION("incompatible iterators")
{
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
CHECK_THROWS_AS(json(jobject.begin(), jobject2.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(jobject2.begin(), jobject.end()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(jobject.begin(), jobject2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible");
CHECK_THROWS_WITH(json(jobject2.begin(), jobject.end()), "[json.exception.invalid_iterator.201] iterators are not compatible");
}
{
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
CHECK_THROWS_AS(json(jobject.cbegin(), jobject2.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(jobject2.cbegin(), jobject.cend()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(jobject.cbegin(), jobject2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible");
CHECK_THROWS_WITH(json(jobject2.cbegin(), jobject.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible");
}
}
}
SECTION("array")
{
SECTION("json(begin(), end())")
{
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.begin(), jarray.end());
CHECK(j_new == jarray);
}
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.cbegin(), jarray.cend());
CHECK(j_new == jarray);
}
}
SECTION("json(begin(), begin())")
{
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.begin(), jarray.begin());
CHECK(j_new == json::array());
}
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.cbegin(), jarray.cbegin());
CHECK(j_new == json::array());
}
}
SECTION("construct from subrange")
{
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.begin() + 1, jarray.begin() + 3);
CHECK(j_new == json({2, 3}));
}
{
json jarray = {1, 2, 3, 4, 5};
json j_new(jarray.cbegin() + 1, jarray.cbegin() + 3);
CHECK(j_new == json({2, 3}));
}
}
SECTION("incompatible iterators")
{
{
json jarray = {1, 2, 3, 4};
json jarray2 = {2, 3, 4, 5};
CHECK_THROWS_AS(json(jarray.begin(), jarray2.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(jarray2.begin(), jarray.end()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(jarray.begin(), jarray2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible");
CHECK_THROWS_WITH(json(jarray2.begin(), jarray.end()), "[json.exception.invalid_iterator.201] iterators are not compatible");
}
{
json jarray = {1, 2, 3, 4};
json jarray2 = {2, 3, 4, 5};
CHECK_THROWS_AS(json(jarray.cbegin(), jarray2.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(jarray2.cbegin(), jarray.cend()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(jarray.cbegin(), jarray2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible");
CHECK_THROWS_WITH(json(jarray2.cbegin(), jarray.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible");
}
}
}
SECTION("other values")
{
SECTION("construct with two valid iterators")
{
SECTION("null")
{
{
json j;
CHECK_THROWS_AS(json(j.begin(), j.end()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.begin(), j.end()),
"[json.exception.invalid_iterator.206] cannot construct with iterators from null");
}
{
json j;
CHECK_THROWS_AS(json(j.cbegin(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cbegin(), j.cend()),
"[json.exception.invalid_iterator.206] cannot construct with iterators from null");
}
}
SECTION("string")
{
{
json j = "foo";
json j_new(j.begin(), j.end());
CHECK(j == j_new);
}
{
json j = "bar";
json j_new(j.cbegin(), j.cend());
CHECK(j == j_new);
}
}
SECTION("number (boolean)")
{
{
json j = false;
json j_new(j.begin(), j.end());
CHECK(j == j_new);
}
{
json j = true;
json j_new(j.cbegin(), j.cend());
CHECK(j == j_new);
}
}
SECTION("number (integer)")
{
{
json j = 17;
json j_new(j.begin(), j.end());
CHECK(j == j_new);
}
{
json j = 17;
json j_new(j.cbegin(), j.cend());
CHECK(j == j_new);
}
}
SECTION("number (unsigned)")
{
{
json j = 17u;
json j_new(j.begin(), j.end());
CHECK(j == j_new);
}
{
json j = 17u;
json j_new(j.cbegin(), j.cend());
CHECK(j == j_new);
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
json j_new(j.begin(), j.end());
CHECK(j == j_new);
}
{
json j = 23.42;
json j_new(j.cbegin(), j.cend());
CHECK(j == j_new);
}
}
}
SECTION("construct with two invalid iterators")
{
SECTION("string")
{
{
json j = "foo";
CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
{
json j = "bar";
CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
}
SECTION("number (boolean)")
{
{
json j = false;
CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
{
json j = true;
CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
}
SECTION("number (integer)")
{
{
json j = 17;
CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
{
json j = 17;
CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
}
SECTION("number (integer)")
{
{
json j = 17u;
CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
{
json j = 17u;
CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
}
SECTION("number (floating point)")
{
{
json j = 23.42;
CHECK_THROWS_AS(json(j.end(), j.end()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.begin(), j.begin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
{
json j = 23.42;
CHECK_THROWS_AS(json(j.cend(), j.cend()), json::invalid_iterator&);
CHECK_THROWS_AS(json(j.cbegin(), j.cbegin()), json::invalid_iterator&);
CHECK_THROWS_WITH(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range");
CHECK_THROWS_WITH(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range");
}
}
}
}
}
}