from code.web.services import preview_cache as pc def _force_interval_elapsed(): # Ensure adaptation interval guard passes if pc._LAST_ADAPT_AT is not None: # type: ignore[attr-defined] pc._LAST_ADAPT_AT -= (pc._ADAPT_INTERVAL_S + 1) # type: ignore[attr-defined] def test_ttl_adapts_down_and_up(capsys): # Enable adaptation regardless of env pc._ADAPTATION_ENABLED = True # type: ignore[attr-defined] pc.TTL_SECONDS = pc._TTL_BASE # type: ignore[attr-defined] pc._RECENT_HITS.clear() # type: ignore[attr-defined] pc._LAST_ADAPT_AT = None # type: ignore[attr-defined] # Low hit ratio pattern (~0.1) for _ in range(72): pc.record_request_hit(False) for _ in range(8): pc.record_request_hit(True) pc.maybe_adapt_ttl() out1 = capsys.readouterr().out assert "theme_preview_ttl_adapt" in out1, "expected adaptation log for low hit ratio" ttl_after_down = pc.TTL_SECONDS assert ttl_after_down <= pc._TTL_BASE # type: ignore[attr-defined] # Force interval elapsed & high hit ratio pattern (~0.9) _force_interval_elapsed() pc._RECENT_HITS.clear() # type: ignore[attr-defined] for _ in range(72): pc.record_request_hit(True) for _ in range(8): pc.record_request_hit(False) pc.maybe_adapt_ttl() out2 = capsys.readouterr().out assert "theme_preview_ttl_adapt" in out2, "expected adaptation log for high hit ratio" ttl_after_up = pc.TTL_SECONDS assert ttl_after_up >= ttl_after_down # Extract hit_ratio fields to assert directionality if logs present ratios = [] for line in (out1 + out2).splitlines(): if 'theme_preview_ttl_adapt' in line: import json try: obj = json.loads(line) ratios.append(obj.get('hit_ratio')) except Exception: pass if len(ratios) >= 2: assert ratios[0] < ratios[-1], "expected second adaptation to have higher hit_ratio"