From 66db505fc6c41eca07f402e29c11d73298249b62 Mon Sep 17 00:00:00 2001 From: Tekktrik Date: Wed, 24 May 2023 12:57:35 -0400 Subject: [PATCH] Switch to pytest --- tests/__init__.py | 0 tests/pytest_helpers.py | 41 ++++++++++ tests/test_mov.py | 29 ++++++++ tests/test_nop.py | 83 +++++++++++++++++++++ tests/test_radix.py | 21 ++++++ tests/test_wrap.py | 19 +++++ tests/testpioasm.py | 161 ---------------------------------------- 7 files changed, 193 insertions(+), 161 deletions(-) delete mode 100644 tests/__init__.py create mode 100644 tests/pytest_helpers.py create mode 100644 tests/test_mov.py create mode 100644 tests/test_nop.py create mode 100644 tests/test_radix.py create mode 100644 tests/test_wrap.py delete mode 100644 tests/testpioasm.py diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/pytest_helpers.py b/tests/pytest_helpers.py new file mode 100644 index 0000000..678e9b7 --- /dev/null +++ b/tests/pytest_helpers.py @@ -0,0 +1,41 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +Pytest helper functions +""" + +import pytest + +import adafruit_pioasm + + +def nice_opcode(opcode): + opcode = f"{opcode:016b}" + return opcode[:3] + "_" + opcode[3:8] + "_" + opcode[8:] + + +def assert_assembles_to(source, expected): + actual = adafruit_pioasm.assemble(source) + expected_bin = [nice_opcode(x) for x in expected] + actual_bin = [nice_opcode(x) for x in actual] + assert ( + expected_bin == actual_bin + ), f"Assembling {source!r}: Expected {expected_bin}, got {actual_bin}" + + +def assert_assembly_fails(source, match=None, errtype=RuntimeError): + with pytest.raises(errtype, match=match): + adafruit_pioasm.assemble(source) + # if match: + # with pytest.raises(errtype, match=match): + # adafruit_pioasm.assemble(source) + # else: + # with pytest.raises(errtype): + # adafruit_pioasm.assemble(source) + + +def assert_pio_kwargs(source, **kw): + program = adafruit_pioasm.Program(source) + assert kw == program.pio_kwargs diff --git a/tests/test_mov.py b/tests/test_mov.py new file mode 100644 index 0000000..b6015cb --- /dev/null +++ b/tests/test_mov.py @@ -0,0 +1,29 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +Tests mov +""" + +from pytest_helpers import assert_assembles_to, assert_assembly_fails + + +def test_mov_non_happy(): + # non happy path + assert_assembly_fails( + "mov x, blah", match="Invalid mov source 'blah'", errtype=ValueError + ) + + +def test_mov_invert(): + # test moving and inverting + assert_assembles_to("mov x, ~ x", [0b101_00000_001_01_001]) + assert_assembles_to("mov x, ~x", [0b101_00000_001_01_001]) + assert_assembles_to("mov x, !x", [0b101_00000_001_01_001]) + + +def test_mov_reverse(): + # test moving and reversing bits + assert_assembles_to("mov x, :: x", [0b101_00000_001_10_001]) + assert_assembles_to("mov x, ::x", [0b101_00000_001_10_001]) diff --git a/tests/test_nop.py b/tests/test_nop.py new file mode 100644 index 0000000..7fd7bca --- /dev/null +++ b/tests/test_nop.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +Tests nop +""" + +from pytest_helpers import assert_assembles_to, assert_assembly_fails, assert_pio_kwargs + + +def test_nonsense(): + assert_assembly_fails("nope") + + +def test_nop(): + assert_assembles_to("nop", [0b101_00000_010_00_010]) + assert_assembles_to("nop\nnop", [0b101_00000_010_00_010, 0b101_00000_010_00_010]) + assert_assembles_to("nop [1]", [0b101_00001_010_00_010]) + assert_assembles_to("nop [31]", [0b101_11111_010_00_010]) + assert_assembles_to(".side_set 1\nnop side 1", [0b101_10000_010_00_010]) + assert_assembles_to(".side_set 1\nnop side 1 [15]", [0b101_11111_010_00_010]) + + +def test_sideset_opt(): + assert_assembles_to(".side_set 1 opt\nnop side 1", [0b101_11000_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop side 0", [0b101_10000_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop side 0 [1]", [0b101_10001_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop [1]", [0b101_00001_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop [7]", [0b101_00111_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop side 1 [1]", [0b101_11001_010_00_010]) + assert_assembles_to(".side_set 1 opt\nnop side 0 [7]", [0b101_10111_010_00_010]) + + +def test_set(): + # non happy path + assert_assembly_fails( + "set isr, 1", match="Invalid set destination 'isr'", errtype=ValueError + ) + + +def test_jmp(): + assert_assembles_to("l:\njmp l", [0b000_00000_000_00000]) + assert_assembles_to("l:\njmp 7", [0b000_00000_000_00111]) + assert_assembles_to("jmp l\nl:", [0b000_00000_000_00001]) + assert_assembles_to("jmp !x, l\nl:", [0b000_00000_001_00001]) + assert_assembles_to("jmp x--, l\nl:", [0b000_00000_010_00001]) + assert_assembles_to("jmp !y, l\nl:", [0b000_00000_011_00001]) + assert_assembles_to("jmp y--, l\nl:", [0b000_00000_100_00001]) + assert_assembles_to("jmp x!=y, l\nl:", [0b000_00000_101_00001]) + assert_assembles_to("jmp pin, l\nl:", [0b000_00000_110_00001]) + assert_assembles_to("jmp !osre, l\nl:", [0b000_00000_111_00001]) + # non happy path + assert_assembly_fails( + "jmp x--., l\nl:", match="Invalid jmp condition 'x--.'", errtype=ValueError + ) + + +def test_wait(): + assert_assembles_to("wait 0 gpio 0", [0b001_00000_0_00_00000]) + assert_assembles_to("wait 0 gpio 1", [0b001_00000_0_00_00001]) + assert_assembles_to("wait 1 gpio 2", [0b001_00000_1_00_00010]) + assert_assembles_to("wait 0 pin 0", [0b001_00000_0_01_00000]) + assert_assembles_to("wait 0 pin 1", [0b001_00000_0_01_00001]) + assert_assembles_to("wait 1 pin 2", [0b001_00000_1_01_00010]) + assert_assembles_to("wait 0 irq 0", [0b001_00000_0_10_00000]) + assert_assembles_to("wait 0 irq 0 rel", [0b001_00000_0_10_10000]) + assert_assembles_to("wait 1 irq 0", [0b001_00000_1_10_00000]) + assert_assembles_to("wait 0 irq 1 rel", [0b001_00000_0_10_10001]) + + +def test_limits(): + assert_assembly_fails(".side_set 1\nnop side 2") + assert_assembly_fails(".side_set 1\nnop side 2 [1]") + assert_assembly_fails("nop [32]") + assert_assembly_fails(".side_set 1\nnop side 0 [16]") + assert_assembly_fails(".side_set 1 opt\nnop side 0 [8]") + + +def test_cls(): + assert_pio_kwargs("", sideset_enable=False) + assert_pio_kwargs(".side_set 1", sideset_pin_count=1, sideset_enable=False) + assert_pio_kwargs(".side_set 3 opt", sideset_pin_count=3, sideset_enable=True) diff --git a/tests/test_radix.py b/tests/test_radix.py new file mode 100644 index 0000000..f3cfb9e --- /dev/null +++ b/tests/test_radix.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +Tests radix +""" + +from pytest_helpers import assert_assembles_to + + +def test_octal(): + assert_assembles_to(".side_set 0o1\nset x, 0o11", [0b111_00000_001_01001]) + + +def test_binary(): + assert_assembles_to(".side_set 0b101\nnop side 0b10001", [0b101_10001_010_00_010]) + + +def test_hex(): + assert_assembles_to(".side_set 0x0\nnop [0x10]", [0b101_10000_010_00_010]) diff --git a/tests/test_wrap.py b/tests/test_wrap.py new file mode 100644 index 0000000..b866a26 --- /dev/null +++ b/tests/test_wrap.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +""" +Tests wrap +""" + +from pytest_helpers import assert_assembly_fails, assert_pio_kwargs + + +def test_wrap(): + assert_assembly_fails(".wrap") + assert_pio_kwargs( + "nop\n.wrap_target\nnop\nnop\n.wrap", + sideset_enable=False, + wrap=2, + wrap_target=1, + ) diff --git a/tests/testpioasm.py b/tests/testpioasm.py deleted file mode 100644 index a2e9b3c..0000000 --- a/tests/testpioasm.py +++ /dev/null @@ -1,161 +0,0 @@ -# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries -# -# SPDX-License-Identifier: MIT - -# pylint: disable=missing-module-docstring,invalid-name,missing-function-docstring,missing-class-docstring - -import pathlib -import sys -import unittest - -sys.path.insert(0, str(pathlib.Path(__file__).absolute().parent.parent)) - -import adafruit_pioasm # pylint: disable=wrong-import-position - - -def nice_opcode(o): - o = f"{o:016b}" - return o[:3] + "_" + o[3:8] + "_" + o[8:] - - -class AssembleChecks(unittest.TestCase): - def assertAssemblesTo(self, source, expected): - actual = adafruit_pioasm.assemble(source) - expected_bin = [nice_opcode(x) for x in expected] - actual_bin = [nice_opcode(x) for x in actual] - self.assertEqual( - expected_bin, - actual_bin, - f"Assembling {source!r}: Expected {expected_bin}, got {actual_bin}", - ) - - def assertAssemblyFails(self, source, match=None, errtype=RuntimeError): - if match: - self.assertRaisesRegex(errtype, match, adafruit_pioasm.assemble, source) - else: - self.assertRaises(errtype, adafruit_pioasm.assemble, source) - - def assertPioKwargs(self, source, **kw): - program = adafruit_pioasm.Program(source) - self.assertEqual(kw, program.pio_kwargs) - - -class TestNop(AssembleChecks): - def testNonsense(self): - self.assertAssemblyFails("nope") - - def testNop(self): - self.assertAssemblesTo("nop", [0b101_00000_010_00_010]) - self.assertAssemblesTo( - "nop\nnop", [0b101_00000_010_00_010, 0b101_00000_010_00_010] - ) - self.assertAssemblesTo("nop [1]", [0b101_00001_010_00_010]) - self.assertAssemblesTo("nop [31]", [0b101_11111_010_00_010]) - self.assertAssemblesTo(".side_set 1\nnop side 1", [0b101_10000_010_00_010]) - self.assertAssemblesTo(".side_set 1\nnop side 1 [15]", [0b101_11111_010_00_010]) - - def testSidesetOpt(self): - self.assertAssemblesTo(".side_set 1 opt\nnop side 1", [0b101_11000_010_00_010]) - self.assertAssemblesTo(".side_set 1 opt\nnop side 0", [0b101_10000_010_00_010]) - self.assertAssemblesTo( - ".side_set 1 opt\nnop side 0 [1]", [0b101_10001_010_00_010] - ) - self.assertAssemblesTo(".side_set 1 opt\nnop [1]", [0b101_00001_010_00_010]) - self.assertAssemblesTo(".side_set 1 opt\nnop [7]", [0b101_00111_010_00_010]) - self.assertAssemblesTo( - ".side_set 1 opt\nnop side 1 [1]", [0b101_11001_010_00_010] - ) - self.assertAssemblesTo( - ".side_set 1 opt\nnop side 0 [7]", [0b101_10111_010_00_010] - ) - - def testSet(self): - # non happy path - self.assertAssemblyFails( - "set isr, 1", match="Invalid set destination 'isr'", errtype=ValueError - ) - - def testJmp(self): - self.assertAssemblesTo("l:\njmp l", [0b000_00000_000_00000]) - self.assertAssemblesTo("l:\njmp 7", [0b000_00000_000_00111]) - self.assertAssemblesTo("jmp l\nl:", [0b000_00000_000_00001]) - self.assertAssemblesTo("jmp !x, l\nl:", [0b000_00000_001_00001]) - self.assertAssemblesTo("jmp x--, l\nl:", [0b000_00000_010_00001]) - self.assertAssemblesTo("jmp !y, l\nl:", [0b000_00000_011_00001]) - self.assertAssemblesTo("jmp y--, l\nl:", [0b000_00000_100_00001]) - self.assertAssemblesTo("jmp x!=y, l\nl:", [0b000_00000_101_00001]) - self.assertAssemblesTo("jmp pin, l\nl:", [0b000_00000_110_00001]) - self.assertAssemblesTo("jmp !osre, l\nl:", [0b000_00000_111_00001]) - # non happy path - self.assertAssemblyFails( - "jmp x--., l\nl:", match="Invalid jmp condition 'x--.'", errtype=ValueError - ) - - def testWait(self): - self.assertAssemblesTo("wait 0 gpio 0", [0b001_00000_0_00_00000]) - self.assertAssemblesTo("wait 0 gpio 1", [0b001_00000_0_00_00001]) - self.assertAssemblesTo("wait 1 gpio 2", [0b001_00000_1_00_00010]) - self.assertAssemblesTo("wait 0 pin 0", [0b001_00000_0_01_00000]) - self.assertAssemblesTo("wait 0 pin 1", [0b001_00000_0_01_00001]) - self.assertAssemblesTo("wait 1 pin 2", [0b001_00000_1_01_00010]) - self.assertAssemblesTo("wait 0 irq 0", [0b001_00000_0_10_00000]) - self.assertAssemblesTo("wait 0 irq 0 rel", [0b001_00000_0_10_10000]) - self.assertAssemblesTo("wait 1 irq 0", [0b001_00000_1_10_00000]) - self.assertAssemblesTo("wait 0 irq 1 rel", [0b001_00000_0_10_10001]) - - def testLimits(self): - self.assertAssemblyFails(".side_set 1\nnop side 2") - self.assertAssemblyFails(".side_set 1\nnop side 2 [1]") - self.assertAssemblyFails("nop [32]") - self.assertAssemblyFails(".side_set 1\nnop side 0 [16]") - self.assertAssemblyFails(".side_set 1 opt\nnop side 0 [8]") - - def testCls(self): - self.assertPioKwargs("", sideset_enable=False) - self.assertPioKwargs(".side_set 1", sideset_pin_count=1, sideset_enable=False) - self.assertPioKwargs( - ".side_set 3 opt", sideset_pin_count=3, sideset_enable=True - ) - - -class TestMov(AssembleChecks): - def testMovNonHappy(self): - # non happy path - self.assertAssemblyFails( - "mov x, blah", match="Invalid mov source 'blah'", errtype=ValueError - ) - - def testMovInvert(self): - # test moving and inverting - self.assertAssemblesTo("mov x, ~ x", [0b101_00000_001_01_001]) - self.assertAssemblesTo("mov x, ~x", [0b101_00000_001_01_001]) - self.assertAssemblesTo("mov x, !x", [0b101_00000_001_01_001]) - - def testMovReverse(self): - # test moving and reversing bits - self.assertAssemblesTo("mov x, :: x", [0b101_00000_001_10_001]) - self.assertAssemblesTo("mov x, ::x", [0b101_00000_001_10_001]) - - -class TestWrap(AssembleChecks): - def testWrap(self): - self.assertAssemblyFails(".wrap") - self.assertPioKwargs( - "nop\n.wrap_target\nnop\nnop\n.wrap", - sideset_enable=False, - wrap=2, - wrap_target=1, - ) - - -class TestRadix(AssembleChecks): - def testOctal(self): - self.assertAssemblesTo(".side_set 0o1\nset x, 0o11", [0b111_00000_001_01001]) - - def testBinary(self): - self.assertAssemblesTo( - ".side_set 0b101\nnop side 0b10001", [0b101_10001_010_00_010] - ) - - def testHex(self): - self.assertAssemblesTo(".side_set 0x0\nnop [0x10]", [0b101_10000_010_00_010])