"""Unit-Tests Adaptive Quality (PLAN.md §5.2).""" from __future__ import annotations from hms_adaptive import AdaptiveQualityController, QualityLevel def _fast_controller() -> AdaptiveQualityController: """Regler ohne echte Wartezeiten für deterministische Tests.""" return AdaptiveQualityController(min_hold_ms=0, downgrade_intervals=2, upgrade_intervals=6) def test_starts_at_high() -> None: assert _fast_controller().level is QualityLevel.HIGH def test_single_bad_interval_does_not_downgrade() -> None: c = _fast_controller() assert c.step(30.0) is QualityLevel.HIGH # 1 schlechtes Intervall genügt nicht def test_downgrades_one_level_per_interval_not_more() -> None: c = _fast_controller() c.step(30.0) c.step(30.0) assert c.level is QualityLevel.MEDIUM # genau eine Stufe (Hysterese, §5.2) c.step(30.0) c.step(30.0) assert c.level is QualityLevel.LOW assert c.step(30.0) is QualityLevel.LOW # Untergrenze def test_upgrade_needs_sustained_reserve() -> None: c = _fast_controller() for _ in range(4): c.step(30.0) assert c.level is QualityLevel.LOW for _ in range(5): # 5 gute Intervalle genügen nicht (Upgrade träger) c.step(1.0) assert c.level is QualityLevel.LOW c.step(1.0) # 6. gutes Intervall → eine Stufe hoch assert c.level is QualityLevel.MEDIUM def test_upgrade_slower_than_downgrade() -> None: c = _fast_controller() assert c.downgrade_intervals < c.upgrade_intervals def test_no_pumping_on_alternating_load() -> None: c = _fast_controller() levels = [] for _ in range(60): levels.append(c.step(30.0)) # Dauerlast → LOW assert c.level is QualityLevel.LOW for _ in range(3): c.step(1.0) # kurze Erholung darf kein Pumpen erzeugen c.step(30.0) assert c.level is QualityLevel.LOW # keine Aufwertung bei alternierender Last def test_reason_is_recorded() -> None: c = _fast_controller() c.step(30.0) c.step(30.0) assert "p99" in c.last_reason and "budget" in c.last_reason def test_default_min_hold_prevents_rapid_changes(monkeypatch) -> None: c = AdaptiveQualityController() # min_hold_ms=2000 (Produktionswert) c.step(30.0) c.step(30.0) assert c.level is QualityLevel.HIGH # Mindesthaltezeit noch nicht vergangen