Files
stack/agents/darkwing/work/queue-103/mutants.sh
T

79 lines
5.4 KiB
Bash
Raw 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.
#!/usr/bin/env bash
# Row 103 (#1597) mutants. Run from the candidate worktree's root:
# LOG=<dir> bash mutants.sh <queue-103 dir> > mutants.txt
# Each mutant edits one site with mut.mjs (exactly one match, else exit 3),
# runs the named test files (DRY=1 only checks the match) in their own
# process group (run.py, killed after 240 s) and restores the file. "killed"
# means the run failed; "survived" means it passed.
set -u
Q=$1
run() {
local name=$1 file=$2 from=$3 to=$4; shift 4
cp -- "$file" "$file.orig"
if ! node "$Q/mut.mjs" "$file" "$from" "$to"; then
echo "$name: NO MATCH"; mv -- "$file.orig" "$file"; return
fi
if [ -n "${DRY:-}" ]; then echo "$name: match"; mv -- "$file.orig" "$file"; return; fi
local log="${LOG:-.}/mut-$name.log"
if python3 "$Q/run.py" 240 "$log" node --test "$@"; then
echo "$name: survived"
else
echo "$name: killed ($(grep -m1 -o 'ℹ fail [0-9]*' "$log"; grep -m1 -o 'TIMEOUT.*' "$log"), $(grep -m1 '^✖' "$log" | cut -c1-90))"
fi
mv -- "$file.orig" "$file"
}
CO=packages/seat/src/checkout.mjs
GTL=packages/harness/src/git-tools.mjs
GS=packages/cli/src/git-socket.mjs
HM=packages/cli/src/host.mjs
CT=packages/seat/tests/checkout.test.mjs
HT=packages/harness/tests/git-tools.test.mjs
GT=packages/cli/tests/git-socket.test.mjs
HOT=packages/cli/tests/host.test.mjs
TERM_THEN_KILL=$' group("SIGTERM");\n kill = setTimeout(() => group("SIGKILL"), limits.graceMs);'
ESCALATE=$' kill = setTimeout(() => group("SIGKILL"), limits.graceMs);\n'
# Host git (checkout.mjs runGit, which working.mjs uses too): SIGTERM, the
# grace period, SIGKILL, all to git's process group, and the sweep.
run co-sigkill-first $CO "$TERM_THEN_KILL" ' group("SIGKILL");' $CT
run co-no-escalation $CO "$ESCALATE" '' $CT
run co-not-detached $CO 'spawn("git", argv, { env, detached: true,' 'spawn("git", argv, { env, detached: false,' $CT
run co-pid-not-group $CO 'process.kill(-child.pid, signal);' 'process.kill(child.pid, signal);' $CT
run co-no-sweep $CO ' if (signalled) group("SIGKILL");' '' $CT
# Runner git (git-tools.mjs): the same sequence.
run gt-sigkill-first $GTL "$TERM_THEN_KILL" ' group("SIGKILL");' $HT
run gt-no-escalation $GTL "$ESCALATE" '' $HT
run gt-not-detached $GTL ' detached: true,' ' detached: false,' $HT
run gt-pid-not-group $GTL 'process.kill(-child.pid, signal);' 'process.kill(child.pid, signal);' $HT
run gt-no-sweep $GTL ' if (signalled) group("SIGKILL");' '' $HT
# have: working refs first, newest first within a clone, at most HAVE_MAX.
run have-origin-first $GTL 'for (const remote of ["refs/remotes/working", "refs/remotes/origin"])' 'for (const remote of ["refs/remotes/origin", "refs/remotes/working"])' $HT
run have-oldest-first $GTL '"--sort=-committerdate"' '"--sort=committerdate"' $HT
run have-uncapped $GTL 'if (OID.test(oid) && have.size < HAVE_MAX) have.add(oid);' 'if (OID.test(oid)) have.add(oid);' $HT
# close(): the cap on the wait for told sockets, then destroy.
run letgo-no-cap $GS 'const capped = new Promise((r) => (timer = setTimeout(r, ms)));' 'const capped = new Promise(() => {});' $GT
run letgo-no-destroy $GS ' for (const s of sockets) s.destroy();' '' $GT
# Expected to survive: a told socket on a real unix socket flushes its few
# bytes whether or not the peer reads (build.md).
run close-skips-letgo $GS ' await letGo([...told]);' '' $GT
# send()'s post-loop arm, and a failed write anywhere.
run postloop-always-served $GS $' if (socket.destroyed) {\n if (served()) return;\n throw aborted();\n }' ' if (socket.destroyed) return;' $GT
run postloop-always-aborted $GS $' if (socket.destroyed) {\n if (served()) return;\n throw aborted();\n }' ' if (socket.destroyed) throw aborted();' $GT
run errored-ignored $GS 'const served = () => !socket.errored;' 'const served = () => true;' $GT
# The idle limit on bundle bytes.
run no-idle $GS ' socket.setTimeout(idleMs);' ' socket.setTimeout(0);' $GT
# host.lock: an atomic claim, the live check, the identity check on the
# moved-aside file, the release on each boot failure and on close, the lock
# kept apart from host.json, and the check for a host that holds only host.json.
run claim-rename $HM ' linkSync(tmp, file);' ' renameSync(tmp, file);' $HOT
run claim-no-live-check $HM ' if (prior.live) throw' ' if (false) throw' $HOT
run claim-dead-blocks $HM ' if (prior.live) throw' ' if (prior) throw' $HOT
run claim-no-identity-check $HM ' if (!same(readState(aside), prior)) {' ' if (false) {' $HOT
run claim-no-release $HM $' if (same(held, state)) rmSync(hostLock(dataRoot), { force: true });' '' $HOT
run release-boot-timeout $HM $' await ended(broker, 5000);\n release();\n throw e;' $' await ended(broker, 5000);\n throw e;' $HOT
run release-broker-refused $HM $' release();\n throw new CliError(`broker refused' $' throw new CliError(`broker refused' $HOT
run release-notifier-dies $HM $' release();\n throw e;' ' throw e;' $HOT
run release-notifier-refused $HM $' release();\n throw new CliError(`notifier refused' $' throw new CliError(`notifier refused' $HOT
run release-on-close $HM $' release();\n finish(result);' ' finish(result);' $HOT
run lock-is-host-json $HM 'join(hostDir(dataRoot), "host.lock")' 'join(hostDir(dataRoot), "host.json")' $HOT
run no-host-json-check $HM ' if (prior?.live) throw new CliError(' ' if (false) throw new CliError(' $HOT