✅ improved test coverage
This commit is contained in:
parent
c87ffad45c
commit
606a25195f
3 changed files with 194 additions and 19 deletions
|
@ -241,13 +241,13 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
case 1:
|
case 1:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||||
case 2:
|
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:
|
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:
|
case 4:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||||
case 5:
|
case 5:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE
|
||||||
default:
|
default:
|
||||||
assert(false); // LCOV_EXCL_LINE
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
|
@ -3377,13 +3377,13 @@ class json_sax_dom_parser : public json_sax<BasicJsonType>
|
||||||
case 1:
|
case 1:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||||
case 2:
|
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:
|
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:
|
case 4:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||||
case 5:
|
case 5:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex)); // LCOV_EXCL_LINE
|
||||||
default:
|
default:
|
||||||
assert(false); // LCOV_EXCL_LINE
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
@ -3946,11 +3946,11 @@ class parser
|
||||||
// stack to remember the hieararchy of structured values we are parsing
|
// stack to remember the hieararchy of structured values we are parsing
|
||||||
std::vector<parse_state_t> states;
|
std::vector<parse_state_t> states;
|
||||||
// value to avoid a goto (see comment where set to true)
|
// value to avoid a goto (see comment where set to true)
|
||||||
bool skip_to_tail = false;
|
bool skip_to_state_evaluation = false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (not skip_to_tail)
|
if (not skip_to_state_evaluation)
|
||||||
{
|
{
|
||||||
// invariant: get_token() was called before each iteration
|
// invariant: get_token() was called before each iteration
|
||||||
switch (last_token)
|
switch (last_token)
|
||||||
|
@ -3999,9 +3999,11 @@ class parser
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator)));
|
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
|
// parse values
|
||||||
get_token();
|
get_token();
|
||||||
states.push_back(parse_state_t::object_value);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4025,8 +4027,10 @@ class parser
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse values (no need to call get_token)
|
// remember we are now inside an array
|
||||||
states.push_back(parse_state_t::array_value);
|
states.push_back(parse_state_t::array_value);
|
||||||
|
|
||||||
|
// parse values (no need to call get_token)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4122,7 +4126,7 @@ class parser
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
skip_to_tail = false;
|
skip_to_state_evaluation = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we reached this line after we successfully parsed a value
|
// 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
|
// We are done with this array. Before we can parse
|
||||||
// a new value, we need to evaluate the new state
|
// a new value, we need to evaluate the new state
|
||||||
// first. By setting skip_to_tail to false, we are
|
// first. By setting skip_to_state_evaluation to
|
||||||
// effectively jumping to the beginning of this
|
// false, we are effectively jumping to the
|
||||||
// switch.
|
// beginning of this switch.
|
||||||
assert(not states.empty());
|
assert(not states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_tail = true;
|
skip_to_state_evaluation = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4218,12 +4222,12 @@ class parser
|
||||||
|
|
||||||
// We are done with this object. Before we can
|
// We are done with this object. Before we can
|
||||||
// parse a new value, we need to evaluate the new
|
// parse a new value, we need to evaluate the new
|
||||||
// state first. By setting skip_to_tail to false,
|
// state first. By setting skip_to_state_evaluation
|
||||||
// we are effectively jumping to the beginning of
|
// to false, we are effectively jumping to the
|
||||||
// this switch.
|
// beginning of this switch.
|
||||||
assert(not states.empty());
|
assert(not states.empty());
|
||||||
states.pop_back();
|
states.pop_back();
|
||||||
skip_to_tail = true;
|
skip_to_state_evaluation = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -134,6 +134,81 @@ class SaxEventLogger : public nlohmann::json::json_sax_t
|
||||||
bool errored = false;
|
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);
|
json parser_helper(const std::string& s);
|
||||||
bool accept_helper(const std::string& s);
|
bool accept_helper(const std::string& s);
|
||||||
|
|
||||||
|
@ -1595,4 +1670,100 @@ TEST_CASE("parser class")
|
||||||
CHECK(j == json(true));
|
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 a new issue