#!/usr/bin/env python3 # Row 139 mutants (slot sage-0518). Each mutates one file, runs the owning suite in its own # process group (killpg on timeout), restores the file and checks its hash before the next. import hashlib, os, signal, subprocess, sys, time W = "/home/jwoltje/dewey-scratch/r139/wt" O = "/home/jwoltje/dewey-scratch/r139/out/mutants" os.makedirs(O, exist_ok=True) ENV = dict(os.environ, TMPDIR="/home/jwoltje/dewey-scratch/tmp", COMPOSE_PROJECT_NAME="dewey-r139") SUITES = {"bus": ["bash", "-c", "cd packages/bus && npm test"], "business": ["bash", "-c", "cd packages/business && npm test"]} MUTANTS = [ ("m1-no-spec-check", "packages/bus/src/broker.mjs", "(cls === 'gated' && spec !== null && !GATED.has(a.action))", "(cls === 'gated' && !GATED.has(a.action))", "bus"), ("m2-no-hard-wait-check", "packages/bus/src/broker.mjs", "(cls === 'gated' && spec !== null && !GATED.has(a.action))", "(cls === 'gated' && spec !== null)", "bus"), ("m3-new-action-not-hard-wait", "packages/bus/src/broker.mjs", "const ROUTED = new Set([\n", "const ROUTED = new Set([\n 'account.create',\n", "bus"), ("m4-hard-wait-routed", "packages/business/src/vocabulary.mjs", "export const ROUTED = Object.freeze([\n", "export const ROUTED = Object.freeze([\n \"spend\",\n", "business"), ("m5-validator-refusal", "packages/business/src/role.mjs", "if (GATED_ONLY.includes(action)) refuse(", "if (false && GATED_ONLY.includes(action)) refuse(", "business"), ] sha = lambda p: hashlib.sha256(open(p, "rb").read()).hexdigest() summary = open(os.path.join(O, "summary.txt"), "w") for name, rel, old, new, suite in MUTANTS: path = os.path.join(W, rel) orig = open(path, "rb").read() h0 = sha(path) text = orig.decode() if text.count(old) != 1: line = f"{name} SKIP anchor count {text.count(old)}" print(line); summary.write(line + "\n"); summary.flush(); sys.exit(3) open(path, "w").write(text.replace(old, new)) assert sha(path) != h0 start = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) with open(os.path.join(O, f"{name}.txt"), "w") as out: p = subprocess.Popen(SUITES[suite], cwd=W, env=ENV, stdout=out, stderr=subprocess.STDOUT, start_new_session=True) try: rc = p.wait(timeout=600) except subprocess.TimeoutExpired: os.killpg(p.pid, signal.SIGKILL); p.wait(); rc = "timeout" open(path, "wb").write(orig) restored = sha(path) == h0 end = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()) verdict = "KILLED" if rc not in (0, "timeout") else ("TIMEOUT" if rc == "timeout" else "SURVIVED") line = f"{name} {rel} suite={suite} rc={rc} {verdict} restored={restored} start={start} end={end}" print(line); summary.write(line + "\n"); summary.flush() if not restored: sys.exit(4)