Mutantenstufe der Plankritik nach der Pruefung vom 2026-09-28: Netzsperre per unshare, ungepufferte Ausgabe, Zeitlimit je Mutant 120 s, Aufraeumen bei SIGTERM, Modus-Zeile, mutanten_status, Faelle und Treiberfall 35
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
bc9b4f4497
commit
b1ad461acf
8 files changed
+336
-49
No files matched your search
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Treiber fuer mutanten_lauf.py: 34 Angriffsfaelle auf einer Wegwerfkopie.
|
||||
"""Treiber fuer mutanten_lauf.py: 35 Angriffsfaelle auf einer Wegwerfkopie.
|
||||
|
||||
Zweck: Baut in einem Temp-Ordner unter /tmp ein kleines Testprojekt, fuehrt
|
||||
mutanten_lauf.py je Fall mit einer eigenen mutanten.toml aus und vergleicht
|
||||
@@ -11,14 +11,21 @@ Aufruf: python mutanten_lauf_treiber.py
|
||||
Baut nichts ausserhalb von /tmp, geht nicht ins Netz, raeumt am Ende auf.
|
||||
|
||||
Spezifikation: .vault-tools/plan-kopie/mutanten_lauf_ENTWURF.md, Abschnitt 6.
|
||||
|
||||
Fall 35 (Nachbesserung 2026-09-28, N11) prueft das Aufraeumen bei SIGTERM: Ein
|
||||
Mutant haengt, der Laeufer bekommt nach wenigen Sekunden selbst ein SIGTERM.
|
||||
Damit die Pruefung nur die Reste dieses einen Falls sieht, bekommt der Laeufer
|
||||
dafuer ein eigenes TMPDIR (tempfile respektiert die Umgebungsvariable).
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
HIER = Path(__file__).resolve().parent
|
||||
@@ -930,11 +937,84 @@ def fall_34(basis, projektpfad):
|
||||
shutil.rmtree(alt_python_dir, ignore_errors=True)
|
||||
|
||||
|
||||
def fall_35(basis, projektpfad):
|
||||
# N11: Ein Mutant haengt (Endlosschleife), der Laeufer selbst bekommt nach wenigen
|
||||
# Sekunden SIGTERM. Erwartet: der Laeufer raeumt auf und meldet ABBRUCH: SIGTERM,
|
||||
# kein pytest-Prozess dieses Falls bleibt am Leben, keine Temp-Reste bleiben liegen,
|
||||
# und die Zieldatei ist danach byte-gleich mit dem Ausgangsstand (generisch geprueft
|
||||
# durch pruefe_unveraendert im main()).
|
||||
toml = projektpfad / "mutanten_35.toml"
|
||||
schreibe_toml(toml, (
|
||||
kopf() +
|
||||
"[[mutant]]\n"
|
||||
"id = \"M35\"\n"
|
||||
"datei = \"paket/modul_zeit.py\"\n"
|
||||
"aus = '''\n"
|
||||
" return n + 1\n"
|
||||
"'''\n"
|
||||
"wird = '''\n"
|
||||
" while True:\n"
|
||||
" pass\n"
|
||||
"'''\n"
|
||||
"rot_bei = [\"tests/test_zeit.py::test_f7\"]\n"
|
||||
))
|
||||
|
||||
eigenes_tmpdir = Path(tempfile.mkdtemp(prefix="mutanten_lauf_fall35_tmpdir_"))
|
||||
env = os.environ.copy()
|
||||
env["TMPDIR"] = str(eigenes_tmpdir)
|
||||
cmd = [INTERPRETER, str(LAEUFER), "--wurzel", str(basis), "--mutanten", str(toml), "--zeitlimit", "60"]
|
||||
ok = True
|
||||
zusatz = ""
|
||||
try:
|
||||
proc = subprocess.Popen(cmd, cwd=str(basis), env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
time.sleep(3)
|
||||
proc.send_signal(signal.SIGTERM)
|
||||
try:
|
||||
stdout, _ = proc.communicate(timeout=30)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.kill()
|
||||
stdout, _ = proc.communicate()
|
||||
ok = False
|
||||
zusatz += "Laeufer endete nicht nach SIGTERM; "
|
||||
|
||||
if "ABBRUCH: SIGTERM" not in stdout:
|
||||
ok = False
|
||||
zusatz += "keine ABBRUCH-Zeile; "
|
||||
|
||||
# kein Prozess dieses Falls lebt danach: Sein HOME liegt unter eigenes_tmpdir,
|
||||
# und diese Umgebungsvariable geht an den pytest-Unterprozess mit.
|
||||
uebrige_pids = []
|
||||
for envdatei in Path("/proc").glob("[0-9]*/environ"):
|
||||
try:
|
||||
inhalt = envdatei.read_bytes()
|
||||
except OSError:
|
||||
continue
|
||||
if str(eigenes_tmpdir).encode() in inhalt:
|
||||
uebrige_pids.append(envdatei.parent.name)
|
||||
if uebrige_pids:
|
||||
ok = False
|
||||
zusatz += "Prozesse mit HOME im Fall-Tmpdir noch da: {0}; ".format(uebrige_pids)
|
||||
|
||||
# keine Temp-Ordner und keine Ergebnisdatei aus diesem Lauf
|
||||
uebrige_ordner = (
|
||||
list(eigenes_tmpdir.glob("mutanten_lauf_home_*"))
|
||||
+ list(eigenes_tmpdir.glob("mutanten_lauf_plugin_*"))
|
||||
+ list(eigenes_tmpdir.glob("mutanten_lauf_ergebnis_*"))
|
||||
)
|
||||
if uebrige_ordner:
|
||||
ok = False
|
||||
zusatz += "Temp-Reste: {0}; ".format(uebrige_ordner)
|
||||
|
||||
melde("Fall 35", ok, zusatz + "stdout(Ende)={0}".format(stdout[-500:]))
|
||||
finally:
|
||||
shutil.rmtree(eigenes_tmpdir, ignore_errors=True)
|
||||
|
||||
|
||||
FAELLE = [
|
||||
fall_01, fall_02, fall_03, fall_04, fall_05, fall_06, fall_07, fall_08, fall_09, fall_10,
|
||||
fall_11, fall_12, fall_13, fall_14, fall_15, fall_16, fall_17, fall_18, fall_19, fall_20,
|
||||
fall_21, fall_22, fall_23, fall_24, fall_25, fall_26, fall_27, fall_28, fall_29, fall_30,
|
||||
fall_31, fall_32, fall_33, fall_34,
|
||||
fall_31, fall_32, fall_33, fall_34, fall_35,
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user