test: add a quicks file validation test
authorPeter Hutterer <peter.hutterer@who-t.net>
Sun, 19 Mar 2023 23:17:39 +0000 (09:17 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 23 Mar 2023 02:13:23 +0000 (12:13 +1000)
Now that we're Python ConfigParser compatible (again), we can check our
quirks file for things our actual parser doesn't care about, but that we
should honour. Right now that means that bustypes and vid/pid matches are
all spelled consistently.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
meson.build
test/test_quirks_files.py [new file with mode: 0755]

index 2d69d22c529707303d814a35ee0bb44fa6c41bda..58b900c5693d6b9a5c9fefd39dd7b69209b36f14 100644 (file)
@@ -478,6 +478,13 @@ test('validate-quirks',
      suite : ['all']
      )
 
+quirks_file_tester = find_program('test/test_quirks_files.py')
+test('validate-quirks-files',
+     quirks_file_tester,
+     suite : ['all'],
+     env: ['MESON_SOURCE_ROOT=@0@'.format(meson.project_source_root())],
+     )
+
 libinput_list_devices_sources = [ 'tools/libinput-list-devices.c' ]
 libinput_list_devices = executable('libinput-list-devices',
                                   libinput_list_devices_sources,
diff --git a/test/test_quirks_files.py b/test/test_quirks_files.py
new file mode 100755 (executable)
index 0000000..91f0074
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+#
+# This file is formatted with Python Black
+#
+# Run with pytest
+
+from pathlib import Path
+
+import configparser
+import os
+import pytest
+import re
+
+
+def quirksdir():
+    return Path(os.getenv("MESON_SOURCE_ROOT") or ".") / "quirks"
+
+
+def pytest_generate_tests(metafunc):
+    # for any function that takes a "quirksfile" argument return the path to
+    # a quirks file
+    if "quirksfile" in metafunc.fixturenames:
+        metafunc.parametrize("quirksfile", [f for f in quirksdir().glob("*.quirks")])
+
+
+def test_matches_are_valid(quirksfile):
+    quirks = configparser.ConfigParser(strict=True)
+    # Don't convert to lowercase
+    quirks.optionxform = lambda option: option  # type: ignore
+    quirks.read(quirksfile)
+
+    for name, section in filter(lambda n: n != "DEFAULT", quirks.items()):
+        bus = section.get("MatchBus")
+        if bus is not None:
+            assert bus in ("ps2", "usb", "bluetooth", "i2c", "spi")
+
+        vid = section.get("MatchVendor")
+        if vid is not None:
+            assert re.match(
+                "0x[0-9A-F]{4}", vid
+            ), f"{quirksfile}: {name}: {vid} must be uppercase hex (0xAB12)"
+
+        pid = section.get("MatchProduct")
+        if pid is not None:
+            assert re.match(
+                "0x[0-9A-F]{4}", pid
+            ), f"{quirksfile}: {name}: {pid} must be uppercase hex (0xAB12)"
+
+
+def main():
+    args = [__file__]
+    try:
+        import xdist  # noqa
+
+        ncores = os.environ.get("FDO_CI_CONCURRENT", "auto")
+        args += ["-n", ncores]
+    except ImportError:
+        pass
+
+    return pytest.main(args)
+
+
+if __name__ == "__main__":
+    raise SystemExit(main())