feat: refuse a profile check with no value

This commit is contained in:
Abdessamad Derraz committed 2026-10-16 07:05:35 +02:00
1 parent d3d83d0116
commit 276588485a
2 files changed
+92

No files matched your search

+37
View File
@@ -57,6 +57,43 @@ def _validate_yaml_directory(
continue
out.extend(_errors(validator, data, str(path.relative_to(ROOT))))
out.extend(_unreachable_citations(path, data))
if schema_name == "emulator.schema.json":
out.extend(_checks_without_values(path, data))
return out
_CHECK_FIELDS = {
"crc32": ("crc32",),
"md5": ("md5",),
"sha1": ("sha1",),
"sha256": ("sha256",),
"size": ("size", "min_size", "max_size"),
}
def _checks_without_values(path: Path, document: object) -> list[str]:
"""A check an entry declares with nothing to compare against.
validation: [crc32] with no crc32 runs nothing: the file passes whatever
it holds, and the report reads as checked. Fourteen profiles carried
one, the code they describe either refusing or warning on a value the
entry never wrote down.
"""
out: list[str] = []
files = document.get("files") if isinstance(document, dict) else None
for index, entry in enumerate(files or []):
if not isinstance(entry, dict):
continue
declared = entry.get("validation") or []
if isinstance(declared, dict):
declared = [check for checks in declared.values() for check in checks or []]
for check in declared:
fields = _CHECK_FIELDS.get(check)
if fields and not any(entry.get(field) not in (None, "", []) for field in fields):
out.append(
f"{path.relative_to(ROOT)}: files[{index}] ({entry.get('name')}) "
f"declares a {check} check with no {'/'.join(fields)} value"
)
return out
+55
View File
@@ -0,0 +1,55 @@
"""A check a profile declares has a value to compare against.
validation: [crc32] with no crc32 ran nothing, and fourteen profiles carried
one. validate_schemas now refuses it.
"""
from __future__ import annotations
import subprocess
import sys
import unittest
from pathlib import Path
import yaml
REPO_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO_ROOT / "scripts"))
class ChecksHaveValues(unittest.TestCase):
def setUp(self):
try:
import validate_schemas
except ImportError as exc:
self.skipTest(f"validate_schemas needs jsonschema: {exc}")
self.check = validate_schemas._checks_without_values
def test_a_valueless_check_is_named(self):
path = REPO_ROOT / "emulators" / "x.yml"
document = {"files": [
{"name": "a.bin", "validation": ["crc32"]},
{"name": "b.bin", "validation": ["size"], "min_size": 4},
{"name": "c.bin", "validation": {"core": ["size"], "upstream": ["sha1"]},
"size": 4},
]}
found = self.check(path, document)
self.assertEqual(len(found), 2)
self.assertIn("a.bin", found[0])
self.assertIn("c.bin", found[1])
def test_every_tracked_profile(self):
tracked = subprocess.run(
["git", "ls-files", "emulators/*.yml"], cwd=REPO_ROOT,
capture_output=True, text=True, check=True,
).stdout.split()
found = []
for name in tracked:
path = REPO_ROOT / name
with path.open(encoding="utf-8") as fh:
found.extend(self.check(path, yaml.safe_load(fh)))
self.assertEqual(found, [])
if __name__ == "__main__":
unittest.main()