test(auth): deflake login rate-limit burst test under CPU load (#10)
All checks were successful
deploy / test-backend (push) Successful in 25m44s
deploy / test-frontend (push) Successful in 10m15s
deploy / build-and-push (push) Successful in 14s
deploy / deploy (push) Successful in 12s

This commit was merged in pull request #10.
This commit is contained in:
2026-06-16 18:04:53 +00:00
parent 32fcebd47a
commit 8445f338f6

View File

@@ -659,7 +659,8 @@ async fn login_no_user_branch_runs_argon2_for_timing_equalisation(pool: PgPool)
async fn login_rate_limited_under_burst_pressure(pool: PgPool) {
let h = common::harness_with_auth_rate_limit(pool, 1, 3);
// Register a victim so the wrong-password branch is real work.
// One register hit first — register and login share the one bucket,
// so this exercises the cross-endpoint limit (and consumes a token).
let _ = h
.app
.clone()
@@ -667,9 +668,18 @@ async fn login_rate_limited_under_burst_pressure(pool: PgPool) {
.await
.unwrap();
// Register consumed one token from the burst-3 bucket. Fire 30
// wrong-password logins back-to-back; with per_sec=1 the refill
// is too slow to keep up and at least one must come back 429.
// Fire 30 logins back-to-back; at least one must come back 429.
//
// We send an EMPTY password on purpose. `login` calls the rate
// limiter FIRST, then short-circuits empty credentials with a 400
// BEFORE any argon2 hash or DB lookup — so each attempt still
// consumes a token but is near-instant. That makes the burst drain
// the bucket far faster than the per_sec=1 refill regardless of how
// loaded the CI box is. (A real wrong-password attempt runs argon2,
// ~1s under load, which lets the 1/sec refill keep exact pace with
// the loop and the bucket never empties — that was the old flake.
// The bucket math itself is covered by rate_limit.rs's unit test;
// here we only need to prove the limiter is wired into the route.)
let mut saw_429 = false;
for _ in 0..30 {
let resp = h
@@ -677,7 +687,7 @@ async fn login_rate_limited_under_burst_pressure(pool: PgPool) {
.clone()
.oneshot(common::post_json(
"/api/v1/auth/login",
json!({ "username": "victim", "password": "wrong" }),
json!({ "username": "victim", "password": "" }),
))
.await
.unwrap();