"""Tests for the LOCKED dispatcher: slot allocation invariants + lifecycle.""" from pathlib import Path import pytest from harness.dispatcher import allocate_slots, extinction_candidates, enforce_cap, living_variants from harness.genome import VariantManifest REPO_ROOT = Path(__file__).resolve().parent.parent # ── allocate_slots: rank-based soft taper, newborn-protected ────────────────── def test_sum_equals_budget(): slots = allocate_slots(5, {"a": 9.0, "b": 1.0, "c": 0.5}, variant_ids=["a", "b", "c"]) assert sum(slots.values()) == 5 def test_best_rank_gets_the_most_and_nobody_scored_is_zeroed(): slots = allocate_slots(5, {"a": 9.0, "b": 5.0, "c": 1.0}, variant_ids=["a", "b", "c"]) assert slots["a"] >= slots["b"] >= slots["c"] >= 1 # soft taper: no scored variant hits 0 assert sum(slots.values()) == 5 def test_newborn_never_starved(): # 'baby' has no fitness row → newborn → guaranteed floor, never 0, even against a strong veteran slots = allocate_slots(5, {"old": 10.0}, variant_ids=["old", "baby"]) assert slots["baby"] >= 1 assert slots["old"] == 4 # veteran soaks the remaining budget assert sum(slots.values()) == 5 def test_rank_uses_order_not_magnitude(): # a runaway-high score for 'a' must NOT let it hoover the budget — the taper is by rank only slots = allocate_slots(4, {"a": 1000.0, "b": 1.0}, variant_ids=["a", "b"]) assert slots == {"a": 2, "b": 2} def test_all_newborns_share_evenly(): slots = allocate_slots(5, {}, variant_ids=["x", "y", "z"]) assert sum(slots.values()) == 5 assert min(slots.values()) >= 1 # every newborn is funded assert max(slots.values()) - min(slots.values()) <= 1 def test_zero_budget_or_no_variants(): assert allocate_slots(0, {"a": 5.0}, variant_ids=["a"]) == {"a": 0} assert allocate_slots(5, {}, variant_ids=[]) == {} @pytest.mark.parametrize("budget", [1, 2, 3, 4, 5]) def test_sum_invariant_across_budgets(budget): # a, b scored; c, d newborns (absent from the map). Sum is always exact. slots = allocate_slots(budget, {"a": 2.0, "b": 1.0}, variant_ids=["a", "b", "c", "d"]) assert sum(slots.values()) == budget # ── per-variant ceiling (throughput guard) ──────────────────────────────────── def test_max_per_variant_caps_a_single_strong_variant(): # One scored variant would normally soak all 5; the cap holds it to 2 (the rest is dropped: # there's no point allocating videos it can't render before its timeout). slots = allocate_slots(5, {"a": 9.0}, variant_ids=["a"], max_per_variant=2) assert slots == {"a": 2} def test_max_per_variant_redistributes_to_others(): slots = allocate_slots(5, {"a": 9.0, "b": 1.0}, variant_ids=["a", "b"], max_per_variant=2) assert slots["a"] == 2 and slots["b"] == 2 # both capped at 2 assert sum(slots.values()) == 4 # 1 slot un-allocatable → dropped def test_max_per_variant_none_is_unchanged(): a = allocate_slots(4, {"a": 1000.0, "b": 1.0}, variant_ids=["a", "b"]) b = allocate_slots(4, {"a": 1000.0, "b": 1.0}, variant_ids=["a", "b"], max_per_variant=None) assert a == b == {"a": 2, "b": 2} # ── exploration (anti-monoculture) ──────────────────────────────────────────── def test_exploration_funds_the_weak_variant(): # Without exploration a tiny budget would skip the weak 'b'. One exploration slot guarantees # 'b' is sampled even though 'a' dominates on fitness. no_explore = allocate_slots(2, {"a": 9.0, "b": 0.1}, variant_ids=["a", "b"], exploration=0) with_explore = allocate_slots(2, {"a": 9.0, "b": 0.1}, variant_ids=["a", "b"], exploration=1) assert with_explore["b"] >= 1 assert sum(with_explore.values()) == 2 assert sum(no_explore.values()) == 2 def test_exploration_zero_is_unchanged(): base = allocate_slots(5, {"a": 9.0, "b": 5.0, "c": 1.0}, variant_ids=["a", "b", "c"]) same = allocate_slots(5, {"a": 9.0, "b": 5.0, "c": 1.0}, variant_ids=["a", "b", "c"], exploration=0) assert base == same # ── lifecycle ────────────────────────────────────────────────────────────────── def test_extinction_at_threshold(): assert extinction_candidates({"v": 12, "w": 11, "x": 13}, k=12) == ["v", "x"] def test_extinction_none_below_threshold(): assert extinction_candidates({"v": 1, "w": 0}, k=12) == [] def test_enforce_cap_ok_and_breach(): one = [VariantManifest(variant_id="a")] five = [VariantManifest(variant_id=str(i)) for i in range(5)] assert enforce_cap(one, max_living=4)[0] is True assert enforce_cap(five, max_living=4)[0] is False def test_living_variants_discovers_variant_1(): ids = [m.variant_id for m in living_variants(REPO_ROOT / "variants")] assert "variant_1" in ids