diff --git a/CMakeLists.txt b/CMakeLists.txt index d7757486b..55fc3887e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,6 +55,8 @@ if(BUILD_TESTING) ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_conventions_comments.py) add_test(NAME test_registration COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_test_registration.py) + add_test(NAME check_skips COMMAND ${Python3_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/tools/tests/test_check_skips.py) add_test(NAME hardware_oracle COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tools/hw-oracle/test_hw_oracle.py) add_test(NAME pr_overlap_exports COMMAND ${Python3_EXECUTABLE} diff --git a/tools/check_skips.py b/tools/check_skips.py index f2f8fe1aa..afe85d4bb 100644 --- a/tools/check_skips.py +++ b/tools/check_skips.py @@ -3,7 +3,7 @@ import re import xml.etree.ElementTree as ET from pathlib import Path -DEVICE_LIMITATION = re.compile(r"skipped,.*(subgroup|the device has no|the device reports|no display)", re.IGNORECASE) +DEVICE_LIMITATION = re.compile(r"skipped,.*(subgroup|the device (has no|reports|lacks|does not|imports no|flushes|binds fewer)|no display|no usable Vulkan device|host imports are unavailable)", re.IGNORECASE) NO_DISPLAY = re.compile(r"skipped,.*no display", re.IGNORECASE) diff --git a/tools/tests/test_check_skips.py b/tools/tests/test_check_skips.py new file mode 100644 index 000000000..c668ca75d --- /dev/null +++ b/tools/tests/test_check_skips.py @@ -0,0 +1,63 @@ +from pathlib import Path +import subprocess +import sys +import tempfile +import unittest + +sys.path.insert(0, str(Path(__file__).resolve().parents[1])) +import check_skips + +TOOL = Path(__file__).resolve().parents[1] / "check_skips.py" + +LIMITATIONS = [ + "skipped, the device lacks fragmentShaderPixelInterlock", + "skipped, the device lacks geometryShader", + "skipped, the device lacks shaderSubgroupClock", + "skipped, the device does not import guest memory", + "skipped, the device imports no host memory", + "skipped, the device flushes f64 subnormals without DenormPreserve", + "skipped, the device binds fewer than 8 storage buffers per stage or set", + "skipped, no usable Vulkan device: ErrorInitializationFailed", + "skipped, unit shadows or host imports are unavailable", + "skipped, the device has no compute queue", + "skipped, the device reports 4 lanes", + "skipped, subgroup size 8", + "skipped, no display", +] + +OTHER = [ + "skipped, flaky", + "skipped, APS5_RAYTRACING replaces the node", + "skipped, interpolation modes require", +] + + +class CheckSkipsTests(unittest.TestCase): + def test_device_limitations_match(self): + for message in LIMITATIONS: + with self.subTest(message=message): + self.assertTrue(check_skips.DEVICE_LIMITATION.search(message)) + + def test_other_reasons_do_not_match(self): + for message in OTHER: + with self.subTest(message=message): + self.assertFalse(check_skips.DEVICE_LIMITATION.search(message)) + + def test_only_unexpected_skip_is_reported(self): + xml = ( + '' + 'skipped, the device lacks geometryShader' + 'skipped, flaky' + '' + ) + with tempfile.TemporaryDirectory() as directory: + junit = Path(directory) / "junit.xml" + junit.write_text(xml, encoding="utf-8") + result = subprocess.run([sys.executable, "-I", str(TOOL), str(junit), "--job", "linux"], capture_output=True, text=True) + self.assertEqual(result.returncode, 1) + self.assertIn("error: odd skipped", result.stdout) + self.assertNotIn("error: geometry skipped", result.stdout) + + +if __name__ == "__main__": + unittest.main()