Merge branch 'develop' into doctest

This commit is contained in:
Viktor Kirilov 2019-03-18 16:59:36 +02:00 committed by GitHub
commit 365944b0bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
60 changed files with 15683 additions and 7958 deletions

View file

@ -64,7 +64,12 @@ set_target_properties(doctest_main PROPERTIES
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
target_compile_features(doctest_main PUBLIC cxx_std_11)
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
target_compile_features(catch_main PUBLIC cxx_range_for)
else()
target_compile_features(catch_main PUBLIC cxx_std_11)
endif()
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake

View file

@ -111,6 +111,12 @@ struct my_allocator : std::allocator<T>
p->~T();
}
}
template <class U>
struct rebind
{
using other = my_allocator<U>;
};
};
// allows deletion of raw pointer, usually hold by json_value

View file

@ -150,7 +150,7 @@ class alt_string
}
private:
std::string str_impl;
std::string str_impl {};
friend bool ::operator<(const char*, const alt_string&);
};

View file

@ -1968,7 +1968,7 @@ TEST_CASE("all CBOR first bytes")
try
{
json::from_cbor(std::vector<uint8_t>(1, byte));
auto res = json::from_cbor(std::vector<uint8_t>(1, byte));
}
catch (const json::parse_error& e)
{

View file

@ -126,7 +126,7 @@ class SaxEventLogger
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
bool errored = false;
};

View file

@ -124,7 +124,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
};
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger

View file

@ -982,6 +982,93 @@ TEST_CASE("element access 2")
}
}
}
SECTION("check existence of key in an object")
{
SECTION("existing element")
{
for (auto key :
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
})
{
CHECK(j.contains(key) == true);
CHECK(j_const.contains(key) == true);
}
}
SECTION("nonexisting element")
{
CHECK(j.contains("foo") == false);
CHECK(j_const.contains("foo") == false);
}
SECTION("all types")
{
SECTION("null")
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("string")
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("object")
{
json j_nonobject(json::value_t::object);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("array")
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("boolean")
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (integer)")
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (unsigned)")
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (floating-point)")
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
}
}
}
}

View file

@ -439,6 +439,7 @@ TEST_CASE("JSON pointers")
})
{
CHECK(json::json_pointer(ptr).to_string() == ptr);
CHECK(std::string(json::json_pointer(ptr)) == ptr);
}
}
@ -460,4 +461,137 @@ TEST_CASE("JSON pointers")
CHECK(j.is_object());
}
}
SECTION("empty, push, pop and parent")
{
const json j =
{
{"", "Hello"},
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99},
{"", "empty string"},
{"/", "slash"},
{"~", "tilde"},
{"~1", "tilde1"}
}
}
};
// empty json_pointer returns the root JSON-object
auto ptr = ""_json_pointer;
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// simple field access
ptr.push_back("pi");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// object and children access
const std::string answer("answer");
ptr.push_back(answer);
ptr.push_back("everything");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_back();
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// push key which has to be encoded
ptr.push_back("object");
ptr.push_back("/");
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
CHECK(j[ptr.parent_pointer()] == j["object"]);
ptr = ptr.parent_pointer().parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// parent-pointer of the empty json_pointer is empty
ptr = ptr.parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
CHECK_THROWS_WITH(ptr.pop_back(),
"[json.exception.out_of_range.405] JSON pointer has no parent");
}
SECTION("operators")
{
const json j =
{
{"", "Hello"},
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99},
{"", "empty string"},
{"/", "slash"},
{"~", "tilde"},
{"~1", "tilde1"}
}
}
};
// empty json_pointer returns the root JSON-object
auto ptr = ""_json_pointer;
CHECK(j[ptr] == j);
// simple field access
ptr = ptr / "pi";
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(j[ptr] == j);
// object and children access
const std::string answer("answer");
ptr /= answer;
ptr = ptr / "everything";
CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_back();
ptr.pop_back();
CHECK(j[ptr] == j);
CHECK(ptr / ""_json_pointer == ptr);
CHECK(j["/answer"_json_pointer / "/everything"_json_pointer] == j["answer"]["everything"]);
// list children access
CHECK(j["/list"_json_pointer / 1] == j["list"][1]);
// push key which has to be encoded
ptr /= "object";
ptr = ptr / "/";
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
}
}

View file

@ -308,7 +308,7 @@ TEST_CASE("README" * doctest::skip())
// }
// calculate a JSON patch from two JSON values
json::diff(j_result, j_original);
auto res = json::diff(j_result, j_original);
// [
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
// { "op":"remove","path":"/hello" },

View file

@ -129,8 +129,10 @@ struct nocopy
struct Data
{
std::string a;
std::string b;
Data() = default;
Data(const std::string& a_, const std::string b_) : a(a_), b(b_) {}
std::string a {};
std::string b {};
};
void from_json(const json& j, Data& data)
@ -1705,13 +1707,81 @@ TEST_CASE("regression tests")
std::map<std::string, Data> expected
{
{"1", {"testa_1", "testb_1" }},
{"1", {"testa_1", "testb_1"}},
{"2", {"testa_2", "testb_2"}},
{"3", {"testa_3", "testb_3"}},
};
const auto data = j.get<decltype(expected)>();
CHECK(expected == data);
}
SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
{
SECTION("a bunch of -1, ensure_ascii=true")
{
json dump_test;
std::vector<char> data(300, -1);
std::vector<std::string> vec_string(300, "\\ufffd");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
}
SECTION("a bunch of -2, ensure_ascii=false")
{
json dump_test;
std::vector<char> data(500, -2);
std::vector<std::string> vec_string(500, "\xEF\xBF\xBD");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
}
SECTION("test case in issue #1445")
{
nlohmann::json dump_test;
const int data[] =
{
109, 108, 103, 125, -122, -53, 115,
18, 3, 0, 102, 19, 1, 15,
-110, 13, -3, -1, -81, 32, 2,
0, 0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -80, 2,
0, 0, 96, -118, 46, -116, 46,
109, -84, -87, 108, 14, 109, -24,
-83, 13, -18, -51, -83, -52, -115,
14, 6, 32, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
64, 3, 0, 0, 0, 35, -74,
-73, 55, 57, -128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 33, 0, 0, 0, -96,
-54, -28, -26
};
std::string s;
for (unsigned i = 0; i < sizeof(data) / sizeof(int); i++)
{
s += static_cast<char>(data[i]);
}
dump_test["1"] = s;
dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
}
}
SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
{
json j = json::parse("[-9223372036854775808]");
CHECK(j.dump() == "[-9223372036854775808]");
}
}
#if not defined(JSON_NOEXCEPTION)

View file

@ -2130,7 +2130,7 @@ TEST_CASE("all UBJSON first bytes")
try
{
json::from_ubjson(std::vector<uint8_t>(1, byte));
auto res = json::from_ubjson(std::vector<uint8_t>(1, byte));
}
catch (const json::parse_error& e)
{

View file

@ -598,9 +598,8 @@ struct pod_serializer
static void to_json(BasicJsonType& j, const T& t) noexcept
{
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
std::uint64_t value = bytes[0];
for (auto i = 1; i < 8; ++i)
value |= std::uint64_t{bytes[i]} << 8 * i;
std::uint64_t value;
std::memcpy(&value, bytes, sizeof(value));
nlohmann::to_json(j, value);
}
};