✅ improved test coverage
This commit is contained in:
parent
c87ffad45c
commit
606a25195f
@ -241,13 +241,13 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||
case 1:
|
||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||
case 2:
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex)); // LCOV_EXCL_LINE
|
||||
case 3:
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex)); // LCOV_EXCL_LINE
|
||||
case 4:
|
||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE
|
||||
default:
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
@ -3377,13 +3377,13 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||
case 1:
|
||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||
case 2:
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex)); // LCOV_EXCL_LINE
|
||||
case 3:
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex)); // LCOV_EXCL_LINE
|
||||
case 4:
|
||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE
|
||||
default:
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
@ -3946,11 +3946,11 @@ class parser
|
||||
// stack to remember the hieararchy of structured values we are parsing
|
||||
std::vector<parse_state_t> states;
|
||||
// value to avoid a goto (see comment where set to true)
|
||||
bool skip_to_tail = false;
|
||||
bool skip_to_state_evaluation = false;
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (not skip_to_tail)
|
||||
if (not skip_to_state_evaluation)
|
||||
{
|
||||
// invariant: get_token() was called before each iteration
|
||||
switch (last_token)
|
||||
@ -3999,9 +3999,11 @@ class parser
|
||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
|
||||
}
|
||||
|
||||
// remember we are now inside an object
|
||||
states.push_back(parse_state_t::object_value);
|
||||
|
||||
// parse values
|
||||
get_token();
|
||||
states.push_back(parse_state_t::object_value);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4025,8 +4027,10 @@ class parser
|
||||
break;
|
||||
}
|
||||
|
||||
// parse values (no need to call get_token)
|
||||
// remember we are now inside an array
|
||||
states.push_back(parse_state_t::array_value);
|
||||
|
||||
// parse values (no need to call get_token)
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4122,7 +4126,7 @@ class parser
|
||||
}
|
||||
else
|
||||
{
|
||||
skip_to_tail = false;
|
||||
skip_to_state_evaluation = false;
|
||||
}
|
||||
|
||||
// we reached this line after we successfully parsed a value
|
||||
@ -4156,12 +4160,12 @@ class parser
|
||||
|
||||
// We are done with this array. Before we can parse
|
||||
// a new value, we need to evaluate the new state
|
||||
// first. By setting skip_to_tail to false, we are
|
||||
// effectively jumping to the beginning of this
|
||||
// switch.
|
||||
// first. By setting skip_to_state_evaluation to
|
||||
// false, we are effectively jumping to the
|
||||
// beginning of this switch.
|
||||
assert(not states.empty());
|
||||
states.pop_back();
|
||||
skip_to_tail = true;
|
||||
skip_to_state_evaluation = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
@ -4218,12 +4222,12 @@ class parser
|
||||
|
||||
// We are done with this object. Before we can
|
||||
// parse a new value, we need to evaluate the new
|
||||
// state first. By setting skip_to_tail to false,
|
||||
// we are effectively jumping to the beginning of
|
||||
// this switch.
|
||||
// state first. By setting skip_to_state_evaluation
|
||||
// to false, we are effectively jumping to the
|
||||
// beginning of this switch.
|
||||
assert(not states.empty());
|
||||
states.pop_back();
|
||||
skip_to_tail = true;
|
||||
skip_to_state_evaluation = true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
|
@ -134,6 +134,81 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
|
||||
bool errored = false;
|
||||
};
|
||||
|
||||
class SaxCountdown : public nlohmann::json::json_sax_t
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t, const std::string&) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string&&) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string&&) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(const std::vector<uint8_t>&) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t, const std::string&, const json::exception&) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
|
||||
json parser_helper(const std::string& s);
|
||||
bool accept_helper(const std::string& s);
|
||||
|
||||
@ -1595,4 +1670,100 @@ TEST_CASE("parser class")
|
||||
CHECK(j == json(true));
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("improve test coverage")
|
||||
{
|
||||
SECTION("parser with callback")
|
||||
{
|
||||
json::parser_callback_t cb = [](int, json::parse_event_t, json&)
|
||||
{
|
||||
return true;
|
||||
};
|
||||
|
||||
CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded());
|
||||
|
||||
CHECK_THROWS_AS(json::parse("{\"foo\": true:", cb), json::parse_error&);
|
||||
CHECK_THROWS_WITH(json::parse("{\"foo\": true:", cb),
|
||||
"[json.exception.parse_error.101] parse error at 13: syntax error - unexpected ':'; expected '}'");
|
||||
|
||||
CHECK_THROWS_AS(json::parse("1.18973e+4932", cb), json::out_of_range&);
|
||||
CHECK_THROWS_WITH(json::parse("1.18973e+4932", cb),
|
||||
"[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'");
|
||||
}
|
||||
|
||||
SECTION("SAX parser")
|
||||
{
|
||||
SECTION("} without value")
|
||||
{
|
||||
SaxCountdown s(1);
|
||||
CHECK(json::sax_parse("{}", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("} with value")
|
||||
{
|
||||
SaxCountdown s(3);
|
||||
CHECK(json::sax_parse("{\"k1\": true}", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("second key")
|
||||
{
|
||||
SaxCountdown s(3);
|
||||
CHECK(json::sax_parse("{\"k1\": true, \"k2\": false}", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("] without value")
|
||||
{
|
||||
SaxCountdown s(1);
|
||||
CHECK(json::sax_parse("[]", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("] with value")
|
||||
{
|
||||
SaxCountdown s(2);
|
||||
CHECK(json::sax_parse("[1]", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("float")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("3.14", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("false")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("false", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("null")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("null", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("true")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("true", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("unsigned")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("12", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("integer")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("-12", &s) == false);
|
||||
}
|
||||
|
||||
SECTION("string")
|
||||
{
|
||||
SaxCountdown s(0);
|
||||
CHECK(json::sax_parse("\"foo\"", &s) == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user