OPEN SOURCE
software/tests/test_rate_limiter.py
Read on this site and download the files you need.
Nichijoyaku was created using AI. A complete review by human biblical-language and biblical-studies specialists has not been established. Read alongside established translations and original-language resources.
← Back to the open-source guide
1"""Tests for shared rate limiter."""23from __future__ import annotations45import threading6import time78import pytest910from src.orchestration.rate_limiter import DummyRateLimiter, SharedRateLimiter111213class TestSharedRateLimiter:14"""Tests for SharedRateLimiter."""1516def test_default_values(self) -> None:17"""Test default configuration values."""18limiter = SharedRateLimiter()19assert limiter.max_concurrent == 520assert limiter.delay == 1.221limiter.shutdown()2223def test_custom_values(self) -> None:24"""Test custom configuration values."""25limiter = SharedRateLimiter(max_concurrent=3, delay=0.5)26assert limiter.max_concurrent == 327assert limiter.delay == 0.528limiter.shutdown()2930def test_acquire_release(self) -> None:31"""Test basic acquire and release."""32limiter = SharedRateLimiter(max_concurrent=2, delay=0.01)33try:34limiter.acquire()35limiter.release()36finally:37limiter.shutdown()3839def test_context_manager_call(self) -> None:40"""Test using limiter as context manager via __call__."""41limiter = SharedRateLimiter(max_concurrent=2, delay=0.01)42try:43with limiter():44pass45finally:46limiter.shutdown()4748def test_context_manager_direct(self) -> None:49"""Test using limiter as context manager directly."""50limiter = SharedRateLimiter(max_concurrent=2, delay=0.01)51try:52with limiter:53pass54finally:55limiter.shutdown()5657def test_delay_enforcement(self) -> None:58"""Test that delay is enforced between calls."""59limiter = SharedRateLimiter(max_concurrent=2, delay=0.1)60try:61start = time.time()6263with limiter():64pass6566with limiter():67pass6869elapsed = time.time() - start70# Should take at least delay seconds for second call71assert elapsed >= 0.172finally:73limiter.shutdown()7475def test_max_concurrent_limit(self) -> None:76"""Test that max concurrent limit is enforced."""77limiter = SharedRateLimiter(max_concurrent=2, delay=0.01)78lock = threading.Lock()79concurrent_count = 080max_observed = 08182def worker() -> None:83nonlocal concurrent_count, max_observed84with limiter:85with lock:86concurrent_count += 187if concurrent_count > max_observed:88max_observed = concurrent_count89time.sleep(0.05)90with lock:91concurrent_count -= 19293try:94threads = [threading.Thread(target=worker) for _ in range(5)]95for t in threads:96t.start()97for t in threads:98t.join()99100# Max concurrent should not exceed limit101assert max_observed <= 2102finally:103limiter.shutdown()104105def test_shutdown_idempotent(self) -> None:106"""Test that shutdown can be called multiple times."""107limiter = SharedRateLimiter(max_concurrent=2, delay=0.01)108limiter.shutdown()109limiter.shutdown() # Should not raise110111class TestDummyRateLimiter:112"""Tests for DummyRateLimiter."""113114def test_default_values(self) -> None:115"""Test default configuration values."""116limiter = DummyRateLimiter()117assert limiter.max_concurrent == 5118assert limiter.delay == 1.2119120def test_acquire_release(self) -> None:121"""Test basic acquire and release."""122limiter = DummyRateLimiter(delay=0.01)123limiter.acquire()124limiter.release()125126def test_context_manager_call(self) -> None:127"""Test using limiter as context manager via __call__."""128limiter = DummyRateLimiter(delay=0.01)129with limiter():130pass131132def test_context_manager_direct(self) -> None:133"""Test using limiter as context manager directly."""134limiter = DummyRateLimiter(delay=0.01)135with limiter:136pass137138def test_delay_enforcement(self) -> None:139"""Test that delay is enforced."""140limiter = DummyRateLimiter(delay=0.1)141142start = time.time()143144with limiter():145pass146147with limiter():148pass149150elapsed = time.time() - start151assert elapsed >= 0.1152153def test_no_concurrency_limit(self) -> None:154"""Test that there's no actual concurrency limit."""155limiter = DummyRateLimiter(delay=0.001)156concurrent_count = 0157max_concurrent = 0158lock = threading.Lock()159160def worker() -> None:161nonlocal concurrent_count, max_concurrent162with limiter:163with lock:164concurrent_count += 1165max_concurrent = max(max_concurrent, concurrent_count)166time.sleep(0.01)167with lock:168concurrent_count -= 1169170threads = [threading.Thread(target=worker) for _ in range(10)]171for t in threads:172t.start()173for t in threads:174t.join()175176# With dummy limiter, all threads can run concurrently177# (they still have delay but no semaphore)178assert max_concurrent >= 1179180def test_shutdown_noop(self) -> None:181"""Test that shutdown is a no-op."""182limiter = DummyRateLimiter()183limiter.shutdown()184limiter.shutdown() # Should not raise185186187class TestLimiterInteroperability:188"""Tests for using different limiters interchangeably."""189190def test_same_interface(self) -> None:191"""Test that both limiters have the same interface."""192for limiter_class in [SharedRateLimiter, DummyRateLimiter]:193limiter = limiter_class(max_concurrent=2, delay=0.01)194195# Should have same methods196assert hasattr(limiter, "acquire")197assert hasattr(limiter, "release")198assert hasattr(limiter, "shutdown")199assert hasattr(limiter, "__enter__")200assert hasattr(limiter, "__exit__")201assert hasattr(limiter, "__call__")202203# Should have same attributes204assert hasattr(limiter, "max_concurrent")205assert hasattr(limiter, "delay")206207limiter.shutdown()208209def test_function_works_with_either(self) -> None:210"""Test that a function can use either limiter type."""211212def do_work(limiter: SharedRateLimiter | DummyRateLimiter) -> str:213with limiter:214return "done"215216shared = SharedRateLimiter(max_concurrent=2, delay=0.01)217dummy = DummyRateLimiter(delay=0.01)218219try:220assert do_work(shared) == "done"221assert do_work(dummy) == "done"222finally:223shared.shutdown()224dummy.shutdown()225