"""The sliding-window limiter behind /auth/register, password-login, password-reset and demo. Pure logic, no DB. `reset()` in particular is only ever called by a test fixture (conftest clears the module-level limiters between tests), so without a test here a refactor could turn it into a no-op and nothing would notice until an unrelated test started failing with a 429. """ from app.ratelimit import RateLimiter def test_allow_trips_at_the_cap_and_stays_tripped(): lim = RateLimiter(max_events=2, window_seconds=300) assert lim.allow("ip") is True assert lim.allow("ip") is True assert lim.allow("ip") is False # A blocked attempt is not counted, so a caller cannot push the window forward by hammering. assert lim.allow("ip") is False def test_keys_are_independent(): lim = RateLimiter(max_events=1, window_seconds=300) assert lim.allow("a") is True assert lim.allow("a") is False assert lim.allow("b") is True def test_reset_clears_every_key(): lim = RateLimiter(max_events=1, window_seconds=300) lim.allow("a") lim.allow("b") assert lim.allow("a") is False lim.reset() assert lim.allow("a") is True assert lim.allow("b") is True def test_expired_attempts_fall_out_of_the_window(): # A zero-length window means every previous attempt is already outside it. lim = RateLimiter(max_events=1, window_seconds=0) assert lim.allow("ip") is True assert lim.allow("ip") is True