#!/usr/bin/env python3 # hold blocks (spec 4.16): accepted programs print what their first line expects, rejected # ones report the error their first line names (exit 1), and trapping ones stop with # exit 2 and the message named. usage: hold_test.py [VM] from pathlib import Path import subprocess, sys root = Path(__file__).resolve().parents[2] vm = sys.argv[1] if len(sys.argv) > 1 else 'build/bin/zy' count = bad = 0 for case in sorted((root / 'tests/hold').glob('*/*.zc')): src = case.read_text(); first = src.splitlines()[0] p = subprocess.run([str(root / vm) if not Path(vm).is_absolute() else vm], input=src, text=True, capture_output=True, cwd=root, timeout=60) out = p.stdout + p.stderr if first.startswith('// expect: '): ok = p.returncode == 0 and p.stdout.strip() == first[11:].strip() elif first.startswith('// error: '): ok = p.returncode == 1 and first[10:].strip() in out elif first.startswith('// trap: '): ok = p.returncode == 2 and first[9:].strip() in out else: ok = False count += 1 if not ok: bad += 1; print(f'FAIL {case.relative_to(root)}: rc={p.returncode} out={out[:300]!r}') else: print(f'ok {case.relative_to(root)}') print(f'{count - bad}/{count} hold fixtures passed') sys.exit(1 if bad or not count else 0)