#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" VERIFIER="$ROOT/tools/vm_verify_sentinel_bundle.py" TV_DIR="$ROOT/testvectors/sentinel" if [[ ! -x "$VERIFIER" && ! -f "$VERIFIER" ]]; then echo "[ERROR] Verifier not found: $VERIFIER" >&2 exit 2 fi if [[ ! -d "$TV_DIR" ]]; then echo "[ERROR] Testvector directory not found: $TV_DIR" >&2 exit 2 fi expected_exit_for() { case "$1" in black-box-that-refused) echo 0 ;; rollback-duplicate-seq) echo 1 ;; corruption-truncated-jsonl) echo 1 ;; revocation-used-after-revoke) echo 1 ;; integrity-size-mismatch) echo 1 ;; *) echo "" ;; esac } expected_code_for() { case "$1" in rollback-duplicate-seq) echo "E_SEQ_NON_MONOTONIC" ;; corruption-truncated-jsonl) echo "E_SCHEMA_INVALID" ;; revocation-used-after-revoke) echo "E_REVOKED_CAPABILITY_USED" ;; integrity-size-mismatch) echo "E_MANIFEST_HASH_MISMATCH" ;; *) echo "" ;; esac } missing=0 for dir in "$TV_DIR"/*; do [[ -d "$dir" ]] || continue name="$(basename "$dir")" expected_exit="$(expected_exit_for "$name")" if [[ -z "$expected_exit" ]]; then echo "[ERROR] Unknown testvector: $name" >&2 missing=1 continue fi report1="$(mktemp)" report2="$(mktemp)" set +e python3 "$VERIFIER" --bundle "$dir" --strict --report "$report1" >/dev/null 2>/dev/null status=$? set -e if [[ "$status" -ne "$expected_exit" ]]; then echo "[FAIL] $name: exit=$status expected=$expected_exit" >&2 python3 "$VERIFIER" --bundle "$dir" --strict --report "$report1" >&2 || true exit 1 fi failure_code="$(python3 -c "import json; p='$report1'; fc=json.load(open(p,'r',encoding='utf-8')).get('failure_code'); print('' if fc is None else fc)")" if [[ "$expected_exit" -eq 0 ]]; then if [[ -n "$failure_code" ]]; then echo "[FAIL] $name: expected PASS but failure_code=$failure_code" >&2 exit 1 fi else expected_code="$(expected_code_for "$name")" if [[ -z "$expected_code" ]]; then echo "[ERROR] Missing EXPECT_CODE mapping for failing vector: $name" >&2 exit 2 fi if [[ "$failure_code" != "$expected_code" ]]; then echo "[FAIL] $name: failure_code=$failure_code expected=$expected_code" >&2 exit 1 fi fi # Determinism: same inputs -> byte-identical report. set +e python3 "$VERIFIER" --bundle "$dir" --strict --report "$report2" >/dev/null 2>/dev/null status2=$? set -e if [[ "$status2" -ne "$expected_exit" ]]; then echo "[FAIL] $name: second run exit=$status2 expected=$expected_exit" >&2 exit 1 fi if ! cmp -s "$report1" "$report2"; then echo "[FAIL] $name: report is not deterministic" >&2 diff -u "$report1" "$report2" | head -n 200 >&2 || true exit 1 fi rm -f "$report1" "$report2" echo "[OK] $name" done if [[ "$missing" -ne 0 ]]; then exit 2 fi echo "[OK] All Sentinel testvectors verified"