Files

78 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""Mutation-test for the probe_forge refactor verifier.
Thin wrapper around the shared :func:`_mutant_scanner.run_scan` harness.
This module declares only what is specific to the probe-forge subject:
the file set, the subject module name, the verifier command, the label
column width, and the mutant transforms. The scan loop itself lives in
``_mutant_scanner.py`` and is shared with the triage scanner.
Exit 0 = every mutant killed (verifier robust).
Exit 1 = at least one mutant survived (verifier too weak).
"""
from __future__ import annotations
import sys
from _mutant_scanner import run_scan # noqa: E402
SUBJECT = "_probe_forge_refactored.py"
VERIFIER = "python3 verify_probe_forge_refactor.py"
LABEL_WIDTH = 26
SRC_FILES = [
"verify_probe_forge_refactor.py",
"_probe_forge.py",
"_probe_forge_refactored.py",
"chunker.py",
]
mutants = []
def mutant(label, fn):
mutants.append((label, fn))
mutant("guardless", lambda s: s.replace(
'if __name__ == "__main__":\n sys.exit(main())',
'main() # guard-less mutant\n'))
mutant("no_main_guard", lambda s: s.replace(
'if __name__ == "__main__":\n sys.exit(main())',
'sys.exit(main()) # no_main_guard mutant\n'))
mutant("ffd_flip", lambda s: s.replace(
"if actual[i] != expected[i]:", "if actual[i] == expected[i]:"))
mutant("ffd_return_none", lambda s: s.replace(
" return i\n", " return None # mutant\n"))
mutant("ffd_return_i_plus_1", lambda s: s.replace(
" return i\n", " return i + 1 # mutant\n"))
mutant("ffd_delete_return", lambda s: s.replace(
" return i\n", " pass # mutant\n"))
mutant("ffd_skip_index_zero", lambda s: s.replace(
"for i in range(min(len(actual), len(expected))):",
"for i in range(1, min(len(actual), len(expected))):"))
mutant("ffd_extend_range", lambda s: s.replace(
"for i in range(min(len(actual), len(expected))):",
"for i in range(min(len(actual), len(expected)) + 1):"))
mutant("ffd_always_return_none", lambda s: s.replace(
" for i in range(min(len(actual), len(expected))):\n",
" return None # mutant\n for i in range(min(len(actual), len(expected))):\n"))
mutant("hardcode_equal", lambda s: s.replace(
'print("equal:", actual == expected)', 'print("equal:", True)'))
mutant("reconstruct_overlap_zero", lambda s: s.replace(
"actual = chunker.reconstruct(cs, 8)", "actual = chunker.reconstruct(cs, 0)"))
def main() -> int:
return run_scan(SRC_FILES, SUBJECT, VERIFIER, mutants, LABEL_WIDTH)
if __name__ == "__main__":
sys.exit(main())