Files
troupe-standup/wizard-work/beam/test_ratelimit.py
T
ledger f864998aba beam: Q128 -- CHECK now grades all 570 cells on stdlib alone (no pytest)
Q105 pointed beam/CHECK at pytest; pytest is not installed on this
interpreter, so the gate exited 2 and ran zero cells. run_lane_tests.py
collects TestCase classes (TestLoader) and bare module-level def test_*()
(FunctionTestCase) itself, treats an unimportable module and a printed
FAIL transcript as faults, and exits 0/1/2. Four test files that imported
pytest now use beam_assert.raises/fail and unittest.mock; no cell dropped.

Measured: unittest discover 353 tests; runner 570 (353 + 217 bare);
bash wizard-work/beam/CHECK rc 0; test_run_lane_tests.py 10 cells OK;
7-mutant battery in scratch copies all as expected (HEAD CHECK rc 2,
broken bare rc 1, pytest import rc 1, failing TestCase rc 1, script FAIL
rc 1, empty lane rc 2, control rc 0).

Record: WORK-QUEUE.md Q128; report wizard-outputs/volt/2026-10-30-q128.md
2026-10-30 16:13:11 +00:00

102 lines
3.0 KiB
Python

import time
import threading
from unittest import mock
from beam_assert import raises
from ratelimit import TokenBucket, make_bucket, RateLimitError
def test_basic_burst():
b = make_bucket(rate=10, capacity=5, clock=lambda: 0.0)
# capacity 5, all available at t=0
for _ in range(5):
assert b.acquire(1, blocking=False) is True
assert b.acquire(1, blocking=False) is False
def test_refill():
t = [0.0]
b = make_bucket(rate=2, capacity=4, clock=lambda: t[0])
assert b.acquire(4, blocking=False) is True
assert b.acquire(1, blocking=False) is False
t[0] = 1.0 # 2 tokens refilled
assert b.acquire(2, blocking=False) is True
assert b.acquire(1, blocking=False) is False
def test_acquire_zero():
b = make_bucket(rate=1, capacity=1, clock=lambda: 0.0)
assert b.acquire(0) is True
assert b.tokens() == 1.0
def test_capacity_cap():
t = [0.0]
b = make_bucket(rate=10, capacity=3, clock=lambda: t[0])
t[0] = 100.0
assert b.tokens() == 3.0 # capped, not 1003
def test_timeout():
t = [0.0]
def clock():
return t[0]
b = make_bucket(rate=1, capacity=1, clock=clock)
assert b.acquire(1, blocking=False) is True
# need 1 more token, refill 1/s; timeout 0.5 -> fail
ok = b.acquire(1, blocking=True, timeout=0.5)
assert ok is False
def test_blocking_success_with_fake_sleep():
# Q128: this cell used pytest's `monkeypatch` fixture, so neither
# `unittest discover` nor run_lane_tests.py could ever execute it --
# it was a test no runner in this lane ran. unittest.mock is stdlib
# and does the same job, so the cell is collected and graded now.
t = [0.0]
b = make_bucket(rate=2, capacity=2, clock=lambda: t[0])
assert b.acquire(2, blocking=False) is True
# patch time.sleep to advance the bucket's clock
def fake_sleep(s):
t[0] += s
with mock.patch.object(time, "sleep", fake_sleep):
assert b.acquire(2, blocking=True, timeout=5) is True
def test_n_exceeds_capacity_nonblocking():
b = make_bucket(rate=1, capacity=2, clock=lambda: 0.0)
assert b.acquire(5, blocking=False) is False
def test_n_exceeds_capacity_blocking_raises():
b = make_bucket(rate=1, capacity=2, clock=lambda: 0.0)
with raises(RateLimitError):
b.acquire(5, blocking=True)
def test_negative_n():
b = make_bucket(rate=1, capacity=2, clock=lambda: 0.0)
with raises(ValueError):
b.acquire(-1, blocking=False)
def test_thread_safety():
b = make_bucket(rate=1000, capacity=100, clock=time.monotonic)
results = []
def worker():
for _ in range(50):
results.append(b.acquire(1, blocking=True))
threads = [threading.Thread(target=worker) for _ in range(4)]
for th in threads:
th.start()
for th in threads:
th.join()
assert all(results)
assert len(results) == 200
def test_invalid_params():
with raises(ValueError):
TokenBucket(rate=0, capacity=1)
with raises(ValueError):
TokenBucket(rate=1, capacity=0)