mirror of
https://github.com/nlohmann/json.git
synced 2026-09-11 18:57:58 +00:00
- bugprone-macro-parentheses: wrap the JSON_THROW_USER macro argument in parentheses at the throw site. - modernize-raw-string-literal: switch two escaped JSON string literals to raw string literals. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
92 lines
4.6 KiB
C++
92 lines
4.6 KiB
C++
// __ _____ _____ _____
|
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
|
// | | |__ | | | | | | version 3.12.0
|
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
|
//
|
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
// This translation unit is a dedicated, small compile-and-run check for two
|
|
// configuration macros that (per #5423) were never exercised anywhere in the
|
|
// test matrix:
|
|
// - JSON_NO_IO, which removes the library's <istream>/<ostream> support
|
|
// (operator<<, operator>>, and the stream-based overloads of dump()/parse())
|
|
// - the JSON_THROW_USER / JSON_TRY_USER / JSON_CATCH_USER trio, which lets a
|
|
// user replace the library's internal exception handling
|
|
//
|
|
// Both macros are about excluding/replacing a facility the library would
|
|
// otherwise pull in on its own, and defining one has no bearing on the other,
|
|
// so -- to keep the test matrix small -- they are exercised together in a
|
|
// single dedicated file instead of two.
|
|
//
|
|
// JSON_NO_IO requires this file itself to never rely on <iostream>/<sstream>;
|
|
// only string-based parsing/dumping is used below.
|
|
#define JSON_NO_IO 1
|
|
|
|
// The user-supplied exception macros below are a *conforming* replacement:
|
|
// they simply forward to the real throw/try/catch keywords (via a counter so
|
|
// the test can assert each macro was actually invoked, not just defined), so
|
|
// every exception-related behavior the library relies on internally --
|
|
// including rethrowing std::out_of_range as json::out_of_range in at() --
|
|
// keeps working exactly as it would with the library's own default macros.
|
|
static int json_throw_user_call_count = 0; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
|
|
|
#define JSON_THROW_USER(exception) do { ++json_throw_user_call_count; throw (exception); } while (false) // NOLINT(cppcoreguidelines-macro-usage)
|
|
#define JSON_TRY_USER try // NOLINT(cppcoreguidelines-macro-usage)
|
|
#define JSON_CATCH_USER(exception) catch (exception) // NOLINT(cppcoreguidelines-macro-usage)
|
|
|
|
#include "doctest_compatibility.h"
|
|
|
|
#include <nlohmann/json.hpp>
|
|
using json = nlohmann::json;
|
|
|
|
TEST_CASE("JSON_NO_IO")
|
|
{
|
|
// everything that does not touch <istream>/<ostream> must keep working:
|
|
// parsing from and dumping to std::string
|
|
const json j = json::parse(R"({"a":[1,2,3],"b":true})");
|
|
CHECK(j.dump() == R"({"a":[1,2,3],"b":true})");
|
|
CHECK(j.at("a").size() == 3);
|
|
CHECK(j.at("b").get<bool>() == true);
|
|
}
|
|
|
|
// this test relies on CHECK_THROWS_AS() actually invoking the guarded
|
|
// expression so json_throw_user_call_count gets bumped and can be observed
|
|
// afterwards; doctest's "--no-throw" test filter (which ci_test_noexceptions
|
|
// passes, together with a global -DJSON_NOEXCEPTION added to CMAKE_CXX_FLAGS
|
|
// for every translation unit in that build, this file included) compiles
|
|
// CHECK_THROWS_AS() out to a no-op that never even invokes the given
|
|
// expression -- so json::parse()/at() below would never be called at all and
|
|
// the call-count assertions would fail even though our JSON_THROW_USER
|
|
// override (which always really throws, regardless of JSON_NOEXCEPTION) would
|
|
// have worked fine on its own
|
|
#if !defined(JSON_NOEXCEPTION)
|
|
TEST_CASE("JSON_THROW_USER, JSON_TRY_USER, JSON_CATCH_USER")
|
|
{
|
|
json_throw_user_call_count = 0;
|
|
|
|
// json::parse() is [[nodiscard]] (JSON_HEDLEY_WARN_UNUSED_RESULT); under
|
|
// GCC in C++11 mode that expands to __attribute__((warn_unused_result)),
|
|
// which -- unlike a [[nodiscard]] attribute proper -- GCC does not
|
|
// consider satisfied by doctest's CHECK_THROWS_AS() wrapping the
|
|
// expression in a (void) cast, so the discarded return value would still
|
|
// be flagged under -Werror=unused-result; assign it to discard it instead,
|
|
// matching the established `json _ = json::parse(...)` pattern used
|
|
// elsewhere in the test suite (see unit-class_parser.cpp)
|
|
json _; // NOLINT(readability-identifier-naming)
|
|
|
|
// a parse error goes through JSON_THROW directly, i.e., through our
|
|
// JSON_THROW_USER override
|
|
CHECK_THROWS_AS(_ = json::parse("this is not JSON"), json::parse_error&);
|
|
CHECK(json_throw_user_call_count > 0);
|
|
|
|
// at() on an out-of-range array index internally catches std::out_of_range
|
|
// (JSON_TRY_USER/JSON_CATCH_USER) and rethrows it as json::out_of_range
|
|
// (JSON_THROW_USER again), so this exercises all three macros together
|
|
const int count_before = json_throw_user_call_count;
|
|
const json arr = json::array({1, 2, 3});
|
|
CHECK_THROWS_AS(arr.at(10), json::out_of_range&);
|
|
CHECK(json_throw_user_call_count > count_before);
|
|
}
|
|
#endif
|