def test_rate_liimter_effective_rate_rates(): limiter = RateLimiter(rate_limit=100) # Static rate limit window starting_window = compat.monotonic() with mock.patch("ddtrace.compat.monotonic") as mock_time: mock_time.return_value = starting_window for _ in range(100): assert limiter.is_allowed() is True assert limiter.effective_rate == 1.0 assert limiter.current_window == starting_window for i in range(1, 101): assert limiter.is_allowed() is False rate = 100 / (100 + i) assert limiter.effective_rate == rate assert limiter.current_window == starting_window prev_rate = 0.5 with mock.patch("ddtrace.compat.monotonic") as mock_time: window = starting_window + 1.0 mock_time.return_value = window for i in range(100): assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 assert limiter.current_window == window for i in range(1, 101): assert limiter.is_allowed() is False rate = 100 / (100 + i) assert limiter.effective_rate == (rate + prev_rate) / 2 assert limiter.current_window == window
def test_rate_liimter_effective_rate_rates(): limiter = RateLimiter(rate_limit=100) # Static rate limit window starting_window_ns = compat.monotonic_ns() for _ in range(100): assert limiter.is_allowed(starting_window_ns) is True assert limiter.effective_rate == 1.0 assert limiter.current_window_ns == starting_window_ns for i in range(1, 101): assert limiter.is_allowed(starting_window_ns) is False rate = 100 / (100 + i) assert limiter.effective_rate == rate assert limiter.current_window_ns == starting_window_ns prev_rate = 0.5 window_ns = starting_window_ns + 1e9 for i in range(100): assert limiter.is_allowed(window_ns) is True assert limiter.effective_rate == 0.75 assert limiter.current_window_ns == window_ns for i in range(1, 101): assert limiter.is_allowed(window_ns) is False rate = 100 / (100 + i) assert limiter.effective_rate == (rate + prev_rate) / 2 assert limiter.current_window_ns == window_ns
def test_rate_limiter_is_allowed_large_gap(): limiter = RateLimiter(rate_limit=100) # Start time now_ns = compat.monotonic_ns() # Keep the same timeframe for _ in range(100): assert limiter.is_allowed(now_ns) is True # Large gap before next call to `is_allowed()` for _ in range(100): assert limiter.is_allowed(now_ns + (1e9 * 100)) is True
def test_rate_liimter_effective_rate_starting_rate(): limiter = RateLimiter(rate_limit=1) now = compat.monotonic() with mock.patch("ddtrace.compat.monotonic") as mock_time: mock_time.return_value = now # Default values assert limiter.current_window == 0 assert limiter.prev_window_rate is None # Accessing the effective rate doesn't change anything assert limiter.effective_rate == 1.0 assert limiter.current_window == 0 assert limiter.prev_window_rate is None # Calling `.is_allowed()` updates the values assert limiter.is_allowed() is True assert limiter.effective_rate == 1.0 assert limiter.current_window == now assert limiter.prev_window_rate is None # Gap of 0.9999 seconds, same window mock_time.return_value = now + 0.9999 assert limiter.is_allowed() is False # DEV: We have rate_limit=1 set assert limiter.effective_rate == 0.5 assert limiter.current_window == now assert limiter.prev_window_rate is None # Gap of 1.0 seconds, new window mock_time.return_value = now + 1.0 assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 assert limiter.current_window == (now + 1.0) assert limiter.prev_window_rate == 0.5 # Gap of 1.9999 seconds, same window mock_time.return_value = now + 1.9999 assert limiter.is_allowed() is False assert limiter.effective_rate == 0.5 assert limiter.current_window == (now + 1.0) # Same as old window assert limiter.prev_window_rate == 0.5 # Large gap of 100 seconds, new window mock_time.return_value = now + 100.0 assert limiter.is_allowed() is True assert limiter.effective_rate == 0.75 assert limiter.current_window == (now + 100.0) assert limiter.prev_window_rate == 0.5
def test_rate_limiter_effective_rate_starting_rate(): limiter = RateLimiter(rate_limit=1) now_ns = compat.monotonic_ns() # Default values assert limiter.current_window_ns == 0 assert limiter.prev_window_rate is None # Accessing the effective rate doesn't change anything assert limiter.effective_rate == 1.0 assert limiter.current_window_ns == 0 assert limiter.prev_window_rate is None # Calling `.is_allowed()` updates the values assert limiter.is_allowed(now_ns) is True assert limiter.effective_rate == 1.0 assert limiter.current_window_ns == now_ns assert limiter.prev_window_rate is None # Gap of 0.9999 seconds, same window time_ns = now_ns + (0.9999 * 1e9) assert limiter.is_allowed(time_ns) is False # DEV: We have rate_limit=1 set assert limiter.effective_rate == 0.5 assert limiter.current_window_ns == now_ns assert limiter.prev_window_rate is None # Gap of 1.0 seconds, new window time_ns = now_ns + 1e9 assert limiter.is_allowed(time_ns) is True assert limiter.effective_rate == 0.75 assert limiter.current_window_ns == (now_ns + 1e9) assert limiter.prev_window_rate == 0.5 # Gap of 1.9999 seconds, same window time_ns = now_ns + (1.9999 * 1e9) assert limiter.is_allowed(time_ns) is False assert limiter.effective_rate == 0.5 assert limiter.current_window_ns == (now_ns + 1e9) # Same as old window assert limiter.prev_window_rate == 0.5 # Large gap of 100 seconds, new window time_ns = now_ns + (100.0 * 1e9) assert limiter.is_allowed(time_ns) is True assert limiter.effective_rate == 0.75 assert limiter.current_window_ns == (now_ns + (100.0 * 1e9)) assert limiter.prev_window_rate == 0.5
def test_rate_limiter_is_allowed_large_gap(): limiter = RateLimiter(rate_limit=100) # Start time now = compat.monotonic() with mock.patch("ddtrace.compat.monotonic") as mock_time: # Keep the same timeframe mock_time.return_value = now for _ in range(100): assert limiter.is_allowed() is True # Large gap before next call to `is_allowed()` with mock.patch("ddtrace.compat.monotonic") as mock_time: mock_time.return_value = now + 100 for _ in range(100): assert limiter.is_allowed() is True
def test_rate_limiter_rate_limit_negative(): limiter = RateLimiter(rate_limit=-1) assert limiter.rate_limit == -1 assert limiter.tokens == -1 assert limiter.max_tokens == -1 now_ns = compat.monotonic_ns() for i in nanoseconds(10000): # Make sure the time is different for every check assert limiter.is_allowed(now_ns + i) is True
def test_rate_limiter_is_allowed_small_gaps(): limiter = RateLimiter(rate_limit=100) # Start time now_ns = compat.monotonic_ns() gap = 1e9 / 100 # Keep incrementing by a gap to keep us at our rate limit for i in nanoseconds(10000): # Keep the same timeframe time_ns = now_ns + (gap * i) assert limiter.is_allowed(time_ns) is True
def test_rate_limiter_rate_limit_negative(): limiter = RateLimiter(rate_limit=-1) assert limiter.rate_limit == -1 assert limiter.tokens == -1 assert limiter.max_tokens == -1 now = compat.monotonic() with mock.patch("ddtrace.compat.monotonic") as mock_time: for i in range(10000): # Make sure the time is different for every check mock_time.return_value = now + i assert limiter.is_allowed() is True
def test_rate_limiter_rate_limit_0(): limiter = RateLimiter(rate_limit=0) assert limiter.rate_limit == 0 assert limiter.tokens == 0 assert limiter.max_tokens == 0 now = monotonic.monotonic() with mock.patch('ddtrace.vendor.monotonic.monotonic') as mock_time: for i in range(10000): # Make sure the time is different for every check mock_time.return_value = now + i assert limiter.is_allowed() is False
def test_rate_limiter_is_allowed_small_gaps(): limiter = RateLimiter(rate_limit=100) # Start time now = compat.monotonic() gap = 1.0 / 100.0 # Keep incrementing by a gap to keep us at our rate limit with mock.patch("ddtrace.compat.monotonic") as mock_time: for i in range(10000): # Keep the same timeframe mock_time.return_value = now + (gap * i) assert limiter.is_allowed() is True