"""Tests for Frequency — rolling average event frequency tracker.""" import time from unittest.mock import patch import pytest from i2p_stat.frequency import Frequency class TestFrequencyInit: def test_valid_period(self): f = Frequency(1000) assert f.period == 1000 def test_zero_period_raises(self): with pytest.raises(ValueError, match="positive"): Frequency(0) def test_negative_period_raises(self): with pytest.raises(ValueError, match="positive"): Frequency(-1) class TestFrequencyBasics: def test_initial_avg_interval(self): f = Frequency(1000) # Initially period + 1 (no events) assert f.get_average_interval() == 1001.0 def test_initial_event_count(self): f = Frequency(1000) assert f.get_event_count() == 0 def test_initial_events_per_period(self): f = Frequency(1000) # period / avg_interval = 1000 / 1001 < 1 assert f.get_average_events_per_period() < 1.0 def test_initial_strict_avg(self): f = Frequency(1000) # No events → period + 1 assert f.get_strict_average_interval() == 1001.0 class TestFrequencyEvents: def test_event_increments_count(self): f = Frequency(10000) f.event_occurred() assert f.get_event_count() == 1 f.event_occurred() assert f.get_event_count() == 2 def test_rapid_events_decrease_interval(self): f = Frequency(10000) initial = f.get_average_interval() # Fire events with small delay so interval < period for _ in range(5): time.sleep(0.002) f.event_occurred() after = f.get_average_interval() # Rapid events should decrease the average interval assert after < initial def test_min_avg_interval_tracks_minimum(self): f = Frequency(10000) # Fire events with small delay for _ in range(10): time.sleep(0.002) f.event_occurred() min_after_rapid = f.get_min_average_interval() # min should be less than initial (period + 1) assert min_after_rapid < 10001.0 def test_max_events_per_period(self): f = Frequency(10000) for _ in range(5): time.sleep(0.002) f.event_occurred() max_epp = f.get_max_average_events_per_period() assert max_epp > 0 def test_strict_average(self): f = Frequency(10000) time.sleep(0.002) f.event_occurred() f.event_occurred() f.event_occurred() strict = f.get_strict_average_interval() # Should be (now - start) / 3, a small positive value assert strict > 0 def test_recalculate_no_events(self): f = Frequency(1) # 1ms period # Sleep >1ms so interval exceeds period time.sleep(0.01) f.recalculate() # Should reset to period + 1 assert f.get_average_interval() == 2.0 class TestFrequencyEdgeCases: def test_events_per_period_zero_avg(self): """If avg_interval is somehow 0, return 0.""" f = Frequency(1000) f._avg_interval = 0.0 assert f.get_average_events_per_period() == 0.0 def test_max_events_zero_min(self): f = Frequency(1000) f._min_avg_interval = 0.0 assert f.get_max_average_events_per_period() == 0.0