Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Argmaster committed Dec 31, 2023
1 parent b016656 commit 2cbc150
Show file tree
Hide file tree
Showing 11 changed files with 292 additions and 0 deletions.
92 changes: 92 additions & 0 deletions test/gerberx3/test_parser2/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
"""Common elements of Rasterized2D tests."""

from __future__ import annotations

from pathlib import Path
from test.gerberx3.common import find_gerberx3_asset_files
from typing import TYPE_CHECKING, Callable

import pytest

from pygerber.gerberx3.parser2.context2 import Parser2Context
from pygerber.gerberx3.parser2.parser2 import Parser2, Parser2Options
from pygerber.gerberx3.tokenizer.tokenizer import Tokenizer

if TYPE_CHECKING:
from test.conftest import AssetLoader


def parse2(
asset_loader: AssetLoader,
src: str,
dest: Path, # noqa: ARG001
*,
expression: bool = False,
) -> None:
"""Tokenize gerber code and save debug output."""
source = asset_loader.load_asset(src).decode("utf-8")
if expression:
stack = Tokenizer().tokenize_expressions(source)
else:
stack = Tokenizer().tokenize(source)

parser = Parser2()
parser.parse(stack)


def make_parser2_test(
test_file_path: str,
path_to_assets: str,
*,
expression: bool = False,
) -> Callable[..., None]:
"""Create parametrized test case for all files from path_to_assets.
All Gerber files from `path_to_assets` will be included as separate test cases
thanks to use of `@pytest.mark.parametrize`.
Parameters
----------
test_file_path : str
Path to test file, simply use `__file__` variable from module global scope.
path_to_assets : str
Path to assets directory, originating from the root of repository, eg.
`test/assets/gerberx3/basic`.
Returns
-------
Callable[..., None]
Test callable. Must be assigned to variable with name starting with `test_`.
"""
image_dump = Path(test_file_path).parent / ".output"

@pytest.mark.parametrize(
("directory", "file_name"),
sorted(find_gerberx3_asset_files(path_to_assets)),
)
def test_sample(
asset_loader: AssetLoader,
directory: str,
file_name: str,
) -> None:
"""Rasterized2D rendering test based on sample files."""
dest = image_dump / directory / Path(file_name).with_suffix("")
dest.mkdir(mode=0o777, parents=True, exist_ok=True)
parse2(
asset_loader,
f"gerberx3/{directory}/{file_name}",
dest,
expression=expression,
)

return test_sample


def parse_code(
gerber_source_code: str,
initial_context: Parser2Context,
) -> Parser2Context:
ast = Tokenizer().tokenize_expressions(gerber_source_code)
p = Parser2(Parser2Options(initial_context=initial_context))
p.parse(ast)
return p.context
7 changes: 7 additions & 0 deletions test/gerberx3/test_parser2/test_a64_olinuxino_rev_g.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""tests based on A64-OLinuXino-rev-G board."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/A64-OLinuXino-rev-G")
7 changes: 7 additions & 0 deletions test/gerberx3/test_parser2/test_altium_gerber_x2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""tests based on AltiumGerberX2 board."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/AltiumGerberX2")
8 changes: 8 additions & 0 deletions test/gerberx3/test_parser2/test_atmega328_motor_board.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""tests based on ATMEGA328-Motor-Board board."""


from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/ATMEGA328-Motor-Board")
11 changes: 11 additions & 0 deletions test/gerberx3/test_parser2/test_expressions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""tests based on Gerber expressions code samples."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(
__file__,
"test/assets/gerberx3/expressions",
expression=True,
)
7 changes: 7 additions & 0 deletions test/gerberx3/test_parser2/test_kicad_arduino.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""tests based on Kicad arduino template."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/kicad/arduino")
7 changes: 7 additions & 0 deletions test/gerberx3/test_parser2/test_kicad_gerber_x2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""tests based on KicadGerberX2 board."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/KicadGerberX2")
7 changes: 7 additions & 0 deletions test/gerberx3/test_parser2/test_kicad_hello.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""tests based on Kicad hello."""

from __future__ import annotations

from test.gerberx3.test_parser2.common import make_parser2_test

test_sample = make_parser2_test(__file__, "test/assets/gerberx3/kicad/hello")
73 changes: 73 additions & 0 deletions test/gerberx3/test_parser2/test_parser2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from __future__ import annotations

