diff --git a/tests/src/unit-alt-string.cpp b/tests/src/unit-alt-string.cpp index 98a13a13f..18648dd09 100644 --- a/tests/src/unit-alt-string.cpp +++ b/tests/src/unit-alt-string.cpp @@ -384,6 +384,9 @@ TEST_CASE("alternative string type") : nlohmann::detail::json_sax_dom_parser(j, false) {} + // sax_parse() calls the SAX parser's own parse_error(), so hiding + // the one of the base class is what recovering takes + // NOLINTNEXTLINE(bugprone-derived-method-shadowing-base-method) bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const nlohmann::detail::exception& /*unused*/) { ++errors; diff --git a/tests/src/unit-class_parser.cpp b/tests/src/unit-class_parser.cpp index d9e3886de..9f8aaf678 100644 --- a/tests/src/unit-class_parser.cpp +++ b/tests/src/unit-class_parser.cpp @@ -143,11 +143,13 @@ class SaxEventLogger { errored = true; events.push_back("parse_error(" + std::to_string(position) + ")"); - return false; + return recover; } std::vector events {}; // NOLINT(readability-redundant-member-init) bool errored = false; + /// whether parse_error() asks the parser to recover from the error (see #3989) + bool recover = false; }; class SaxCountdown : public nlohmann::json::json_sax_t @@ -2822,57 +2824,61 @@ namespace { /// builds a value like json::parse(), but asks the parser to recover from /// errors (see #3989), and checks that the events it receives are balanced -class RecoveringDomParser : public nlohmann::detail::json_sax_dom_parser +class RecoveringDomParser { - using base = nlohmann::detail::json_sax_dom_parser; - public: explicit RecoveringDomParser(json& j, std::size_t max_errors_ = static_cast(-1)) - : base(j, false) + : dom(j, false) , max_errors(max_errors_) {} bool null() { value(); - return base::null(); + return dom.null(); } bool boolean(bool val) { value(); - return base::boolean(val); + return dom.boolean(val); } bool number_integer(json::number_integer_t val) { value(); - return base::number_integer(val); + return dom.number_integer(val); } bool number_unsigned(json::number_unsigned_t val) { value(); - return base::number_unsigned(val); + return dom.number_unsigned(val); } bool number_float(json::number_float_t val, const std::string& s) { value(); - return base::number_float(val, s); + return dom.number_float(val, s); } bool string(std::string& val) { value(); - return base::string(val); + return dom.string(val); + } + + bool binary(json::binary_t& val) + { + value(); + return dom.binary(val); } bool start_object(std::size_t elements) { value(); stack.push_back('o'); - return base::start_object(elements); + return dom.start_object(elements); } bool key(std::string& val) @@ -2884,7 +2890,7 @@ class RecoveringDomParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.back() = 'v'; - return base::key(val); + return dom.key(val); } bool end_object() @@ -2896,14 +2902,14 @@ class RecoveringDomParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.pop_back(); - return base::end_object(); + return dom.end_object(); } bool start_array(std::size_t elements) { value(); stack.push_back('a'); - return base::start_array(elements); + return dom.start_array(elements); } bool end_array() @@ -2915,7 +2921,7 @@ class RecoveringDomParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.pop_back(); - return base::end_array(); + return dom.end_array(); } bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& ex) @@ -2930,6 +2936,8 @@ class RecoveringDomParser : public nlohmann::detail::json_sax_dom_parser return well_formed && stack.empty(); } + /// builds the value + nlohmann::detail::json_sax_dom_parser dom; std::vector errors {}; // NOLINT(readability-redundant-member-init) std::size_t events = 0; /// the open containers: 'a' for an array, 'o' for an object that expects @@ -2979,17 +2987,6 @@ RecoveryResult parse_recovering(InputType&& input, const bool strict = true, return {j, sax.errors, sax.events, ok, sax.balanced()}; } -/// logs the events as strings and recovers from errors -class RecoveringEventLogger : public SaxEventLogger -{ - public: - bool parse_error(std::size_t position, const std::string& /*unused*/, const json::exception& /*unused*/) - { - events.push_back("parse_error(" + std::to_string(position) + ")"); - return true; - } -}; - /// stops after a number of events, but recovers from errors class RecoveringCountdown : public SaxCountdown { @@ -3139,7 +3136,8 @@ TEST_CASE("parser error recovery (#3989)") CHECK(result.value[1].get() == -std::numeric_limits::infinity()); // the SAX parser gets the number's text - RecoveringEventLogger logger; + SaxEventLogger logger; + logger.recover = true; CHECK(!json::sax_parse("1e999", &logger)); CHECK(logger.events == std::vector({"parse_error(5)", "number_float(1e999)"})); } @@ -3191,7 +3189,8 @@ TEST_CASE("parser error recovery (#3989)") SECTION("events") { // see #4522 - RecoveringEventLogger logger; + SaxEventLogger logger; + logger.recover = true; CHECK(!json::sax_parse(R"([{1}, "a"])", &logger)); CHECK(logger.events == std::vector( { diff --git a/tests/src/unit-regression2.cpp b/tests/src/unit-regression2.cpp index 4aa4b144b..c49b00c7c 100644 --- a/tests/src/unit-regression2.cpp +++ b/tests/src/unit-regression2.cpp @@ -874,62 +874,60 @@ namespace { /// builds a value from SAX events, asks the parser to recover from its first /// 100 errors, and checks that the events are balanced (see #3989) -class RecoveringParser : public nlohmann::detail::json_sax_dom_parser +class RecoveringParser { - using base = nlohmann::detail::json_sax_dom_parser; - public: explicit RecoveringParser(json& j) - : base(j, false) + : dom(j, false) {} bool null() { value(); - return base::null(); + return dom.null(); } bool boolean(bool val) { value(); - return base::boolean(val); + return dom.boolean(val); } bool number_integer(json::number_integer_t val) { value(); - return base::number_integer(val); + return dom.number_integer(val); } bool number_unsigned(json::number_unsigned_t val) { value(); - return base::number_unsigned(val); + return dom.number_unsigned(val); } bool number_float(json::number_float_t val, const std::string& s) { value(); - return base::number_float(val, s); + return dom.number_float(val, s); } bool string(std::string& val) { value(); - return base::string(val); + return dom.string(val); } bool binary(json::binary_t& val) { value(); - return base::binary(val); + return dom.binary(val); } bool start_object(std::size_t elements) { value(); stack.push_back('o'); - return base::start_object(elements); + return dom.start_object(elements); } bool key(std::string& val) @@ -940,7 +938,7 @@ class RecoveringParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.back() = 'v'; - return base::key(val); + return dom.key(val); } bool end_object() @@ -951,14 +949,14 @@ class RecoveringParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.pop_back(); - return base::end_object(); + return dom.end_object(); } bool start_array(std::size_t elements) { value(); stack.push_back('a'); - return base::start_array(elements); + return dom.start_array(elements); } bool end_array() @@ -969,7 +967,7 @@ class RecoveringParser : public nlohmann::detail::json_sax_dom_parser return false; } stack.pop_back(); - return base::end_array(); + return dom.end_array(); } bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& ex) @@ -986,6 +984,8 @@ class RecoveringParser : public nlohmann::detail::json_sax_dom_parser return well_formed && stack.empty(); } + /// builds the value + nlohmann::detail::json_sax_dom_parser dom; std::size_t errors = 0; std::vector messages {}; // NOLINT(readability-redundant-member-init) std::vector stack {}; // NOLINT(readability-redundant-member-init)