Add tests for some parsing errors

This commit is contained in:
Laria 2021-12-19 00:27:34 +01:00
parent 0995739ca8
commit 8d1eaf5d78
3 changed files with 148 additions and 0 deletions

View file

@ -131,6 +131,8 @@ enum apfl_error_type {
APFL_ERR_EMPTY_ASSIGNMENT,
};
const char *apfl_error_type_name(enum apfl_error_type);
struct apfl_error {
enum apfl_error_type type;

View file

@ -6,6 +6,49 @@
#define POSARGS error.position.line, error.position.col
#define POS2ARGS error.position2.line, error.position2.col
const char *
apfl_error_type_name(enum apfl_error_type type)
{
switch (type) {
case APFL_ERR_MALLOC_FAILED:
return "APFL_ERR_MALLOC_FAILED";
case APFL_ERR_INPUT_ERROR:
return "APFL_ERR_INPUT_ERROR";
case APFL_ERR_UNEXPECTED_EOF:
return "APFL_ERR_UNEXPECTED_EOF";
case APFL_ERR_EXPECTED_EQ_AFTER_COLON:
return "APFL_ERR_EXPECTED_EQ_AFTER_COLON";
case APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER:
return "APFL_ERR_UNEXPECTED_BYTE_IN_NUMBER";
case APFL_ERR_EXPECTED_DIGIT:
return "APFL_ERR_EXPECTED_DIGIT";
case APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE:
return "APFL_ERR_EXPECTED_HEX_IN_HEX_ESCAPE";
case APFL_ERR_INVALID_ESCAPE_SEQUENCE:
return "APFL_ERR_INVALID_ESCAPE_SEQUENCE";
case APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE:
return "APFL_ERR_NO_LINEBREAK_AFTER_CONTINUE_LINE";
case APFL_ERR_UNEXPECTED_TOKEN:
return "APFL_ERR_UNEXPECTED_TOKEN";
case APFL_ERR_MISMATCHING_CLOSING_BRACKET:
return "APFL_ERR_MISMATCHING_CLOSING_BRACKET";
case APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN:
return "APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN";
case APFL_ERR_STATEMENTS_BEFORE_PARAMETERS:
return "APFL_ERR_STATEMENTS_BEFORE_PARAMETERS";
case APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS:
return "APFL_ERR_EMPTY_ASSIGNMENT_BEFORE_PARAMETERS";
case APFL_ERR_UNEXPECTED_EXPRESSION:
return "APFL_ERR_UNEXPECTED_EXPRESSION";
case APFL_ERR_INVALID_ASSIGNMENT_LHS:
return "APFL_ERR_INVALID_ASSIGNMENT_LHS";
case APFL_ERR_EMPTY_ASSIGNMENT:
return "APFL_ERR_EMPTY_ASSIGNMENT";
}
return "<unknown error>";
}
void
apfl_error_print(struct apfl_error error, FILE *file)
{

View file

@ -87,6 +87,27 @@ expect_expr(struct parser_test *pt, struct apfl_expr expected)
}
}
static void
expect_error_of_type(struct parser_test *pt, enum apfl_error_type want)
{
struct apfl_error have;
switch (apfl_parser_next(pt->parser)) {
case APFL_PARSE_OK:
test_failf(pt->t, "Expected error but got an OK");
break;
case APFL_PARSE_EOF:
test_fatalf(pt->t, "Expected error but got an EOF");
break;
case APFL_PARSE_ERROR:
have = apfl_parser_get_error(pt->parser);
if (have.type != want) {
test_failf(pt->t, "Expected error of type %s, got this error instead:", apfl_error_type_name(want));
apfl_error_print(have, stderr);
}
break;
}
}
static struct apfl_string
new_string(struct parser_test *pt, const char *in)
{
@ -1120,6 +1141,77 @@ TEST(complex_function, t) {
destroy_parser_test(pt);
}
TEST(err_empty_assignment, t) {
struct parser_test *pt = new_parser_test(t, "= foo bar");
expect_error_of_type(pt, APFL_ERR_EMPTY_ASSIGNMENT);
destroy_parser_test(pt);
}
TEST(err_mismatching_parens, t) {
struct parser_test *pt = new_parser_test(t, "{[(}");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_TOKEN);
destroy_parser_test(pt);
}
TEST(err_unclosed_func, t) {
struct parser_test *pt = new_parser_test(t, "{ foo -> bar; baz a; b ->");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_EOF);
destroy_parser_test(pt);
}
TEST(err_unclosed_paren, t) {
struct parser_test *pt = new_parser_test(t, "(a b.c@d");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_EOF_AFTER_TOKEN);
destroy_parser_test(pt);
}
TEST(err_assignment_missing_rhs, t) {
struct parser_test *pt = new_parser_test(t, "foo = bar = ;");
expect_error_of_type(pt, APFL_ERR_EMPTY_ASSIGNMENT);
// TODO: Actually kinda weird that we return the same error as in err_empty_assignment.
destroy_parser_test(pt);
}
TEST(err_assignment_invalid_lhs, t) {
struct parser_test *pt = new_parser_test(t, "{foo} = bar");
expect_error_of_type(pt, APFL_ERR_INVALID_ASSIGNMENT_LHS);
destroy_parser_test(pt);
pt = new_parser_test(t, "(a b) = bar");
expect_error_of_type(pt, APFL_ERR_INVALID_ASSIGNMENT_LHS);
destroy_parser_test(pt);
}
TEST(err_fragments_after_mapsto_in_empty_dict, t) {
struct parser_test *pt = new_parser_test(t, "[-> foo]");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_TOKEN);
destroy_parser_test(pt);
}
TEST(err_fragments_after_mapsto_in_dict, t) {
struct parser_test *pt = new_parser_test(t, "[a -> b, (c d) -> e foo->]");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_TOKEN);
destroy_parser_test(pt);
}
TEST(err_mapsto_in_list, t) {
struct parser_test *pt = new_parser_test(t, "[a b c -> d]");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_TOKEN);
destroy_parser_test(pt);
}
TEST(err_expr_in_param, t) {
struct parser_test *pt = new_parser_test(t, "{ foo (bar baz) -> }");
expect_error_of_type(pt, APFL_ERR_UNEXPECTED_EXPRESSION);
destroy_parser_test(pt);
}
TEST(err_statements_before_params, t) {
struct parser_test *pt = new_parser_test(t, "{ a = b = foo bar; 1 \n baz -> }");
expect_error_of_type(pt, APFL_ERR_STATEMENTS_BEFORE_PARAMETERS);
destroy_parser_test(pt);
}
TESTS_BEGIN
ADDTEST(empty),
ADDTEST(hello_world),
@ -1139,4 +1231,15 @@ TESTS_BEGIN
ADDTEST(assignment),
ADDTEST(simple_function),
ADDTEST(complex_function),
ADDTEST(err_empty_assignment),
ADDTEST(err_mismatching_parens),
ADDTEST(err_unclosed_func),
ADDTEST(err_unclosed_paren),
ADDTEST(err_assignment_missing_rhs),
ADDTEST(err_assignment_invalid_lhs),
ADDTEST(err_fragments_after_mapsto_in_empty_dict),
ADDTEST(err_fragments_after_mapsto_in_dict),
ADDTEST(err_mapsto_in_list),
ADDTEST(err_expr_in_param),
ADDTEST(err_statements_before_params),
TESTS_END