Files

148 lines
10 KiB
Bash
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Row 302 (#1809, Vikunja 588) gate. Plan: agents/gizmoduck/work/queue-302/BUILD.md d3 "Run plan", d4, d5.
# 0. Preflight: worktree at TIP and clean, the five test blobs from d5. TIP is the local merge of 64f6558ee
# onto origin/refactor 1ac655005 (sage-3289); the 12 row paths are unchanged in BASE..1ac655005.
# 1. Red (mos-1415): f799e8b15 (final tests, unfixed product). idle-stop-race and the runner.test land case
# must fail. The bus files are run and recorded. A green forcing case here is a STOP.
# 2. On TIP: idle-stop-race alone 600 s, runner.test whole 900 s, compactions-launch whole 600 s,
# bus 1200 s, harness 1200 s, cli 2100 s, then the scripts/test-*.sh at 900 s each.
# 3. M1-M5, M7, M8, M9 (mutants.py). Each kill-listed file runs whole; every listed test name must fail.
# After each: git checkout, sha256 equal to the candidate's, tree clean. A survivor is a STOP to Sage.
# mos-1272: a first-run red in a new test is placed and reported after; any other red stops the run.
set -o pipefail
WT=/mnt/storage/scratch/gizmo-302
# Run 2 (BUILD d6): FIX is the d6 tip; TIP is a fresh merge of it onto ONTO, set when the run is cleared.
TIP=${TIP:?set TIP to the run-2 merge sha}
FIX=5b63ea3236d82e14956594b41a00cbd7f7dc5f71
ONTO=${ONTO:?set ONTO to origin/refactor at the merge}
BR=gizmoduck/row302-gate
RED=f799e8b15561ea2c0f0735e5328ba149c7a1a7b5
BASE=0e30a85fa
OUT=/mnt/storage/scratch/gizmo-302-out/gate
PY=/mnt/storage/scratch/gizmo-302-out/mutants.py
cd "$WT" || exit 9
[ "$(git rev-parse HEAD)" = "$TIP" ] || { echo "not on the gate commit"; exit 9; }
[ -z "$(git status --porcelain --untracked-files=no)" ] || { echo "dirty"; exit 9; }
TESTS=""
while read -r blob f; do
[ "$(git rev-parse "$TIP:$f")" = "$blob" ] && [ "$(git rev-parse "$FIX:$f")" = "$blob" ] || { echo "blob mismatch $f"; exit 9; }
TESTS="$TESTS $f"
done <<'EOF'
52343932b231691ba2b4fc117547ea7f6f504704 packages/bus/tests/land.test.mjs
6fb6e15c2fd34f742f9aab718ff654ab2704e198 packages/bus/tests/launcher-released.test.mjs
27193a745c4ed8d4936de96c1768ab010a572856 packages/bus/tests/threads.test.mjs
9dfacfea15a487c4e7056ebae3e311cb514b0467 packages/cli/tests/idle-stop-race.test.mjs
0792431b60314a17ed74b3df0c5b3748dc3c1286 packages/harness/tests/runner.test.mjs
EOF
echo "blobs: the five final test blobs (d5, launcher-released from d6) match in $FIX and $TIP"
[ -L node_modules ] || ln -s /mnt/storage/src/mosaic-stack/node_modules node_modules
[ -L node_modules ] || { echo "no node_modules link"; exit 8; }
[ "$(git rev-parse $TIP^1) $(git rev-parse $TIP^2)" = "$ONTO $FIX" ] || { echo "merge parents wrong"; exit 9; }
paths=$(git diff --name-only $BASE $FIX)
[ "$(echo "$paths" | wc -l)" -eq 12 ] || { echo "row paths not 12"; exit 9; }
over=$(git diff --name-only $BASE $ONTO -- $paths)
[ -z "$over" ] || { echo "BASE..ONTO touches row paths:"; echo "$over"; exit 9; }
git diff --quiet $FIX $TIP -- $paths || { echo "merge changed a row path"; exit 9; }
echo "merge: $TIP = $FIX onto $ONTO; 12 row paths equal to $FIX, none touched in $BASE..$ONTO"
[ -e "$OUT" ] && { echo "$OUT exists; move it first"; exit 9; }
mkdir -p "$OUT/red" "$OUT/suite" "$OUT/mut"
newtmp() { export TMPDIR=$(mktemp -d /mnt/storage/scratch/tmp/gXXX); echo " TMPDIR $TMPDIR"; }
echo "TIP $TIP (merge) FIX $FIX RED $RED base $BASE onto $ONTO origin/refactor $(git rev-parse origin/refactor) start $(date -u +%FT%TZ)"; echo "loadavg: $(cat /proc/loadavg)"
T0=$SECONDS; t0=$SECONDS; lap() { echo " wall $((SECONDS - t0)) s"; t0=$SECONDS; }
counts() { grep -E '^ℹ (tests|pass|fail|cancelled|skipped|todo) ' "$1" | tr '\n' ' '; echo; }
timed() { # log dir limit args... ; sets rc
local log=$1 dir=$2 lim=$3; shift 3
newtmp
(cd "$dir" && timeout -k 10 "$lim" "$@") > "$log" 2>&1
rc=$?
if [ $rc -eq 124 ] || [ $rc -eq 137 ]; then
echo "TIMEOUT after $lim s: $(basename "$log" .log). To Sage."
case $(basename "$log") in test-*.log) echo "SHELL-PHASE TIMEOUT (mos-1275): to Mos unplaced";; esac
fi
echo "$(basename "$log" .log) rc=$rc $(counts "$log")"
}
green() { # log dir limit args... ; any red stops
timed "$@"
if [ $rc -ne 0 ]; then
echo "RED: $(basename "$1" .log), stop at $(date -u +%FT%TZ), wall $((SECONDS - T0)) s"
grep -nE '^not ok|✖|AssertionError|Error:' "$1" | head -40
exit 1
fi
}
echo "== 1. red first: $RED product with the final test files from $FIX checked out on top"
git checkout -q --detach "$RED" || exit 9
git checkout -q "$FIX" -- $TESTS || exit 9
while read -r f; do [ "$(git hash-object "$f")" = "$(git rev-parse "$FIX:$f")" ] || { echo "red tree blob wrong $f"; exit 9; }; done < <(echo $TESTS | tr ' ' '\n')
[ -z "$(git diff --name-only HEAD -- 'packages/*/src/*')" ] || exit 9
echo " red tree: product of $RED, tests of $FIX: $(git diff --cached --name-only HEAD | tr '\n' ' ')"
[ -z "$(git diff --name-only $BASE HEAD -- 'packages/*/src/*')" ] || { echo "red commit changes product files"; git checkout -q $BR; exit 9; }
timed "$OUT/red/idle-stop-race.log" "$WT/packages/cli" 600 node --test tests/idle-stop-race.test.mjs; r1=$rc
timed "$OUT/red/runner-land.log" "$WT/packages/harness" 600 node --test --test-name-pattern="^a run in a landing turn isn't released for a second held decision" tests/runner.test.mjs; r2=$rc
timed "$OUT/red/bus.log" "$WT/packages/bus" 600 node --test tests/launcher-released.test.mjs tests/threads.test.mjs tests/land.test.mjs
grep -E '✖ ' "$OUT/red/bus.log" | sort -u | sed 's/^/ /' | head -20
git reset -q --hard "$RED" && git checkout -q $BR || exit 9
[ "$(git rev-parse HEAD)" = "$TIP" ] && [ -z "$(git status --porcelain --untracked-files=no)" ] || { echo "not back on TIP clean"; exit 9; }
red_ok=1
[ $r1 -ne 0 ] && grep -qF "✖ row 302 REQ-THREAD-2 an idle-released run" "$OUT/red/idle-stop-race.log" || { echo " idle-stop-race NOT red on $RED"; red_ok=0; }
[ $r2 -ne 0 ] && grep -qF "✖ a run in a landing turn isn't released for a second held decision" "$OUT/red/runner-land.log" || { echo " runner.test land case NOT red on $RED"; red_ok=0; }
grep -nE 'AssertionError|actual|expected' "$OUT/red/idle-stop-race.log" | head -12 | sed 's/^/ /'
grep -nE 'AssertionError|actual|expected' "$OUT/red/runner-land.log" | head -8 | sed 's/^/ /'
# The four ruled pins (mos-1414/1415/1416). :772 sits after :771 in one test, so :771 stops it first;
# :771's message is out.stderr, so the log shows the old "stopped working: not-holder" line and no
# "released by the launcher" line, which is the line :772 now pins.
grep -qF "✖ REQ-THREAD-2 REQ-LAUNCH-1: threadIdle releases only a thread with nothing waiting" "$OUT/red/bus.log" || { echo " threads.test threadIdle case NOT red"; red_ok=0; }
grep -qF "✖ landRelease releases the holding run by land-relaunch" "$OUT/red/bus.log" || { echo " land.test landRelease case NOT red"; red_ok=0; }
for pin in "threads.test.mjs:394:" "land.test.mjs:464:"; do
grep -qF "$pin" "$OUT/red/bus.log" && echo " pin red at $pin" || { echo " pin $pin not in the failure stacks"; red_ok=0; }
done
grep -qF "runner.test.mjs:771:" "$OUT/red/runner-land.log" && echo " pin red at runner.test.mjs:771:" || { echo " pin runner.test.mjs:771 not in the failure stack"; red_ok=0; }
grep -qF "session stopped working: not-holder" "$OUT/red/runner-land.log" && ! grep -qF "session released by the launcher" "$OUT/red/runner-land.log" \
&& echo " :772 pattern absent from stderr (old not-holder line present)" || { echo " :772 evidence missing"; red_ok=0; }
echo " every red on $RED:"; cat "$OUT"/red/*.log | grep -E '^✖ |^ ✖ |✖ ' | sed 's/^ *//' | sort -u | sed 's/^/ /'
[ $red_ok -eq 1 ] && echo " red stage: both forcing cases and the four pins red" || { echo "STOP: red stage failed, to Sage"; exit 3; }
lap
echo "== 2. green on $TIP"
green "$OUT/suite/idle-stop-race.log" "$WT/packages/cli" 600 node --test tests/idle-stop-race.test.mjs; lap
green "$OUT/suite/runner.log" "$WT/packages/harness" 900 node --test tests/runner.test.mjs; lap
green "$OUT/suite/compactions-launch.log" "$WT/packages/cli" 600 node --test tests/compactions-launch.test.mjs; lap
green "$OUT/suite/bus.log" "$WT/packages/bus" 1200 node --test tests/*.test.mjs; lap
green "$OUT/suite/harness.log" "$WT/packages/harness" 1200 node --test tests/*.test.mjs; lap
green "$OUT/suite/cli.log" "$WT/packages/cli" 2100 node --test tests/*.test.mjs; lap
for s in "$WT"/scripts/test-*.sh; do
n=$(basename "$s" .sh)
green "$OUT/suite/$n.log" "$WT" 900 bash "$s"
tail -2 "$OUT/suite/$n.log" | sed 's/^/ /'; lap
done
[ -z "$(git status --porcelain --untracked-files=no)" ] && echo "after tests: clean" || { echo "after tests: DIRTY"; exit 1; }
echo "== skips"
grep -HE '^ℹ skipped [1-9]|^ℹ todo [1-9]' "$OUT"/suite/*.log | sed "s#$OUT/##"
grep -HiE '^(skip|# skip|SKIP)|skipped' "$OUT"/suite/test-*.log | grep -v '^ℹ' | sed "s#$OUT/##" | head -40
echo "== 3. mutants"
limit() { case $1 in *cli/*) echo 600;; *runner.test*) echo 900;; *) echo 600;; esac; }
for m in $(python3 -B "$PY" list); do
src=$(python3 -B "$PY" file "$m")
sum=$(git show "HEAD:$src" | sha256sum | cut -c1-64)
python3 -B "$PY" apply "$m" >/dev/null || { echo "$m apply-failed"; git checkout -- "$src"; exit 8; }
git diff > "$OUT/mut/$m.diff"
ok=1
for f in $(python3 -B "$PY" kills "$m" | cut -f1 | sort -u); do
pkg=${f%%/tests/*}; rel=tests/${f#*/tests/}
log="$OUT/mut/$m.$(basename "$f" .test.mjs).log"
timed "$log" "$WT/$pkg" "$(limit "$f")" node --test "$rel"
[ $rc -ne 0 ] || { echo " $m survived in $f"; ok=0; }
while IFS=$'\t' read -r kf name; do
[ "$kf" = "$f" ] || continue
grep -qF "✖ $name" "$log" && echo " killed: $name" || { echo " NOT failing: $name"; ok=0; }
done < <(python3 -B "$PY" kills "$m")
done
git checkout -- "$src"
[ "$(sha256sum "$WT/$src" | cut -c1-64)" = "$sum" ] && [ -z "$(git status --porcelain --untracked-files=no)" ] || { echo "$m restore-failed"; exit 7; }
if [ $ok -eq 1 ]; then echo "$m KILLED by rule"; else echo "STOP: $m kill rule not met, to Sage"; exit 4; fi
lap
done
echo "end $(date -u +%FT%TZ) wall $((SECONDS - T0)) s"
cd /; echo "node with cwd in the worktree: $(for p in $(pgrep -x node); do readlink /proc/$p/cwd; done 2>/dev/null | grep -c "$WT")"