Adds the algorithm-layer guarantee tests for
docs/KVC_ROUTER_ALGORITHM.md §4.1. The full Dispatch loop
lives in replay.py (HTTP + mooncake), but the policy-layer
guarantee is testable in isolation: under any reject
sequence, select() must keep returning a valid worker.
Cases:
- select returns a valid decision even after every (s,d)
is past τ_reject (degenerate fallback)
- |D|·τ_reject rejects suffice to explore every D
(cannot trap a session on one D under universal
rejection)
- degenerate fallback picks the least-rejected D
(Algorithm 1 line 4)
- per-(session, D) isolation: session A's blacklist
does not affect session B
- migration_reject_threshold=0 disables blacklist
- select() does NOT silently bump the reject counter
(the only mutator is record_admission_reject)
Adds tests/_fixtures.py with minimal make_topology() and
make_request() helpers that skip build_single_node_topology's
GPU-budget validation (irrelevant in unit tests).
Verified locally: 20/20 passing under pytest 9.0.3. The
six new tests cover only Algorithm 1's policy-layer
half of Theorem 1; the reset-on-success half lives in
Algorithm 3 (replay.py) and is a future test target.
Adds the project's first test suite. Covers the
score_candidate() pure function from the previous refactor
commit, validating the qualitative properties that
KVC_ROUTER_ALGORITHM.md §3.1 and §4.2 rely on.
Tests / properties:
- determinism: same args -> same tuple
- shape: 4-int tuple
- primary term: overlap dominates pure sticky
- primary term: sticky_bonus credited
- tie-2 inflight: lower wins
- tie-3 assigned: lower wins
- strict lex order: sticky wins position-1 over fresh-idle
- load_floor disabled by default
- load_floor gated off when sticky=True
- load_floor zero during warmup (mean=0)
- load_floor proportional to deficit (200/100/0 at 0/50/100% load)
- load_floor does not underflow when overloaded
- real per-session overlap beats load_floor on warm D
- boilerplate overlap loses to load_floor on cold D
(the cold-D fix from E1_E2_FIX_DESIGN §Q2)
Test infrastructure:
- tests/ package with README explaining the GPU-free
scope and the run instruction
- pyproject.toml [dependency-groups] test = [pytest>=8]
(install via `uv sync --group test`)
- pyproject.toml [tool.pytest.ini_options] sets testpaths
Verified locally: 14/14 passing under pytest 9.0.3 in an
isolated 3.13 venv. No SGLang / GPU touched.