diff --git a/tools/case_manifest.py b/tools/case_manifest.py index 30509623..acaaef74 100644 --- a/tools/case_manifest.py +++ b/tools/case_manifest.py @@ -51,6 +51,8 @@ } NAME_PATTERN = re.compile(r"^[a-z0-9][a-z0-9_-]*$") ROOT_KEYS = {"version", "supported", "ci", "target"} +LEGACY_PLATFORM_KEYS = {"host-os", "host-arch"} +WAVE_TEST_MARKER = "// wave-test:" class CaseManifestError(ValueError): @@ -327,6 +329,31 @@ def _test_number(path): return int(suffix) if suffix.isdigit() else 0 +def _has_legacy_platform_metadata(path: Path) -> bool: + try: + lines = path.read_text(encoding="utf-8").splitlines() + except OSError: + return False + + for line in lines: + stripped = line.strip() + if not stripped.startswith("//"): + if stripped: + break + continue + if not stripped.startswith(WAVE_TEST_MARKER): + continue + + body = stripped[len(WAVE_TEST_MARKER):].strip() + for raw_item in body.split(","): + item = raw_item.strip() + if "=" in item: + key = item.split("=", 1)[0].strip() + if key in LEGACY_PLATFORM_KEYS: + return True + return False + + def _validate_case_layout(targets): suites = { suite @@ -357,8 +384,7 @@ def _validate_case_layout(targets): raise CaseManifestError(f"case files must live in a configured suite: {names}") for source in CASES_ROOT.rglob("*.wave"): - text = source.read_text(encoding="utf-8") - if "host-os=" in text or "host-arch=" in text: + if _has_legacy_platform_metadata(source): relative = source.relative_to(CASES_ROOT).as_posix() raise CaseManifestError( f"case '{relative}' uses legacy platform metadata; use its directory" diff --git a/tools/test_case_manifest.py b/tools/test_case_manifest.py index ee12a5e3..79ef4fb8 100644 --- a/tools/test_case_manifest.py +++ b/tools/test_case_manifest.py @@ -10,12 +10,17 @@ # SPDX-License-Identifier: MPL-2.0 # AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +import tempfile import unittest from pathlib import Path +from types import SimpleNamespace +from unittest.mock import patch +from tools import case_manifest from tools.case_manifest import ( MIN_CASES_PER_SUITE, CaseManifestError, + _validate_case_layout, load_case_manifest, ) @@ -164,6 +169,53 @@ def test_every_configured_suite_has_the_baseline_case_count(self): for target in self.manifest.targets: self.assertGreaterEqual(counts[target.suite], MIN_CASES_PER_SUITE) + def test_case_layout_accepts_platform_metadata_in_literals_and_comments(self): + cases = ( + 'fun main() { println("host-os=linux"); }\n', + 'fun main() { var arch = "host-arch=arm64"; }\n', + '// Ordinary comment: host-arch=arm64\nfun main() {}\n', + '// Note: host-os=windows is handled elsewhere\nfun main() {}\n', + ) + for content in cases: + with self.subTest(content=content): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + suite = root / "shared" + suite.mkdir() + for number in range(1, 11): + (suite / f"test{number}.wave").write_text(content, encoding="utf-8") + target = SimpleNamespace(suite="shared", suites=()) + with patch.object(case_manifest, "CASES_ROOT", root): + _validate_case_layout((target,)) + + def test_case_layout_rejects_legacy_platform_metadata_in_wave_test_directives(self): + invalid_cases = ( + "// wave-test: host-os=linux\nfun main() {}\n", + "// wave-test: mode=check, host-arch=x86_64\nfun main() {}\n", + "// wave-test: host-os = linux\nfun main() {}\n", + "// wave-test: mode=check, host-arch = arm64\nfun main() {}\n", + ) + for content in invalid_cases: + with self.subTest(content=content): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + suite = root / "shared" + suite.mkdir() + for number in range(1, 11): + (suite / f"test{number}.wave").write_text( + "fun main() {}\n", + encoding="utf-8", + ) + (suite / "test1.wave").write_text(content, encoding="utf-8") + target = SimpleNamespace(suite="shared", suites=()) + with patch.object(case_manifest, "CASES_ROOT", root): + with self.assertRaises(CaseManifestError) as context: + _validate_case_layout((target,)) + self.assertEqual( + str(context.exception), + "case 'shared/test1.wave' uses legacy platform metadata; use its directory", + ) + if __name__ == "__main__": unittest.main()