# Row 146 (#1640) mutants: one per new check. Each is applied to the worktree's source, the test # files that cover row 146 run per package, and the source is restored afterwards. import subprocess, os W = os.path.expanduser('~/dewey-scratch/r146/wt') OUT = os.path.expanduser('~/dewey-scratch/r146/mut') os.makedirs(OUT, exist_ok=True) BROKER = 'packages/bus/src/broker.mjs' CLI = 'packages/cli/src/cli.mjs' M = { 'B1-recipient': (BROKER, " if (this.#recipient(s.business, to, thread)) return null;\n", ""), 'B2-to-human': (BROKER, "if (to === 'human' || to === 'tester' ||", "if (to === 'tester' ||"), 'B3-to-tester': (BROKER, "if (to === 'human' || to === 'tester' ||", "if (to === 'human' ||"), 'B4-thread-instance': (BROKER, " || (thread && this.#threaded(s.business, to))) return null;", ") return null;"), 'B5-to-launcher': (BROKER, "by !== null && to !== by && sender", "by !== null && sender"), 'B6-from-launcher': (BROKER, " && sender !== by && sender !== 'tester';", " && sender !== 'tester';"), 'B7-from-tester': (BROKER, " && sender !== 'tester';", ";"), 'B8-no-launcher': (BROKER, "const told = by !== null && ", "const told = "), 'B9-notice-sent': (BROKER, "if (told) this.#notice(", "if (false) this.#notice("), 'B10-class-result': (BROKER, " 'RESULT',\n mid,\n", " 'INFO',\n mid,\n"), 'B11-launcher-running': (BROKER, "launcherRunning: by === null ? null : this.#recipient(s.business, by, null) !== null", "launcherRunning: by === null ? null : false"), 'B12-result-waiting': (BROKER, "return waiting ? { id: mid, request, waiting } : { id: mid, request };", "return { id: mid, request };"), 'C1-printed': (CLI, " if (sent.waiting) io.stdout.write(", " if (false) io.stdout.write("), 'C2-no-launch-by': (CLI, " if (w.launcher === null) return", " if (false) return"), 'C3-launcher-down-self': (CLI, " if (w.role === w.launcher) return restart(w.role);\n", ""), 'C4-tester-line': (CLI, " if (!w.told) return", " if (false) return"), 'C5-launcher-down-either': (CLI, '(w.launcherRunning ? "" : restart(w.launcher, " either"))', '""'), } FILES = [ ('packages/bus', ['tests/launch-notice.test.mjs']), ('packages/harness', ['tests/runner.test.mjs']), ('packages/cli', ['tests/verbs.test.mjs', 'tests/tester.test.mjs']), ] env = dict(os.environ, TMPDIR=os.path.expanduser('~/dewey-scratch/tmp')) origs = {f: open(os.path.join(W, f)).read() for f in (BROKER, CLI)} try: for name, (f, a, b) in M.items(): assert origs[f].count(a) == 1, name open(os.path.join(W, f), 'w').write(origs[f].replace(a, b)) killed, log = [], '' for pkg, tests in FILES: r = subprocess.run(['node', '--test', *tests], cwd=os.path.join(W, pkg), env=env, capture_output=True, text=True, timeout=300) log += f'== {pkg} rc={r.returncode}\n' + r.stdout + r.stderr fails = sorted({l[2:].split(' (')[0] for l in r.stdout.splitlines() if l.startswith('✖ ') and 'failing tests' not in l}) if r.returncode != 0: killed.append(f'{pkg.split("/")[1]}: ' + '; '.join(fails)) open(os.path.join(W, f), 'w').write(origs[f]) open(os.path.join(OUT, f'{name}.log'), 'w').write(log) print(name, 'KILLED' if killed else 'SURVIVED', '|', ' | '.join(killed)[:600], flush=True) finally: for f, s in origs.items(): open(os.path.join(W, f), 'w').write(s) print('restored', all(open(os.path.join(W, f)).read() == s for f, s in origs.items()))