import logging from resonance_engine.dsp.enums import DSPClientName from resonance_engine.fandata.timings import CollectTimings class TestCollectTimings: def test_all_lists_empty_by_default(self) -> None: timings = CollectTimings() assert timings.token_ms == [] assert timings.profile_ms == [] assert timings.top_artists_ms == [] assert timings.top_tracks_ms == [] assert timings.recently_played_ms == [] assert timings.playlists_ms == [] assert timings.saved_albums_ms == [] assert timings.saved_tracks_ms == [] assert timings.followed_artists_ms == [] def test_log_summary_emits_processed_and_error_counts(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[10, 20, 30], profile_ms=[5, 15]).log_summary( processed=3, errors=1 ) assert "3 ok" in caplog.text assert "1 err" in caplog.text def test_log_summary_empty_timings_does_not_raise(self) -> None: CollectTimings().log_summary(processed=0, errors=0) def test_log_summary_includes_dsp_client_when_provided(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings().log_summary( processed=1, errors=0, dsp_client_name=DSPClientName.spotify_songwhip, ) assert caplog.records[0].dsp_client_name == DSPClientName.spotify_songwhip # avg via log_summary def test_avg_zero_for_empty(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings().log_summary(processed=0, errors=0) assert "token avg=0ms p95=0ms" in caplog.text def test_avg_single_value(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[42]).log_summary(processed=1, errors=0) assert "token avg=42ms p95=42ms" in caplog.text def test_avg_rounds_to_nearest_int(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[1, 2]).log_summary(processed=1, errors=0) assert "token avg=2ms" in caplog.text # 1.5 → 2 def test_avg_computes_mean(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[10, 20, 30]).log_summary(processed=1, errors=0) assert "token avg=20ms" in caplog.text # p95 via log_summary def test_p95_zero_for_empty(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings().log_summary(processed=0, errors=0) assert "token avg=0ms p95=0ms" in caplog.text def test_p95_single_value(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[100]).log_summary(processed=1, errors=0) assert "token avg=100ms p95=100ms" in caplog.text def test_p95_returns_95th_percentile(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=list(range(1, 101))).log_summary( processed=1, errors=0 ) assert "p95=96ms" in caplog.text # index 95 of sorted [1..100] def test_p95_ignores_top_4_percent(self, caplog) -> None: with caplog.at_level(logging.INFO): CollectTimings(token_ms=[1] * 96 + [9999] * 4).log_summary( processed=1, errors=0 ) assert "token avg=401ms p95=1ms" in caplog.text