from __future__ import annotations from yuxi.channels.adapters.nextcloudtalk.metrics import NextcloudTalkMetrics, _percentile class TestPercentile: def test_empty_returns_zero(self): assert _percentile([], 50) == 0.0 def test_single_element(self): assert _percentile([5.0], 50) == 5.0 assert _percentile([5.0], 95) == 5.0 def test_median_even_count(self): data = [1.0, 2.0, 3.0, 4.0] assert _percentile(data, 50) == 2.5 def test_median_odd_count(self): data = [1.0, 2.0, 3.0, 4.0, 5.0] assert _percentile(data, 50) == 3.0 def test_p95(self): data = [float(i) for i in range(100)] result = _percentile(data, 95) assert 93 <= result <= 95 def test_p99(self): data = [float(i) for i in range(100)] result = _percentile(data, 99) assert 97 <= result <= 99 def test_unsorted_input(self): data = [5.0, 1.0, 4.0, 2.0, 3.0] assert _percentile(data, 50) == 3.0 class TestNextcloudTalkMetrics: def test_initial_snapshot(self): metrics = NextcloudTalkMetrics() snap = metrics.snapshot() assert "uptime_seconds" in snap assert snap["send"]["count"] == 0 assert snap["send"]["error_count"] == 0 assert snap["receive"]["count"] == 0 assert snap["receive"]["error_count"] == 0 assert snap["circuit_breaker"]["trip_count"] == 0 assert snap["send"]["avg_latency_ms"] is None assert snap["receive"]["avg_latency_ms"] is None def test_record_send_success_updates_counts(self): metrics = NextcloudTalkMetrics() metrics.record_send_success(0.1) metrics.record_send_success(0.2) snap = metrics.snapshot() assert snap["send"]["count"] == 2 assert snap["send"]["error_count"] == 0 def test_record_send_error(self): metrics = NextcloudTalkMetrics() metrics.record_send_error() metrics.record_send_error() snap = metrics.snapshot() assert snap["send"]["count"] == 0 assert snap["send"]["error_count"] == 2 def test_record_receive_success(self): metrics = NextcloudTalkMetrics() metrics.record_receive_success(0.05) metrics.record_receive_success(0.15) snap = metrics.snapshot() assert snap["receive"]["count"] == 2 assert snap["receive"]["error_count"] == 0 def test_record_receive_error(self): metrics = NextcloudTalkMetrics() metrics.record_receive_error() snap = metrics.snapshot() assert snap["receive"]["count"] == 0 assert snap["receive"]["error_count"] == 1 def test_record_circuit_breaker_trip(self): metrics = NextcloudTalkMetrics() metrics.record_circuit_breaker_trip() metrics.record_circuit_breaker_trip() snap = metrics.snapshot() assert snap["circuit_breaker"]["trip_count"] == 2 def test_average_latency_calculation(self): metrics = NextcloudTalkMetrics() metrics.record_send_success(0.1) metrics.record_send_success(0.3) metrics.record_send_success(0.2) snap = metrics.snapshot() avg = snap["send"]["avg_latency_ms"] assert avg is not None assert 199 <= avg <= 201 def test_percentile_values(self): metrics = NextcloudTalkMetrics() for i in range(100): metrics.record_send_success(float(i) / 1000.0) snap = metrics.snapshot() assert snap["send"]["p50_latency_ms"] is not None assert snap["send"]["p95_latency_ms"] is not None assert snap["send"]["p99_latency_ms"] is not None assert snap["send"]["p95_latency_ms"] > snap["send"]["p50_latency_ms"] def test_latency_deque_bounded(self): metrics = NextcloudTalkMetrics(max_latency_samples=10) for i in range(20): metrics.record_send_success(float(i) / 1000.0) snap = metrics.snapshot() assert snap["send"]["count"] == 20 assert snap["send"]["avg_latency_ms"] is not None def test_uptime_seconds_positive(self): metrics = NextcloudTalkMetrics() import time time.sleep(0.1) snap = metrics.snapshot() assert snap["uptime_seconds"] >= 0