Files
OPNexus/backend/tests/mutation_check.py
T
Julian Boldt 5cb2ebe1c6
Release / verify (push) Canceled after 0s
CI / checks (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / backend (push) Canceled after 0s
Release / test (push) Canceled after 0s
Release / publish (backend) (push) Canceled after 0s
Release / publish (frontend) (push) Canceled after 0s
Release / publish (proxy) (push) Canceled after 0s
Release / publish (updater) (push) Canceled after 0s
Release v1.27.0
Vorgesehen als MINOR-Release **1.27.0** „Firewall-Oberfläche über OPNexus“.

- **Firewall-Oberfläche über OPNexus:** Auf der Host-Seite öffnet **Oberfläche öffnen** die Weboberfläche der Firewall
  in einem neuen Tab, auch bei Firewalls hinter NAT im Management-Tunnel. Nur für Admins; jede Firewall läuft in einer
  eigenen Browser-Origin (Platz = Port), Cookies bleiben auf dem Server, das Ticket gilt einmalig 30 Sekunden,
  Inaktivitäts- und Gesamtlimit sind einstellbar, Ticket, Start und Ende stehen im Audit (Art „GUI-Zugriff“).
  Standardmäßig **aus**: braucht das Compose-Profil `gui`, `OPNEXUS_GUI_SITES`, `GUI_PORTS`, `GUI_GATEWAY_TOKEN`,
  `COOKIE_SECURE=true` und den Schalter unter Einstellungen (Handbuch, „Firewall-Oberfläche über OPNexus“).
  Live getestet auf OPNsense 26.7.
- **Einschränkungen:** kein WebSocket, keine automatische Anmeldung, höchstens 4 Plätze gleichzeitig. OPNexus-Adresse
  vorher in die Whitelist des Anmeldeschutzes (sshguard) der Firewall eintragen, sonst können Fehlanmeldungen die
  API-Zugriffe von OPNexus aussperren. Nach einem Neustart des wg-hub braucht der Tunnel 2 bis 4 Minuten.
- **Hinweis für Betreiber mit eigenen Skripten:** Bei HTTPS heißt das Sitzungs-Cookie jetzt `__Host-opnexus-session`
  (bestehende Sitzungen werden ohne Abmelden übernommen), und Cookie-Anfragen an `/api` mit `Sec-Fetch-Site: same-site/cross-site`
  werden abgelehnt. Zugriffe mit API-Token sind nicht betroffen.
2026-10-21 20:14:06 +02:00

40 lines
1.4 KiB
Python

"""Mutation check helper (run manually, not collected by pytest).
python tests/mutation_check.py tests/mutations_gui.json
Each mutation: {"file": ..., "old": ..., "new": ..., "tests": "pytest selection"}.
The file is patched, the selected tests must FAIL, then the file is restored.
"""
import json
import subprocess
import sys
from pathlib import Path
def main(spec_path: str) -> int:
mutations = json.loads(Path(spec_path).read_text())
survivors = []
for i, m in enumerate(mutations, 1):
path = Path(m["file"])
original = path.read_text()
if original.count(m["old"]) != 1:
print(f"[{i}] SKIP (anchor not unique/found): {m['file']}: {m['old'][:60]!r}")
survivors.append(m)
continue
try:
path.write_text(original.replace(m["old"], m["new"]))
result = subprocess.run([sys.executable, "-m", "pytest", "-q", "-x", "-p", "no:cacheprovider", *m["tests"].split()],
capture_output=True, text=True)
finally:
path.write_text(original)
killed = result.returncode != 0
print(f"[{i}] {'KILLED ' if killed else 'SURVIVED'} {m.get('name', m['old'][:50])}")
if not killed:
survivors.append(m)
print(f"{len(mutations) - len(survivors)}/{len(mutations)} mutations killed")
return 1 if survivors else 0
if __name__ == "__main__":
sys.exit(main(sys.argv[1]))