From 8ce64b9c16276a28e7c0babeef43a67c72d1009e Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Fri, 28 Aug 2026 19:02:04 +0000 Subject: [PATCH] Move the custom BinaryType tests into their own translation unit The two sections added to unit-regression2.cpp brought a third full basic_json instantiation into a translation unit that was already large. With Clang on MinGW that pushed the object over the reach of a 32-bit relocation and test-regression2_cpp20.exe failed to link: relocation truncated to fit: IMAGE_REL_AMD64_REL32 against `.rdata' unit-regression2.cpp is restored to exactly what it was before, and the coverage moves to unit-custom-binary-type.cpp, next to the object and array type tests it belongs with. The signed value type is now also covered in C++11, where std::byte is not available. Signed-off-by: Niels Lohmann --- tests/src/unit-custom-binary-type.cpp | 79 +++++++++++++++++++++++++++ tests/src/unit-regression2.cpp | 33 ----------- 2 files changed, 79 insertions(+), 33 deletions(-) create mode 100644 tests/src/unit-custom-binary-type.cpp diff --git a/tests/src/unit-custom-binary-type.cpp b/tests/src/unit-custom-binary-type.cpp new file mode 100644 index 000000000..d357ec9a3 --- /dev/null +++ b/tests/src/unit-custom-binary-type.cpp @@ -0,0 +1,79 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ (supporting code) +// | | |__ | | | | | | version 3.12.0 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann +// SPDX-License-Identifier: MIT + +#include "doctest_compatibility.h" + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef JSON_HAS_CPP_17 + #include +#endif + +namespace +{ + +// a BinaryType whose value type is signed: the elements must still be +// processed as the numbers 0..255 +using char_binary_json = nlohmann::basic_json < + std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, + double, std::allocator, nlohmann::adl_serializer, std::vector, void >; + +#ifdef JSON_HAS_CPP_17 + // a BinaryType whose value type is not an integer type at all + using byte_binary_json = nlohmann::basic_json < + std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, + double, std::allocator, nlohmann::adl_serializer, std::vector, void >; +#endif + +} // namespace + +TEST_CASE("binary type whose value type is not std::uint8_t") +{ + SECTION("a signed value type does not dump negative numbers") + { + const std::vector chars{'\0', '\x01', '\xFF'}; + CHECK(char_binary_json::binary(chars).dump() == R"({"bytes":[0,1,255],"subtype":null})"); + CHECK(char_binary_json::binary(chars, 42).dump() == R"({"bytes":[0,1,255],"subtype":42})"); + CHECK(char_binary_json::binary({}).dump() == R"({"bytes":[],"subtype":null})"); + } + + SECTION("the default binary type is unchanged") + { + CHECK(nlohmann::json::binary({0, 1, 255}, 42).dump() == R"({"bytes":[0,1,255],"subtype":42})"); + } + +#ifdef JSON_HAS_CPP_17 + SECTION("dumping a value type that is not an integer") + { + const std::vector bytes{std::byte{0}, std::byte{1}, std::byte{0xFF}}; + CHECK(byte_binary_json::binary(bytes).dump() == R"({"bytes":[0,1,255],"subtype":null})"); + CHECK(byte_binary_json::binary(bytes, 42).dump() == R"({"bytes":[0,1,255],"subtype":42})"); + CHECK(byte_binary_json::binary({}).dump() == R"({"bytes":[],"subtype":null})"); + } + + SECTION("hashing and the binary formats") + { + const std::vector bytes{std::byte{0}, std::byte{1}, std::byte{0xFF}}; + const auto j = byte_binary_json::binary(bytes); + + CHECK(std::hash {}(j) == std::hash {}(j)); + CHECK(byte_binary_json::from_cbor(byte_binary_json::to_cbor(j)) == j); + CHECK(byte_binary_json::from_msgpack(byte_binary_json::to_msgpack(j)) == j); + + // UBJSON has no binary type, so binary values are written as an array + CHECK(byte_binary_json::from_ubjson(byte_binary_json::to_ubjson(j)) == byte_binary_json({0, 1, 255})); + } +#endif +} diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp index fb1dffd1b..2e7450e2e 100644 --- a/tests/src/unit-regression2.cpp +++ b/tests/src/unit-regression2.cpp @@ -1154,39 +1154,6 @@ TEST_CASE("regression tests 2") CHECK(!default_json.is_binary()); } - SECTION("dumping a binary value with a custom BinaryType") - { - // the elements of a binary value are dumped as the numbers 0..255, - // whatever the value type of the configured BinaryType is - const std::vector bytes{std::byte{0}, std::byte{1}, std::byte{0xFF}}; - CHECK(json_4804::binary(bytes).dump() == R"({"bytes":[0,1,255],"subtype":null})"); - CHECK(json_4804::binary(bytes, 42).dump() == R"({"bytes":[0,1,255],"subtype":42})"); - CHECK(json_4804::binary({}).dump() == R"({"bytes":[],"subtype":null})"); - - // a signed byte type must not dump negative numbers - using json_char_binary = nlohmann::basic_json < - std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, - double, std::allocator, nlohmann::adl_serializer, std::vector, void >; - const std::vector chars{'\0', '\x01', '\xFF'}; - CHECK(json_char_binary::binary(chars).dump() == R"({"bytes":[0,1,255],"subtype":null})"); - - // the default binary type is unchanged - CHECK(json::binary({0, 1, 255}, 42).dump() == R"({"bytes":[0,1,255],"subtype":42})"); - } - - SECTION("hashing and UBJSON with a custom BinaryType") - { - const std::vector bytes{std::byte{0}, std::byte{1}, std::byte{0xFF}}; - const auto j = json_4804::binary(bytes); - - CHECK(std::hash {}(j) == std::hash {}(j)); - CHECK(json_4804::from_cbor(json_4804::to_cbor(j)) == j); - CHECK(json_4804::from_msgpack(json_4804::to_msgpack(j)) == j); - - // UBJSON has no binary type, so binary values are written as arrays - CHECK(json_4804::from_ubjson(json_4804::to_ubjson(j)) == json_4804({0, 1, 255})); - } - SECTION("discussion #4209 - custom BinaryType extraction from parsed array") { // Test that extracting a custom BinaryType from a parsed JSON array still works