diff --git a/pyproject.toml b/pyproject.toml index 3437b0f..4878d10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,9 +14,9 @@ dependencies = ["grpcio-tools"] dynamic = ["version"] [project.optional-dependencies] -dev = ["flake8", "flake8-blind-except", "flake8-builtins", "flake8-docstrings", "flake8-executable", "flake8-fixme", - "flake8-isort", "flake8-logging-format", "flake8-mutable", "flake8-pyproject", "mypy", "pip-tools", "pytest", - "setuptools-scm"] +dev = ["decorator", "flake8", "flake8-blind-except", "flake8-builtins", "flake8-docstrings", "flake8-executable", + "flake8-fixme", "flake8-isort", "flake8-logging-format", "flake8-mutable", "flake8-pyproject", "mypy", + "pip-tools", "pytest", "setuptools-scm"] [project.scripts] visualize-storage = "gp2040ce_bintools.storage:visualize" diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index 7131e94..73574c6 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -8,6 +8,8 @@ build==0.10.0 # via pip-tools click==8.1.3 # via pip-tools +decorator==5.1.1 + # via gp2040ce-binary-tools (pyproject.toml) exceptiongroup==1.1.1 # via pytest flake8==6.0.0 diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..107eb84 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,16 @@ +"""Create the test fixtures and other data.""" +import os + +import pytest + +HERE = os.path.dirname(os.path.abspath(__file__)) + + +@pytest.fixture +def storage_dump(): + """Read in a test storage dump file (101FE000-10200000) of a GP2040-CE board.""" + filename = os.path.join(HERE, 'test-files', 'test-storage-area.bin') + with open(filename, 'rb') as file: + content = file.read() + + yield content diff --git a/tests/test-files/test-storage-area.bin b/tests/test-files/test-storage-area.bin new file mode 100644 index 0000000..829754a Binary files /dev/null and b/tests/test-files/test-storage-area.bin differ diff --git a/tests/test_storage.py b/tests/test_storage.py new file mode 100644 index 0000000..1588325 --- /dev/null +++ b/tests/test_storage.py @@ -0,0 +1,64 @@ +"""Unit tests for the storage module.""" +import os +import sys + +import pytest +from decorator import decorator + +from gp2040ce_bintools.storage import get_config, get_config_footer + +HERE = os.path.dirname(os.path.abspath(__file__)) + + +@decorator +def with_pb2s(test, *args, **kwargs): + """Wrap a test with precompiled pb2 files on the path.""" + proto_path = os.path.join(HERE, 'test-files', 'pb2-files') + sys.path.append(proto_path) + + test(*args, **kwargs) + + sys.path.pop() + del sys.modules['config_pb2'] + + +def test_config_footer(storage_dump): + """Test that a config footer is identified as expected.""" + size, crc, magic = get_config_footer(storage_dump) + assert size == 2032 + assert crc == 3799109329 + assert magic == '0x65e3f1d2' + + +def test_config_footer_way_too_small(storage_dump): + """Test that a config footer isn't detected if the size is way too small.""" + with pytest.raises(ValueError): + size, crc, magic = get_config_footer(storage_dump[-11:]) + + +def test_config_footer_too_small(storage_dump): + """Test that a config footer isn't detected if the size is smaller than that found in the header.""" + with pytest.raises(ValueError): + size, crc, magic = get_config_footer(storage_dump[-1000:]) + + +def test_config_footer_bad_magic(storage_dump): + """Test that a config footer isn't detected if the magic is incorrect.""" + unmagical = bytearray(storage_dump) + unmagical[-1] = 0 + with pytest.raises(ValueError): + size, crc, magic = get_config_footer(unmagical) + + +def test_config_fails_without_pb2s(storage_dump): + """Test that we need the config_pb2 to exist/be compiled for reading the config to work.""" + with pytest.raises(ModuleNotFoundError): + _ = get_config(storage_dump) + + +@with_pb2s +def test_config_parses(storage_dump): + """Test that we need the config_pb2 to exist/be compiled for reading the config to work.""" + config = get_config(storage_dump) + assert config.boardVersion == 'v0.7.2' + assert config.hotkeyOptions.hotkeyF1Up.dpadMask == 1