Files
stack/scripts/test-case2.sh
T
jason.woltje 04e1ce24cc row 227 R2 (#1728): run test-case2.sh standalone, without the slot controller
Remove the R1 slot-controller ties from the C2-14 fixture: the ROW227_CONTROL_ROOT
check, the native permit wait in bindLaunch, the fixture-cleanup.json write, the
priority.mjs preload and the owned-bwrap.sh override. The launcher uses its own bwrap.

The shell runs the driver from an explicit env -i environment (PATH, LANG, a sandbox
HOME, XDG dirs and TMPDIR, MOSAIC_CONFIG, no global git config) as its own process
group. On a signal the driver gets 3 s by the clock, then its group and any process
whose cwd is in the sandbox get SIGKILL, inside the landing gate's 5 s grace.

The fixture credentials are defined only in scripts/case2/fixture-credentials.mjs.
The new scripts/case2/leak-check.mjs reads them from there and never prints them.
2026-11-02 15:41:17 -06:00

98 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# C2-14 (#1728, row 227): one acceptance run on a scratch root, no skipped steps.
# Entry point for the real launcher/runner, C2-06 scripted adapter, fake TLS Gitea and Console DOM.
# Stands alone: the landing gate runs it as `bash scripts/test-case2.sh` with nothing else set up.
# The only human stand-in is bindHuman in-process; a development agent cannot prove human CLI ancestry.
set -uo pipefail
cd "$(dirname "$0")/.."
SANDBOX="$(mktemp -d)"
DRIVER_PID=''
CASE2_HOME="$SANDBOX/home"
CASE2_TMP="$SANDBOX/t"
CASE2_CONFIG="$SANDBOX/root/config/config.json"
mkdir -p "$CASE2_HOME" "$CASE2_TMP"
# The driver runs from an explicit environment: PATH and LANG, a sandbox HOME, XDG dirs and TMPDIR,
# and the variables it needs. Nothing else from the caller, a credential variable included, reaches
# the driver or the launcher it starts. TMPDIR in the sandbox takes the Chromium profile and the
# plug-in tree with it when the sandbox goes.
CLEAN_ENV=(env -i PATH="$PATH" LANG=C.UTF-8 HOME="$CASE2_HOME"
XDG_CONFIG_HOME="$CASE2_HOME/.config" XDG_CACHE_HOME="$CASE2_HOME/.cache"
XDG_DATA_HOME="$CASE2_HOME/.local/share" XDG_STATE_HOME="$CASE2_HOME/.local/state"
TMPDIR="$CASE2_TMP" MOSAIC_CONFIG="$CASE2_CONFIG" GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_NOSYSTEM=1)
alive() {
local stat
read -r stat 2>/dev/null <"/proc/$1/stat" || return 1
stat="${stat##*) }"
[ "${stat%% *}" != Z ]
}
# The driver leads its own process group (setsid below). On a signal it gets SIGTERM and 3 s by the
# clock to close, inside the landing gate's 5 s grace, then its group gets SIGKILL. The launcher
# starts each bwrap session in a group of its own, with its working directory in the sandbox; any
# such process still alive then gets SIGKILL too, before the sandbox goes. One find reads every
# cwd link, so the sweep stays in milliseconds however many processes the host runs.
now_us() { echo "${EPOCHREALTIME/[.,]/}"; }
stop_driver() {
local deadline p left=0
if [ -n "$DRIVER_PID" ]; then
kill -TERM "$DRIVER_PID" 2>/dev/null
deadline=$(( $(now_us) + 3000000 ))
while alive "$DRIVER_PID" && [ "$(now_us)" -lt "$deadline" ]; do sleep 0.1; done
kill -KILL -- "-$DRIVER_PID" 2>/dev/null
wait "$DRIVER_PID" 2>/dev/null
DRIVER_PID=''
fi
for p in $(find /proc/[0-9]*/cwd -maxdepth 0 \( -lname "$SANDBOX" -o -lname "$SANDBOX/*" \) 2>/dev/null); do
p="${p#/proc/}"
kill -KILL "${p%/cwd}" 2>/dev/null && left=$((left+1))
done
if [ "$left" -gt 0 ]; then echo "note: $left process(es) under the sandbox outlived the driver; sent SIGKILL"; fi
}
cleanup() {
local result=$?
trap - EXIT INT TERM
stop_driver
rm -rf "$SANDBOX"
exit "$result"
}
trap cleanup EXIT
trap 'exit 130' INT
trap 'exit 143' TERM
PASS=0 FAIL=0
if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
C_OK=$'\033[0;32m'; C_FAIL=$'\033[0;31m'; C_RESET=$'\033[0m'
else
C_OK=''; C_FAIL=''; C_RESET=''
fi
check() {
if [ "$2" = 0 ]; then PASS=$((PASS+1)); echo "${C_OK}OK${C_RESET} $1"
else FAIL=$((FAIL+1)); echo "${C_FAIL}FAIL${C_RESET} $1"; fi
}
DRIVER=scripts/case2/e2e.mjs
STEPS='S1a S1b S2a S2b S2c S2d S3a S3b S3c S4 S5a S5b S6 S7 S8 S9 S10'
"${CLEAN_ENV[@]}" node --check "$DRIVER" >/dev/null 2>&1
check "syntax: $DRIVER" "$?"
OUT="$SANDBOX/steps.txt" ERR="$SANDBOX/stderr.txt"
"${CLEAN_ENV[@]}" setsid node "$DRIVER" "$SANDBOX/root" >"$OUT" 2>"$ERR" &
DRIVER_PID=$!
wait "$DRIVER_PID"
RC=$?
DRIVER_PID=''
check "driver ran to the end (exit $RC)" "$RC"
if [ "$RC" -ne 0 ]; then grep '^e2e: ' "$ERR" | head -5; fi
seen=''
while IFS= read -r line; do
case "$line" in
'ok '*) id="${line#ok }"; id="${id%% *}"; check "${line#ok }" 0 ;;
'not ok '*) id="${line#not ok }"; id="${id%% *}"; check "${line#not ok }" 1 ;;
*) id=''; check 'driver line not understood (a skip cannot pass acceptance)' 1 ;;
esac
[ -n "$id" ] && seen="$seen $id"
done <"$OUT"
[ "${seen# }" = "$STEPS" ]
check 'every acceptance step ran once, in order, with nothing skipped' "$?"
# The values come from scripts/case2/fixture-credentials.mjs and are never printed.
"${CLEAN_ENV[@]}" node scripts/case2/leak-check.mjs "$OUT" "$ERR"
check 'fixture credentials are in no driver output' "$?"
printf '\nselftest: %s passed, %s failed, 0 skipped\n' "$PASS" "$FAIL"
[ "$FAIL" -eq 0 ]