# SPDX-License-Identifier: LGPL-2.1-only # Copyright 2022 Jookia <contact@jookia.org> from hypothesis import assume, given from hypothesis.strategies import ( composite, lists, ) from src.parse import ( skip_note, ParseContext, ParseError, ParseErrorException, ParseTask, ) from tests.parse.templates import ( draw_random_within, template_test_invalid, template_test_valid, ) from tests.parse.test_error import static_parse_context from tests.test_token import ( static_token_by_value, draw_token_random, ) # Static tokens representing a note def static_note_tokens(): return [static_token_by_value("StartNote"), static_token_by_value("EndNote")] # An invalid note token def static_note_invalid(): return [static_token_by_value("StartNote")] # An invalid note token error def static_note_invalid_error(parent_context): token = static_note_invalid()[0] note_context = ParseContext(ParseTask.PARSE_NOTE, token, parent_context) return ParseErrorException(ParseError.NO_TOKEN, None, None, note_context) # Draws a random token suitable for note building @composite def draw_note_value_token(draw): token = draw(draw_token_random()) assume(token.value not in ["StartNote", "EndNote"]) return token # Draws a random token that isn't a StartNote token @composite def draw_token_not_startnote(draw): token = draw(draw_token_random()) assume(token.value != "StartNote") return token # Draws tokens to make a valid note @composite def draw_token_note_valid(draw): tokens = draw(lists(draw_note_value_token())) start = static_token_by_value("StartNote") end = static_token_by_value("EndNote") all_tokens = [start] + tokens + [end] return all_tokens # Tests skip_note works correctly # We expect the following behaviour: # - No value is returned # template_test provides general parsing properties @given(draw_token_note_valid()) def test_parse_note_valid(tokens): template_test_valid(skip_note, tokens, None) # Tests parsing notes without StartNote # We expect the following behaviour: # - Error if StartNote's token value is not "StartNote" # - Have ParseError.WRONG_TOKEN as the exception code # - Have ParseTask.PARSE_NOTE as the context's parse task @given(draw_token_note_valid(), draw_token_not_startnote()) def test_parse_note_invalid_nostartnote(tokens, token): new_tokens = [token] + tokens[1:0] parent_context = static_parse_context() context = ParseContext(ParseTask.PARSE_NOTE, new_tokens[0], parent_context) error = ParseErrorException(ParseError.WRONG_TOKEN, token, "StartNote", context) template_test_invalid(skip_note, parent_context, new_tokens, error) # Tests parsing empty notes # We expect the following behaviour: # - Error if there is no StartNote token at all # - Have ParseError.NO_TOKEN as the exception code # - Have ParseTask.PARSE_NOTE as the context's parse task def test_parse_note_invalid_empty(): parent_context = static_parse_context() context = ParseContext(ParseTask.PARSE_NOTE, None, parent_context) error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) template_test_invalid(skip_note, parent_context, [], error) # Tests parsing a note with a StartNote token in it # We expect the following behaviour: # - Error if a StartNote token is in the note content # - Have ParseTask.PARSE_NOTE as the context's parse task @given(draw_random_within(draw_token_note_valid(), "StartNote")) def test_parse_note_invalid_extrastartnote(within): (tokens, start) = within parent_context = static_parse_context() context = ParseContext(ParseTask.PARSE_NOTE, tokens[0], parent_context) error = ParseErrorException(ParseError.FOUND_STARTNOTE, start, None, context) template_test_invalid(skip_note, parent_context, tokens, error) # Tests parsing a note without an EndNote token # We expect the following behaviour: # - Error if there is no EndNote token at all # - Have ParseError.NO_TOKEN as the exception code # - Have ParseTask.PARSE_NOTE as the context's parse task @given(draw_token_note_valid()) def test_parse_note_invalid_noendnote(tokens): new_tokens = tokens[0:-1] parent_context = static_parse_context() context = ParseContext(ParseTask.PARSE_NOTE, tokens[0], parent_context) error = ParseErrorException(ParseError.NO_TOKEN, None, None, context) template_test_invalid(skip_note, parent_context, new_tokens, error)