# -*- coding: utf-8 -*- """Test-Skript fuer aza_audit_log.py""" import os, sys, json sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__))) from pathlib import Path from aza_audit_log import ( log_event, export_audit_log, get_log_stats, _LOG_FILE, ) if _LOG_FILE.exists(): _LOG_FILE.unlink() passed = 0 failed = 0 def check(name, condition): global passed, failed if condition: print(f" PASS: {name}") passed += 1 else: print(f" FAIL: {name}") failed += 1 print("=== TEST 1: Events schreiben ===") log_event("APP_START", "test_user", detail="test") log_event("LOGIN_OK", "test_user") log_event("LOGIN_FAIL", "test_user", success=False, detail="wrong password") log_event("CONSENT_GRANT", "test_user") log_event("AI_TRANSCRIBE", "test_user") log_event("AI_CHAT", "test_user", detail="model=gpt-5.2") log_event("AI_BLOCKED", "test_user", success=False, detail="kein Consent") log_event("CONSENT_REVOKE", "test_user") log_event("2FA_OK", "test_user") log_event("2FA_FAIL", "test_user", success=False) log_event("PASSWORD_CHANGE", "test_user") log_event("APP_STOP", "test_user") check("Logdatei existiert", _LOG_FILE.exists()) print("\n=== TEST 2: Log-Inhalt pruefen ===") with open(_LOG_FILE, "r", encoding="utf-8") as f: lines = [l.strip() for l in f if l.strip()] check(f"12 Zeilen (gefunden: {len(lines)})", len(lines) == 12) line1 = lines[0] parts = [p.strip() for p in line1.split("|")] check("6 Felder pro Zeile", len(parts) == 6) check("Timestamp endet mit +00:00", "+00:00" in parts[0]) check("Event = APP_START", parts[1] == "APP_START") check("User = test_user", parts[2] == "test_user") check("Status = OK", parts[3] == "OK") check("Source = desktop", parts[4] == "desktop") line3 = lines[2] parts3 = [p.strip() for p in line3.split("|")] check("LOGIN_FAIL Status = FAIL", parts3[3] == "FAIL") print("\n=== TEST 3: Statistiken ===") stats = get_log_stats() check("Datei existiert", stats["exists"]) check(f"12 Zeilen (stats: {stats['total_lines']})", stats["total_lines"] == 12) check("APP_START in events", stats["events"].get("APP_START", 0) == 1) check("LOGIN_FAIL in events", stats["events"].get("LOGIN_FAIL", 0) == 1) check("AI_CHAT in events", stats["events"].get("AI_CHAT", 0) == 1) print("\n=== TEST 4: Export ===") path = export_audit_log() check("Export-Datei existiert", os.path.exists(path)) with open(path, "r", encoding="utf-8") as f: data = json.load(f) check(f"12 Eintraege (export: {data['total_entries']})", data["total_entries"] == 12) check("Erster Eintrag APP_START", data["entries"][0]["event"] == "APP_START") check("Letzter Eintrag APP_STOP", data["entries"][-1]["event"] == "APP_STOP") os.remove(path) print("\n=== TEST 5: Data Minimization ===") all_text = open(_LOG_FILE, "r", encoding="utf-8").read() check("Kein Passwort im Log", "password" not in all_text.lower() or "wrong password" in all_text.lower()) check("Kein API-Key im Log", "sk-" not in all_text) check("Kein Prompt im Log", "TRANSKRIPT:" not in all_text) check("Detail < 200 Zeichen", all(len(p.strip()) < 200 for line in lines for p in [line.split("|")[-1]])) print("\n=== TEST 6: Pipe-Sanitierung ===") log_event("TEST", "user", detail="detail|mit|pipes") with open(_LOG_FILE, "r", encoding="utf-8") as f: last = [l.strip() for l in f if l.strip()][-1] pipe_count = last.count("|") check(f"Pipes ersetzt (nur 5 Trennzeichen, gefunden: {pipe_count})", pipe_count == 5) # Cleanup if _LOG_FILE.exists(): _LOG_FILE.unlink() print(f"\n{'='*50}") print(f"ERGEBNIS: {passed} PASS, {failed} FAIL") if failed == 0: print("ALLE TESTS BESTANDEN") else: sys.exit(1)