36 lines
2.5 KiB
Python
36 lines
2.5 KiB
Python
# mutate.py <id>: apply one named mutant (each edit exact text, must match once). Run from the tree root.
|
|
import sys
|
|
CT = "packages/conversation/src/controller.mjs"
|
|
PROOF = " if (b.state !== \"stopped\" || b.admission !== \"closed\" || !this.#stopped(s)) return refused(\"stop-proof\");\n"
|
|
RECREL = " // After every check, so a refused recover changes nothing (K6).\n await this.#releaseListed(\"recover\", this.claim);\n"
|
|
REL = " await this.#releaseListed(\"recover\", this.claim);\n"
|
|
CONF = " if (!this.#checkConfirmation(r, c, \"recover\")) return refused(\"confirmation\");\n"
|
|
TARGET = " if (session.leaf !== this.claim.record.leafAtProof || session.branch !== this.claim.record.branchAtProof) return refused(\"target\");\n"
|
|
KILL = " const kill = killEngine && this.b?.state !== \"stopped\";\n"
|
|
M = {
|
|
# Round 1's order: the release right after the stop-proof check.
|
|
"recconf": [(CT, CONF + RECREL, CONF), (CT, PROOF, PROOF + REL)],
|
|
# The release above the stop-proof check.
|
|
"recbefore": [(CT, CONF + RECREL, CONF), (CT, PROOF, REL + PROOF)],
|
|
# The release after the pins and target checks, before the confirmation.
|
|
"recpreconf": [(CT, CONF + RECREL, CONF), (CT, TARGET, TARGET + REL)],
|
|
# The release after the acquire.
|
|
"recafteracq": [(CT, CONF + RECREL, CONF), (CT, " const e = { id: newId(\"eligibility\")", REL + " const e = { id: newId(\"eligibility\")")],
|
|
"norecover": [(CT, CONF + RECREL, CONF)],
|
|
# The free-path release isn't awaited.
|
|
"startnoawait": [(CT, " await this.#releaseListed(\"start\", { claimId: h.record.claimId, record: h.record });\n", " void this.#releaseListed(\"start\", { claimId: h.record.claimId, record: h.record });\n")],
|
|
"noseat": [(CT, " for (const h of [prior, seatHead]) {\n", " for (const h of [prior]) {\n")],
|
|
"nolookup": [(CT, " if ((await this.units.lookup(claim.record)).state === \"absent\") return null;\n", "")],
|
|
"nodelete": [(CT, " if (this.scopeReleases.get(claim.claimId) === earlier) this.scopeReleases.delete(claim.claimId);\n", "")],
|
|
"closeproof": [(CT, KILL, " const kill = killEngine && !(this.b?.state === \"stopped\" && this.#stopped(this.stops.get(this.b.stop)));\n")],
|
|
"closekill": [(CT, KILL, " const kill = killEngine;\n")],
|
|
}
|
|
if "--files" in sys.argv:
|
|
print(" ".join(sorted({f for f, _, _ in M[sys.argv[1]]}))); sys.exit(0)
|
|
for f, old, new in M[sys.argv[1]]:
|
|
s = open(f).read()
|
|
n = s.count(old)
|
|
if n != 1: sys.exit(f"{sys.argv[1]}: {n} matches in {f}")
|
|
open(f, "w").write(s.replace(old, new))
|
|
print(f)
|