Candidate on 686fc1cb6: candidate-manifest.sha256 cb831847...78ed, 2 test files, +44.
Mutants 4/4 killed; owner's gate rc 0 (bus 265, cli 213, every scripts/test-*.sh).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
44 lines
2.5 KiB
Python
44 lines
2.5 KiB
Python
import subprocess, sys, os, signal
|
|
# Row 151 (#1645): one mutant per pinned path. Each applies to its source in the worktree, runs the
|
|
# owning test file, and the source is restored after every mutant.
|
|
W=os.path.expanduser('~/dewey-scratch/r151/wt')
|
|
OUT=os.path.expanduser('~/dewey-scratch/r151/mut')
|
|
os.makedirs(OUT, exist_ok=True)
|
|
BROKER='packages/bus/src/broker.mjs'
|
|
CLI='packages/cli/src/cli.mjs'
|
|
LOOP=' for (const m of await call("message.receive")) {\n'
|
|
M={
|
|
# Filbert's row 146 M1: the notice is routed to the target instead of launch.by.
|
|
'B1-notice-routed-to-target': (BROKER, 'packages/bus', 'tests/launch-notice.test.mjs',
|
|
'this.#route(business, nid, by, null);', 'this.#route(business, nid, to, null);'),
|
|
# Row 142's reply filter is dropped: talk prints and reads every message.
|
|
'C1-no-reply-filter': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
|
' if (!follow && m.in_reply_to !== sent.id) continue;\n', ''),
|
|
# Row 146's waitingLines write is dropped.
|
|
'C2-no-waiting-lines': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
|
' if (sent.waiting) io.stdout.write(', ' if (false) io.stdout.write('),
|
|
# The waiting line is printed again on every receive poll instead of once.
|
|
'C3-waiting-every-poll': (CLI, 'packages/cli', 'tests/verbs.test.mjs',
|
|
LOOP, ' if (sent?.waiting) io.stdout.write(waitingLines(sent.waiting, () => "demo"));\n' + LOOP),
|
|
}
|
|
env=dict(os.environ, TMPDIR=os.path.expanduser('~/dewey-scratch/tmp'))
|
|
origs={p: open(os.path.join(W,p)).read() for p in (BROKER, CLI)}
|
|
try:
|
|
for name,(path,pkg,test,a,b) in M.items():
|
|
orig=origs[path]
|
|
assert orig.count(a)==1, name
|
|
open(os.path.join(W,path),'w').write(orig.replace(a,b))
|
|
p=subprocess.Popen(['node','--test','--test-reporter=spec',test],cwd=os.path.join(W,pkg),env=env,
|
|
stdout=subprocess.PIPE,stderr=subprocess.STDOUT,text=True,start_new_session=True)
|
|
try:
|
|
out,_=p.communicate(timeout=300)
|
|
except subprocess.TimeoutExpired:
|
|
os.killpg(p.pid, signal.SIGKILL); out,_=p.communicate(); out+='\nTIMEOUT\n'
|
|
fails=sorted({l.strip()[2:].split(' (')[0] for l in out.splitlines() if l.lstrip().startswith('✖') and 'failing tests' not in l})
|
|
print(name, 'KILLED' if p.returncode!=0 else 'SURVIVED', 'rc=%d'%p.returncode, '| '+' | '.join(fails))
|
|
open(os.path.join(OUT,f'{name}.log'),'w').write(out)
|
|
open(os.path.join(W,path),'w').write(orig)
|
|
finally:
|
|
for path,orig in origs.items(): open(os.path.join(W,path),'w').write(orig)
|
|
print('restored', all(open(os.path.join(W,p)).read()==o for p,o in origs.items()))
|