Newer
Older
NewLang / tests / parse / test_parse.py
# SPDX-License-Identifier: LGPL-2.1-only
# Copyright 2022 Jookia <contact@jookia.org>

from hypothesis import given
from hypothesis.strategies import (
    composite,
    lists,
    sampled_from,
    text,
)

from src.parse import (
    NoteSkipper,
    ParseError,
    ParseErrorException,
    ParseTask,
    ParseContext,
    parse,
)
from src.syntax import SyntaxStream
from tests.templates import template_test_structure
from tests.test_syntax import draw_syntax_token, draw_syntax_random


# Draws a random parse task
@composite
def draw_parse_task(draw):
    return draw(sampled_from(list(ParseTask)))


# Draws a random parse context without a parent
@composite
def draw_parse_context(draw):
    task = draw(draw_parse_task())
    syntax = draw(draw_syntax_random())
    return ParseContext(task, syntax, None)


# Test parse context structure
@template_test_structure(
    ParseContext,
    draw_parse_context(),
    task=draw_parse_task(),
    syntax=draw_syntax_random(),
    parent=text(),
)
def test_parse_context_structure():
    pass


# Draws a random parse error
@composite
def draw_parse_error(draw):
    return draw(sampled_from(list(ParseError)))


# Draws a random parse error exception
@composite
def draw_parse_error_exception(draw):
    error = draw(draw_parse_error())
    syntax = draw(draw_syntax_random())
    expected = draw(text())
    context = draw(draw_parse_context())
    return ParseErrorException(error, syntax, expected, context)


# Test parse error exception structure
@template_test_structure(
    ParseErrorException,
    draw_parse_error_exception(),
    error=draw_syntax_random(),
    syntax=draw_syntax_random(),
    expected=text(),
    context=draw_parse_context(),
)
def test_parse_error_exception_structure():
    pass


# Tests the parser wrapper works correctly
# We expect the following behaviour:
# - Notes to be removed from the tokens
@given(lists(draw_syntax_token()), draw_parse_context())
def test_parse_fuzz(tokens, context):
    result = None
    parsed = None
    try:
        stream = SyntaxStream(tokens.copy())
        result = NoteSkipper().clear_notes(stream, context)
    except ParseErrorException as e:
        result = e
    try:
        parsed = parse(tokens, context)
    except ParseErrorException as e:
        parsed = e
    assert parsed == result