#!/usr/bin/env bash set -euo pipefail usage() { cat <<'EOF' Usage: ./scripts/cir/run_cir_replay_sequence_ours.sh \ --sequence-root \ [--rpki-bin ] \ [--real-rsync-bin ] EOF } ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" SEQUENCE_ROOT="" RPKI_BIN="${RPKI_BIN:-$ROOT_DIR/target/release/rpki}" REAL_RSYNC_BIN="${REAL_RSYNC_BIN:-/usr/bin/rsync}" STEP_SCRIPT="$ROOT_DIR/scripts/cir/run_cir_replay_ours.sh" while [[ $# -gt 0 ]]; do case "$1" in --sequence-root) SEQUENCE_ROOT="$2"; shift 2 ;; --rpki-bin) RPKI_BIN="$2"; shift 2 ;; --real-rsync-bin) REAL_RSYNC_BIN="$2"; shift 2 ;; -h|--help) usage; exit 0 ;; *) echo "unknown argument: $1" >&2; usage; exit 2 ;; esac done [[ -n "$SEQUENCE_ROOT" ]] || { usage >&2; exit 2; } SEQUENCE_ROOT="$(python3 - <<'PY' "$SEQUENCE_ROOT" from pathlib import Path import sys print(Path(sys.argv[1]).resolve()) PY )" SUMMARY_JSON="$SEQUENCE_ROOT/sequence-summary.json" SUMMARY_MD="$SEQUENCE_ROOT/sequence-summary.md" DETAIL_JSON="$SEQUENCE_ROOT/sequence-detail.json" python3 - <<'PY' "$SEQUENCE_ROOT" "$SUMMARY_JSON" "$SUMMARY_MD" "$DETAIL_JSON" "$STEP_SCRIPT" "$RPKI_BIN" "$REAL_RSYNC_BIN" import json import subprocess import sys from pathlib import Path sequence_root = Path(sys.argv[1]) summary_json = Path(sys.argv[2]) summary_md = Path(sys.argv[3]) detail_json = Path(sys.argv[4]) step_script = Path(sys.argv[5]) rpki_bin = sys.argv[6] real_rsync_bin = sys.argv[7] sequence = json.loads((sequence_root / "sequence.json").read_text(encoding="utf-8")) static_root = sequence_root / sequence["staticRoot"] if "staticRoot" in sequence else None raw_store_db = sequence_root / sequence["rawStoreDbPath"] if "rawStoreDbPath" in sequence else None backend_count = sum(x is not None for x in (static_root, raw_store_db)) if backend_count != 1: raise SystemExit("sequence must set exactly one of staticRoot or rawStoreDbPath") steps = sequence["steps"] results = [] all_match = True for step in steps: step_id = step["stepId"] out_dir = sequence_root / "replay-ours" / step_id out_dir.parent.mkdir(parents=True, exist_ok=True) cmd = [ str(step_script), "--cir", str(sequence_root / step["cirPath"]), "--out-dir", str(out_dir), "--reference-ccr", str(sequence_root / step["ccrPath"]), "--rpki-bin", rpki_bin, "--real-rsync-bin", real_rsync_bin, ] if static_root is not None: cmd.extend(["--static-root", str(static_root)]) else: cmd.extend(["--raw-store-db", str(raw_store_db)]) proc = subprocess.run(cmd, capture_output=True, text=True) if proc.returncode != 0: raise SystemExit( f"ours sequence replay failed for {step_id}: stdout={proc.stdout} stderr={proc.stderr}" ) compare = json.loads((out_dir / "compare-summary.json").read_text(encoding="utf-8")) timing = json.loads((out_dir / "timing.json").read_text(encoding="utf-8")) if (out_dir / "timing.json").exists() else {} record = { "stepId": step_id, "kind": step["kind"], "validationTime": step["validationTime"], "outDir": str(out_dir), "comparePath": str(out_dir / "compare-summary.json"), "timingPath": str(out_dir / "timing.json"), "compare": compare, "timing": timing, "match": bool(compare["vrps"]["match"]) and bool(compare["vaps"]["match"]), } all_match = all_match and record["match"] results.append(record) summary = { "version": 1, "participant": "ours", "sequenceRoot": str(sequence_root), "stepCount": len(results), "allMatch": all_match, "steps": results, } summary_json.write_text(json.dumps(summary, indent=2), encoding="utf-8") detail_json.write_text(json.dumps(results, indent=2), encoding="utf-8") lines = [ "# Ours CIR Sequence Replay Summary", "", f"- `sequence_root`: `{sequence_root}`", f"- `step_count`: `{len(results)}`", f"- `all_match`: `{all_match}`", "", "| Step | Kind | VRP actual/ref | VRP match | VAP actual/ref | VAP match | Duration (ms) |", "| --- | --- | --- | --- | --- | --- | ---: |", ] for item in results: compare = item["compare"] timing = item.get("timing") or {} lines.append( "| {step} | {kind} | {va}/{vr} | {vm} | {aa}/{ar} | {am} | {dur} |".format( step=item["stepId"], kind=item["kind"], va=compare["vrps"]["actual"], vr=compare["vrps"]["reference"], vm=compare["vrps"]["match"], aa=compare["vaps"]["actual"], ar=compare["vaps"]["reference"], am=compare["vaps"]["match"], dur=timing.get("durationMs", "-"), ) ) summary_md.write_text("\n".join(lines) + "\n", encoding="utf-8") PY echo "done: $SEQUENCE_ROOT"