2413 lines
64 KiB
C++
2413 lines
64 KiB
C++
#define CATCH_CONFIG_MAIN
|
|
#include "catch.hpp"
|
|
|
|
#include "json.hpp"
|
|
|
|
#include <sstream>
|
|
|
|
using nlohmann::json;
|
|
|
|
TEST_CASE()
|
|
{
|
|
{
|
|
json j = {1, 2, 3, 4};
|
|
std::cerr << j << std::endl;
|
|
}
|
|
|
|
{
|
|
json j = {{}};
|
|
std::cerr << j << std::endl;
|
|
}
|
|
|
|
{
|
|
json j = {{"foo", nullptr}};
|
|
std::cerr << j << std::endl;
|
|
}
|
|
{
|
|
json j =
|
|
{
|
|
{"pi", 3.141},
|
|
{"happy", true},
|
|
{"name", "Niels"},
|
|
{"nothing", nullptr},
|
|
{
|
|
"answer", {
|
|
{"everything", 42}
|
|
}
|
|
},
|
|
{"list", {1, 0, 2}},
|
|
{
|
|
"object", {
|
|
{"currency", "USD"},
|
|
{"value", 42.99}
|
|
}
|
|
}
|
|
};
|
|
std::cerr << j.dump(4) << std::endl;
|
|
j["pi"] = {3, 1, 4, 1};
|
|
std::cerr << j << std::endl;
|
|
}
|
|
{
|
|
// ways to express the empty array []
|
|
json empty_array_implicit = {{}};
|
|
std::cerr << "empty_array_implicit: " << empty_array_implicit << std::endl;
|
|
json empty_array_explicit = json::array();
|
|
std::cerr << "empty_array_explicit: " << empty_array_explicit << std::endl;
|
|
|
|
// a way to express the empty object {}
|
|
json empty_object_explicit = json::object();
|
|
std::cerr << "empty_object_explicit: " << empty_object_explicit << std::endl;
|
|
|
|
// a way to express an _array_ of key/value pairs [["currency", "USD"], ["value", 42.99]]
|
|
json array_not_object = { json::array({"currency", "USD"}), json::array({"value", 42.99}) };
|
|
std::cerr << "array_not_object: " << array_not_object << std::endl;
|
|
}
|
|
}
|
|
|
|
TEST_CASE("null")
|
|
{
|
|
SECTION("constructors")
|
|
{
|
|
SECTION("no arguments")
|
|
{
|
|
{
|
|
json j;
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
{
|
|
json j{};
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("nullptr_t argument")
|
|
{
|
|
{
|
|
json j(nullptr);
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("value_t::null argument")
|
|
{
|
|
{
|
|
json j(json::value_t::null);
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy constructor")
|
|
{
|
|
{
|
|
json other;
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
{
|
|
json j = nullptr;
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("move constructor")
|
|
{
|
|
{
|
|
json other;
|
|
json j(std::move(other));
|
|
CHECK(j.m_type == json::value_t::null);
|
|
CHECK(other.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy assignment")
|
|
{
|
|
{
|
|
json other;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("object inspection")
|
|
{
|
|
json j;
|
|
|
|
SECTION("dump()")
|
|
{
|
|
CHECK(j.dump() == "null");
|
|
CHECK(j.dump(-1) == "null");
|
|
CHECK(j.dump(4) == "null");
|
|
}
|
|
|
|
SECTION("type()")
|
|
{
|
|
CHECK(j.type() == j.m_type);
|
|
}
|
|
|
|
SECTION("operator value_t()")
|
|
{
|
|
json::value_t t = j;
|
|
CHECK(t == j.m_type);
|
|
}
|
|
}
|
|
|
|
SECTION("value conversion")
|
|
{
|
|
json j;
|
|
|
|
SECTION("get()/operator() for objects")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::object_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::object_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for arrays")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::array_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::array_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for strings")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::string_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::string_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for booleans")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::boolean_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for integer numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_integer_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_integer_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for floating point numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_float_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_float_t o = j, std::logic_error);
|
|
}
|
|
}
|
|
|
|
SECTION("element access")
|
|
{
|
|
json j;
|
|
const json jc;
|
|
|
|
SECTION("operator[size_type]")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j[0], std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc[0], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(size_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at(0), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(0), std::runtime_error);
|
|
}
|
|
|
|
SECTION("operator[object_t::key_type]")
|
|
{
|
|
CHECK_THROWS_AS(j["key"], std::runtime_error);
|
|
CHECK_THROWS_AS(j[std::string("key")], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(object_t::key_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = j.at(std::string("key")), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(std::string("key")), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("iterators")
|
|
{
|
|
json j;
|
|
const json jc;
|
|
|
|
SECTION("begin()")
|
|
{
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.begin();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cbegin()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cbegin();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cbegin()
|
|
CHECK(const_cast<json::const_reference>(j).begin() == j.cbegin());
|
|
CHECK(const_cast<json::const_reference>(jc).begin() == jc.cbegin());
|
|
}
|
|
}
|
|
|
|
SECTION("end()")
|
|
{
|
|
{
|
|
json::iterator it = j.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cend()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cend()
|
|
CHECK(const_cast<json::const_reference>(j).end() == j.cend());
|
|
CHECK(const_cast<json::const_reference>(jc).end() == jc.cend());
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("capacity")
|
|
{
|
|
json j;
|
|
const json jc;
|
|
|
|
SECTION("empty()")
|
|
{
|
|
// null values are empty
|
|
CHECK(j.empty());
|
|
CHECK(jc.empty());
|
|
|
|
// check semantics definition of empty()
|
|
CHECK(j.begin() == j.end());
|
|
CHECK(j.cbegin() == j.cend());
|
|
}
|
|
|
|
SECTION("size()")
|
|
{
|
|
// null values have size 0
|
|
CHECK(j.size() == 0);
|
|
CHECK(jc.size() == 0);
|
|
|
|
// check semantics definition of size()
|
|
CHECK(std::distance(j.begin(), j.end()) == 0);
|
|
CHECK(std::distance(j.cbegin(), j.cend()) == 0);
|
|
}
|
|
|
|
SECTION("max_size()")
|
|
{
|
|
// null values have max_size 0
|
|
CHECK(j.max_size() == 0);
|
|
CHECK(jc.max_size() == 0);
|
|
}
|
|
}
|
|
|
|
SECTION("modifiers")
|
|
{
|
|
json j;
|
|
|
|
SECTION("clear()")
|
|
{
|
|
j.clear();
|
|
CHECK(j.empty());
|
|
}
|
|
|
|
SECTION("push_back")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v;
|
|
j.push_back(v);
|
|
CHECK(j.type() == json::value_t::array);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
j.push_back(nullptr);
|
|
CHECK(j.type() == json::value_t::array);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", nullptr };
|
|
j.push_back(v);
|
|
CHECK(j.type() == json::value_t::object);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
}
|
|
|
|
SECTION("emplace_back")
|
|
{
|
|
j.emplace_back(nullptr);
|
|
CHECK(j.type() == json::value_t::array);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
|
|
/*
|
|
SECTION("operator+=")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v;
|
|
j += v;
|
|
CHECK(j.type() == json::value_t::array);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
j += nullptr;
|
|
CHECK(j.type() == json::value_t::array);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", nullptr };
|
|
j += v;
|
|
CHECK(j.type() == json::value_t::object);
|
|
CHECK(j.empty() == false);
|
|
CHECK(j.size() == 1);
|
|
CHECK(j.max_size() >= 1);
|
|
}
|
|
}
|
|
*/
|
|
|
|
SECTION("swap")
|
|
{
|
|
SECTION("array_t&")
|
|
{
|
|
json::array_t other = {nullptr, nullptr, nullptr};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t&")
|
|
{
|
|
json::object_t other = {{"key1", nullptr}, {"key2", nullptr}};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("string_t&")
|
|
{
|
|
json::string_t other = "string";
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("lexicographical comparison operators")
|
|
{
|
|
json j1, j2;
|
|
|
|
CHECK(j1 == j2);
|
|
CHECK(not(j1 != j2));
|
|
CHECK(not(j1 < j2));
|
|
CHECK(j1 <= j2);
|
|
CHECK(not(j1 > j2));
|
|
CHECK(j1 >= j2);
|
|
}
|
|
|
|
SECTION("serialization")
|
|
{
|
|
json j;
|
|
|
|
SECTION("operator<<")
|
|
{
|
|
std::stringstream s;
|
|
s << j;
|
|
CHECK(s.str() == "null");
|
|
}
|
|
|
|
SECTION("operator>>")
|
|
{
|
|
std::stringstream s;
|
|
j >> s;
|
|
CHECK(s.str() == "null");
|
|
}
|
|
}
|
|
|
|
SECTION("convenience functions")
|
|
{
|
|
json j;
|
|
|
|
SECTION("type_name")
|
|
{
|
|
CHECK(j.type_name() == "null");
|
|
}
|
|
}
|
|
|
|
SECTION("nonmember functions")
|
|
{
|
|
json j1, j2;
|
|
|
|
SECTION("swap")
|
|
{
|
|
std::swap(j1, j2);
|
|
}
|
|
|
|
SECTION("hash")
|
|
{
|
|
std::hash<json> hash_fn;
|
|
auto h1 = hash_fn(j1);
|
|
auto h2 = hash_fn(j2);
|
|
CHECK(h1 == h2);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("boolean")
|
|
{
|
|
SECTION("constructors")
|
|
{
|
|
SECTION("booleant_t argument")
|
|
{
|
|
{
|
|
json j(true);
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == true);
|
|
}
|
|
{
|
|
json j(false);
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
}
|
|
|
|
SECTION("value_t::boolean argument")
|
|
{
|
|
{
|
|
json j(json::value_t::boolean);
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
}
|
|
|
|
SECTION("copy constructor")
|
|
{
|
|
{
|
|
json other(true);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == true);
|
|
}
|
|
{
|
|
json other(false);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
{
|
|
json j = true;
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == true);
|
|
}
|
|
{
|
|
json j = false;
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
}
|
|
|
|
SECTION("move constructor")
|
|
{
|
|
{
|
|
json other = true;
|
|
json j(std::move(other));
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == true);
|
|
CHECK(other.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy assignment")
|
|
{
|
|
{
|
|
json other = true;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == true);
|
|
}
|
|
{
|
|
json other = false;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::boolean);
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("object inspection")
|
|
{
|
|
json jt = true;
|
|
json jf = false;
|
|
|
|
SECTION("dump()")
|
|
{
|
|
CHECK(jt.dump() == "true");
|
|
CHECK(jt.dump(-1) == "true");
|
|
CHECK(jt.dump(4) == "true");
|
|
CHECK(jf.dump() == "false");
|
|
CHECK(jf.dump(-1) == "false");
|
|
CHECK(jf.dump(4) == "false");
|
|
}
|
|
|
|
SECTION("type()")
|
|
{
|
|
CHECK(jt.type() == jt.m_type);
|
|
CHECK(jf.type() == jf.m_type);
|
|
}
|
|
|
|
SECTION("operator value_t()")
|
|
{
|
|
{
|
|
json::value_t t = jt;
|
|
CHECK(t == jt.m_type);
|
|
}
|
|
{
|
|
json::value_t t = jf;
|
|
CHECK(t == jf.m_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("value conversion")
|
|
{
|
|
json j = true;
|
|
|
|
SECTION("get()/operator() for objects")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::object_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::object_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for arrays")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::array_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::array_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for strings")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::string_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::string_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for booleans")
|
|
{
|
|
{
|
|
auto o = j.get<json::boolean_t>();
|
|
CHECK(o == true);
|
|
}
|
|
{
|
|
json::boolean_t o = j;
|
|
CHECK(o == true);
|
|
}
|
|
}
|
|
|
|
SECTION("get()/operator() for integer numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_integer_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_integer_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for floating point numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_float_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_float_t o = j, std::logic_error);
|
|
}
|
|
}
|
|
|
|
SECTION("element access")
|
|
{
|
|
json j = true;
|
|
const json jc = false;
|
|
|
|
SECTION("operator[size_type]")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j[0], std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc[0], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(size_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at(0), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(0), std::runtime_error);
|
|
}
|
|
|
|
SECTION("operator[object_t::key_type]")
|
|
{
|
|
CHECK_THROWS_AS(j["key"], std::runtime_error);
|
|
CHECK_THROWS_AS(j[std::string("key")], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(object_t::key_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = j.at(std::string("key")), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(std::string("key")), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("iterators")
|
|
{
|
|
json j = true;
|
|
const json jc = false;
|
|
|
|
SECTION("begin()")
|
|
{
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.begin();
|
|
CHECK(*it == jc);
|
|
}
|
|
}
|
|
|
|
SECTION("cbegin()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cbegin();
|
|
CHECK(*it == jc);
|
|
}
|
|
{
|
|
// check semantics definition of cbegin()
|
|
CHECK(const_cast<json::const_reference>(j).begin() == j.cbegin());
|
|
CHECK(const_cast<json::const_reference>(jc).begin() == jc.cbegin());
|
|
}
|
|
}
|
|
|
|
SECTION("end()")
|
|
{
|
|
{
|
|
json::iterator it = j.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cend()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cend()
|
|
CHECK(const_cast<json::const_reference>(j).end() == j.cend());
|
|
CHECK(const_cast<json::const_reference>(jc).end() == jc.cend());
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("capacity")
|
|
{
|
|
json j = true;
|
|
const json jc = false;
|
|
|
|
SECTION("empty()")
|
|
{
|
|
// null values are empty
|
|
CHECK(not j.empty());
|
|
CHECK(not jc.empty());
|
|
|
|
// check semantics definition of empty()
|
|
CHECK(j.begin() != j.end());
|
|
CHECK(j.cbegin() != j.cend());
|
|
}
|
|
|
|
SECTION("size()")
|
|
{
|
|
// boolean values have size 1
|
|
CHECK(j.size() == 1);
|
|
CHECK(jc.size() == 1);
|
|
|
|
// check semantics definition of size()
|
|
CHECK(std::distance(j.begin(), j.end()) == 1);
|
|
CHECK(std::distance(j.cbegin(), j.cend()) == 1);
|
|
}
|
|
|
|
SECTION("max_size()")
|
|
{
|
|
// null values have max_size 0
|
|
CHECK(j.max_size() == 1);
|
|
CHECK(jc.max_size() == 1);
|
|
}
|
|
}
|
|
|
|
SECTION("modifiers")
|
|
{
|
|
json j = true;
|
|
|
|
SECTION("clear()")
|
|
{
|
|
j.clear();
|
|
CHECK(not j.empty());
|
|
CHECK(j.m_value.boolean == false);
|
|
}
|
|
|
|
SECTION("push_back")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = true;
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j.push_back(false), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", true };
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("emplace_back")
|
|
{
|
|
CHECK_THROWS_AS(j.emplace_back(true), std::runtime_error);
|
|
}
|
|
|
|
/*
|
|
SECTION("operator+=")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = true;
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j += true, std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", true };
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
}
|
|
*/
|
|
|
|
SECTION("swap")
|
|
{
|
|
SECTION("array_t&")
|
|
{
|
|
json::array_t other = {true, false};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t&")
|
|
{
|
|
json::object_t other = {{"key1", true}, {"key2", false}};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("string_t&")
|
|
{
|
|
json::string_t other = "string";
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("lexicographical comparison operators")
|
|
{
|
|
json j1 = true;
|
|
json j2 = false;
|
|
|
|
CHECK(j1 == j1);
|
|
CHECK(not(j1 != j1));
|
|
CHECK(not(j1 < j1));
|
|
CHECK(j1 <= j1);
|
|
CHECK(not(j1 > j1));
|
|
CHECK(j1 >= j1);
|
|
|
|
CHECK(j2 == j2);
|
|
CHECK(not(j2 != j2));
|
|
CHECK(not(j2 < j2));
|
|
CHECK(j2 <= j2);
|
|
CHECK(not(j2 > j2));
|
|
CHECK(j2 >= j2);
|
|
|
|
CHECK(not(j1 == j2));
|
|
CHECK(j1 != j2);
|
|
CHECK(not(j1 < j2));
|
|
CHECK(not(j1 <= j2));
|
|
CHECK(j1 > j2);
|
|
CHECK(j1 >= j2);
|
|
}
|
|
|
|
SECTION("serialization")
|
|
{
|
|
json j1 = true;
|
|
json j2 = false;
|
|
|
|
SECTION("operator<<")
|
|
{
|
|
std::stringstream s;
|
|
s << j1 << " " << j2;
|
|
CHECK(s.str() == "true false");
|
|
}
|
|
|
|
SECTION("operator>>")
|
|
{
|
|
std::stringstream s;
|
|
j1 >> s;
|
|
j2 >> s;
|
|
CHECK(s.str() == "truefalse");
|
|
}
|
|
}
|
|
|
|
SECTION("convenience functions")
|
|
{
|
|
json j = true;
|
|
|
|
SECTION("type_name")
|
|
{
|
|
CHECK(j.type_name() == "boolean");
|
|
}
|
|
}
|
|
|
|
SECTION("nonmember functions")
|
|
{
|
|
json j1 = true;
|
|
json j2 = false;
|
|
|
|
SECTION("swap")
|
|
{
|
|
std::swap(j1, j2);
|
|
CHECK(j1 == json(false));
|
|
CHECK(j2 == json(true));
|
|
}
|
|
|
|
SECTION("hash")
|
|
{
|
|
std::hash<json> hash_fn;
|
|
auto h1 = hash_fn(j1);
|
|
auto h2 = hash_fn(j2);
|
|
CHECK(h1 != h2);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("number (integer)")
|
|
{
|
|
SECTION("constructors")
|
|
{
|
|
SECTION("number_integer_t argument")
|
|
{
|
|
{
|
|
json j(17);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 17);
|
|
}
|
|
{
|
|
json j(0);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 0);
|
|
}
|
|
{
|
|
json j(-42);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == -42);
|
|
}
|
|
}
|
|
|
|
SECTION("integer type argument")
|
|
{
|
|
{
|
|
int8_t v = -128;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
uint8_t v = 255;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
int16_t v = -32768;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
uint16_t v = 65535;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
int32_t v = -2147483648;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
uint32_t v = 4294967295;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
int64_t v = INT64_MIN;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
{
|
|
int64_t v = INT64_MAX;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == v);
|
|
}
|
|
}
|
|
|
|
SECTION("value_t::number_integer argument")
|
|
{
|
|
{
|
|
json j(json::value_t::number_integer);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 0);
|
|
}
|
|
}
|
|
|
|
SECTION("copy constructor")
|
|
{
|
|
{
|
|
json other(117);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 117);
|
|
}
|
|
{
|
|
json other(-49);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == -49);
|
|
}
|
|
{
|
|
json j = 110;
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 110);
|
|
}
|
|
{
|
|
json j = 112;
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 112);
|
|
}
|
|
}
|
|
|
|
SECTION("move constructor")
|
|
{
|
|
{
|
|
json other = 7653434;
|
|
json j(std::move(other));
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 7653434);
|
|
CHECK(other.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy assignment")
|
|
{
|
|
{
|
|
json other = 333;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 333);
|
|
}
|
|
{
|
|
json other = 555;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::number_integer);
|
|
CHECK(j.m_value.number_integer == 555);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("object inspection")
|
|
{
|
|
json jp = 4294967295;
|
|
json jn = -4294967295;
|
|
|
|
SECTION("dump()")
|
|
{
|
|
CHECK(jp.dump() == "4294967295");
|
|
CHECK(jn.dump(-1) == "-4294967295");
|
|
CHECK(jp.dump(4) == "4294967295");
|
|
CHECK(jn.dump() == "-4294967295");
|
|
CHECK(jp.dump(-1) == "4294967295");
|
|
CHECK(jn.dump(4) == "-4294967295");
|
|
}
|
|
|
|
SECTION("type()")
|
|
{
|
|
CHECK(jp.type() == jp.m_type);
|
|
CHECK(jn.type() == jn.m_type);
|
|
}
|
|
|
|
SECTION("operator value_t()")
|
|
{
|
|
{
|
|
json::value_t t = jp;
|
|
CHECK(t == jp.m_type);
|
|
}
|
|
{
|
|
json::value_t t = jn;
|
|
CHECK(t == jn.m_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("value conversion")
|
|
{
|
|
json j = 1003;
|
|
|
|
SECTION("get()/operator() for objects")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::object_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::object_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for arrays")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::array_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::array_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for strings")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::string_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::string_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for booleans")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::boolean_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for integer numbers")
|
|
{
|
|
{
|
|
auto o = j.get<json::number_integer_t>();
|
|
CHECK(o == 1003);
|
|
}
|
|
{
|
|
json::number_integer_t o = j;
|
|
CHECK(o == 1003);
|
|
}
|
|
}
|
|
|
|
SECTION("get()/operator() for floating point numbers")
|
|
{
|
|
{
|
|
auto o = j.get<json::number_float_t>();
|
|
CHECK(o == 1003);
|
|
}
|
|
{
|
|
json::number_float_t o = j;
|
|
CHECK(o == 1003);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("element access")
|
|
{
|
|
json j = 119;
|
|
const json jc = -65433;
|
|
|
|
SECTION("operator[size_type]")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j[0], std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc[0], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(size_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at(0), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(0), std::runtime_error);
|
|
}
|
|
|
|
SECTION("operator[object_t::key_type]")
|
|
{
|
|
CHECK_THROWS_AS(j["key"], std::runtime_error);
|
|
CHECK_THROWS_AS(j[std::string("key")], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(object_t::key_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = j.at(std::string("key")), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(std::string("key")), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("iterators")
|
|
{
|
|
json j = 0;
|
|
const json jc = 666;
|
|
|
|
SECTION("begin()")
|
|
{
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.begin();
|
|
CHECK(*it == jc);
|
|
}
|
|
}
|
|
|
|
SECTION("cbegin()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cbegin();
|
|
CHECK(*it == jc);
|
|
}
|
|
{
|
|
// check semantics definition of cbegin()
|
|
CHECK(const_cast<json::const_reference>(j).begin() == j.cbegin());
|
|
CHECK(const_cast<json::const_reference>(jc).begin() == jc.cbegin());
|
|
}
|
|
}
|
|
|
|
SECTION("end()")
|
|
{
|
|
{
|
|
json::iterator it = j.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cend()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cend()
|
|
CHECK(const_cast<json::const_reference>(j).end() == j.cend());
|
|
CHECK(const_cast<json::const_reference>(jc).end() == jc.cend());
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("capacity")
|
|
{
|
|
json j = 4344;
|
|
const json jc = -255;
|
|
|
|
SECTION("empty()")
|
|
{
|
|
// null values are empty
|
|
CHECK(not j.empty());
|
|
CHECK(not jc.empty());
|
|
|
|
// check semantics definition of empty()
|
|
CHECK(j.begin() != j.end());
|
|
CHECK(j.cbegin() != j.cend());
|
|
}
|
|
|
|
SECTION("size()")
|
|
{
|
|
// number values have size 1
|
|
CHECK(j.size() == 1);
|
|
CHECK(jc.size() == 1);
|
|
|
|
// check semantics definition of size()
|
|
CHECK(std::distance(j.begin(), j.end()) == 1);
|
|
CHECK(std::distance(j.cbegin(), j.cend()) == 1);
|
|
}
|
|
|
|
SECTION("max_size()")
|
|
{
|
|
// null values have max_size 0
|
|
CHECK(j.max_size() == 1);
|
|
CHECK(jc.max_size() == 1);
|
|
}
|
|
}
|
|
|
|
SECTION("modifiers")
|
|
{
|
|
json j = 1119;
|
|
|
|
SECTION("clear()")
|
|
{
|
|
j.clear();
|
|
CHECK(not j.empty());
|
|
CHECK(j.m_value.number_integer == 0);
|
|
}
|
|
|
|
SECTION("push_back")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 6;
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j.push_back(56), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 12 };
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("emplace_back")
|
|
{
|
|
CHECK_THROWS_AS(j.emplace_back(-42), std::runtime_error);
|
|
}
|
|
|
|
/*
|
|
SECTION("operator+=")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 8;
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j += 0, std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 42 };
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
}
|
|
*/
|
|
|
|
SECTION("swap")
|
|
{
|
|
SECTION("array_t&")
|
|
{
|
|
json::array_t other = {11, 2};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t&")
|
|
{
|
|
json::object_t other = {{"key1", 4}, {"key2", 33}};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("string_t&")
|
|
{
|
|
json::string_t other = "string";
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("lexicographical comparison operators")
|
|
{
|
|
json j1 = -100;
|
|
json j2 = 100;
|
|
|
|
CHECK(j1 == j1);
|
|
CHECK(not(j1 != j1));
|
|
CHECK(not(j1 < j1));
|
|
CHECK(j1 <= j1);
|
|
CHECK(not(j1 > j1));
|
|
CHECK(j1 >= j1);
|
|
|
|
CHECK(j2 == j2);
|
|
CHECK(not(j2 != j2));
|
|
CHECK(not(j2 < j2));
|
|
CHECK(j2 <= j2);
|
|
CHECK(not(j2 > j2));
|
|
CHECK(j2 >= j2);
|
|
|
|
CHECK(not(j1 == j2));
|
|
CHECK(j1 != j2);
|
|
CHECK(j1 < j2);
|
|
CHECK(j1 <= j2);
|
|
CHECK(not(j1 > j2));
|
|
CHECK(not(j1 >= j2));
|
|
}
|
|
|
|
SECTION("serialization")
|
|
{
|
|
json j1 = 42;
|
|
json j2 = 66;
|
|
|
|
SECTION("operator<<")
|
|
{
|
|
std::stringstream s;
|
|
s << j1 << " " << j2;
|
|
CHECK(s.str() == "42 66");
|
|
}
|
|
|
|
SECTION("operator>>")
|
|
{
|
|
std::stringstream s;
|
|
j1 >> s;
|
|
j2 >> s;
|
|
CHECK(s.str() == "4266");
|
|
}
|
|
}
|
|
|
|
SECTION("convenience functions")
|
|
{
|
|
json j = 2354;
|
|
|
|
SECTION("type_name")
|
|
{
|
|
CHECK(j.type_name() == "number");
|
|
}
|
|
}
|
|
|
|
SECTION("nonmember functions")
|
|
{
|
|
json j1 = 23;
|
|
json j2 = 32;
|
|
|
|
SECTION("swap")
|
|
{
|
|
std::swap(j1, j2);
|
|
CHECK(j1 == json(32));
|
|
CHECK(j2 == json(23));
|
|
}
|
|
|
|
SECTION("hash")
|
|
{
|
|
std::hash<json> hash_fn;
|
|
auto h1 = hash_fn(j1);
|
|
auto h2 = hash_fn(j2);
|
|
CHECK(h1 != h2);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("number (floating point)")
|
|
{
|
|
SECTION("constructors")
|
|
{
|
|
SECTION("number_float_t argument")
|
|
{
|
|
{
|
|
json j(17.23);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 17.23);
|
|
}
|
|
{
|
|
json j(0.0);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 0.0);
|
|
}
|
|
{
|
|
json j(-42.1211);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == -42.1211);
|
|
}
|
|
}
|
|
|
|
SECTION("floating type argument")
|
|
{
|
|
{
|
|
float v = 3.14159265359;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == v);
|
|
}
|
|
{
|
|
double v = 2.71828182846;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == v);
|
|
}
|
|
{
|
|
long double v = 1.57079632679;
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == v);
|
|
}
|
|
}
|
|
|
|
SECTION("value_t::number_float argument")
|
|
{
|
|
{
|
|
json j(json::value_t::number_float);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 0.0);
|
|
}
|
|
}
|
|
|
|
SECTION("copy constructor")
|
|
{
|
|
{
|
|
json other(117.1);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 117.1);
|
|
}
|
|
{
|
|
json other(-49.00);
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == -49.00);
|
|
}
|
|
{
|
|
json j = 110.22;
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 110.22);
|
|
}
|
|
{
|
|
json j = 112.5;
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 112.5);
|
|
}
|
|
}
|
|
|
|
SECTION("move constructor")
|
|
{
|
|
{
|
|
json other = 7653434.99999;
|
|
json j(std::move(other));
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 7653434.99999);
|
|
CHECK(other.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy assignment")
|
|
{
|
|
{
|
|
json other = 333.444;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 333.444);
|
|
}
|
|
{
|
|
json other = 555.333;
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::number_float);
|
|
CHECK(j.m_value.number_float == 555.333);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("object inspection")
|
|
{
|
|
json jp = 4294967295.333;
|
|
json jn = -4294967249.222;
|
|
|
|
SECTION("dump()")
|
|
{
|
|
CHECK(jp.dump() == "4294967295.333000");
|
|
CHECK(jn.dump(-1) == "-4294967249.222000");
|
|
CHECK(jp.dump(4) == "4294967295.333000");
|
|
CHECK(jn.dump() == "-4294967249.222000");
|
|
CHECK(jp.dump(-1) == "4294967295.333000");
|
|
CHECK(jn.dump(4) == "-4294967249.222000");
|
|
}
|
|
|
|
SECTION("type()")
|
|
{
|
|
CHECK(jp.type() == jp.m_type);
|
|
CHECK(jn.type() == jn.m_type);
|
|
}
|
|
|
|
SECTION("operator value_t()")
|
|
{
|
|
{
|
|
json::value_t t = jp;
|
|
CHECK(t == jp.m_type);
|
|
}
|
|
{
|
|
json::value_t t = jn;
|
|
CHECK(t == jn.m_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("value conversion")
|
|
{
|
|
json j = 10203.444344;
|
|
|
|
SECTION("get()/operator() for objects")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::object_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::object_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for arrays")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::array_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::array_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for strings")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::string_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::string_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for booleans")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::boolean_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for integer numbers")
|
|
{
|
|
{
|
|
auto o = j.get<json::number_integer_t>();
|
|
CHECK(o == 10203);
|
|
}
|
|
{
|
|
json::number_integer_t o = j;
|
|
CHECK(o == 10203);
|
|
}
|
|
}
|
|
|
|
SECTION("get()/operator() for floating point numbers")
|
|
{
|
|
{
|
|
auto o = j.get<json::number_float_t>();
|
|
CHECK(o == 10203.444344);
|
|
}
|
|
{
|
|
json::number_float_t o = j;
|
|
CHECK(o == 10203.444344);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("element access")
|
|
{
|
|
json j = 119.3333;
|
|
const json jc = -65433.55343;
|
|
|
|
SECTION("operator[size_type]")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j[0], std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc[0], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(size_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at(0), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(0), std::runtime_error);
|
|
}
|
|
|
|
SECTION("operator[object_t::key_type]")
|
|
{
|
|
CHECK_THROWS_AS(j["key"], std::runtime_error);
|
|
CHECK_THROWS_AS(j[std::string("key")], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(object_t::key_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = j.at(std::string("key")), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(std::string("key")), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("iterators")
|
|
{
|
|
json j = 0.0;
|
|
const json jc = -666.22233322;
|
|
|
|
SECTION("begin()")
|
|
{
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.begin();
|
|
CHECK(*it == jc);
|
|
}
|
|
}
|
|
|
|
SECTION("cbegin()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cbegin();
|
|
CHECK(*it == jc);
|
|
}
|
|
{
|
|
// check semantics definition of cbegin()
|
|
CHECK(const_cast<json::const_reference>(j).begin() == j.cbegin());
|
|
CHECK(const_cast<json::const_reference>(jc).begin() == jc.cbegin());
|
|
}
|
|
}
|
|
|
|
SECTION("end()")
|
|
{
|
|
{
|
|
json::iterator it = j.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cend()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cend()
|
|
CHECK(const_cast<json::const_reference>(j).end() == j.cend());
|
|
CHECK(const_cast<json::const_reference>(jc).end() == jc.cend());
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("capacity")
|
|
{
|
|
json j = 4344.0;
|
|
const json jc = -255.1;
|
|
|
|
SECTION("empty()")
|
|
{
|
|
// null values are empty
|
|
CHECK(not j.empty());
|
|
CHECK(not jc.empty());
|
|
|
|
// check semantics definition of empty()
|
|
CHECK(j.begin() != j.end());
|
|
CHECK(j.cbegin() != j.cend());
|
|
}
|
|
|
|
SECTION("size()")
|
|
{
|
|
// number values have size 1
|
|
CHECK(j.size() == 1);
|
|
CHECK(jc.size() == 1);
|
|
|
|
// check semantics definition of size()
|
|
CHECK(std::distance(j.begin(), j.end()) == 1);
|
|
CHECK(std::distance(j.cbegin(), j.cend()) == 1);
|
|
}
|
|
|
|
SECTION("max_size()")
|
|
{
|
|
// null values have max_size 0
|
|
CHECK(j.max_size() == 1);
|
|
CHECK(jc.max_size() == 1);
|
|
}
|
|
}
|
|
|
|
SECTION("modifiers")
|
|
{
|
|
json j = 1119.12;
|
|
|
|
SECTION("clear()")
|
|
{
|
|
j.clear();
|
|
CHECK(not j.empty());
|
|
CHECK(j.m_value.number_float == 0.0);
|
|
}
|
|
|
|
SECTION("push_back")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 6.2;
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j.push_back(56.11), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 12.2 };
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("emplace_back")
|
|
{
|
|
CHECK_THROWS_AS(j.emplace_back(-42.55), std::runtime_error);
|
|
}
|
|
|
|
/*
|
|
SECTION("operator+=")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 8.4;
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j += 0, std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 4.42 };
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
}
|
|
*/
|
|
|
|
SECTION("swap")
|
|
{
|
|
SECTION("array_t&")
|
|
{
|
|
json::array_t other = {11.2, 2.4};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t&")
|
|
{
|
|
json::object_t other = {{"key1", 44.4}, {"key2", 23.2}};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("string_t&")
|
|
{
|
|
json::string_t other = "string";
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("lexicographical comparison operators")
|
|
{
|
|
json j1 = -100.55;
|
|
json j2 = 100.4;
|
|
|
|
CHECK(j1 == j1);
|
|
CHECK(not(j1 != j1));
|
|
CHECK(not(j1 < j1));
|
|
CHECK(j1 <= j1);
|
|
CHECK(not(j1 > j1));
|
|
CHECK(j1 >= j1);
|
|
|
|
CHECK(j2 == j2);
|
|
CHECK(not(j2 != j2));
|
|
CHECK(not(j2 < j2));
|
|
CHECK(j2 <= j2);
|
|
CHECK(not(j2 > j2));
|
|
CHECK(j2 >= j2);
|
|
|
|
CHECK(not(j1 == j2));
|
|
CHECK(j1 != j2);
|
|
CHECK(j1 < j2);
|
|
CHECK(j1 <= j2);
|
|
CHECK(not(j1 > j2));
|
|
CHECK(not(j1 >= j2));
|
|
}
|
|
|
|
SECTION("serialization")
|
|
{
|
|
json j1 = 42.23;
|
|
json j2 = 66.66;
|
|
|
|
SECTION("operator<<")
|
|
{
|
|
std::stringstream s;
|
|
s << j1 << " " << j2;
|
|
auto res = s.str();
|
|
CHECK(res.find("42.23") != std::string::npos);
|
|
CHECK(res.find("66.66") != std::string::npos);
|
|
}
|
|
|
|
SECTION("operator>>")
|
|
{
|
|
std::stringstream s;
|
|
j1 >> s;
|
|
j2 >> s;
|
|
auto res = s.str();
|
|
CHECK(res.find("42.23") != std::string::npos);
|
|
CHECK(res.find("66.66") != std::string::npos);
|
|
}
|
|
}
|
|
|
|
SECTION("convenience functions")
|
|
{
|
|
json j = 2354.222;
|
|
|
|
SECTION("type_name")
|
|
{
|
|
CHECK(j.type_name() == "number");
|
|
}
|
|
}
|
|
|
|
SECTION("nonmember functions")
|
|
{
|
|
json j1 = 23.44;
|
|
json j2 = 32.44;
|
|
|
|
SECTION("swap")
|
|
{
|
|
std::swap(j1, j2);
|
|
CHECK(j1 == json(32.44));
|
|
CHECK(j2 == json(23.44));
|
|
}
|
|
|
|
SECTION("hash")
|
|
{
|
|
std::hash<json> hash_fn;
|
|
auto h1 = hash_fn(j1);
|
|
auto h2 = hash_fn(j2);
|
|
CHECK(h1 != h2);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("string")
|
|
{
|
|
SECTION("constructors")
|
|
{
|
|
SECTION("string_t argument")
|
|
{
|
|
{
|
|
json j("hello");
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "hello");
|
|
}
|
|
{
|
|
json j("world");
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "world");
|
|
}
|
|
{
|
|
json j("this");
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "this");
|
|
}
|
|
}
|
|
|
|
SECTION("string type argument")
|
|
{
|
|
{
|
|
std::string v = "3.14159265359";
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == v);
|
|
}
|
|
{
|
|
const char* v = "3.14159265359";
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == v);
|
|
}
|
|
{
|
|
char v[14] = "3.14159265359";
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == v);
|
|
}
|
|
{
|
|
const char v[14] = "3.14159265359";
|
|
json j(v);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == v);
|
|
}
|
|
}
|
|
|
|
SECTION("value_t::string argument")
|
|
{
|
|
{
|
|
json j(json::value_t::string);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "");
|
|
}
|
|
}
|
|
|
|
SECTION("copy constructor")
|
|
{
|
|
{
|
|
json other("foo");
|
|
json j(other);
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "foo");
|
|
}
|
|
{
|
|
json j = "baz";
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "baz");
|
|
}
|
|
}
|
|
|
|
SECTION("move constructor")
|
|
{
|
|
{
|
|
json other = "ß";
|
|
json j(std::move(other));
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "ß");
|
|
CHECK(other.m_type == json::value_t::null);
|
|
}
|
|
}
|
|
|
|
SECTION("copy assignment")
|
|
{
|
|
{
|
|
json other = "a string";
|
|
json j = other;
|
|
CHECK(j.m_type == json::value_t::string);
|
|
CHECK(*(j.m_value.string) == "a string");
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("object inspection")
|
|
{
|
|
json j = "This is a string.";
|
|
|
|
SECTION("dump()")
|
|
{
|
|
CHECK(j.dump() == "\"This is a string.\"");
|
|
CHECK(j.dump(-1) == "\"This is a string.\"");
|
|
CHECK(j.dump(4) == "\"This is a string.\"");
|
|
}
|
|
|
|
SECTION("type()")
|
|
{
|
|
CHECK(j.type() == j.m_type);
|
|
}
|
|
|
|
SECTION("operator value_t()")
|
|
{
|
|
{
|
|
json::value_t t = j;
|
|
CHECK(t == j.m_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("value conversion")
|
|
{
|
|
json j = "another example string";
|
|
|
|
SECTION("get()/operator() for objects")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::object_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::object_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for arrays")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::array_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::array_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for strings")
|
|
{
|
|
{
|
|
auto o = j.get<json::string_t>();
|
|
CHECK(o == "another example string");
|
|
}
|
|
{
|
|
json::string_t o = j;
|
|
CHECK(o == "another example string");
|
|
}
|
|
}
|
|
|
|
SECTION("get()/operator() for booleans")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::boolean_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for integer numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_integer_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_integer_t o = j, std::logic_error);
|
|
}
|
|
|
|
SECTION("get()/operator() for floating point numbers")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.get<json::number_float_t>(), std::logic_error);
|
|
CHECK_THROWS_AS(json::number_float_t o = j, std::logic_error);
|
|
}
|
|
}
|
|
|
|
SECTION("element access")
|
|
{
|
|
json j = "!§$&/()=";
|
|
const json jc = "!§$&/()=";
|
|
|
|
SECTION("operator[size_type]")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j[0], std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc[0], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(size_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at(0), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(0), std::runtime_error);
|
|
}
|
|
|
|
SECTION("operator[object_t::key_type]")
|
|
{
|
|
CHECK_THROWS_AS(j["key"], std::runtime_error);
|
|
CHECK_THROWS_AS(j[std::string("key")], std::runtime_error);
|
|
}
|
|
|
|
SECTION("at(object_t::key_type)")
|
|
{
|
|
CHECK_THROWS_AS(auto o = j.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = j.at(std::string("key")), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at("key"), std::runtime_error);
|
|
CHECK_THROWS_AS(auto o = jc.at(std::string("key")), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("iterators")
|
|
{
|
|
json j = "@";
|
|
const json jc = "€";
|
|
|
|
SECTION("begin()")
|
|
{
|
|
{
|
|
json::iterator it = j.begin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.begin();
|
|
CHECK(*it == jc);
|
|
}
|
|
}
|
|
|
|
SECTION("cbegin()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cbegin();
|
|
CHECK(*it == j);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cbegin();
|
|
CHECK(*it == jc);
|
|
}
|
|
{
|
|
// check semantics definition of cbegin()
|
|
CHECK(const_cast<json::const_reference>(j).begin() == j.cbegin());
|
|
CHECK(const_cast<json::const_reference>(jc).begin() == jc.cbegin());
|
|
}
|
|
}
|
|
|
|
SECTION("end()")
|
|
{
|
|
{
|
|
json::iterator it = j.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.end();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
}
|
|
|
|
SECTION("cend()")
|
|
{
|
|
{
|
|
json::const_iterator it = j.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
json::const_iterator it = jc.cend();
|
|
CHECK_THROWS_AS(*it, std::out_of_range);
|
|
}
|
|
{
|
|
// check semantics definition of cend()
|
|
CHECK(const_cast<json::const_reference>(j).end() == j.cend());
|
|
CHECK(const_cast<json::const_reference>(jc).end() == jc.cend());
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("capacity")
|
|
{
|
|
json j = "Franz jagt im komplett verwahrlosten Taxi quer durch Bayern.";
|
|
const json jc = "The quick brown fox jumps over the lazy dog.";
|
|
|
|
SECTION("empty()")
|
|
{
|
|
// null values are empty
|
|
CHECK(not j.empty());
|
|
CHECK(not jc.empty());
|
|
|
|
// check semantics definition of empty()
|
|
CHECK(j.begin() != j.end());
|
|
CHECK(j.cbegin() != j.cend());
|
|
}
|
|
|
|
SECTION("size()")
|
|
{
|
|
// string values have size 1
|
|
CHECK(j.size() == 1);
|
|
CHECK(jc.size() == 1);
|
|
|
|
// check semantics definition of size()
|
|
CHECK(std::distance(j.begin(), j.end()) == 1);
|
|
CHECK(std::distance(j.cbegin(), j.cend()) == 1);
|
|
}
|
|
|
|
SECTION("max_size()")
|
|
{
|
|
// null values have max_size 0
|
|
CHECK(j.max_size() == 1);
|
|
CHECK(jc.max_size() == 1);
|
|
}
|
|
}
|
|
|
|
SECTION("modifiers")
|
|
{
|
|
json j = "YOLO";
|
|
|
|
SECTION("clear()")
|
|
{
|
|
j.clear();
|
|
CHECK(not j.empty());
|
|
CHECK(*(j.m_value.string) == "");
|
|
}
|
|
|
|
SECTION("push_back")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 6.2;
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j.push_back(56.11), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 12.2 };
|
|
CHECK_THROWS_AS(j.push_back(v), std::runtime_error);
|
|
}
|
|
}
|
|
|
|
SECTION("emplace_back")
|
|
{
|
|
CHECK_THROWS_AS(j.emplace_back(-42.55), std::runtime_error);
|
|
}
|
|
|
|
/*
|
|
SECTION("operator+=")
|
|
{
|
|
SECTION("const json&")
|
|
{
|
|
const json v = 8.4;
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
|
|
SECTION("json&&")
|
|
{
|
|
CHECK_THROWS_AS(j += 0, std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t::value_type&")
|
|
{
|
|
json::object_t::value_type v { "foo", 4.42 };
|
|
CHECK_THROWS_AS(j += v, std::runtime_error);
|
|
}
|
|
}
|
|
*/
|
|
|
|
SECTION("swap")
|
|
{
|
|
SECTION("array_t&")
|
|
{
|
|
json::array_t other = {11.2, 2.4};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("object_t&")
|
|
{
|
|
json::object_t other = {{"key1", 44.4}, {"key2", 23.2}};
|
|
CHECK_THROWS_AS(j.swap(other), std::runtime_error);
|
|
}
|
|
|
|
SECTION("string_t&")
|
|
{
|
|
json::string_t other = "string";
|
|
j.swap(other);
|
|
CHECK(other == json("YOLO"));
|
|
CHECK(j == json("string"));
|
|
}
|
|
}
|
|
}
|
|
|
|
SECTION("lexicographical comparison operators")
|
|
{
|
|
json j1 = "Alpha";
|
|
json j2 = "Omega";
|
|
|
|
CHECK(j1 == j1);
|
|
CHECK(not(j1 != j1));
|
|
CHECK(not(j1 < j1));
|
|
CHECK(j1 <= j1);
|
|
CHECK(not(j1 > j1));
|
|
CHECK(j1 >= j1);
|
|
|
|
CHECK(j2 == j2);
|
|
CHECK(not(j2 != j2));
|
|
CHECK(not(j2 < j2));
|
|
CHECK(j2 <= j2);
|
|
CHECK(not(j2 > j2));
|
|
CHECK(j2 >= j2);
|
|
|
|
CHECK(not(j1 == j2));
|
|
CHECK(j1 != j2);
|
|
CHECK(j1 < j2);
|
|
CHECK(j1 <= j2);
|
|
CHECK(not(j1 > j2));
|
|
CHECK(not(j1 >= j2));
|
|
}
|
|
|
|
SECTION("serialization")
|
|
{
|
|
json j1 = "flip";
|
|
json j2 = "flop";
|
|
|
|
SECTION("operator<<")
|
|
{
|
|
std::stringstream s;
|
|
s << j1 << " " << j2;
|
|
CHECK(s.str() == "\"flip\" \"flop\"");
|
|
}
|
|
|
|
SECTION("operator>>")
|
|
{
|
|
std::stringstream s;
|
|
j1 >> s;
|
|
j2 >> s;
|
|
CHECK(s.str() == "\"flip\"\"flop\"");
|
|
}
|
|
}
|
|
|
|
SECTION("convenience functions")
|
|
{
|
|
json j = "I am a string, believe me!";
|
|
|
|
SECTION("type_name")
|
|
{
|
|
CHECK(j.type_name() == "string");
|
|
}
|
|
}
|
|
|
|
SECTION("nonmember functions")
|
|
{
|
|
json j1 = "A";
|
|
json j2 = "B";
|
|
|
|
SECTION("swap")
|
|
{
|
|
std::swap(j1, j2);
|
|
CHECK(j1 == json("B"));
|
|
CHECK(j2 == json("A"));
|
|
}
|
|
|
|
SECTION("hash")
|
|
{
|
|
std::hash<json> hash_fn;
|
|
auto h1 = hash_fn(j1);
|
|
auto h2 = hash_fn(j2);
|
|
CHECK(h1 != h2);
|
|
}
|
|
}
|
|
}
|