"""Tests for A4 SRR loadgen helpers (no network I/O).""" from __future__ import annotations import random from replayer.srr import ( _build_session_pool, _clone_session_for_arrival, _window_for, ) from replayer.trace import TraceRequest def _mk_req(session_id: str, turn: int, chat_id: int, ts: float) -> TraceRequest: return TraceRequest( request_id=f"{session_id}:{turn}:{chat_id}:{turn}", session_id=session_id, chat_id=chat_id, parent_chat_id=-1 if turn == 0 else chat_id - 1, timestamp_s=ts, input_length=100, output_length=10, request_type="user", turn_id=turn, hash_ids=(chat_id,), ) def test_build_session_pool_groups_and_orders_turns(): reqs = [ _mk_req("s1", 1, 11, 2.0), _mk_req("s2", 0, 20, 1.5), _mk_req("s1", 0, 10, 1.0), ] pool = _build_session_pool(reqs, pool_cap=None) assert len(pool) == 2 by_sid = {turns[0].session_id: turns for turns in pool} assert [t.turn_id for t in by_sid["s1"]] == [0, 1] assert [t.turn_id for t in by_sid["s2"]] == [0] def test_build_session_pool_honors_pool_cap(): reqs = [_mk_req(f"s{i}", 0, i, float(i)) for i in range(5)] pool = _build_session_pool(reqs, pool_cap=2) assert len(pool) == 2 def test_window_for_classifies_correctly(): warmup_end = 100.0 steady_end = 400.0 assert _window_for(50.0, warmup_end, steady_end) == "warmup" assert _window_for(100.0, warmup_end, steady_end) == "steady" assert _window_for(399.999, warmup_end, steady_end) == "steady" assert _window_for(400.0, warmup_end, steady_end) == "drain" assert _window_for(500.0, warmup_end, steady_end) == "drain" def test_clone_session_uses_fresh_ids_so_arrivals_do_not_alias(): template = [_mk_req("orig", 0, 100, 1.0), _mk_req("orig", 1, 101, 2.0)] clone_a = _clone_session_for_arrival(template, arrival_idx=7) clone_b = _clone_session_for_arrival(template, arrival_idx=8) for c in (clone_a, clone_b): assert c[0].session_id == c[1].session_id # within an arrival assert c[0].session_id.startswith("srr") assert c[0].request_id != template[0].request_id assert clone_a[0].session_id != clone_b[0].session_id assert clone_a[0].request_id != clone_b[0].request_id def test_clone_session_preserves_token_payload_fields(): template = [_mk_req("orig", 0, 100, 1.0)] template = [TraceRequest( request_id=template[0].request_id, session_id=template[0].session_id, chat_id=template[0].chat_id, parent_chat_id=template[0].parent_chat_id, timestamp_s=template[0].timestamp_s, input_length=4000, output_length=300, request_type="user", turn_id=0, hash_ids=(1, 2, 3, 4, 5), )] cloned = _clone_session_for_arrival(template, arrival_idx=1) assert cloned[0].input_length == 4000 assert cloned[0].output_length == 300 assert cloned[0].hash_ids == (1, 2, 3, 4, 5) assert cloned[0].turn_id == 0 def test_poisson_inter_arrival_mean_matches_rate(): """Sanity check on the exponential RNG used for arrivals.""" rng = random.Random(0) rate = 5.0 # 5 sess/s -> mean inter-arrival ~ 0.2 s samples = [rng.expovariate(rate) for _ in range(20000)] mean = sum(samples) / len(samples) assert abs(mean - 1.0 / rate) < 0.01