From 3173c28dacb63e76b9002746a3435969703213ea Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 4 Oct 2026 14:49:53 +0200 Subject: [PATCH] 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 include Signed-off-by: Niels Lohmann --- tests/src/test_utils.hpp | 3 +- tests/src/unit-allocator.cpp | 2 +- tests/src/unit-binary_utf8_error_handler.cpp | 120 ++++++++++--------- tests/src/unit-binary_utf8_strict.cpp | 36 +++++- tests/src/unit-bjdata.cpp | 2 +- tests/src/unit-bon8.cpp | 2 + tests/src/unit-bson.cpp | 4 +- tests/src/unit-cbor.cpp | 8 +- tests/src/unit-class_parser.cpp | 6 +- tests/src/unit-comparison.cpp | 4 +- tests/src/unit-custom-base-class.cpp | 2 +- tests/src/unit-disabled_exceptions.cpp | 3 + tests/src/unit-element_access2.cpp | 9 +- tests/src/unit-modifiers.cpp | 2 + tests/src/unit-msgpack.cpp | 2 +- tests/src/unit-ordered_map.cpp | 6 +- tests/src/unit-ubjson.cpp | 2 +- 17 files changed, 132 insertions(+), 81 deletions(-) diff --git a/tests/src/test_utils.hpp b/tests/src/test_utils.hpp index b2a381fb0..8f7bd06a0 100644 --- a/tests/src/test_utils.hpp +++ b/tests/src/test_utils.hpp @@ -10,7 +10,8 @@ #include // uint8_t #include // size_t -#include // ifstream, istreambuf_iterator, ios +#include // ifstream, ios +#include // istream_iterator #include // vector namespace utils diff --git a/tests/src/unit-allocator.cpp b/tests/src/unit-allocator.cpp index fbdfaa351..bc283ab28 100644 --- a/tests/src/unit-allocator.cpp +++ b/tests/src/unit-allocator.cpp @@ -567,7 +567,7 @@ struct allocator_no_forward : std::allocator { allocator_no_forward() = default; template - allocator_no_forward(allocator_no_forward /*unused*/) {} + allocator_no_forward(const allocator_no_forward& /*unused*/) {} template struct rebind diff --git a/tests/src/unit-binary_utf8_error_handler.cpp b/tests/src/unit-binary_utf8_error_handler.cpp index 85505bffb..c3f2435fd 100644 --- a/tests/src/unit-binary_utf8_error_handler.cpp +++ b/tests/src/unit-binary_utf8_error_handler.cpp @@ -7,6 +7,7 @@ // SPDX-License-Identifier: MIT #include "doctest_compatibility.h" +#include "test_utils.hpp" #include 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_cases = +std::vector 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 all_handlers = {eh::strict, eh::replace, eh::ignore, eh::keep}; +std::vector 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(h)); + CAPTURE(static_cast(h)) const std::string expected = dump_and_parse(c.bytes, h); CHECK(json::from_cbor(json::to_cbor(jval, h)).get() == 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(h)); + CAPTURE(static_cast(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() == 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(h)); + CAPTURE(static_cast(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() == 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(h)); + CAPTURE(static_cast(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(h)); + CAPTURE(static_cast(h)) - CHECK(json::from_cbor(json::to_cbor(jval, h)).get() == valid_sequence); - CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get() == valid_sequence); - CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get() == valid_sequence); - CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get() == 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() == valid_sequence()); + CHECK(json::from_msgpack(json::to_msgpack(jval, h)).get() == valid_sequence()); + CHECK(json::from_ubjson(json::to_ubjson(jval, false, false, h)).get() == valid_sequence()); + CHECK(json::from_bjdata(json::to_bjdata(jval, false, false, json::bjdata_version_t::draft2, h)).get() == 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() == valid_sequence); - CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get() == valid_sequence); + CHECK(json::from_cbor(json::to_cbor(jval, eh::keep), true, true, json::cbor_tag_handler_t::error, h).get() == valid_sequence()); + CHECK(json::from_msgpack(json::to_msgpack(jval), true, true, h).get() == 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() == ill_formed_cases[1].bytes); + CHECK(json::from_msgpack(json::to_msgpack(jval)).get() == 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() == ill_formed_cases[0].bytes); + CHECK(json::from_cbor(cbor_bytes).get() == ill_formed_cases()[0].bytes); const auto ubjson_bytes = json::to_ubjson(jval, false, false, eh::keep); - CHECK(json::from_ubjson(ubjson_bytes).get() == ill_formed_cases[0].bytes); + CHECK(json::from_ubjson(ubjson_bytes).get() == 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() == ill_formed_cases[0].bytes); + CHECK(json::from_bjdata(bjdata_bytes).get() == ill_formed_cases()[0].bytes); const auto msgpack_bytes = json::to_msgpack(jval); - CHECK(json::from_msgpack(msgpack_bytes).get() == ill_formed_cases[0].bytes); + CHECK(json::from_msgpack(msgpack_bytes).get() == 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() == ill_formed_cases[0].bytes); + CHECK(json::from_bson(bson_bytes)["k"].get() == ill_formed_cases()[0].bytes); } } diff --git a/tests/src/unit-binary_utf8_strict.cpp b/tests/src/unit-binary_utf8_strict.cpp index 2ac8aabf4..96d96e61c 100644 --- a/tests/src/unit-binary_utf8_strict.cpp +++ b/tests/src/unit-binary_utf8_strict.cpp @@ -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 out{0x42}; // a sentinel byte the writer must not touch - CHECK_THROWS_WITH_AS(json::to_bson(json{{"s", "\xFF"}}, nlohmann::detail::output_adapter(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(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(out)), "[json.exception.type_error.316] invalid UTF-8 byte at index 0: 0xFF", json::type_error&); +#endif CHECK(out == std::vector {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") diff --git a/tests/src/unit-bjdata.cpp b/tests/src/unit-bjdata.cpp index f34df1717..0098541cf 100644 --- a/tests/src/unit-bjdata.cpp +++ b/tests/src/unit-bjdata.cpp @@ -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() == 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 diff --git a/tests/src/unit-bon8.cpp b/tests/src/unit-bon8.cpp index a751d7dbe..491189867 100644 --- a/tests/src/unit-bon8.cpp +++ b/tests/src/unit-bon8.cpp @@ -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()) { diff --git a/tests/src/unit-bson.cpp b/tests/src/unit-bson.cpp index 92a14e6fe..17819dc65 100644 --- a/tests/src/unit-bson.cpp +++ b/tests/src/unit-bson.cpp @@ -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() == 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); diff --git a/tests/src/unit-cbor.cpp b/tests/src/unit-cbor.cpp index 633f50fea..f3f4301e5 100644 --- a/tests/src/unit-cbor.cpp +++ b/tests/src/unit-cbor.cpp @@ -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({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({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({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()) { diff --git a/tests/src/unit-class_parser.cpp b/tests/src/unit-class_parser.cpp index 0ae5e382b..f2de97ea3 100644 --- a/tests/src/unit-class_parser.cpp +++ b/tests/src/unit-class_parser.cpp @@ -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") diff --git a/tests/src/unit-comparison.cpp b/tests/src/unit-comparison.cpp index 15715fec2..b9257cb17 100644 --- a/tests/src/unit-comparison.cpp +++ b/tests/src/unit-comparison.cpp @@ -969,7 +969,7 @@ TEST_CASE("copying an object preserves its comparator's state") for (const std::size_t depth : std::vector {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 {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* diff --git a/tests/src/unit-custom-base-class.cpp b/tests/src/unit-custom-base-class.cpp index 38b665793..b9e544705 100644 --- a/tests/src/unit-custom-base-class.cpp +++ b/tests/src/unit-custom-base-class.cpp @@ -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)}); } diff --git a/tests/src/unit-disabled_exceptions.cpp b/tests/src/unit-disabled_exceptions.cpp index 8e3adf944..40a37c339 100644 --- a/tests/src/unit-disabled_exceptions.cpp +++ b/tests/src/unit-disabled_exceptions.cpp @@ -14,6 +14,9 @@ DOCTEST_GCC_SUPPRESS_WARNING("-Wnoexcept") #include using json = nlohmann::json; +#ifdef JSON_TEST_NO_GLOBAL_UDLS + using namespace nlohmann::literals; // NOLINT(google-build-using-namespace) +#endif ///////////////////////////////////////////////////////////////////// // for #2824 diff --git a/tests/src/unit-element_access2.cpp b/tests/src/unit-element_access2.cpp index efd7b15a0..9a7a58e6b 100644 --- a/tests/src/unit-element_access2.cpp +++ b/tests/src/unit-element_access2.cpp @@ -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") { diff --git a/tests/src/unit-modifiers.cpp b/tests/src/unit-modifiers.cpp index 532283f95..3377eace0 100644 --- a/tests/src/unit-modifiers.cpp +++ b/tests/src/unit-modifiers.cpp @@ -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") { diff --git a/tests/src/unit-msgpack.cpp b/tests/src/unit-msgpack.cpp index a92496144..c4b447d64 100644 --- a/tests/src/unit-msgpack.cpp +++ b/tests/src/unit-msgpack.cpp @@ -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 ill_formed_key = {0x81, 0xa2, 0xc0, 0xae, 0x01}; diff --git a/tests/src/unit-ordered_map.cpp b/tests/src/unit-ordered_map.cpp index dce3f61a5..0d0f7730c 100644 --- a/tests/src/unit-ordered_map.cpp +++ b/tests/src/unit-ordered_map.cpp @@ -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); diff --git a/tests/src/unit-ubjson.cpp b/tests/src/unit-ubjson.cpp index 450882a12..80ca214a4 100644 --- a/tests/src/unit-ubjson.cpp +++ b/tests/src/unit-ubjson.cpp @@ -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() == 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