106 lines
3.0 KiB
Go
106 lines
3.0 KiB
Go
package rules
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestPipeline_NoRules_Accepts(t *testing.T) {
|
|
p := NewPipeline(nil)
|
|
result := p.Evaluate(EmailContext{Sender: "anyone@test.com"})
|
|
if !result.Accepted {
|
|
t.Fatal("expected accept with no rules")
|
|
}
|
|
}
|
|
|
|
func TestPipeline_AllRulesAccept_Accepts(t *testing.T) {
|
|
allowAll := &stubRule{name: "allow-all", result: Accept()}
|
|
p := NewPipeline([]Rule{allowAll})
|
|
result := p.Evaluate(EmailContext{Sender: "a@b.com"})
|
|
if !result.Accepted {
|
|
t.Fatal("expected accept")
|
|
}
|
|
}
|
|
|
|
func TestPipeline_OneRuleRejects_Rejects(t *testing.T) {
|
|
rejector := &stubRule{name: "rejector", result: Reject("nope")}
|
|
p := NewPipeline([]Rule{rejector})
|
|
result := p.Evaluate(EmailContext{Sender: "a@b.com"})
|
|
if result.Accepted {
|
|
t.Fatal("expected reject")
|
|
}
|
|
if result.Reason != "nope" {
|
|
t.Fatalf("expected reason 'nope', got %s", result.Reason)
|
|
}
|
|
}
|
|
|
|
func TestPipeline_MergesMetadata(t *testing.T) {
|
|
r1 := &stubRule{name: "r1", result: Accept().WithMetadata("a", "1")}
|
|
r2 := &stubRule{name: "r2", result: Accept().WithMetadata("b", "2")}
|
|
p := NewPipeline([]Rule{r1, r2})
|
|
result := p.Evaluate(EmailContext{})
|
|
if result.Metadata["a"] != "1" {
|
|
t.Fatal("missing metadata a")
|
|
}
|
|
if result.Metadata["b"] != "2" {
|
|
t.Fatal("missing metadata b")
|
|
}
|
|
}
|
|
|
|
func TestPipeline_StopsOnFirstReject(t *testing.T) {
|
|
rejector := &stubRule{name: "rejector", result: Reject("stop")}
|
|
neverCalled := &trackingRule{}
|
|
p := NewPipeline([]Rule{rejector, neverCalled})
|
|
p.Evaluate(EmailContext{})
|
|
if neverCalled.called {
|
|
t.Fatal("expected second rule not to be called after rejection")
|
|
}
|
|
}
|
|
|
|
func TestWhitelistRule_EmptyList_Accepts(t *testing.T) {
|
|
r := NewWhitelistRule(nil)
|
|
result := r.Evaluate(EmailContext{Sender: "anyone@test.com"})
|
|
if !result.Accepted {
|
|
t.Fatal("empty whitelist should accept all")
|
|
}
|
|
}
|
|
|
|
func TestWhitelistRule_SenderInList_Accepts(t *testing.T) {
|
|
r := NewWhitelistRule([]string{"allowed@test.com"})
|
|
result := r.Evaluate(EmailContext{Sender: "allowed@test.com"})
|
|
if !result.Accepted {
|
|
t.Fatal("expected accept for whitelisted sender")
|
|
}
|
|
}
|
|
|
|
func TestWhitelistRule_SenderNotInList_Rejects(t *testing.T) {
|
|
r := NewWhitelistRule([]string{"allowed@test.com"})
|
|
result := r.Evaluate(EmailContext{Sender: "unknown@test.com"})
|
|
if result.Accepted {
|
|
t.Fatal("expected reject for non-whitelisted sender")
|
|
}
|
|
}
|
|
|
|
func TestWhitelistRule_CaseInsensitive(t *testing.T) {
|
|
r := NewWhitelistRule([]string{"Allowed@Test.com"})
|
|
result := r.Evaluate(EmailContext{Sender: "allowed@test.com"})
|
|
if !result.Accepted {
|
|
t.Fatal("whitelist should be case-insensitive")
|
|
}
|
|
}
|
|
|
|
// stubs
|
|
|
|
type stubRule struct {
|
|
name string
|
|
result RuleResult
|
|
}
|
|
|
|
func (s *stubRule) Name() string { return s.name }
|
|
func (s *stubRule) Evaluate(_ EmailContext) RuleResult { return s.result }
|
|
|
|
type trackingRule struct {
|
|
called bool
|
|
}
|
|
|
|
func (t *trackingRule) Name() string { return "tracker" }
|
|
func (t *trackingRule) Evaluate(_ EmailContext) RuleResult { t.called = true; return Accept() } |