51 lines
1.0 KiB
Go
51 lines
1.0 KiB
Go
package api
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestLoginGuardLockout(t *testing.T) {
|
|
g := newLoginGuard()
|
|
ip := "203.0.113.1"
|
|
|
|
for i := 0; i < loginMaxFailures-1; i++ {
|
|
locked, _ := g.recordFailure(ip)
|
|
if locked {
|
|
t.Fatalf("unexpected lock on attempt %d", i+1)
|
|
}
|
|
}
|
|
if locked, _ := g.check(ip); locked {
|
|
t.Fatal("should not be locked before threshold")
|
|
}
|
|
|
|
locked, retryAfter := g.recordFailure(ip)
|
|
if !locked || retryAfter <= 0 {
|
|
t.Fatalf("expected lockout, locked=%v retryAfter=%d", locked, retryAfter)
|
|
}
|
|
if locked, _ := g.check(ip); !locked {
|
|
t.Fatal("expected locked after threshold")
|
|
}
|
|
|
|
g.reset(ip)
|
|
if locked, _ := g.check(ip); locked {
|
|
t.Fatal("expected unlocked after reset")
|
|
}
|
|
}
|
|
|
|
func TestLoginGuardLockExpires(t *testing.T) {
|
|
g := newLoginGuard()
|
|
ip := "203.0.113.2"
|
|
|
|
g.mu.Lock()
|
|
g.byIP[ip] = &loginGuardEntry{
|
|
failures: loginMaxFailures,
|
|
lockedUntil: time.Now().Add(-time.Second),
|
|
}
|
|
g.mu.Unlock()
|
|
|
|
if locked, _ := g.check(ip); locked {
|
|
t.Fatal("expected expired lock to clear")
|
|
}
|
|
}
|