diff --git a/tests/parse/test_clear_notes.py b/tests/parse/test_clear_notes.py index 4d6ffbe..a682147 100644 --- a/tests/parse/test_clear_notes.py +++ b/tests/parse/test_clear_notes.py @@ -1,8 +1,8 @@ # SPDX-License-Identifier: LGPL-2.1-only # Copyright 2022 Jookia -from hypothesis import assume, given -from hypothesis.strategies import composite, lists +from hypothesis import given +from hypothesis.strategies import composite, just, lists, one_of from src.parse import ( NoteSkipper, @@ -14,89 +14,41 @@ from src.token import TokenStream from tests.parse.templates import template_test_invalid from tests.parse.test_error import static_parse_context -from tests.test_token import static_token_by_value, draw_token_random +from tests.parse.test_note import draw_note_value_token, static_note_tokens +from tests.test_token import static_token_by_value -# Dummy NoteSkipper for testing note clearing -# This redefines skip_note to skip the StartNote and not do anything else -# Effectively this turns notes in to a single token for our tests, not needing -# a terminating EndNote -class NoteSkipperMockValid(NoteSkipper): - def skip_note(self, stream, context): - stream.pop() - return None - - -# Dummy NoteSkipper for testing error propagation -# This redefines skip_note to always throw an error -class NoteSkipperMockInvalid(NoteSkipper): - def skip_note(self, stream, context): - s = stream.peek() - raise ParseErrorException(ParseError.TEST_ERROR, s, None, context) - - -# Draws a random token suitable for note clearing testing +# Draws a tokens of notes and non-notes and output without notes @composite -def draw_clear_notes_value(draw): - token = draw(draw_token_random()) - assume(token.value != "EndNote") - return token - - -# Draws token to make a valid soup to clear notes -@composite -def draw_token_clear_notes_valid(draw): - tokens = draw(lists(draw_clear_notes_value())) +def draw_notes_to_clear(draw): + token_sets = draw( + lists(one_of([lists(draw_note_value_token()), just(static_note_tokens())])) + ) output = [] - for token in tokens: - # Our modified parse_note only parses the StartNote, so we expect - # the output to only remove StartNote values - if token.value != "StartNote": - output.append(token) + tokens = [] + for set in token_sets: + tokens += set + if set != static_note_tokens(): + output += set return (tokens, output) -# Tests clear_notes works correctly -# We expect the following behaviour: -# - When StartNote is encountered skip_note is called to skip the note -# - Other token is passed through -@given(draw_token_clear_notes_valid()) +# Tests clear_notes filters out notes +@given(draw_notes_to_clear()) def test_parse_clear_notes_valid(test_data): (tokens, result) = test_data stream = TokenStream(tokens) - cleared = NoteSkipperMockValid().clear_notes(stream, None) + cleared = NoteSkipper().clear_notes(stream, None) assert cleared == result -# Check that a specific token in a stream triggers an error -def error_on_token(parser, tokens, value, error_value): - # Ensure we have a value somewhere - start = static_token_by_value(value) - new_tokens = tokens + [start] +# Tests clear_notes errors when finding an EndNote +@given(lists(draw_note_value_token())) +def test_parse_clear_notes_invalid_endnote(tokens): + token = static_token_by_value("EndNote") + new_tokens = tokens + [token] + parser = NoteSkipper().clear_notes parent_context = static_parse_context() context = ParseContext(ParseTask.CLEAR_NOTES, new_tokens[0], parent_context) - for token in new_tokens: - if token.value == value: - error = ParseErrorException(error_value, token, None, context) - template_test_invalid(parser, parent_context, new_tokens, error) - - -# Tests clear_notes passes through skip_note errors -# We expect the following behaviour: -# - When a StartNote token is encountered skip_note is called to skip the note -# - Any error skip_note gives is propagated through clear_notes -# - Have ParseTask.CLEAR_NOTES as the context's parse task -@given(lists(draw_clear_notes_value())) -def test_parse_clear_notes_startnote_propagation(tokens): - parser = NoteSkipperMockInvalid().clear_notes - error_on_token(parser, tokens, "StartNote", ParseError.TEST_ERROR) - - -# Tests clear_notes errors when finding an EndNote -# We expect the following behaviour: -# - When an EndNote token is encountered a FOUND_ENDNOTE error is raised -# - Have ParseTask.CLEAR_NOTES as the context's parse task -@given(lists(draw_clear_notes_value())) -def test_parse_clear_notes_invalid_endnote(tokens): - parser = NoteSkipperMockValid().clear_notes - error_on_token(parser, tokens, "EndNote", ParseError.FOUND_ENDNOTE) + error = ParseErrorException(ParseError.FOUND_ENDNOTE, token, None, context) + template_test_invalid(parser, parent_context, new_tokens, error) diff --git a/tests/parse/test_note.py b/tests/parse/test_note.py index 339fccc..da7c800 100644 --- a/tests/parse/test_note.py +++ b/tests/parse/test_note.py @@ -26,6 +26,11 @@ ) +# Static tokens representing a note +def static_note_tokens(): + return [static_token_by_value("StartNote"), static_token_by_value("EndNote")] + + # Draws a random token suitable for note building @composite def draw_note_value_token(draw):