mirror of
https://github.com/nlohmann/json.git
synced 2026-10-04 21:50:33 +00:00
Fix the tests added by the merged PRs for all CI configurations
- discard the results of dump() and from_*() in CHECK_THROWS with utils::ignore_return_value (GCC -Werror=unused-result) - give unit-bson's huge_string_t a default constructor (MSVC C2512, GCC 5, clang 3.5) - unit-disabled_exceptions: use the literals namespace when the global UDLs are off (ci_test_noglobaludls; #5700) - unit-binary_utf8_strict: expect the JSON pointer prefix with JSON_DIAGNOSTICS (#5741) - skip the tests that rely on exceptions under JSON_NOEXCEPTION (#5678, #5732) - clang-tidy and clang -Werror: static test data, CAPTURE(...);, const-correctness, use-after-move alias, unused conversion operator, a missing <iterator> include Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -10,7 +10,8 @@
|
||||
|
||||
#include <cstdint> // uint8_t
|
||||
#include <cstddef> // size_t
|
||||
#include <fstream> // ifstream, istreambuf_iterator, ios
|
||||
#include <fstream> // ifstream, ios
|
||||
#include <iterator> // istream_iterator
|
||||
#include <vector> // vector
|
||||
|
||||
namespace utils
|
||||
|
||||
@@ -567,7 +567,7 @@ struct allocator_no_forward : std::allocator<T>
|
||||
{
|
||||
allocator_no_forward() = default;
|
||||
template <class U>
|
||||
allocator_no_forward(allocator_no_forward<U> /*unused*/) {}
|
||||
allocator_no_forward(const allocator_no_forward<U>& /*unused*/) {}
|
||||
|
||||
template <class U>
|
||||
struct rebind
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
#include "test_utils.hpp"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
@@ -25,18 +26,27 @@ struct ill_formed_case
|
||||
|
||||
// RFC 3629 ill-formed sequences used throughout this file, plus one
|
||||
// well-formed sequence for contrast
|
||||
const std::vector<ill_formed_case> ill_formed_cases =
|
||||
std::vector<ill_formed_case> ill_formed_cases()
|
||||
{
|
||||
{"overlong", "\xC0\xAE"},
|
||||
{"lone_0xFF", "\xFF"},
|
||||
{"truncated", "\xE2\x82"},
|
||||
{"surrogate", "\xED\xA0\x80"},
|
||||
};
|
||||
return
|
||||
{
|
||||
{"overlong", "\xC0\xAE"},
|
||||
{"lone_0xFF", "\xFF"},
|
||||
{"truncated", "\xE2\x82"},
|
||||
{"surrogate", "\xED\xA0\x80"},
|
||||
};
|
||||
}
|
||||
|
||||
const std::string valid_sequence = "\xC3\xA9"; // U+00E9, "é"
|
||||
std::string valid_sequence()
|
||||
{
|
||||
return "\xC3\xA9"; // U+00E9, "é"
|
||||
}
|
||||
|
||||
using eh = json::error_handler_t;
|
||||
const std::vector<eh> all_handlers = {eh::strict, eh::replace, eh::ignore, eh::keep};
|
||||
std::vector<eh> all_handlers()
|
||||
{
|
||||
return {eh::strict, eh::replace, eh::ignore, eh::keep};
|
||||
}
|
||||
|
||||
// what dump()+parse() produces for a sanitizing error_handler; this is the
|
||||
// ground truth every binary writer/reader is checked against
|
||||
@@ -51,9 +61,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
{
|
||||
SECTION("writers: string value")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases)
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name);
|
||||
CAPTURE(c.name)
|
||||
const json jval = c.bytes;
|
||||
|
||||
CHECK_THROWS_AS(json::to_cbor(jval, eh::strict), json::type_error&);
|
||||
@@ -71,7 +81,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
eh::replace, eh::ignore
|
||||
})
|
||||
{
|
||||
CAPTURE(static_cast<int>(h));
|
||||
CAPTURE(static_cast<int>(h))
|
||||
const std::string expected = dump_and_parse(c.bytes, h);
|
||||
|
||||
CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == expected);
|
||||
@@ -103,9 +113,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("writers: object key")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases)
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name);
|
||||
CAPTURE(c.name)
|
||||
json jobj;
|
||||
jobj[c.bytes] = 1;
|
||||
|
||||
@@ -120,7 +130,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
eh::replace, eh::ignore
|
||||
})
|
||||
{
|
||||
CAPTURE(static_cast<int>(h));
|
||||
CAPTURE(static_cast<int>(h))
|
||||
const std::string expected = dump_and_parse(c.bytes, h);
|
||||
|
||||
CHECK(json::from_cbor(json::to_cbor(jobj, h)).begin().key() == expected);
|
||||
@@ -141,9 +151,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("readers: string value")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases)
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name);
|
||||
CAPTURE(c.name)
|
||||
|
||||
// bytes produced the lenient (keep) way, as any binary reader
|
||||
// accepted them before this parameter existed
|
||||
@@ -166,15 +176,15 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == c.bytes);
|
||||
|
||||
// strict: parse_error.113, discarded (not thrown) when allow_exceptions is false
|
||||
CHECK_THROWS_AS(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict)), json::parse_error&);
|
||||
CHECK(json::from_cbor(cbor_bytes, true, false, json::cbor_tag_handler_t::error, eh::strict).is_discarded());
|
||||
CHECK_THROWS_AS(json::from_msgpack(msgpack_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_msgpack(msgpack_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK(json::from_msgpack(msgpack_bytes, true, false, eh::strict).is_discarded());
|
||||
CHECK_THROWS_AS(json::from_ubjson(ubjson_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_ubjson(ubjson_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK(json::from_ubjson(ubjson_bytes, true, false, eh::strict).is_discarded());
|
||||
CHECK_THROWS_AS(json::from_bjdata(bjdata_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_bjdata(bjdata_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK(json::from_bjdata(bjdata_bytes, true, false, eh::strict).is_discarded());
|
||||
CHECK_THROWS_AS(json::from_bson(bson_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_bson(bson_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK(json::from_bson(bson_bytes, true, false, eh::strict).is_discarded());
|
||||
|
||||
// replace / ignore: match what dump() would have sanitized the same bytes to
|
||||
@@ -183,7 +193,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
eh::replace, eh::ignore
|
||||
})
|
||||
{
|
||||
CAPTURE(static_cast<int>(h));
|
||||
CAPTURE(static_cast<int>(h))
|
||||
const std::string expected = dump_and_parse(c.bytes, h);
|
||||
|
||||
CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == expected);
|
||||
@@ -197,9 +207,9 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("readers: object key")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases)
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name);
|
||||
CAPTURE(c.name)
|
||||
|
||||
json jobj;
|
||||
jobj[c.bytes] = 1;
|
||||
@@ -215,18 +225,18 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
CHECK(json::from_bjdata(bjdata_bytes).begin().key() == c.bytes);
|
||||
CHECK(json::from_bson(bson_bytes).begin().key() == c.bytes);
|
||||
|
||||
CHECK_THROWS_AS(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(json::from_msgpack(msgpack_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(json::from_ubjson(ubjson_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(json::from_bjdata(bjdata_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(json::from_bson(bson_bytes, true, true, eh::strict), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, eh::strict)), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_msgpack(msgpack_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_ubjson(ubjson_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_bjdata(bjdata_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(json::from_bson(bson_bytes, true, true, eh::strict)), json::parse_error&);
|
||||
|
||||
for (const auto h :
|
||||
{
|
||||
eh::replace, eh::ignore
|
||||
})
|
||||
{
|
||||
CAPTURE(static_cast<int>(h));
|
||||
CAPTURE(static_cast<int>(h))
|
||||
const std::string expected = dump_and_parse(c.bytes, h);
|
||||
|
||||
CHECK(json::from_cbor(cbor_bytes, true, true, json::cbor_tag_handler_t::error, h).begin().key() == expected);
|
||||
@@ -240,30 +250,30 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("well-formed UTF-8 is unaffected by error_handler")
|
||||
{
|
||||
const json jval = valid_sequence;
|
||||
const json jval = valid_sequence();
|
||||
json jobj;
|
||||
jobj[valid_sequence] = valid_sequence;
|
||||
jobj[valid_sequence()] = valid_sequence();
|
||||
|
||||
for (const auto h : all_handlers)
|
||||
for (const auto h : all_handlers())
|
||||
{
|
||||
CAPTURE(static_cast<int>(h));
|
||||
CAPTURE(static_cast<int>(h))
|
||||
|
||||
CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_bson(json::to_bson(jobj, h)).begin().key() == valid_sequence);
|
||||
CHECK(json::from_cbor(json::to_cbor(jval, h)).get<std::string>() == valid_sequence());
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get<std::string>() == valid_sequence());
|
||||
CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get<std::string>() == valid_sequence());
|
||||
CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get<std::string>() == valid_sequence());
|
||||
CHECK(json::from_bson(json::to_bson(jobj, h)).begin().key() == valid_sequence());
|
||||
|
||||
CHECK(json::from_cbor(json::to_cbor(jval, eh::keep), true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get<std::string>() == valid_sequence);
|
||||
CHECK(json::from_cbor(json::to_cbor(jval, eh::keep), true, true, json::cbor_tag_handler_t::error, h).get<std::string>() == valid_sequence());
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get<std::string>() == valid_sequence());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("dump() with error_handler_t::keep writes raw bytes as is")
|
||||
{
|
||||
for (const auto& c : ill_formed_cases)
|
||||
for (const auto& c : ill_formed_cases())
|
||||
{
|
||||
CAPTURE(c.name);
|
||||
CAPTURE(c.name)
|
||||
|
||||
const json jval = c.bytes;
|
||||
const std::string dumped = jval.dump(-1, ' ', false, eh::keep);
|
||||
@@ -276,10 +286,10 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
// well-formed characters around an ill-formed sequence are still
|
||||
// escaped as usual under ensure_ascii
|
||||
const json mixed = valid_sequence + ill_formed_cases[1].bytes; // "é" + lone 0xFF
|
||||
const json mixed = valid_sequence() + ill_formed_cases()[1].bytes; // "é" + lone 0xFF
|
||||
const std::string dumped_mixed = mixed.dump(-1, ' ', true, eh::keep);
|
||||
CHECK(dumped_mixed.find("\\u00e9") != std::string::npos);
|
||||
CHECK(dumped_mixed.find(ill_formed_cases[1].bytes) != std::string::npos);
|
||||
CHECK(dumped_mixed.find(ill_formed_cases()[1].bytes) != std::string::npos);
|
||||
|
||||
// the byte that ends an ill-formed sequence is read again, so a quote,
|
||||
// a backslash, or a control character after it is still escaped, and
|
||||
@@ -289,7 +299,7 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
false, true
|
||||
})
|
||||
{
|
||||
CAPTURE(ensure_ascii);
|
||||
CAPTURE(ensure_ascii)
|
||||
CHECK(json("\xC3\"").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\"\"");
|
||||
CHECK(json("\xC3\\").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\\\\"");
|
||||
CHECK(json("\xC3\n").dump(-1, ' ', ensure_ascii, eh::keep) == "\"\xC3\\n\"");
|
||||
@@ -303,12 +313,12 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("to_msgpack defaults to keep; to_bon8 is not affected by error_handler")
|
||||
{
|
||||
const json jval = ill_formed_cases[1].bytes; // lone 0xFF
|
||||
const json jval = ill_formed_cases()[1].bytes; // lone 0xFF
|
||||
|
||||
// to_msgpack's error_handler defaults to keep, as MessagePack's spec
|
||||
// allows any bytes in a str, so the bytes are passed through
|
||||
CHECK(json::to_msgpack(jval) == json::to_msgpack(jval, eh::keep));
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval)).get<std::string>() == ill_formed_cases[1].bytes);
|
||||
CHECK(json::from_msgpack(json::to_msgpack(jval)).get<std::string>() == ill_formed_cases()[1].bytes);
|
||||
|
||||
// the diagnostics context of an ill-formed key is the object
|
||||
json jobj;
|
||||
@@ -322,14 +332,14 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
|
||||
SECTION("allow_exceptions=false with error_handler_t::strict discards the value")
|
||||
{
|
||||
const auto bytes = json::to_cbor(json(ill_formed_cases[0].bytes), eh::keep);
|
||||
const auto bytes = json::to_cbor(json(ill_formed_cases()[0].bytes), eh::keep);
|
||||
const json result = json::from_cbor(bytes, true, false, json::cbor_tag_handler_t::error, eh::strict);
|
||||
CHECK(result.is_discarded());
|
||||
}
|
||||
|
||||
SECTION("default parameters are unchanged")
|
||||
{
|
||||
const json jval = ill_formed_cases[0].bytes;
|
||||
const json jval = ill_formed_cases()[0].bytes;
|
||||
|
||||
// to_*: the default error_handler is keep, so ill-formed bytes are
|
||||
// written unchanged, exactly as in release 3.12.0 (it is strict only
|
||||
@@ -347,16 +357,16 @@ TEST_CASE("UTF-8 error_handler for the binary readers and writers")
|
||||
// from_*: the default error_handler is keep, so ill-formed bytes are
|
||||
// still accepted unchanged, exactly as in release 3.12.0
|
||||
const auto cbor_bytes = json::to_cbor(jval, eh::keep);
|
||||
CHECK(json::from_cbor(cbor_bytes).get<std::string>() == ill_formed_cases[0].bytes);
|
||||
CHECK(json::from_cbor(cbor_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
const auto ubjson_bytes = json::to_ubjson(jval, false, false, eh::keep);
|
||||
CHECK(json::from_ubjson(ubjson_bytes).get<std::string>() == ill_formed_cases[0].bytes);
|
||||
CHECK(json::from_ubjson(ubjson_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
const auto bjdata_bytes = json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, eh::keep);
|
||||
CHECK(json::from_bjdata(bjdata_bytes).get<std::string>() == ill_formed_cases[0].bytes);
|
||||
CHECK(json::from_bjdata(bjdata_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
const auto msgpack_bytes = json::to_msgpack(jval);
|
||||
CHECK(json::from_msgpack(msgpack_bytes).get<std::string>() == ill_formed_cases[0].bytes);
|
||||
CHECK(json::from_msgpack(msgpack_bytes).get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
json bson_obj;
|
||||
bson_obj["k"] = jval;
|
||||
const auto bson_bytes = json::to_bson(bson_obj, eh::keep);
|
||||
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == ill_formed_cases[0].bytes);
|
||||
CHECK(json::from_bson(bson_bytes)["k"].get<std::string>() == ill_formed_cases()[0].bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,21 +83,45 @@ TEST_CASE("JSON_STRICT_BINARY_UTF8 (see #5529, #5651)")
|
||||
// any bytes reach the output adapter (the BSON document length
|
||||
// prefix must be known up front, so nothing is written incrementally)
|
||||
std::vector<std::uint8_t> out{0x42}; // a sentinel byte the writer must not touch
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}, nlohmann::detail::output_adapter<std::uint8_t>(out)), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#endif
|
||||
CHECK(out == std::vector<std::uint8_t> {0x42});
|
||||
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xFF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xFF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#endif
|
||||
// a truncated multi-byte sequence
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xC3"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC3", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC3"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xC3", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC3"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC3", json::type_error&);
|
||||
#endif
|
||||
// an encoded surrogate half (U+D800)
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xED", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xED", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xED\xA0\x80"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xED", json::type_error&);
|
||||
#endif
|
||||
// an overlong encoding of '.'
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC0", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] (/s) invalid UTF-8 byte at index 0: 0xC0", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"s", "\xC0\xAF"}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xC0", json::type_error&);
|
||||
#endif
|
||||
|
||||
// an object key with ill-formed UTF-8 is rejected as well; unlike
|
||||
// the reader (which never validates element names), the writer
|
||||
// checks both string values and object keys
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json{{"\xFF", 1}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#if JSON_DIAGNOSTICS
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"\xFF", 1}}), "[json.exception.type_error.316] (/\xFF) invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#else
|
||||
CHECK_THROWS_WITH_AS(json::to_bson(json {{"\xFF", 1}}), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&);
|
||||
#endif
|
||||
}
|
||||
|
||||
SECTION("an explicit error_handler overrides the default")
|
||||
|
||||
@@ -3921,7 +3921,7 @@ TEST_CASE("Universal Binary JSON Specification Examples 1")
|
||||
CHECK_NOTHROW(j = json::from_bjdata(v));
|
||||
REQUIRE(j.is_string());
|
||||
CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae"));
|
||||
CHECK_THROWS_AS(j.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
|
||||
CHECK(json::from_bjdata(json::to_bjdata(j)) == j);
|
||||
|
||||
// the same bytes as an object key round-trip as well
|
||||
|
||||
@@ -786,6 +786,7 @@ TEST_CASE("Parse BON8 directly from a file using iterator and sentinel")
|
||||
CHECK((parsed.is_object() || parsed.is_array()));
|
||||
}
|
||||
|
||||
#if !defined(JSON_NOEXCEPTION) // corpus values that do not survive the round trip are skipped by catching the exception
|
||||
TEST_CASE("BON8 round-trip invariants")
|
||||
{
|
||||
// This checks what the parse_bon8_fuzzer driver checks (see
|
||||
@@ -818,6 +819,7 @@ TEST_CASE("BON8 round-trip invariants")
|
||||
CHECK(json::to_bon8(j2) == vec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("BON8 roundtrips" * doctest::skip())
|
||||
{
|
||||
|
||||
@@ -62,6 +62,8 @@ class huge_string_t : public std::string
|
||||
{
|
||||
public:
|
||||
using std::string::string;
|
||||
// inheriting std::string's constructors does not inherit its default constructor
|
||||
huge_string_t() = default;
|
||||
huge_string_t(const std::string& s) : std::string(s) {} // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||
|
||||
// returns a copy of @a s whose size() pretends to be huge
|
||||
@@ -174,7 +176,7 @@ TEST_CASE("BSON")
|
||||
REQUIRE(j.contains("s"));
|
||||
CHECK(j["s"].get_ref<const json::string_t&>() == std::string("\xc0\xae"));
|
||||
// dump() still requires valid UTF-8 and throws for such a value
|
||||
CHECK_THROWS_AS(j.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
|
||||
// to_bson() writes the bytes back unchanged, as before 3.13.0,
|
||||
// unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp)
|
||||
CHECK(json::from_bson(json::to_bson(j)) == j);
|
||||
|
||||
@@ -1820,7 +1820,7 @@ TEST_CASE("CBOR")
|
||||
// dump() still requires valid UTF-8 and throws for such a value,
|
||||
// unless an error handler that replaces or ignores the bytes is
|
||||
// passed
|
||||
CHECK_THROWS_AS(j_value.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(j_value.dump()), json::type_error&);
|
||||
// to_cbor() writes the bytes back unchanged, as before 3.13.0,
|
||||
// unless JSON_STRICT_BINARY_UTF8 is enabled (see unit-binary_utf8_strict.cpp)
|
||||
CHECK(json::from_cbor(json::to_cbor(j_value)) == j_value);
|
||||
@@ -1878,13 +1878,13 @@ TEST_CASE("CBOR")
|
||||
// a truncated code point is kept as is
|
||||
CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x61, 0xc3, 0xff})));
|
||||
CHECK(_ == "\xc3");
|
||||
CHECK_THROWS_AS(_.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(_.dump()), json::type_error&);
|
||||
CHECK(json::from_cbor(json::to_cbor(_)) == _);
|
||||
|
||||
// an ill-formed later chunk is kept after valid ones
|
||||
CHECK_NOTHROW(_ = json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc0, 0xae, 0xff})));
|
||||
CHECK(_ == "\xc3\xa9\xc0\xae");
|
||||
CHECK_THROWS_AS(_.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(_.dump()), json::type_error&);
|
||||
|
||||
// valid multi-byte chunks are accepted
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0x7f, 0x62, 0xc3, 0xa9, 0x62, 0xc3, 0xb6, 0xff})) == "\xc3\xa9\xc3\xb6");
|
||||
@@ -2390,6 +2390,7 @@ TEST_CASE("issue #5405 - array reserve for definite-length CBOR arrays")
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(JSON_NOEXCEPTION) // corpus values that do not survive the round trip are skipped by catching the exception
|
||||
TEST_CASE("CBOR round-trip invariants")
|
||||
{
|
||||
// This checks what the parse_cbor_fuzzer driver checks (see
|
||||
@@ -2422,6 +2423,7 @@ TEST_CASE("CBOR round-trip invariants")
|
||||
CHECK(json::to_cbor(j2) == vec);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("CBOR roundtrips" * doctest::skip())
|
||||
{
|
||||
|
||||
@@ -2704,9 +2704,9 @@ TEST_CASE("diagnostic positions: value lifetime, input adapters, and SAX")
|
||||
CHECK(b["b"].end_pos() == nested_end);
|
||||
|
||||
// the moved-from value is reset to a null and reports npos
|
||||
CHECK(a.is_null()); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move)
|
||||
CHECK(a.start_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move)
|
||||
CHECK(a.end_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,clang-analyzer-cplusplus.Move)
|
||||
CHECK(a.is_null()); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
|
||||
CHECK(a.start_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
|
||||
CHECK(a.end_pos() == std::string::npos); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved,clang-analyzer-cplusplus.Move)
|
||||
}
|
||||
|
||||
SECTION("swap() exchanges positions along with values")
|
||||
|
||||
@@ -969,7 +969,7 @@ TEST_CASE("copying an object preserves its comparator's state")
|
||||
|
||||
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
|
||||
{
|
||||
CAPTURE(depth);
|
||||
CAPTURE(depth)
|
||||
|
||||
key_case_json original = object;
|
||||
for (std::size_t i = 0; i < depth; ++i)
|
||||
@@ -1138,7 +1138,7 @@ TEST_CASE("operator<=> of binary values with a different subtype does not depend
|
||||
// and must still agree with the levels that do
|
||||
for (const std::size_t depth : std::vector<std::size_t> {0, 127, 128, 200})
|
||||
{
|
||||
CAPTURE(depth);
|
||||
CAPTURE(depth)
|
||||
const json x = deep(a, depth);
|
||||
const json y = deep(b, depth);
|
||||
CHECK((x <=> y) == std::partial_ordering::less); // *NOPAD*
|
||||
|
||||
@@ -505,7 +505,7 @@ static json_with_const_base make_nested_array(std::size_t depth)
|
||||
{
|
||||
if (depth == 0)
|
||||
{
|
||||
return json_with_const_base(1);
|
||||
return json_with_const_base(1); // NOLINT(modernize-return-braced-init-list): {1} would be an array
|
||||
}
|
||||
return json_with_const_base::array({make_nested_array(depth - 1)});
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept")
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// for #2824
|
||||
|
||||
@@ -1963,8 +1963,8 @@ TEST_CASE("operator[] with user-defined std::string_view-convertible types")
|
||||
};
|
||||
|
||||
json j = {{"foo", "from_class"}, {"bar", "from_struct"}};
|
||||
TestClass foo_obj;
|
||||
TestStruct bar_obj;
|
||||
const TestClass foo_obj;
|
||||
const TestStruct bar_obj;
|
||||
|
||||
SECTION("read access")
|
||||
{
|
||||
@@ -2005,6 +2005,10 @@ TEST_CASE("keys convertible to std::string_view work with all lookup functions (
|
||||
// 3.12.0, such a key worked with at, the const operator[], find, count and
|
||||
// contains via the conversion to std::string; #4958 made the KeyType&&
|
||||
// templates win overload resolution for it instead, and those then failed
|
||||
// the lookups pick the conversion to std::string_view, which leaves the one
|
||||
// to std::string unused; it has to exist to reproduce the ambiguity
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING("-Wunused-member-function")
|
||||
struct DualKey
|
||||
{
|
||||
operator std::string() const
|
||||
@@ -2016,6 +2020,7 @@ TEST_CASE("keys convertible to std::string_view work with all lookup functions (
|
||||
return "a";
|
||||
}
|
||||
};
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_POP
|
||||
|
||||
SECTION("nlohmann::json")
|
||||
{
|
||||
|
||||
@@ -1162,6 +1162,7 @@ TEST_CASE("update() on deeply nested values")
|
||||
|
||||
TEST_CASE("update() with an argument that aliases *this (#5641)")
|
||||
{
|
||||
#if !defined(JSON_NOEXCEPTION) // checks which exception is thrown, and that nothing changed
|
||||
SECTION("the target is checked before the argument, as before the copy")
|
||||
{
|
||||
json j = 1;
|
||||
@@ -1172,6 +1173,7 @@ TEST_CASE("update() with an argument that aliases *this (#5641)")
|
||||
CHECK_THROWS_WITH_AS(k.update(json::array()), "[json.exception.type_error.312] cannot use update() with array", json::type_error&);
|
||||
CHECK(k == json::object());
|
||||
}
|
||||
#endif
|
||||
|
||||
SECTION("const reference")
|
||||
{
|
||||
|
||||
@@ -1560,7 +1560,7 @@ TEST_CASE("MessagePack")
|
||||
// dump() still requires valid UTF-8 and throws for such a value,
|
||||
// unless an error handler that replaces or ignores the bytes is
|
||||
// passed
|
||||
CHECK_THROWS_AS(j_value.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(j_value.dump()), json::type_error&);
|
||||
|
||||
// the same bytes as an object key round-trip as well
|
||||
const std::vector<uint8_t> ill_formed_key = {0x81, 0xa2, 0xc0, 0xae, 0x01};
|
||||
|
||||
@@ -430,8 +430,8 @@ TEST_CASE("ordered_map")
|
||||
|
||||
SECTION("with T& (lvalue)")
|
||||
{
|
||||
std::string one = "1";
|
||||
std::string four = "four";
|
||||
std::string one = "1"; // NOLINT(misc-const-correctness): emplace must accept a non-const lvalue
|
||||
std::string four = "four"; // NOLINT(misc-const-correctness): see above
|
||||
|
||||
auto res1 = om.emplace("eins", one);
|
||||
CHECK(res1.first == om.begin());
|
||||
@@ -467,7 +467,7 @@ TEST_CASE("ordered_map")
|
||||
SECTION("with key of key_type (non-template overload)")
|
||||
{
|
||||
const std::string key_vier{"vier"};
|
||||
std::string four = "four";
|
||||
std::string four = "four"; // NOLINT(misc-const-correctness): emplace must accept a non-const lvalue
|
||||
|
||||
auto res4 = om.emplace(key_vier, four);
|
||||
CHECK(res4.first == om.begin() + 3);
|
||||
|
||||
@@ -2520,7 +2520,7 @@ TEST_CASE("Universal Binary JSON Specification Examples 1")
|
||||
CHECK_NOTHROW(j = json::from_ubjson(v));
|
||||
REQUIRE(j.is_string());
|
||||
CHECK(j.get_ref<const json::string_t&>() == std::string("\xc0\xae"));
|
||||
CHECK_THROWS_AS(j.dump(), json::type_error&);
|
||||
CHECK_THROWS_AS(utils::ignore_return_value(j.dump()), json::type_error&);
|
||||
CHECK(json::from_ubjson(json::to_ubjson(j)) == j);
|
||||
|
||||
// the same bytes as an object key round-trip as well
|
||||
|
||||
Reference in New Issue
Block a user