48 lines
2.5 KiB
Python
48 lines
2.5 KiB
Python
#!/usr/bin/env python3
|
|
# Row 300 mutant M12 (BUILD.md "Mutant"): serve.mjs keeps the owner's send for a user session. The
|
|
# edit must match exactly once; the new file runs alone under timeout -k 10 300 with the TAP
|
|
# reporter; git checkout restores and the tree must be clean. Killed = "R6-N1" reports "not ok".
|
|
import json, os, re, subprocess, sys, time
|
|
|
|
WT = '/mnt/storage/scratch/launchpad-r300/wt'
|
|
LOG = '/mnt/storage/scratch/launchpad-r300/run1'
|
|
SWAP = "({ bus, send, settingsWrite, projectFiles, projectFile, projectSave, chat, nameWrite, assistantStop, instancesWrite, routesWrite, agentWrite, processing } = userOptions(session));"
|
|
MUTANTS = [
|
|
('M12', 'packages/webui/src/serve.mjs', SWAP,
|
|
"({ bus, settingsWrite, projectFiles, projectFile, projectSave, chat, nameWrite, assistantStop, instancesWrite, routesWrite, agentWrite, processing } = userOptions(session));",
|
|
('packages/webui', 'tests/user-option-swap.test.mjs'), 'R6-N1'),
|
|
]
|
|
|
|
def git(*a):
|
|
return subprocess.run(['git', '-C', WT, *a], capture_output=True, text=True, check=True).stdout
|
|
|
|
def main():
|
|
if git('status', '--porcelain'): raise SystemExit('worktree not clean at start')
|
|
summary, bad = [], 0
|
|
for mid, path, old, new, (pkg, test), killer in MUTANTS:
|
|
p = os.path.join(WT, path)
|
|
try:
|
|
s = open(p).read()
|
|
if s.count(old) != 1: raise SystemExit(f'{mid}: anchor count {s.count(old)} in {path}')
|
|
open(p, 'w').write(s.replace(old, new))
|
|
diff = git('diff')
|
|
t0 = time.time()
|
|
r = subprocess.run(['timeout', '-k', '10', '300', 'node', '--test', '--test-reporter=tap', test],
|
|
cwd=os.path.join(WT, pkg), capture_output=True, text=True)
|
|
dt = round(time.time() - t0, 1)
|
|
finally:
|
|
git('checkout', '--', path)
|
|
if git('status', '--porcelain'): raise SystemExit('worktree not clean after restore')
|
|
open(f'{LOG}/{mid}.diff', 'w').write(diff)
|
|
open(f'{LOG}/{mid}.tap', 'w').write(r.stdout + '\n# stderr\n' + r.stderr)
|
|
res = {m.group(2): m.group(1) == 'ok' for m in re.finditer(r'^(ok|not ok) \d+ - (.*)$', r.stdout, re.M)}
|
|
hit = [n for n in res if n.startswith(killer)]
|
|
killed = r.returncode not in (0, 124, 137) and bool(hit) and all(not res[n] for n in hit)
|
|
bad += not killed
|
|
print(f'{mid} rc={r.returncode} seconds={dt} killed={killed} red={[n for n, ok in res.items() if not ok]}', flush=True)
|
|
summary.append({'mutant': mid, 'rc': r.returncode, 'seconds': dt, 'killed': killed, 'killer': killer})
|
|
json.dump(summary, open(f'{LOG}/mutants.json', 'w'), indent=1)
|
|
sys.exit(1 if bad else 0)
|
|
|
|
main()
|