#!/bin/sh
set -eu

: "${PRE15_DUT:?PRE15_DUT is required}"
: "${PRE15_CASE_TMP:?PRE15_CASE_TMP is required}"
: "${PRE15_LIB_DIR:?PRE15_LIB_DIR is required}"
. "$PRE15_LIB_DIR/runner.sh"

controls=$PRE15_DUT/tests/pre15/fixtures/B01-runner-controls.json
pre15_record_fixture runner-control-contract "$controls"
pre15_record_fixture evidence-schema "$PRE15_DUT/tests/pre15/EVIDENCE-SCHEMA.json"

command -v qemu-system-x86_64 >/dev/null 2>&1 || \
	pre15_infra_blocked 'qemu-system-x86_64 is required for the early-exit control'
command -v ssh >/dev/null 2>&1 || \
	pre15_infra_blocked 'ssh is required for the connection-failure control'

pre15_control_run "$PRE15_CASE_TMP/known-good" 5 \
	sh -c 'printf "reached\n" > "$PRE15_TARGET_MARKER_FILE"'
pre15_control_run "$PRE15_CASE_TMP/dut-mismatch" 5 \
	sh -c 'printf "reached\n" > "$PRE15_TARGET_MARKER_FILE"; exit 10'
pre15_control_run "$PRE15_CASE_TMP/guest-command-failure" 5 sh -c 'exit 1'
pre15_control_run "$PRE15_CASE_TMP/ssh-failure" 5 sh -c \
	'if ssh -o BatchMode=yes -o ConnectTimeout=1 -p 1 root@127.0.0.1 true >/dev/null 2>&1; then exit 20; fi; exit 21'
pre15_control_run "$PRE15_CASE_TMP/qemu-early-exit" 5 sh -c \
	'qemu-system-x86_64 --pre15-invalid-option >/dev/null 2>&1; qemu_rc=$?; test "$qemu_rc" -ne 0 || exit 20; exit 21'

timeout_pid_file=$PRE15_CASE_TMP/timeout.pid
export timeout_pid_file
pre15_control_run "$PRE15_CASE_TMP/timeout" 1 sh -c \
	'printf "%s\n" "$$" > "$timeout_pid_file"; exec sleep 30'
timeout_pid=$(cat "$timeout_pid_file")
if kill -0 "$timeout_pid" 2>/dev/null; then
	pre15_runner_fail "timeout control left PID $timeout_pid alive"
fi

pre15_control_run "$PRE15_CASE_TMP/owned-cleanup" 5 sh -c '
	sleep 30 >/dev/null 2>&1 &
	owned_pid=$!
	printf "pid\t%s\tselftest-owned-sleep\n" "$owned_pid" >> "$PRE15_OWNERSHIP_FILE"
	printf "%s\n" "$owned_pid" > "$PRE15_RUN_DIR/owned.pid"
	printf "reached\n" > "$PRE15_TARGET_MARKER_FILE"
'
owned_pid=$(cat "$PRE15_CASE_TMP/owned-cleanup/owned.pid")
if kill -0 "$owned_pid" 2>/dev/null; then
	pre15_runner_fail "owned cleanup left PID $owned_pid alive"
fi

outside_path=$PRE15_CASE_TMP/cleanup-must-refuse
printf 'owned by outer selftest\n' > "$outside_path"
export outside_path
pre15_control_run "$PRE15_CASE_TMP/cleanup-failure" 5 sh -c '
	printf "path\t%s\toutside-control-boundary\n" "$outside_path" >> "$PRE15_OWNERSHIP_FILE"
	printf "reached\n" > "$PRE15_TARGET_MARKER_FILE"
'
test -f "$outside_path" || \
	pre15_runner_fail 'cleanup safety control deleted a non-owned path'

python3 - "$controls" "$PRE15_CASE_TMP" <<'PY'
import json
from pathlib import Path
import sys

contract = json.loads(Path(sys.argv[1]).read_text(encoding="ascii"))["controls"]
root = Path(sys.argv[2])
for name, expected in contract.items():
    actual = (root / name / "result.tsv").read_text(encoding="ascii").rstrip("\n").split("\t")
    if actual != expected:
        raise SystemExit(f"{name}: {actual!r}, expected {expected!r}")
    print(f"{name}: status={actual[0]} origin={actual[1]} cleanup={actual[2]} timeout={actual[3]}")
PY

mkdir -p "$PRE15_RUN_DIR/artifacts/controls"
for control in \
	cleanup-failure dut-mismatch guest-command-failure known-good \
	owned-cleanup qemu-early-exit ssh-failure timeout; do
	mkdir "$PRE15_RUN_DIR/artifacts/controls/$control"
	cp "$PRE15_CASE_TMP/$control/result.tsv" \
		"$PRE15_CASE_TMP/$control/stdout.log" \
		"$PRE15_CASE_TMP/$control/stderr.log" \
		"$PRE15_CASE_TMP/$control/cleanup.log" \
		"$PRE15_RUN_DIR/artifacts/controls/$control/"
done

pre15_target_reached
