package smtp import ( "errors" "testing" "time" ) func TestCircuitBreaker_opensAfterThreshold(t *testing.T) { cb := NewCircuitBreaker(3, time.Minute) account := "acc-1" for i := 0; i < 3; i++ { if err := cb.Allow(account); err != nil { t.Fatalf("allow %d: %v", i, err) } cb.RecordFailure(account) } if err := cb.Allow(account); !errors.Is(err, ErrCircuitOpen) { t.Fatalf("allow after failures = %v, want %v", err, ErrCircuitOpen) } } func TestCircuitBreaker_recoversAfterCooldown(t *testing.T) { cb := NewCircuitBreaker(1, 10*time.Millisecond) account := "acc-2" _ = cb.Allow(account) cb.RecordFailure(account) if err := cb.Allow(account); !errors.Is(err, ErrCircuitOpen) { t.Fatalf("expected open circuit: %v", err) } time.Sleep(15 * time.Millisecond) if err := cb.Allow(account); err != nil { t.Fatalf("expected half-open allow: %v", err) } cb.RecordSuccess(account) if err := cb.Allow(account); err != nil { t.Fatalf("expected closed circuit: %v", err) } }