Unclaimed files left in the canonical checkout. Inventory: canonical-cleanup-inventory.md (commit-as-evidence groups). detect-secrets scan clean on 2026-11-02: hits are sha256 pins, git object ids, test sentinels already in tracked tests and unit-file lines.
71 lines
3.5 KiB
Bash
Executable File
71 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Row 170 (#1667) mutant driver. Slot work: run only on Sage's go.
|
|
# mutants.sh <worktree> <outdir> <manifest>
|
|
# Verifies the candidate against the manifest, runs each named test file once as a control (all must
|
|
# pass), then per mutant: back up the file, apply, run its test files, restore, re-verify the manifest.
|
|
# A mutant is killed when its test run exits non-zero and every test title the spec names for it
|
|
# failed (mutants.mjs expect). MUTANT_DRY=1 lists the plan; MUTANT_ONLY=NAME
|
|
# runs one mutant. Exit 0 only if every mutant was killed.
|
|
set -uo pipefail
|
|
WT=$(realpath -e "${1:?worktree}") || exit 2
|
|
OUT=$(realpath -m "${2:?outdir}")
|
|
MANIFEST=$(realpath -e "${3:?manifest}") || exit 2
|
|
SPEC=$(realpath -e "$(dirname "$0")/mutants.mjs") || exit 2
|
|
export TMPDIR=$HOME/dewey-scratch/tmp/r170
|
|
mkdir -p "$TMPDIR" "$OUT" || { echo "abort: cannot create $TMPDIR or $OUT"; exit 2; }
|
|
[ -d "$OUT" ] && [ -w "$OUT" ] || { echo "abort: $OUT not writable"; exit 2; }
|
|
cd "$WT" || exit 2
|
|
|
|
BACKUP=""; TARGET=""
|
|
restore() {
|
|
if [ -n "$BACKUP" ] && [ -n "$TARGET" ]; then
|
|
cp -p "$BACKUP" "$TARGET" || echo "RESTORE FAILED: $TARGET from $BACKUP"
|
|
BACKUP=""; TARGET=""
|
|
fi
|
|
sha256sum --quiet -c "$MANIFEST" || echo "MANIFEST MISMATCH after restore"
|
|
}
|
|
trap restore EXIT
|
|
|
|
sha256sum --quiet -c "$MANIFEST" || { echo "abort: candidate differs from $MANIFEST"; exit 2; }
|
|
node "$SPEC" check > "$OUT/check.txt" || { cat "$OUT/check.txt"; echo "abort: spec check failed"; exit 2; }
|
|
|
|
PLAN=$(node "$SPEC" list) || { echo "abort: spec list failed"; exit 2; }
|
|
if [ -n "${MUTANT_ONLY:-}" ]; then
|
|
PLAN=$(printf '%s\n' "$PLAN" | awk -F'\t' -v n="$MUTANT_ONLY" '$1==n')
|
|
[ -n "$PLAN" ] || { echo "abort: no mutant $MUTANT_ONLY"; exit 2; }
|
|
fi
|
|
if [ "${MUTANT_DRY:-0}" = 1 ]; then printf '%s\n' "$PLAN"; exit 0; fi
|
|
|
|
run() { # run <log> <test files...>
|
|
local log=$1; shift
|
|
setsid -w timeout -k 10 600 node --test --test-reporter=spec "$@" > "$log" 2>&1
|
|
}
|
|
|
|
# Controls: each test file the plan names, alone, on the unmutated candidate.
|
|
CONTROLS=$(printf '%s\n' "$PLAN" | cut -f3 | tr ' ' '\n' | sort -u)
|
|
for f in $CONTROLS; do
|
|
log="$OUT/control-$(echo "$f" | tr / _).log"
|
|
if run "$log" "$f"; then echo "control ok $f"; else echo "abort: control failed $f (rc $?), see $log"; exit 2; fi
|
|
done
|
|
|
|
killed=0; survived=0; timedout=0
|
|
while IFS=$'\t' read -r name file tests; do
|
|
[ -n "$name" ] || continue
|
|
TARGET="$WT/$file"; BACKUP="$OUT/$name.orig"
|
|
cp -p "$TARGET" "$BACKUP" && cmp -s "$TARGET" "$BACKUP" || { echo "abort: backup failed for $file"; BACKUP=""; TARGET=""; exit 2; }
|
|
node "$SPEC" apply "$name" || { echo "abort: apply $name failed"; exit 2; }
|
|
cmp -s "$TARGET" "$BACKUP" && { echo "abort: $name changed nothing"; exit 2; }
|
|
# shellcheck disable=SC2086
|
|
run "$OUT/$name.log" $tests; rc=$?
|
|
cp -p "$BACKUP" "$TARGET" || { echo "abort: restore failed for $file"; exit 2; }
|
|
BACKUP=""; TARGET=""
|
|
sha256sum --quiet -c "$MANIFEST" || { echo "abort: manifest mismatch after $name"; exit 2; }
|
|
if [ "$rc" -eq 124 ] || [ "$rc" -eq 137 ]; then timedout=$((timedout+1)); echo "TIMEOUT $name rc=$rc"
|
|
elif [ "$rc" -ne 0 ] && node "$SPEC" expect "$name" "$OUT/$name.log"; then killed=$((killed+1)); echo "killed $name rc=$rc"
|
|
elif [ "$rc" -ne 0 ]; then survived=$((survived+1)); echo "SURVIVED $name: rc=$rc but a named test passed"
|
|
else survived=$((survived+1)); echo "SURVIVED $name"; fi
|
|
done <<< "$PLAN"
|
|
|
|
echo "killed $killed survived $survived timeout $timedout"
|
|
[ "$survived" -eq 0 ] && [ "$timedout" -eq 0 ]
|