more work on exceptions (#160)

This commit is contained in:
Niels 2015-12-26 13:17:32 +01:00
parent dc8ab92552
commit d6b8830e03
4 changed files with 87 additions and 58 deletions

View file

@ -398,7 +398,7 @@ $ make
$ ./json_unit "*" $ ./json_unit "*"
=============================================================================== ===============================================================================
All tests passed (3341947 assertions in 28 test cases) All tests passed (3343239 assertions in 28 test cases)
``` ```
For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml). For more information, have a look at the file [.travis.yml](https://github.com/nlohmann/json/blob/master/.travis.yml).

View file

@ -6459,21 +6459,21 @@ class basic_json
case token_type::value_number: case token_type::value_number:
return "number literal"; return "number literal";
case token_type::begin_array: case token_type::begin_array:
return "["; return "'['";
case token_type::begin_object: case token_type::begin_object:
return "{"; return "'{'";
case token_type::end_array: case token_type::end_array:
return "]"; return "']'";
case token_type::end_object: case token_type::end_object:
return "}"; return "'}'";
case token_type::name_separator: case token_type::name_separator:
return ":"; return "':'";
case token_type::value_separator: case token_type::value_separator:
return ","; return "','";
case token_type::parse_error: case token_type::parse_error:
return "<parse error>"; return "<parse error>";
case token_type::end_of_input: case token_type::end_of_input:
return "<end of input>"; return "end of input";
default: default:
{ {
// catch non-enum values // catch non-enum values
@ -7752,10 +7752,10 @@ basic_json_parser_64:
{ {
if (t != last_token) if (t != last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected ";
error_msg += m_lexer.get_token(); error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
error_msg += "\' (" + lexer::token_type_name(last_token); lexer::token_type_name(last_token));
error_msg += "); expected " + lexer::token_type_name(t); error_msg += "; expected " + lexer::token_type_name(t);
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
@ -7764,9 +7764,9 @@ basic_json_parser_64:
{ {
if (t == last_token) if (t == last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected ";
error_msg += m_lexer.get_token(); error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
error_msg += "\'"; lexer::token_type_name(last_token));
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }

View file

@ -6441,7 +6441,7 @@ class basic_json
return result; return result;
} }
/// return name of values of type token_type /// return name of values of type token_type (only used for errors)
static std::string token_type_name(token_type t) static std::string token_type_name(token_type t)
{ {
switch (t) switch (t)
@ -6459,21 +6459,21 @@ class basic_json
case token_type::value_number: case token_type::value_number:
return "number literal"; return "number literal";
case token_type::begin_array: case token_type::begin_array:
return "["; return "'['";
case token_type::begin_object: case token_type::begin_object:
return "{"; return "'{'";
case token_type::end_array: case token_type::end_array:
return "]"; return "']'";
case token_type::end_object: case token_type::end_object:
return "}"; return "'}'";
case token_type::name_separator: case token_type::name_separator:
return ":"; return "':'";
case token_type::value_separator: case token_type::value_separator:
return ","; return "','";
case token_type::parse_error: case token_type::parse_error:
return "<parse error>"; return "<parse error>";
case token_type::end_of_input: case token_type::end_of_input:
return "<end of input>"; return "end of input";
default: default:
{ {
// catch non-enum values // catch non-enum values
@ -7031,10 +7031,10 @@ class basic_json
{ {
if (t != last_token) if (t != last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected ";
error_msg += m_lexer.get_token(); error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
error_msg += "\' (" + lexer::token_type_name(last_token); lexer::token_type_name(last_token));
error_msg += "); expected " + lexer::token_type_name(t); error_msg += "; expected " + lexer::token_type_name(t);
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }
@ -7043,9 +7043,9 @@ class basic_json
{ {
if (t == last_token) if (t == last_token)
{ {
std::string error_msg = "parse error - unexpected \'"; std::string error_msg = "parse error - unexpected ";
error_msg += m_lexer.get_token(); error_msg += (last_token == lexer::token_type::parse_error ? ("'" + m_lexer.get_token() + "'") :
error_msg += "\'"; lexer::token_type_name(last_token));
throw std::invalid_argument(error_msg); throw std::invalid_argument(error_msg);
} }
} }

View file

@ -8647,14 +8647,14 @@ TEST_CASE("lexer class")
CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal"); CHECK(json::lexer::token_type_name(json::lexer::token_type::literal_null) == "null literal");
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal"); CHECK(json::lexer::token_type_name(json::lexer::token_type::value_string) == "string literal");
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal"); CHECK(json::lexer::token_type_name(json::lexer::token_type::value_number) == "number literal");
CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "["); CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_array) == "'['");
CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "{"); CHECK(json::lexer::token_type_name(json::lexer::token_type::begin_object) == "'{'");
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "]"); CHECK(json::lexer::token_type_name(json::lexer::token_type::end_array) == "']'");
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "}"); CHECK(json::lexer::token_type_name(json::lexer::token_type::end_object) == "'}'");
CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == ":"); CHECK(json::lexer::token_type_name(json::lexer::token_type::name_separator) == "':'");
CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == ","); CHECK(json::lexer::token_type_name(json::lexer::token_type::value_separator) == "','");
CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == "<parse error>"); CHECK(json::lexer::token_type_name(json::lexer::token_type::parse_error) == "<parse error>");
CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "<end of input>"); CHECK(json::lexer::token_type_name(json::lexer::token_type::end_of_input) == "end of input");
} }
SECTION("parse errors on first character") SECTION("parse errors on first character")
@ -8929,31 +8929,31 @@ TEST_CASE("parser class")
CHECK_THROWS_NAME(json::parser("1.").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("1.").parse(), std::invalid_argument,
"parse error - 1 is not a number"); "parse error - 1 is not a number");
CHECK_THROWS_NAME(json::parser("1E").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("1E").parse(), std::invalid_argument,
"parse error - unexpected 'E' (<parse error>); expected <end of input>"); "parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("1E-").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("1E-").parse(), std::invalid_argument,
"parse error - unexpected 'E' (<parse error>); expected <end of input>"); "parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("1.E1").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("1.E1").parse(), std::invalid_argument,
"parse error - 1 is not a number"); "parse error - 1 is not a number");
CHECK_THROWS_NAME(json::parser("-1E").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-1E").parse(), std::invalid_argument,
"parse error - unexpected 'E' (<parse error>); expected <end of input>"); "parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0E#").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0E#").parse(), std::invalid_argument,
"parse error - unexpected 'E' (<parse error>); expected <end of input>"); "parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0E-#").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0E-#").parse(), std::invalid_argument,
"parse error - unexpected 'E' (<parse error>); expected <end of input>"); "parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0#").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0#").parse(), std::invalid_argument,
"parse error - unexpected '#' (<parse error>); expected <end of input>"); "parse error - unexpected '#'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0.0:").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0.0:").parse(), std::invalid_argument,
"parse error - unexpected ':' (:); expected <end of input>"); "parse error - unexpected ':'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0.0Z").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0.0Z").parse(), std::invalid_argument,
"parse error - unexpected 'Z' (<parse error>); expected <end of input>"); "parse error - unexpected 'Z'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0E123:").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0E123:").parse(), std::invalid_argument,
"parse error - unexpected ':' (:); expected <end of input>"); "parse error - unexpected ':'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0e0-:").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0e0-:").parse(), std::invalid_argument,
"parse error - unexpected '-' (<parse error>); expected <end of input>"); "parse error - unexpected '-'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0e-:").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0e-:").parse(), std::invalid_argument,
"parse error - unexpected 'e' (<parse error>); expected <end of input>"); "parse error - unexpected 'e'; expected end of input");
CHECK_THROWS_NAME(json::parser("-0f").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("-0f").parse(), std::invalid_argument,
"parse error - unexpected 'f' (<parse error>); expected <end of input>"); "parse error - unexpected 'f'; expected end of input");
} }
} }
} }
@ -8975,6 +8975,33 @@ TEST_CASE("parser class")
CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("1E.").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("1E/").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("1E:").parse(), std::invalid_argument);
CHECK_THROWS_NAME(json::parser("0.").parse(), std::invalid_argument,
"parse error - 0 is not a number");
CHECK_THROWS_NAME(json::parser("-").parse(), std::invalid_argument, "parse error - unexpected '-'");
CHECK_THROWS_NAME(json::parser("--").parse(), std::invalid_argument,
"parse error - unexpected '-'");
CHECK_THROWS_NAME(json::parser("-0.").parse(), std::invalid_argument,
"parse error - -0 is not a number");
CHECK_THROWS_NAME(json::parser("-.").parse(), std::invalid_argument,
"parse error - unexpected '-'");
CHECK_THROWS_NAME(json::parser("-:").parse(), std::invalid_argument,
"parse error - unexpected '-'");
CHECK_THROWS_NAME(json::parser("0.:").parse(), std::invalid_argument,
"parse error - 0 is not a number");
CHECK_THROWS_NAME(json::parser("e.").parse(), std::invalid_argument,
"parse error - unexpected 'e'");
CHECK_THROWS_NAME(json::parser("1e.").parse(), std::invalid_argument,
"parse error - unexpected 'e'; expected end of input");
CHECK_THROWS_NAME(json::parser("1e/").parse(), std::invalid_argument,
"parse error - unexpected 'e'; expected end of input");
CHECK_THROWS_NAME(json::parser("1e:").parse(), std::invalid_argument,
"parse error - unexpected 'e'; expected end of input");
CHECK_THROWS_NAME(json::parser("1E.").parse(), std::invalid_argument,
"parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("1E/").parse(), std::invalid_argument,
"parse error - unexpected 'E'; expected end of input");
CHECK_THROWS_NAME(json::parser("1E:").parse(), std::invalid_argument,
"parse error - unexpected 'E'; expected end of input");
// unexpected end of null // unexpected end of null
CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("n").parse(), std::invalid_argument);
@ -9010,36 +9037,38 @@ TEST_CASE("parser class")
"parse error - unexpected 'f'"); "parse error - unexpected 'f'");
// missing/unexpected end of array // missing/unexpected end of array
// TODO: Better error messages - "parse error - unexpected '" just ends
CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1,").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("[1,]").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("]").parse(), std::invalid_argument);
CHECK_THROWS_NAME(json::parser("[").parse(), std::invalid_argument, "parse error - unexpected '"); CHECK_THROWS_NAME(json::parser("[").parse(), std::invalid_argument,
CHECK_THROWS_NAME(json::parser("[1").parse(), std::invalid_argument, "parse error - unexpected '"); "parse error - unexpected end of input");
CHECK_THROWS_NAME(json::parser("[1,").parse(), std::invalid_argument, "parse error - unexpected '"); CHECK_THROWS_NAME(json::parser("[1").parse(), std::invalid_argument,
"parse error - unexpected end of input; expected ']'");
CHECK_THROWS_NAME(json::parser("[1,").parse(), std::invalid_argument,
"parse error - unexpected end of input");
CHECK_THROWS_NAME(json::parser("[1,]").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("[1,]").parse(), std::invalid_argument,
"parse error - unexpected ']'"); "parse error - unexpected ']'");
CHECK_THROWS_NAME(json::parser("]").parse(), std::invalid_argument, "parse error - unexpected ']'"); CHECK_THROWS_NAME(json::parser("]").parse(), std::invalid_argument, "parse error - unexpected ']'");
// missing/unexpected end of object // missing/unexpected end of object
// TODO: Better error messages - "parse error - unexpected '" just ends
CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\"").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":}").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("{\"foo\":1,}").parse(), std::invalid_argument);
CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument); CHECK_THROWS_AS(json::parser("}").parse(), std::invalid_argument);
CHECK_THROWS_NAME(json::parser("{").parse(), std::invalid_argument, "parse error - unexpected '"); CHECK_THROWS_NAME(json::parser("{").parse(), std::invalid_argument,
"parse error - unexpected end of input; expected string literal");
CHECK_THROWS_NAME(json::parser("{\"foo\"").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("{\"foo\"").parse(), std::invalid_argument,
"parse error - unexpected '"); "parse error - unexpected end of input; expected ':'");
CHECK_THROWS_NAME(json::parser("{\"foo\":").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("{\"foo\":").parse(), std::invalid_argument,
"parse error - unexpected '"); "parse error - unexpected end of input");
CHECK_THROWS_NAME(json::parser("{\"foo\":}").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("{\"foo\":}").parse(), std::invalid_argument,
"parse error - unexpected '}'"); "parse error - unexpected '}'");
CHECK_THROWS_NAME(json::parser("{\"foo\":1,}").parse(), std::invalid_argument, CHECK_THROWS_NAME(json::parser("{\"foo\":1,}").parse(), std::invalid_argument,
"parse error - unexpected '}' (}); expected string literal"); "parse error - unexpected '}'; expected string literal");
CHECK_THROWS_NAME(json::parser("}").parse(), std::invalid_argument, "parse error - unexpected '}'"); CHECK_THROWS_NAME(json::parser("}").parse(), std::invalid_argument, "parse error - unexpected '}'");
// missing/unexpected end of string // missing/unexpected end of string