From 5877bb9745d87ee8dab05a8bad2c5b8c561a7698 Mon Sep 17 00:00:00 2001 From: Niels Date: Sun, 8 Feb 2015 13:25:09 +0100 Subject: [PATCH] systematic unit tests --- test/unit.cpp | 2582 +++---------------------------------------------- 1 file changed, 118 insertions(+), 2464 deletions(-) diff --git a/test/unit.cpp b/test/unit.cpp index b131fcb3..c3493008 100644 --- a/test/unit.cpp +++ b/test/unit.cpp @@ -2,2488 +2,142 @@ #include "catch.hpp" #include "json.hpp" - -#include -#include -#include - using nlohmann::json; -TEST_CASE() +#include + +TEST_CASE("Constructors") { - CHECK(json::parser("[1,2,3,4,5,6]").parse().dump() == "[1,2,3,4,5,6]"); -} - -TEST_CASE() -{ - CHECK(json::escape_string("\\") == "\\\\"); - CHECK(json::escape_string("\"") == "\\\""); - CHECK(json::escape_string("\n") == "\\n"); - CHECK(json::escape_string("\r") == "\\r"); - CHECK(json::escape_string("\f") == "\\f"); - CHECK(json::escape_string("\b") == "\\b"); - CHECK(json::escape_string("\t") == "\\t"); - - CHECK(json::escape_string("Lorem ipsum \"dolor\" sit amet,\nconsectetur \\ adipiscing elit.") - == "Lorem ipsum \\\"dolor\\\" sit amet,\\nconsectetur \\\\ adipiscing elit."); - CHECK(json::escape_string("the main said, \"cool!\"") == "the main said, \\\"cool!\\\""); - CHECK(json::escape_string("\a") == "\\u0007"); - CHECK(json::escape_string("\v") == "\\u000b"); - + SECTION("create an empty value with a given type") { - json j = "AC/DC"; - CHECK(j.dump() == "\"AC/DC\""); - } - - { - 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 = + SECTION("null") { - {"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; - - const json jc(j); - CHECK(j.find("name") != j.end()); - CHECK(j.find("foo") == j.end()); - CHECK(*(j.find("name")) == json("Niels") ); - CHECK(jc.find("name") != jc.end()); - CHECK(jc.find("foo") == jc.end()); - } - { - // 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; - } - { - CHECK_THROWS_AS(json::object({1, 2, 3}), std::logic_error); - } - { - CHECK(json::object({{"foo", 1}, {"bar", 2}, {"baz", 3}}).size() == 3); - CHECK(json::object({{"foo", 1}}).size() == 1); - CHECK(json::object().size() == 0); - } - { - json j = json::object({{"foo", 1}, {"bar", 2}, {"baz", 3}}); - { - CHECK(j["foo"] == json(1)); - CHECK(j.at("foo") == json(1)); + auto t = json::value_t::null; + json j(t); + CHECK(j.type() == t); } + + SECTION("object") { - std::map m = j; - auto k = j.get>(); - CHECK(m == k); + auto t = json::value_t::object; + json j(t); + CHECK(j.type() == t); } + + SECTION("array") { - std::unordered_map m = j; - auto k = j.get>(); - CHECK(m == k); + 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); + } + + SECTION("number_integer") + { + auto t = json::value_t::number_integer; + json j(t); + CHECK(j.type() == t); + } + + SECTION("number_float") + { + auto t = json::value_t::number_float; + json j(t); + CHECK(j.type() == t); } } + SECTION("create a null object (implicitly)") { - json j = {1, 2, 3, 4, 5}; + SECTION("no parameter") { - CHECK(j[0] == json(1)); - CHECK(j.at(0) == json(1)); + json j; + CHECK(j.type() == json::value_t::null); } + } + + SECTION("create a null object (explicitly)") + { + SECTION("parameter") { - std::vector m = j; - auto k = j.get>(); - CHECK(m == k); + json j(nullptr); + CHECK(j.type() == json::value_t::null); } + + SECTION("assignment") { - std::set m = j; - auto k = j.get>(); - CHECK(m == k); - } - } -} - -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(), 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(), 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(), 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(), 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(), 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(), 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(j).begin() == j.cbegin()); - CHECK(const_cast(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(j).end() == j.cend()); - CHECK(const_cast(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 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(), 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(), 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(), std::logic_error); - CHECK_THROWS_AS(json::string_t o = j, std::logic_error); - } - - SECTION("get()/operator() for booleans") - { - { - auto o = j.get(); - CHECK(o == true); - } - { - json::boolean_t o = j; - CHECK(o == true); - } - } - - SECTION("get()/operator() for integer numbers") - { - CHECK_THROWS_AS(auto o = j.get(), 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(), 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(j).begin() == j.cbegin()); - CHECK(const_cast(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(j).end() == j.cend()); - CHECK(const_cast(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 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(), 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(), 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(), 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(), std::logic_error); - CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error); - } - - SECTION("get()/operator() for integer numbers") - { - { - auto o = j.get(); - CHECK(o == 1003); - } - { - json::number_integer_t o = j; - CHECK(o == 1003); - } - } - - SECTION("get()/operator() for floating point numbers") - { - { - auto o = j.get(); - 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(j).begin() == j.cbegin()); - CHECK(const_cast(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(j).end() == j.cend()); - CHECK(const_cast(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 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(), 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(), 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(), 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(), std::logic_error); - CHECK_THROWS_AS(json::boolean_t o = j, std::logic_error); - } - - SECTION("get()/operator() for integer numbers") - { - { - auto o = j.get(); - CHECK(o == 10203); - } - { - json::number_integer_t o = j; - CHECK(o == 10203); - } - } - - SECTION("get()/operator() for floating point numbers") - { - { - auto o = j.get(); - 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(j).begin() == j.cbegin()); - CHECK(const_cast(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(j).end() == j.cend()); - CHECK(const_cast(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 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(), 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(), std::logic_error); - CHECK_THROWS_AS(json::array_t o = j, std::logic_error); - } - - SECTION("get()/operator() for strings") - { - { - auto o = j.get(); - 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(), 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(), 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(), 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(j).begin() == j.cbegin()); - CHECK(const_cast(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(j).end() == j.cend()); - CHECK(const_cast(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 hash_fn; - auto h1 = hash_fn(j1); - auto h2 = hash_fn(j2); - CHECK(h1 != h2); + 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(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", 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(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j_reference(o_reference); + + SECTION("std::map") + { + std::map o = {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j(o); + CHECK(j.type() == json::value_t::object); + CHECK(j == j_reference); + } + + SECTION("std::map") + { + std::map o = {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j(o); + CHECK(j.type() == json::value_t::object); + CHECK(j == j_reference); + } + + SECTION("std::multimap") + { + std::multimap o = {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j(o); + CHECK(j.type() == json::value_t::object); + CHECK(j == j_reference); + } + + SECTION("std::unordered_map") + { + std::unordered_map o = {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j(o); + CHECK(j.type() == json::value_t::object); + CHECK(j == j_reference); + } + + SECTION("std::unordered_multimap") + { + std::unordered_multimap o = {{"a", json(1)}, {"b", json(2.2)}, {"c", json(false)}, {"d", json("string")}, {"e", json()}}; + json j(o); + CHECK(j.type() == json::value_t::object); + CHECK(j == j_reference); } } }