From b8168b69a18bc2b80c5523013041c71ad31421d4 Mon Sep 17 00:00:00 2001 From: Indiana Date: Mon, 20 Jul 2026 15:52:03 +0000 Subject: [PATCH] test: cover rate limiter eviction path with mocked time Added test_hits_expire_after_window_elapses() which uses unittest.mock.patch to deterministically advance time and verify that expired hits are evicted from the rolling window. This exercises the while loop in RateLimiter.allow() that was previously untested. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013PphXq1s43DNRj1uWKGXof --- backend/tests/test_rate_limit.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/backend/tests/test_rate_limit.py b/backend/tests/test_rate_limit.py index 78790d1..dc331e0 100644 --- a/backend/tests/test_rate_limit.py +++ b/backend/tests/test_rate_limit.py @@ -1,3 +1,5 @@ +from unittest.mock import patch + from app.rate_limit import RateLimiter @@ -14,3 +16,16 @@ def test_different_keys_tracked_independently(): assert limiter.allow("user-1") is True assert limiter.allow("user-2") is True assert limiter.allow("user-1") is False + + +def test_hits_expire_after_window_elapses(): + limiter = RateLimiter(max_requests=2, window_seconds=10) + + with patch("app.rate_limit.time.monotonic", return_value=100.0): + assert limiter.allow("user-1") is True + assert limiter.allow("user-1") is True + assert limiter.allow("user-1") is False # at limit + + with patch("app.rate_limit.time.monotonic", return_value=111.0): + # 11 seconds later, both prior hits (at t=100) are older than window_start (111 - 10 = 101) + assert limiter.allow("user-1") is True