svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Infrastructure.Tests/Health/PassiveHealthTrackerTests.cs
Svrnty 19ef79362e refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries
- Renamed all directories: OpenHarbor.MCP.* → Svrnty.MCP.*
- Updated all namespaces in 179 C# files
- Renamed 20 .csproj files and 3 .sln files
- Updated 193 documentation references
- Updated 33 references in main CODEX codebase
- Updated Codex.sln with new paths
- Build verified: 0 errors

Preparing for extraction to standalone repositories.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:04:17 -04:00

223 lines
6.7 KiB
C#

using Xunit;
using Svrnty.MCP.Gateway.Infrastructure.Health;
using Svrnty.MCP.Gateway.Core.Models;
namespace Svrnty.MCP.Gateway.Infrastructure.Tests.Health;
/// <summary>
/// Unit tests for PassiveHealthTracker following TDD approach.
/// Tests passive health tracking based on response times and errors.
/// </summary>
public class PassiveHealthTrackerTests
{
[Fact]
public void RecordSuccess_UpdatesHealthStatus()
{
// Arrange
var tracker = new PassiveHealthTracker();
var serverId = "server-1";
var responseTime = TimeSpan.FromMilliseconds(50);
// Act
tracker.RecordSuccess(serverId, responseTime);
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.True(health.IsHealthy);
Assert.Equal(responseTime, health.ResponseTime);
}
[Fact]
public void RecordFailure_UpdatesHealthStatus()
{
// Arrange
var tracker = new PassiveHealthTracker
{
UnhealthyThreshold = 1 // Mark unhealthy after 1 failure for this test
};
var serverId = "server-2";
var errorMessage = "Connection timeout";
// Act
tracker.RecordFailure(serverId, errorMessage);
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.False(health.IsHealthy);
Assert.Equal(errorMessage, health.ErrorMessage);
}
[Fact]
public void RecordSuccess_MultipleRequests_CalculatesAverageResponseTime()
{
// Arrange
var tracker = new PassiveHealthTracker();
var serverId = "server-3";
// Act - record 3 successful requests
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(100));
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(200));
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(300));
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.True(health.IsHealthy);
// Average should be around 200ms
Assert.NotNull(health.ResponseTime);
Assert.InRange(health.ResponseTime.Value.TotalMilliseconds, 150, 250);
}
[Fact]
public void RecordFailure_MultipleFailures_MarksServerUnhealthy()
{
// Arrange
var tracker = new PassiveHealthTracker
{
UnhealthyThreshold = 3 // Mark unhealthy after 3 failures
};
var serverId = "server-4";
// Act - record 3 failures
tracker.RecordFailure(serverId, "Error 1");
tracker.RecordFailure(serverId, "Error 2");
tracker.RecordFailure(serverId, "Error 3");
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.False(health.IsHealthy);
}
[Fact]
public void RecordSuccess_AfterFailures_RecoverToHealthy()
{
// Arrange
var tracker = new PassiveHealthTracker
{
UnhealthyThreshold = 2,
HealthyThreshold = 3 // Recover after 3 successes
};
var serverId = "server-5";
// Record failures to make unhealthy
tracker.RecordFailure(serverId, "Error 1");
tracker.RecordFailure(serverId, "Error 2");
// Act - record successes to recover
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(50));
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(50));
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(50));
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.True(health.IsHealthy);
}
[Fact]
public void GetServerHealth_WithUnknownServer_ReturnsNull()
{
// Arrange
var tracker = new PassiveHealthTracker();
// Act
var health = tracker.GetServerHealth("unknown-server");
// Assert
Assert.Null(health);
}
[Fact]
public void GetAllServerHealth_ReturnsAllTrackedServers()
{
// Arrange
var tracker = new PassiveHealthTracker
{
UnhealthyThreshold = 1 // Mark unhealthy after 1 failure for this test
};
tracker.RecordSuccess("server-1", TimeSpan.FromMilliseconds(50));
tracker.RecordSuccess("server-2", TimeSpan.FromMilliseconds(100));
tracker.RecordFailure("server-3", "Connection failed");
// Act
var allHealth = tracker.GetAllServerHealth();
// Assert
Assert.Equal(3, allHealth.Count());
Assert.Contains(allHealth, h => h.ServerId == "server-1" && h.IsHealthy);
Assert.Contains(allHealth, h => h.ServerId == "server-2" && h.IsHealthy);
Assert.Contains(allHealth, h => h.ServerId == "server-3" && !h.IsHealthy);
}
[Fact]
public void RecordSuccess_WithSlowResponse_MarksAsUnhealthy()
{
// Arrange
var tracker = new PassiveHealthTracker
{
SlowResponseThreshold = TimeSpan.FromMilliseconds(100)
};
var serverId = "server-6";
// Act - record slow response
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(500));
// Assert - should still be marked as success, but noted as slow
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.True(health.IsHealthy); // Still healthy, just slow
Assert.Equal(TimeSpan.FromMilliseconds(500), health.ResponseTime);
}
[Fact]
public void Reset_ClearsAllHealthData()
{
// Arrange
var tracker = new PassiveHealthTracker();
tracker.RecordSuccess("server-1", TimeSpan.FromMilliseconds(50));
tracker.RecordFailure("server-2", "Error");
// Act
tracker.Reset();
// Assert
var allHealth = tracker.GetAllServerHealth();
Assert.Empty(allHealth);
}
[Fact]
public void RecordSuccess_UpdatesLastCheckTime()
{
// Arrange
var tracker = new PassiveHealthTracker();
var serverId = "server-7";
var beforeRecord = DateTime.UtcNow;
// Act
tracker.RecordSuccess(serverId, TimeSpan.FromMilliseconds(50));
var afterRecord = DateTime.UtcNow;
// Assert
var health = tracker.GetServerHealth(serverId);
Assert.NotNull(health);
Assert.True(health.LastCheck >= beforeRecord);
Assert.True(health.LastCheck <= afterRecord);
}
[Fact]
public void Constructor_SetsDefaultThresholds()
{
// Act
var tracker = new PassiveHealthTracker();
// Assert
Assert.Equal(5, tracker.UnhealthyThreshold);
Assert.Equal(3, tracker.HealthyThreshold);
Assert.Equal(TimeSpan.FromSeconds(5), tracker.SlowResponseThreshold);
}
}