Add renderer and package readiness validation gates
This commit is contained in:
119
scripts/dev/check_renderer_conformance_matrix.py
Normal file
119
scripts/dev/check_renderer_conformance_matrix.py
Normal file
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Validate that renderer conformance fixtures are registered and labeled consistently."""
|
||||
|
||||
import re
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
TESTS_CMAKE = REPO_ROOT / "tests" / "CMakeLists.txt"
|
||||
|
||||
REQUIRED_TEST_LABELS = {
|
||||
"pp_renderer_api_tests": {"renderer-conformance", "renderer"},
|
||||
}
|
||||
|
||||
OPTIONAL_BACKEND_TEST_LABELS = {
|
||||
"pp_renderer_gl_capabilities_tests": {"renderer-conformance", "renderer"},
|
||||
"pp_renderer_gl_command_plan_tests": {"renderer-conformance", "renderer"},
|
||||
"pp_renderer_gl_gpu_readback_tests": {"renderer-conformance", "renderer", "gpu"},
|
||||
}
|
||||
|
||||
def parse_labels() -> dict[str, set[str]]:
|
||||
labels_by_test: dict[str, set[str]] = {}
|
||||
text = TESTS_CMAKE.read_text(encoding="utf-8").splitlines()
|
||||
i = 0
|
||||
while i < len(text):
|
||||
line = text[i].strip()
|
||||
if not line.startswith("set_tests_properties("):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if "set_tests_properties(" not in line or "PROPERTIES" not in line:
|
||||
i += 1
|
||||
continue
|
||||
after_paren = line.split("set_tests_properties(", 1)[1]
|
||||
test_name = after_paren.split()[0].strip()
|
||||
test_name = test_name.strip()
|
||||
|
||||
label_value: str | None = None
|
||||
j = i
|
||||
while j < len(text):
|
||||
search = text[j].strip()
|
||||
if search.startswith("LABELS"):
|
||||
colon = search.find("\"")
|
||||
if colon != -1:
|
||||
value = search[colon:].strip()
|
||||
if value.startswith("\"") and value.endswith("\""):
|
||||
label_value = value[1:-1]
|
||||
break
|
||||
# Fallback for multiline values: LABELS "a;b"; split on quotes in line.
|
||||
quotes = re.findall(r'"([^"]+)"', search)
|
||||
if quotes:
|
||||
label_value = quotes[0]
|
||||
break
|
||||
if search == ")" or (search.startswith(")") and "LABELS" not in search):
|
||||
break
|
||||
j += 1
|
||||
|
||||
if label_value is not None:
|
||||
labels_by_test[test_name] = {label.strip() for label in label_value.split(";") if label.strip()}
|
||||
|
||||
i = j + 1
|
||||
|
||||
return labels_by_test
|
||||
|
||||
|
||||
def validate() -> tuple[bool, list[dict[str, Any]]]:
|
||||
labels_by_test = parse_labels()
|
||||
test_names = set(labels_by_test)
|
||||
violations: list[dict[str, Any]] = []
|
||||
|
||||
for test_name, required_labels in REQUIRED_TEST_LABELS.items():
|
||||
actual = labels_by_test.get(test_name)
|
||||
if actual is None:
|
||||
violations.append({"test": test_name, "kind": "missing-test", "detail": "required conformance test not registered"})
|
||||
continue
|
||||
|
||||
missing = sorted(required_labels - actual)
|
||||
if missing:
|
||||
violations.append(
|
||||
{
|
||||
"test": test_name,
|
||||
"kind": "missing-label",
|
||||
"detail": f"required labels missing: {', '.join(missing)}",
|
||||
}
|
||||
)
|
||||
|
||||
for test_name, required_labels in OPTIONAL_BACKEND_TEST_LABELS.items():
|
||||
if test_name not in test_names:
|
||||
continue
|
||||
actual = labels_by_test[test_name]
|
||||
missing = sorted(required_labels - actual)
|
||||
if missing:
|
||||
violations.append(
|
||||
{
|
||||
"test": test_name,
|
||||
"kind": "missing-label",
|
||||
"detail": f"required labels missing: {', '.join(missing)}",
|
||||
}
|
||||
)
|
||||
|
||||
return (len(violations) == 0), violations
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ok, violations = validate()
|
||||
payload = {
|
||||
"ok": ok,
|
||||
"summary": {
|
||||
"requiredTestCount": len(REQUIRED_TEST_LABELS),
|
||||
"violationCount": len(violations),
|
||||
},
|
||||
"violations": violations,
|
||||
}
|
||||
print(payload)
|
||||
return 0 if ok else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user