diff --git a/tests/parse/test_statement.py b/tests/parse/test_statement.py index 23602b1..ca5b029 100644 --- a/tests/parse/test_statement.py +++ b/tests/parse/test_statement.py @@ -3,7 +3,7 @@ import enum -from hypothesis import assume +from hypothesis import assume, given from hypothesis.strategies import composite, integers, lists from src.ast_types import Statement @@ -16,9 +16,10 @@ read_token, ) from tests.parse.templates import ( - template_parse_valid_composite, - template_parse_invalid_composite, + template_test_valid, + template_test_invalid, ) +from tests.parse.test_error import static_parse_context from tests.test_token import ( draw_token_known, draw_token_random, @@ -129,18 +130,33 @@ return (tokens, statement) +# Draws a statement with an invalid subject or argument +@composite +def draw_token_statement_invalid_value(draw): + tokens = draw(draw_token_statement()) + new_token = draw(draw_token_random()) + assume(not new_token.value.startswith("TestValue")) # Not a value + assume(new_token.value != tokens[-1].value) # Not the terminator + max_position = len(tokens) - 2 # Ignore Terminator and Verb + position = draw(integers(min_value=0, max_value=max_position)) + if position != 0: + position += 1 # Skip Verb + new_tokens = tokens[:position] + [new_token] + tokens[position + 1 :] + return (tokens, new_tokens, new_token, position) + + # Tests parsing a valid statement # We expect the following behaviour: # - A value is read as the subject # - Optionally, a name is read as the verb # - Optionally, any number of arguments are read as values # - A terminator is found afterwards -# template_parse_valid_composite provides general parsing properties -@template_parse_valid_composite -def test_parse_statement_valid(draw): - (tokens, expected) = draw(draw_token_statement_valid()) +# template_test_valid provides general parsing properties +@given(draw_token_statement_valid()) +def test_parse_statement_valid(valid_data): + (tokens, expected) = valid_data parser = make_test_parser(tokens) - return (parser, tokens, expected) + template_test_valid(parser, tokens, expected) # Tests parsing a statement without a terminator @@ -150,15 +166,15 @@ # - Have ParseTask.PARSE_VERB or ParseTask.PARSE_ARGUMENT as the context's parse task # - Have ParseTask.PARSE_STATEMENT as the context's parse task's parent # - Have ParseError.NO_TOKEN as the exception code -# template_parse_invalid_composite provides general parsing properties -@template_parse_invalid_composite -def test_parse_statement_invalid_no_terminator(draw, parent_context): - tokens = draw(draw_token_statement()) +# template_test_invalid provides general parsing properties +@given(draw_token_statement()) +def test_parse_statement_invalid_no_terminator(tokens): truncated = tokens[:-1] + parent_context = static_parse_context() context = make_test_context(parent_context, len(truncated), tokens[0], None) error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) parser = make_test_parser(tokens) - return (parser, truncated, error) + template_test_invalid(parser, parent_context, truncated, error) # Tests parsing a statement with an invalid value @@ -167,22 +183,15 @@ # - Have ParseTask.PARSE_SUBJECT or ParseTask.PARSE_ARGUMENT as the context's parse task # - Have ParseTask.PARSE_STATEMENT as the context's parse task's parent # - Have ParserMockAction.WRONG_VALUE as the exception code -# template_parse_invalid_composite provides general parsing properties -@template_parse_invalid_composite -def test_parse_statement_invalid_value(draw, parent_context): - tokens = draw(draw_token_statement()) - new_token = draw(draw_token_random()) - assume(not new_token.value.startswith("TestValue")) # Not a value - assume(new_token.value != tokens[-1].value) # Not the terminator - max_chosen = len(tokens) - 2 # Ignore Terminator and Verb - chosen = draw(integers(min_value=0, max_value=max_chosen)) - if chosen != 0: - chosen += 1 # Skip Verb - new_tokens = tokens[:chosen] + [new_token] + tokens[chosen + 1 :] - context = make_test_context_tokens(parent_context, chosen, new_tokens) - error = ParseErrorException(ParserMockAction.WRONG_VALUE, new_token, None, context) +# template_test_invalid provides general parsing properties +@given(draw_token_statement_invalid_value()) +def test_parse_statement_invalid_value(invalid): + (tokens, new_tokens, new_value, position) = invalid + parent_context = static_parse_context() + context = make_test_context_tokens(parent_context, position, new_tokens) + error = ParseErrorException(ParserMockAction.WRONG_VALUE, new_value, None, context) parser = make_test_parser(tokens) - return (parser, new_tokens, error) + template_test_invalid(parser, parent_context, new_tokens, error) # Tests parsing a statement with an invalid verb @@ -191,17 +200,16 @@ # - Have ParseTask.PARSE_VERB as the context's parse task # - Have ParseTask.PARSE_STATEMENT as the context's parse task's parent # - Have ParseError.RESERVED_NAME as the exception code -# template_parse_invalid_composite provides general parsing properties -@template_parse_invalid_composite -def test_parse_statement_invalid_verb(draw, parent_context): - tokens = draw(draw_token_statement()) - new_token = draw(draw_token_known()) +# template_test_invalid provides general parsing properties +@given(draw_token_statement(), draw_token_known()) +def test_parse_statement_invalid_verb(tokens, new_token): assume(new_token.value != tokens[-1].value) new_tokens = tokens[:1] + [new_token] + tokens[1:] + parent_context = static_parse_context() context = make_test_context_tokens(parent_context, 1, new_tokens) error = ParseErrorException(ParseError.RESERVED_NAME, new_token, None, context) parser = make_test_parser(new_tokens) - return (parser, new_tokens, error) + template_test_invalid(parser, parent_context, new_tokens, error) # Tests parsing an empty statement @@ -210,11 +218,11 @@ # - Have ParseTask.PARSE_SUBJECT as the context's parse task # - Have ParseTask.PARSE_STATEMENT as the context's parse task's parent # - Have ParserError.NO_TOKEN as the exception code -# template_parse_invalid_composite provides general parsing properties -@template_parse_invalid_composite -def test_parse_statement_invalid_empty(draw, parent_context): +# template_test_invalid provides general parsing properties +def test_parse_statement_invalid_empty(): tokens = [] + parent_context = static_parse_context() context = make_test_context(parent_context, 0, None, None) error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) parser = make_test_parser(tokens) - return (parser, tokens, error) + template_test_invalid(parser, parent_context, tokens, error)