# SPDX-License-Identifier: LGPL-2.1-only # Copyright 2022 Jookia <contact@jookia.org> from hypothesis import given from hypothesis.strategies import composite, integers from src.parse import ParseErrorException from src.token import TokenStream from tests.parse.test_parse import static_parse_context from tests.test_token import draw_token_random # Inserts an element randomly between the first and last token of a list def insert_random_within(draw, list, data): pos = draw(integers(min_value=1, max_value=(len(list) - 1))) new_data = list[0:pos] + [data] + list[pos:] return new_data # Tests that something parses correctly # We expect the following behaviour: # - The decoration supplies a generator for test data and expected output # - The decorated function is unused # - Only the supplied tokens are parsed # - The supplied tokens parse to the expected value # - The Token's value is the expected value # - The Token's location is the first token's location def template_parse_valid(parser, draw): @given(draw_token_random(), draw) def do(canary, test_data): (tokens, expected) = test_data stream = TokenStream(tokens + [canary]) parsed = parser(stream, None) if expected is None: assert parsed is None else: assert parsed is not None assert parsed == expected assert stream.pop() == canary assert stream.pop() is None return lambda func: do # Test that something parses incorrectly # We expect the following behaviour: # - The decoration supplies a parser function # - The decorated function takes a parse context # - The decorated function generates input tokens and an error # - Parsing causes an error # - The parse error is as expected def template_parse_invalid(parser): # Wrapper to add parse_context to our test_data @composite def wrapper(draw, func): context = static_parse_context() (tokens, error) = draw(composite(func)(context)) return (tokens, error, context) # test_data is the output of wrapper def do(test_data): (tokens, error, context) = test_data stream = TokenStream(tokens) try: parsed = parser(stream, context) raise AssertionError("Parsed invalid data: %s" % (parsed)) except ParseErrorException as e: assert e == error return lambda func: given(wrapper(func))(do)