package main import ( "testing" "time" ) func TestLoginRateLimit(t *testing.T) { var l limiter for i := range loginMaxFailures - 1 { l.fail("esa@example.com") if l.locked("esa@example.com") { t.Fatalf("locked after %d failures, limit is %d", i+1, loginMaxFailures) } } l.fail("esa@example.com") if !l.locked("esa@example.com") { t.Fatalf("not locked after %d failures", loginMaxFailures) } // The limit is per email: locking one address must not lock anyone else out. if l.locked("toinen@example.com") { t.Fatal("a different address was locked too") } // A correct password clears it, so a member who mistypes nine times and then gets it right // starts from zero. l.succeed("esa@example.com") if l.locked("esa@example.com") { t.Fatal("still locked after a successful login") } // Failures older than the window don't accumulate. for range loginMaxFailures - 1 { l.fail("esa@example.com") } l.by["esa@example.com"].first = time.Now().Add(-loginWindow - time.Minute) l.fail("esa@example.com") if l.locked("esa@example.com") { t.Fatal("failures outside the window were counted") } }