IMP-09: import-testsuite
Testsuite für Import-Scheduler, Anhangsverarbeitung und Regelwerk, inklusive Tenant-Scoping und nicht-konformer Server. - tenant_scoping_test.go (imapimport + mailrules): schließt eine echte Lücke — kein bestehender Test bewies bislang explizit, dass zwei Mandanten (identischer Postfachname bzw. fehlende eigene Regel) sich nicht gegenseitig beeinflussen. - importtestgate/gate.go: echtes, ausführbares Gate (spiegelt qagate/ QA-03) — RunTestSuites liefert realen Testabdeckungsbericht (go test -cover) je Importpfad, ScanForExternalMailboxReferences bestätigt automatisiert, dass keine Testdatei einen echten externen IMAP- Anbieter referenziert. - Echten Bug beim eigenen Testlauf gefunden und behoben: die t.Cleanup-Löschfilter in scheduler_test.go/engine_test.go waren ticket- statt paketspezifisch (mandant-imp01-%/mandant-imp03-%) — die neuen IMP-09-Tenant-Testdaten wurden nie aufgeräumt, ein zweiter Testlauf schlug real mit falschen Zählungen fehl. Auf mandant-% verallgemeinert. Prüfungen (alle real durchgeführt, siehe mail/docs/IMP-09-PRUEFPROTOKOLL.md): 1. TestRun_RealGateAgainstImportPackages: realer Abdeckungsbericht imapimport 81.5%, attachments 94.4%, mailrules 71.2%. 2. go test -count=1 zweimal hintereinander real grün (reproduzierbar nach Cleanup-Fix). 3. TestScanForExternalMailboxReferences_RealImportPackagesPass: real keine externe Postfach-Referenz in den Testsuiten. Kein Umbau der geprüften Produktionslogik. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
56d31c9176
commit
dac7854440
@@ -31,7 +31,12 @@ func setupStore(t *testing.T) *Store {
|
||||
t.Fatalf("schema: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_, _ = pool.Exec(context.Background(), `DELETE FROM mail_rules WHERE tenant_slug LIKE 'mandant-imp03-%'`)
|
||||
// LIKE-Muster bewusst paket-, nicht ticketspezifisch (mandant-%
|
||||
// statt mandant-imp03-%) — mehrere Tickets (u. a. IMP-09) fügen
|
||||
// diesem Paket über die Zeit weitere Tests mit eigenen
|
||||
// Mandanten-Präfixen hinzu; ein zu enges Muster ließ bereits real
|
||||
// Testdaten ungelöscht zurück (siehe IMP-09-Prüfprotokoll).
|
||||
_, _ = pool.Exec(context.Background(), `DELETE FROM mail_rules WHERE tenant_slug LIKE 'mandant-%'`)
|
||||
})
|
||||
return store
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// IMP-09: Tenant-Scoping-Nachweis für die Regelanwendung
|
||||
// (Akzeptanzkriterium 2). Bekannten Fehler vermeiden (known-issues-
|
||||
// archivmail.md #4): dieser Test schließt eine reale Lücke, die vor
|
||||
// IMP-09 bestand — kein bestehender Test bewies bislang explizit, dass
|
||||
// die Regeln eines Mandanten nicht auf die Nachrichten eines anderen
|
||||
// angewendet werden.
|
||||
package mailrules
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestStore_TenantScopingIsolatesRuleApplication(t *testing.T) {
|
||||
store := setupStore(t)
|
||||
ctx := context.Background()
|
||||
|
||||
tenantA := "mandant-imp09-regeln-a"
|
||||
tenantB := "mandant-imp09-regeln-b"
|
||||
|
||||
if _, err := store.Create(ctx, tenantA, Rule{Name: "a-regel", SenderPattern: "^ziel@", Category: "Kategorie-A", Priority: 10}); err != nil {
|
||||
t.Fatalf("regel mandant a anlegen: %v", err)
|
||||
}
|
||||
// Mandant B legt bewusst KEINE eigene Regel an — sein Regelset muss
|
||||
// leer bleiben, unabhängig davon, was Mandant A definiert hat.
|
||||
|
||||
rulesA, err := store.List(ctx, tenantA)
|
||||
if err != nil {
|
||||
t.Fatalf("list mandant a: %v", err)
|
||||
}
|
||||
if len(rulesA) != 1 {
|
||||
t.Fatalf("mandant a: erwartete 1 eigene regel, habe %d", len(rulesA))
|
||||
}
|
||||
|
||||
rulesB, err := store.List(ctx, tenantB)
|
||||
if err != nil {
|
||||
t.Fatalf("list mandant b: %v", err)
|
||||
}
|
||||
if len(rulesB) != 0 {
|
||||
t.Fatalf("mandant b sieht regeln von mandant a — mandantentrennung verletzt, habe: %+v", rulesB)
|
||||
}
|
||||
|
||||
engineA, err := NewEngine(rulesA)
|
||||
if err != nil {
|
||||
t.Fatalf("newengine mandant a: %v", err)
|
||||
}
|
||||
engineB, err := NewEngine(rulesB)
|
||||
if err != nil {
|
||||
t.Fatalf("newengine mandant b: %v", err)
|
||||
}
|
||||
|
||||
msg := EmailMetadata{Sender: "ziel@lieferant.example"}
|
||||
resultA := engineA.Evaluate(msg)
|
||||
resultB := engineB.Evaluate(msg)
|
||||
|
||||
if resultA.Category != "Kategorie-A" {
|
||||
t.Fatalf("mandant a: erwartete 'Kategorie-A', habe %q", resultA.Category)
|
||||
}
|
||||
if resultB.Category != "" {
|
||||
t.Fatalf("mandant b wendet fälschlich regel von mandant a an, kategorie %q", resultB.Category)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user