using FluentAssertions; using Xunit; namespace ZB.MOM.WW.LmxProxy.Client.Tests; public class ClientMetricsTests { private static LmxProxyClient.ClientMetrics CreateMetrics() => new(); [Fact] public void IncrementOperationCount_Increments() { var metrics = CreateMetrics(); metrics.IncrementOperationCount("Read"); metrics.IncrementOperationCount("Read"); metrics.IncrementOperationCount("Read"); var snapshot = metrics.GetSnapshot(); snapshot["Read_count"].Should().Be(3L); } [Fact] public void IncrementErrorCount_Increments() { var metrics = CreateMetrics(); metrics.IncrementErrorCount("Write"); metrics.IncrementErrorCount("Write"); var snapshot = metrics.GetSnapshot(); snapshot["Write_errors"].Should().Be(2L); } [Fact] public void RecordLatency_StoresValues() { var metrics = CreateMetrics(); metrics.RecordLatency("Read", 10); metrics.RecordLatency("Read", 20); metrics.RecordLatency("Read", 30); var snapshot = metrics.GetSnapshot(); snapshot.Should().ContainKey("Read_avg_latency_ms"); snapshot.Should().ContainKey("Read_p95_latency_ms"); snapshot.Should().ContainKey("Read_p99_latency_ms"); var avg = (double)snapshot["Read_avg_latency_ms"]; avg.Should().BeApproximately(20.0, 0.1); } [Fact] public void RollingBuffer_CapsAt1000() { var metrics = CreateMetrics(); for (int i = 0; i < 1100; i++) { metrics.RecordLatency("Read", i); } var snapshot = metrics.GetSnapshot(); // After 1100 entries, the buffer should have capped at 1000 (oldest removed) // The earliest remaining value should be 100 (entries 0-99 were evicted) var p95 = (long)snapshot["Read_p95_latency_ms"]; // p95 of values 100-1099 should be around 1050 p95.Should().BeGreaterThan(900); } [Fact] public void GetSnapshot_IncludesP95AndP99() { var metrics = CreateMetrics(); // Add 100 values: 1, 2, 3, ..., 100 for (int i = 1; i <= 100; i++) { metrics.RecordLatency("Op", i); } var snapshot = metrics.GetSnapshot(); var p95 = (long)snapshot["Op_p95_latency_ms"]; var p99 = (long)snapshot["Op_p99_latency_ms"]; // P95 of 1..100 should be 95 p95.Should().Be(95); // P99 of 1..100 should be 99 p99.Should().Be(99); } [Fact] public void GetSnapshot_ReturnsEmptyForNoData() { var metrics = CreateMetrics(); var snapshot = metrics.GetSnapshot(); snapshot.Should().BeEmpty(); } [Fact] public void GetSnapshot_TracksMultipleOperations() { var metrics = CreateMetrics(); metrics.IncrementOperationCount("Read"); metrics.IncrementOperationCount("Write"); metrics.IncrementErrorCount("Read"); metrics.RecordLatency("Read", 10); metrics.RecordLatency("Write", 20); var snapshot = metrics.GetSnapshot(); snapshot["Read_count"].Should().Be(1L); snapshot["Write_count"].Should().Be(1L); snapshot["Read_errors"].Should().Be(1L); snapshot.Should().ContainKey("Read_avg_latency_ms"); snapshot.Should().ContainKey("Write_avg_latency_ms"); } }