Mutation check done on all accepted tasks; mutant fixes; dump filter in proxy
- skip sy-subrc lines and CDS type lengths; CDS literal mutants; mutate helper classes - proxy: sap_short_dumps shows only dumps of the current run - 26/26 tasks pass; results in docs/faz1-tasarim.md 11g Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014aUaQeLnwbb1zTpN7kHeat
This commit is contained in:
@@ -115,10 +115,21 @@ def mutants(src, otype, seed, n=MAX_MUTANTS):
|
||||
continue
|
||||
if kind == "arith" and re.search(r"(\(|\bSELECT)\s*$", src[line_start:x.start()], re.I):
|
||||
continue # COUNT( * ), SELECT *
|
||||
if _skip_line(line) or (kind == "const" and re.search(r"\bLENGTH\b|\bDECIMALS\b|\(\s*\d+\s*,", line, re.I)):
|
||||
if re.search(r"\bsy-subrc\b|\bsy-tabix\b", line, re.I):
|
||||
continue # mostly gives a short dump (unassigned field symbol), not a behavior change
|
||||
if _skip_line(line) or (kind == "const" and (re.search(r"\bLENGTH\b|\bDECIMALS\b|\(\s*\d+\s*,", line, re.I)
|
||||
or re.search(r"abap\.\w+\(\s*[\d\s,]*$", src[line_start:x.start()], re.I))):
|
||||
continue
|
||||
new = str(int(x.group(1)) + 1) if rep is None else rep
|
||||
sites.append((kind, x.start(), x.end(), new, src.count("\n", 0, x.start()) + 1, x.group(0)))
|
||||
if cds: # literal values in the select list (G0025: source 'A' / 'B' was the only logic)
|
||||
for x in re.finditer(r"'([^'\n]{1,20})'", src):
|
||||
line_start = src.rfind("\n", 0, x.start()) + 1
|
||||
if not lo <= x.start() < hi or src[line_start:x.start()].lstrip().startswith(("@", "//")):
|
||||
continue
|
||||
v = x.group(1)
|
||||
new = "'" + ("Z" if v[0] != "Z" else "Y") + v[1:] + "'"
|
||||
sites.append(("lit", x.start(), x.end(), new, src.count("\n", 0, x.start()) + 1, x.group(0)))
|
||||
rnd = random.Random(seed)
|
||||
rnd.shuffle(sites)
|
||||
chosen, kinds, lines = [], set(), set()
|
||||
@@ -141,9 +152,12 @@ def check_task(pool_root, task_id, run_base, n=MAX_MUTANTS, keep=False):
|
||||
"""Run the mutants of one task. Returns a summary dict; writes it to <task>/mutation.json."""
|
||||
task_dir = os.path.join(pool_root, task_id)
|
||||
meta = json.load(open(os.path.join(task_dir, "task.json")))
|
||||
contract = {c["name"].upper() for c in meta["contract"]}
|
||||
targets = [o for o in meta["reference"] if o["name"].upper() in contract and o.get("file")
|
||||
and o["type"] in ("CLAS", "FUNC", "PROG", "DDLS")]
|
||||
# every reference object except test classes: the logic can sit in a helper (G0026: FM calls a class)
|
||||
def is_test(o):
|
||||
return o["type"] == "CLAS" and re.search(r"^\s*CLASS\s+\S+\s+DEFINITION[^.]*FOR\s+TESTING",
|
||||
open(os.path.join(task_dir, o["file"])).read(), re.I | re.M)
|
||||
targets = [o for o in meta["reference"] if o.get("file") and o["type"] in ("CLAS", "FUNC", "PROG", "DDLS")
|
||||
and not is_test(o)]
|
||||
work = os.path.join(ROOT, "runs", "gen", "mut")
|
||||
os.makedirs(work, exist_ok=True)
|
||||
runner = Runner(os.path.join(work, "pool"), os.path.join(work, "runs"))
|
||||
|
||||
Reference in New Issue
Block a user