from typing import Generator

import pytest

from pygerber.gerberx3.parser2.command_buffer2 import CommandBuffer2
from pygerber.gerberx3.parser2.parser2 import (
Parser2,
Parser2OnErrorAction,
Parser2Options,
)
from pygerber.gerberx3.tokenizer.tokenizer import Tokenizer
from pygerber.gerberx3.tokenizer.tokens.groups.ast import AST


@pytest.fixture()
def parser() -> Parser2:
return Parser2()


def to_ast(source: str) -> AST:
"""Create AST from Gerber source."""
return Tokenizer().tokenize_expressions(source)


def test_parser_parse(parser: Parser2) -> None:
"""Test the parse method of the Parser2 class."""
ast = to_ast(
"""
""",
)
command_buffer: CommandBuffer2 = parser.parse(ast)
assert isinstance(command_buffer, CommandBuffer2)


def test_parser_parse_iter(parser: Parser2) -> None:
"""Test the parse_iter method of the Parser2 class."""
ast = to_ast(
"""
%TF.FilePolarity,Positive*%
%FSLAX46Y46*%
%MOMM*%
%LPD*%
%TA.AperFunction,EtchedComponent*%
%ADD10C,0.508000*%
D10*
%TO.C,3.3V/VCC-PE:2.8V1*%
X151892000Y-58801000D02*
X151892000Y-57658000D01*
""",
)
token_generator = parser.parse_iter(ast)
assert isinstance(token_generator, Generator)


def test_parser_get_hooks(parser: Parser2) -> None:
"""Test the get_hooks method of the Parser2 class."""
hooks = parser.get_hooks()
assert hooks is not None


def test_parser_options() -> None:
"""Test the Parser2Options class."""
options = Parser2Options(
initial_context=None,
context_options=None,
on_update_drawing_state_error=Parser2OnErrorAction.Raise,
)
assert options.initial_context is None
assert options.context_options is None
assert options.on_update_drawing_state_error == Parser2OnErrorAction.Raise
30 changes: 30 additions & 0 deletions test/gerberx3/test_parser2/test_parser2context.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from __future__ import annotations

from test.gerberx3.test_parser2.common import parse_code

from pygerber.gerberx3.parser2.context2 import Parser2Context
from pygerber.gerberx3.tokenizer.aperture_id import ApertureID


def test_ensure_mutable_context() -> None:
gerber_source = "D10*"

initial_context = Parser2Context()
initial_context.set_current_aperture_id(ApertureID("D11"))

context = parse_code(gerber_source, initial_context)

assert context is initial_context


def test_ensure_immutable_state() -> None:
gerber_source = "D10*"

initial_context = Parser2Context()
initial_context.set_current_aperture_id(ApertureID("D11"))

initial_state = initial_context.get_state()

context = parse_code(gerber_source, initial_context)

assert context.get_state() is not initial_state
43 changes: 43 additions & 0 deletions test/gerberx3/test_parser2/test_parser2hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from __future__ import annotations

from test.gerberx3.test_parser2.common import parse_code

from pygerber.gerberx3.parser2.context2 import Parser2Context
from pygerber.gerberx3.tokenizer.tokens.dnn_select_aperture import ApertureID


def test_begin_block_aperture_token_hooks() -> None:
gerber_source = "%ABD10*%"

initial_context = Parser2Context()
initial_context.set_is_aperture_block(is_aperture_block=False)
initial_context.set_aperture_block_id(None)

context = parse_code(gerber_source, initial_context)

assert context.get_is_aperture_block() is True
assert context.get_aperture_block_id() == "D10"


def test_end_block_aperture_token_hooks() -> None:
gerber_source = "%AB*%"

initial_context = Parser2Context()
initial_context.set_is_aperture_block(is_aperture_block=True)
initial_context.set_aperture_block_id(ApertureID("D10"))

context = parse_code(gerber_source, initial_context)

assert context.get_is_aperture_block() is False
assert context.get_aperture_block_id() is None


def test_select_aperture_token_hooks() -> None:
gerber_source = "D10*"

initial_context = Parser2Context()
initial_context.set_current_aperture_id(ApertureID("D11"))

context = parse_code(gerber_source, initial_context)

assert context.get_current_aperture_id() == "D10"

0 comments on commit 2cbc150

Please sign in to comment.