Assistent mit Menuefuehrung, dazu zwei Haertungen

kerio_tui.py fuehrt durch Umbenennung und Uebernahme, ohne dass man
Parameter kennen muss: Benutzer und Domains kommen zur Auswahl, verwaiste
Mailbox-Verzeichnisse findet der Assistent selbst, und vor dem Ausfuehren
zeigt er den gleichwertigen Kommandozeilenaufruf. Nur curses aus der
Standardbibliothek, keine neue Abhaengigkeit.

Beim Durchfahren ueber ein PTY kamen zwei Dinge heraus:

keypad(True) loest die Pfeiltasten auf diesem Server nicht auf - getch()
liefert 27, 91, 66 statt KEY_DOWN, wofuer ein unpassendes terminfo
genuegt. Das fuehrende ESC haette als "zurueck" gegolten und den
Assistenten bei jedem Pfeildruck verlassen. Er loest die Sequenzen jetzt
selbst auf; ein einzelnes ESC wirkt weiterhin als Abbruch.

Und: Bricht die Verbindung weg, waehrend Kerio gestoppt ist, stirbt das
Script an SIGHUP und laesst den Dienst unten - genau so passiert, als der
Testtreiber die Verbindung schloss. ServiceController.abgesichert() faengt
SIGHUP, SIGTERM und SIGINT ab und startet den Dienst wieder, bevor der
Abbruch durchgereicht wird. Gegen den Testserver geprueft: Signal mitten
im Stopp-Fenster, Dienst kommt hoch, Daten unberuehrt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
duffyduck
2026-08-07 14:54:33 +02:00
co-authored by Claude Opus 5
parent b9cbf65fac
commit 24070cba4e
5 changed files with 751 additions and 69 deletions
+65
View File
@@ -0,0 +1,65 @@
"""Testet die Logik des Assistenten, soweit sie ohne Terminal pruefbar ist."""
import sys, tempfile
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from kerio_tui import verwaiste_verzeichnisse, _befehl_text
ok = True
def check(label, cond):
global ok
print(f" {'ok ' if cond else 'FEHLER'} {label}")
if not cond:
ok = False
store = Path(tempfile.mkdtemp()) / "store"
for name in ("anna.schmidt", "bob", "alt.name", "ex.mitarbeiter",
"#public", "anna.schmidt.abgeloest-20260807-120000"):
(store / "mail" / "firma.de" / name).mkdir(parents=True)
# Mails nur im verwaisten Verzeichnis
msgs = store / "mail" / "firma.de" / "alt.name" / "INBOX" / "#msgs"
msgs.mkdir(parents=True)
for i in range(4):
(msgs / f"{i}.eml").write_text("x")
# ein Archiv-Verzeichnis ohne Gegenstueck in mail/
(store / "archive" / "firma.de" / "nur.archiv").mkdir(parents=True)
# eine zweite Domain, die nicht hineinfunken darf
(store / "mail" / "andere.de" / "fremd.user").mkdir(parents=True)
print("== Verwaiste Verzeichnisse erkennen ==")
bekannt = {"anna.schmidt", "bob"}
gefunden = verwaiste_verzeichnisse(store, "firma.de", bekannt)
check("findet 'alt.name'", "alt.name" in gefunden)
check("findet 'ex.mitarbeiter'", "ex.mitarbeiter" in gefunden)
check("findet auch reine Archiv-Verzeichnisse", "nur.archiv" in gefunden)
check("uebergeht bestehende Benutzer",
"anna.schmidt" not in gefunden and "bob" not in gefunden)
check("uebergeht Kerio-Ordner (#public)", "#public" not in gefunden)
check("uebergeht bereits abgeloeste Sicherungen",
not any(".abgeloest-" in g for g in gefunden))
check("greift nicht in andere Domains", "fremd.user" not in gefunden)
check("keine Doppelten", len(gefunden) == len(set(gefunden)))
print("\n== Gross-/Kleinschreibung ==")
gefunden2 = verwaiste_verzeichnisse(store, "FIRMA.DE", {"ANNA.SCHMIDT", "bob"})
check("Domain unabhaengig von Schreibweise", "alt.name" in gefunden2)
check("bekannte Logins unabhaengig von Schreibweise",
"anna.schmidt" not in gefunden2)
print("\n== Domain ohne Store-Verzeichnis ==")
check("liefert leere Liste statt Fehler",
verwaiste_verzeichnisse(store, "gibtsnicht.de", set()) == [])
print("\n== Befehlszeile fuer die Anzeige ==")
text = _befehl_text(["--domain", "firma.de", "--old-login", "alt.name",
"--new-login", "neu.name", "--full-name", "Neue Person"])
check("beginnt mit dem Scriptnamen", text.startswith("sudo ./kerio_rename_user.py"))
check("Namen mit Leerzeichen werden gequotet", '"Neue Person"' in text)
check("Namen ohne Leerzeichen bleiben blank", " firma.de " in text)
print("\n" + ("ALLE TESTS BESTANDEN" if ok else "FEHLGESCHLAGEN"))
sys.exit(0 if ok else 1)