# SPDX-License-Identifier: LGPL-2.1-only # Copyright 2022 Jookia <contact@jookia.org> from hypothesis import assume, given from hypothesis.strategies import booleans, composite from src.parse import ParseContext, ParseError, ParseErrorException, ParseTask, Parser from src.syntax import Syntax, SyntaxStream, SyntaxType from tests.parse.test_parse import draw_parse_context from tests.test_syntax import draw_token_bool, draw_syntax_random # Draws tokens to make a valid boolean @composite def draw_syntax_bool_valid(draw): token = draw(draw_token_bool()) value = token.value == "True" result = Syntax(value, token.location, SyntaxType.BOOL) return (token, result) # Tests parse_bool works correctly # We expect the following behaviour: # - Only the first token is parsed # - The resulting boolean is True if the first token is True # - The resulting boolean is False if the first token is False # - The Syntax's value is the resulting token # - The Syntax's type is SyntaxType.BOOL # - The Syntax's location is the first token's location @given(draw_syntax_random(), draw_syntax_bool_valid()) def test_parse_bool_valid(canary, test_data): (token, result) = test_data stream = SyntaxStream([token] + [canary]) parsed = Parser().parse_bool(stream, None) assert parsed is not None assert parsed == result assert stream.pop() == canary assert stream.pop() is None # Generate an invalid boolean # We expect the following behaviour: # - Error if there isn't a token # - Error if the token is not a SyntaxType.TOKEN # - Error if the token is not True or False @composite def draw_syntax_bool_invalid(draw): parent_context = draw(draw_parse_context()) if draw(booleans()): token = draw(draw_syntax_random()) assume( not (token.type == SyntaxType.TOKEN and token.value in ["True", "False"]) ) context = ParseContext(ParseTask.PARSE_BOOL, token, parent_context) if token.type == SyntaxType.TOKEN: error = ParseErrorException(ParseError.NOT_BOOL, token, None, context) else: error = ParseErrorException(ParseError.NOT_TOKEN, token, None, context) return ([token], error, parent_context) else: context = ParseContext(ParseTask.PARSE_BOOL, None, parent_context) error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) return ([], error, parent_context) # Test that parse_bool errors in invalid cases @given(draw_syntax_bool_invalid()) def test_parse_bool_invalid(test_data): (tokens, error, context) = test_data stream = SyntaxStream(tokens) try: parsed = Parser().parse_bool(stream, context) raise AssertionError("Parsed invalid data: %s" % (parsed)) except ParseErrorException as e: assert e == error