#!/usr/bin/env bash set -euo pipefail RUN_DIR="${1:-}" usage() { cat <<'USAGE' Usage: tests/compat/verify_run_abi.sh USAGE } if [[ -z "$RUN_DIR" || "$RUN_DIR" == "-h" || "$RUN_DIR" == "--help" ]]; then usage >&2 exit 2 fi [[ -d "$RUN_DIR" ]] || { echo "missing run directory: $RUN_DIR" >&2; exit 2; } required_files=( run-meta.json run-summary.json daemon-status.json report.json input.cir result.ccr vrps.csv vaps.csv validation-contract.json stage-timing.json stdout.log stderr.log process-time.txt ) for name in "${required_files[@]}"; do [[ -f "$RUN_DIR/$name" ]] || { echo "missing ABI file: $RUN_DIR/$name" >&2; exit 1; } done python3 - "$RUN_DIR" <<'PY' import csv import json import pathlib import sys run_dir = pathlib.Path(sys.argv[1]) meta = json.loads((run_dir / "run-meta.json").read_text(encoding="utf-8")) summary = json.loads((run_dir / "run-summary.json").read_text(encoding="utf-8")) daemon = json.loads((run_dir / "daemon-status.json").read_text(encoding="utf-8")) contract = json.loads((run_dir / "validation-contract.json").read_text(encoding="utf-8")) report = json.loads((run_dir / "report.json").read_text(encoding="utf-8")) checks = { "run-meta status": meta.get("status") == "success", "run-meta id": meta.get("run_id") == run_dir.name, "run-summary status": summary.get("status") == "success", "run-summary exit": summary.get("exitCode") == 0, "run-summary id": summary.get("runId") == run_dir.name, "daemon state": daemon.get("state") == "exited", "daemon last run": daemon.get("lastRunId") == run_dir.name, "contract schema": contract.get("schemaVersion") == 1, "report format": report.get("format_version") == 2, } failed = [name for name, passed in checks.items() if not passed] if failed: raise SystemExit("ABI semantic checks failed: " + ", ".join(failed)) expected_headers = { "vrps.csv": ["ASN", "IP Prefix", "Max Length", "Trust Anchor"], "vaps.csv": ["Customer ASN", "Providers", "Trust Anchor"], } for name, expected in expected_headers.items(): with (run_dir / name).open(newline="", encoding="utf-8") as handle: actual = next(csv.reader(handle), []) if actual != expected: raise SystemExit(f"{name} header changed: expected={expected!r} actual={actual!r}") print(f"normal run ABI verified: {run_dir}") PY