# Tests & Benchmarks Stand: 2026-10-07. Alles läuft mit **einem Befehl** aus dem Projektordner: ``` pwsh scripts/test.ps1 # Analyse + Unit-Tests (~1 min) – vor jedem Commit pwsh scripts/test.ps1 -Live # + Live-Test gegen steggi-matrix.work (Test-Account) pwsh scripts/test.ps1 -Bench # + Benchmarks (Datenbank/Verschlüsselung, Migration) pwsh scripts/test.ps1 -All # alles (~4 min) ``` Am Ende steht eine Zusammenfassung mit OK/FEHLER je Schritt. Fehlt die SQLCipher-Bibliothek (frischer Checkout), baut das Skript einmalig `flutter build windows --debug`. **Für Bernd in einem Satz:** Die Tests prüfen automatisch die heiklen Stellen (Login-/Logout-Schutz, Verschlüsselung der Datenbank, Suche, Einstellungen), die Benchmarks messen, ob die App dabei langsamer wird. Was man nur mit Klicken oder zwei echten Geräten prüfen kann, steht weiterhin in `docs/PC_TESTPLAN.md`. ## Tests (`test/`) | Datei | Prüft | Läuft wann | |---|---|---| | `app_database_test.dart` | SQLCipher: Bibliothek echt, Header-Erkennung, Klartext→verschlüsselt-Migration, falscher Schlüssel, Fehlschlag lässt Daten unangetastet | immer (braucht die DLL aus dem Windows-Build) | | `soft_logout_guard_test.dart` | Uta-Random-Logout-Fix: Token-Refresh-Fehler enden nie im stillen Logout | immer | | `auth_log_test.dart` | Login-Protokoll (Diagnose für Logout-Bugs) | immer | | `power_levels_safety_test.dart` | Space-Admin kann sich nicht selbst aussperren | immer | | `settings_prefs_test.dart` | VoicePrefs-Fassade (gespeicherte Spracheinstellungen) | immer | | `streaming_presets_test.dart` | 60-FPS-Streaming-Presets (Auflösung/FPS/Bitrate) | immer | | `local_message_search_test.dart` | Lokale Nachrichtensuche (Strg+K): Treffer, Sortierung, Groß-/Kleinschreibung inkl. Umlaute, Medien-Filter, Trefferdeckel | immer (neu 2026-10-07) | | `live_encryption_e2e_test.dart` | Echter Login (pyramidtest1) → Platte verschlüsselt → Neustart → Logout → Re-Login → alte Nachricht lesbar; Utas Update-Fall mit echter Session | nur mit `-Live` | | `live_call_setup_test.dart` | Kein Test im engeren Sinn: legt den Voice-Testraum für GUI-Call-Tests mit zwei Test-Accounts an | nur manuell mit `PYRAMID_LIVE_TEST=1` | `test/support/synthetic_matrix_data.dart` erzeugt synthetische Räume und Nachrichten über die **echte SDK-Speicherschicht** – komplett offline, ohne Konten. Tests und Benchmarks nutzen sie gemeinsam. Live-Tests: Zugangsdaten liegen AUSSERHALB des Repos (`%USERPROFILE%\.pyramid-autopilot\test-accounts.txt` bzw. `PYRAMID_TEST_ACCOUNTS`). Es sind die Test-Accounts `pyramidtest1/2`, nie Bernds oder Utas Konten. ## Benchmarks (`benchmark/`) Laufen bewusst NICHT im normalen `flutter test` mit (nur `-Bench` bzw. `flutter test benchmark --concurrency=1`). | Suite | Misst | |---|---| | `db_benchmark_test.dart` | Klartext- vs. SQLCipher-DB mit derselben Bibliothek: Sync-Schreiben (Transaktionen wie beim echten Sync), App-Start (DB öffnen + Raumliste), Chat öffnen (50 Nachrichten), lokale Suche (ohne Treffer = Worst Case, mit Treffern) | | `migration_benchmark_test.dart` | Dauer der einmaligen Klartext→SQLCipher-Migration beim ersten Start nach dem Update (exakt der App-Codepfad), danach Vollständigkeitsprüfung | **Wie gemessen wird:** DB im eigenen Isolate wie in der App; ungemessener Aufwärm-Durchlauf; Modi abwechselnd A-B-B-A (ohne das gewann einfach der später gemessene Modus um ±20 %, weil der Dart-JIT während des Laufs schneller wird); Median mehrerer Durchläufe. **Baseline & Regressionen:** Jeder Lauf schreibt `build/benchmarks/.json` und vergleicht mit `benchmark/baseline/.json`. Mehr als 25 % langsamer (und bei Zeiten mehr als 2 ms absolut) wird als „⚠ LANGSAMER" markiert. Umgebungsvariablen: - `-UpdateBaseline` bzw. `PYRAMID_BENCH_UPDATE_BASELINE=1` – aktuelle Werte als neue Baseline speichern (nach bewusster Änderung oder auf neuer Hardware). Die Baseline gilt nur für den Rechner, auf dem sie entstand. - `PYRAMID_BENCH_STRICT=1` – Regressionen lassen den Lauf scheitern. - `PYRAMID_BENCH_SCALE=0.2` – kleinere Datenmenge für einen schnellen Probelauf (andere Mengen sind mit der Baseline nicht vergleichbar). ### Erste Ergebnisse (2026-10-07, Bernds PC, 12 Kerne, Commit b2413ef) 20 Räume × 500 Nachrichten (DB-Suite), 20 × 1000 (Migration): | Messung | Klartext | SQLCipher | |---|---|---| | Sync-Schreiben je Nachricht | 0,25 ms | 0,26 ms | | App-Start (DB + Raumliste) | 4,1 ms | 4,3 ms | | Chat öffnen (50 Nachrichten) | 0,33 ms | 0,32 ms | | Suche ohne Treffer (10 000 Nachrichten) | 64 ms | 64 ms | | Suche mit Treffern | 32 ms | 32 ms | | Migration Klartext → SQLCipher | – | 325 ms für 7,8 MB (≈ 42 ms/MB) | Was das heißt: - **Die Verschlüsselung kostet praktisch nichts.** Alle Unterschiede liegen im Messrauschen (±5–10 %, zwei Läufe hintereinander). Die Kosten stecken im Matrix-SDK selbst (JSON-Verarbeitung), nicht in SQLCipher. - **Sync-Schreiben** liegt bei ~0,26 ms pro Nachricht und hängt kaum von der Raumgröße ab (nachgemessen: 250 vs. 4 000 Nachrichten pro Raum ≈ +15 %). - **Suche** wächst linear mit der Zahl der gespeicherten Nachrichten (gedeckelt auf 1 500 pro Raum). Hochrechnung, nicht gemessen: 100 aktive Räume am Deckel ≈ 150 000 Nachrichten ≈ 1 s pro Suche auf diesem PC – auf Handys entsprechend länger. Kandidat für einen Suchindex (FTS), falls das in der Praxis stört. - **Migration**: Hochrechnung für eine 100-MB-DB ≈ 4 s einmalig auf diesem PC; auf Utas Handy vermutlich ein Mehrfaches davon (nicht gemessen). ## Bekannte Grenzen (ehrlich) - Synthetische Daten: unverschlüsselte Räume, keine Olm/Megolm-Sessions (vodozemac läuft im Host-Test nicht). Die DB-Struktur ist aber die echte. - Gemessen auf Windows im JIT-Modus von `flutter test`; die Release-App läuft AOT-kompiliert und ist eher schneller. Für Vergleiche über die Zeit taugt das, für absolute Aussagen über Handys nicht. - Nicht automatisiert: alles mit Klicks, echte Calls/Audio, 60-FPS-Streaming zwischen zwei Geräten, Android-Push → `docs/PC_TESTPLAN.md`. ## Nächste sinnvolle Messungen - **Streaming (M4 „Ursache messen"):** WebRTC-`getStats()` des Senders auswerten (`framesPerSecond`, `qualityLimitationReason`, Encoder-Name) – zeigt direkt, ob CPU, Bandbreite oder Encoder bremst. Braucht eine kleine Diagnose-Anzeige im Call und zwei echte Geräte. - **UI-Flüssigkeit:** `integration_test` mit Frame-Timing beim Scrollen der Raumliste/Timeline (Windows, Test-Account-Profil über `PYRAMID_PROFILE_DIR`).