#!/usr/bin/env python3 """Run the wall-contract registry (``harness/contracts.py``, docs/50). Every solved wall is pinned as a contract over an existing tool entry point; this CLI runs them and prints pass/fail per contract plus per-wall-class coverage. Fast contracts are the suite default; slow ones run with ``--all`` (or by name). Offline only: never touches a GPU, kernel module, mdev, guest or network. Exit codes: 0 = every selected contract passed (or skipped for a missing prerequisite), 1 = at least one failure, 2 = usage error. """ from __future__ import annotations import argparse import json import os import sys TOOL_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if TOOL_ROOT not in sys.path: sys.path.insert(0, TOOL_ROOT) from harness.contracts import ( # noqa: E402 Contract, all_contracts, fast_contracts, run_contracts, summarize, ) def _select(args: argparse.Namespace) -> tuple[list[Contract], list[str]]: if args.name: wanted = set(args.name) chosen = [c for c in all_contracts() if c.name in wanted] unknown = sorted(wanted - {c.name for c in chosen}) return chosen, unknown return (all_contracts() if args.all else fast_contracts()), [] def _table(rows: list[tuple[str, ...]], headers: tuple[str, ...]) -> list[str]: widths = [ max(len(headers[index]), *(len(row[index]) for row in rows)) for index in range(len(headers)) ] lines = [" ".join(head.ljust(widths[i]) for i, head in enumerate(headers))] lines.append(" ".join("-" * width for width in widths)) for row in rows: lines.append(" ".join(cell.ljust(widths[i]) for i, cell in enumerate(row))) return lines def _render(results, summary: dict) -> list[str]: rows = [ ( result.name, result.wall_class, result.speed, result.status.upper(), f"{result.seconds:.2f}s", result.detail, ) for result in results ] lines = _table(rows, ("contract", "class", "speed", "status", "time", "detail")) lines.append("") lines.append("wall-class coverage (selected):") for domain in summary["domains"]: lines.append( f" {domain['wall_class']} {domain['domain']:<28} " f"{domain['total']} contracts: {domain['pass']} pass, " f"{domain['fail']} fail, {domain['skip']} skip" ) counts = summary["counts"] lines.append("") lines.append( f"total: {counts['pass']} pass, {counts['fail']} fail, {counts['skip']} skip " f"-> {'OK' if summary['ok'] else 'FAIL'}" ) return lines def build_parser() -> argparse.ArgumentParser: parser = argparse.ArgumentParser( prog="run_contracts.py", description=( "Run the wall-contract registry: fast contracts by default, all " "with --all (offline; never touches hardware)." ), ) group = parser.add_mutually_exclusive_group() group.add_argument( "--fast", action="store_true", help="run fast contracts only (default)" ) group.add_argument("--all", action="store_true", help="run fast and slow contracts") parser.add_argument( "--name", action="append", default=[], metavar="NAME", help="run one named contract (repeatable); overrides --fast/--all selection", ) parser.add_argument("--json", metavar="PATH", help="write the run summary as JSON here") return parser def main(argv: list[str] | None = None) -> int: parser = build_parser() args = parser.parse_args(argv) selected, unknown = _select(args) if unknown: parser.error("unknown contract name(s): " + ", ".join(unknown)) results = run_contracts(selected) summary = summarize(results) for line in _render(results, summary): print(line) if args.json: out_path = os.path.abspath(args.json) parent = os.path.dirname(out_path) if parent: os.makedirs(parent, exist_ok=True) with open(out_path, "w", encoding="utf-8") as fh: json.dump(summary, fh, indent=2, sort_keys=True) fh.write("\n") print(f"json: {out_path}") return 0 if summary["ok"] else 1 if __name__ == "__main__": raise SystemExit(main())