svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Core.Tests/Interfaces/IHealthCheckerTests.cs
Svrnty a4a1dd2e38 docs: comprehensive AI coding assistant research and MCP-first implementation plan
Research conducted on modern AI coding assistants (Cursor, GitHub Copilot, Cline,
Aider, Windsurf, Replit Agent) to understand architecture patterns, context management,
code editing workflows, and tool use protocols.

Key Decision: Pivoted from building full CLI (40-50h) to validation-driven MCP-first
approach (10-15h). Build 5 core CODEX MCP tools that work with ANY coding assistant,
validate adoption over 2-4 weeks, then decide on full CLI if demand proven.

Files:
- research/ai-systems/modern-coding-assistants-architecture.md (comprehensive research)
- research/ai-systems/codex-coding-assistant-implementation-plan.md (original CLI plan, preserved)
- research/ai-systems/codex-mcp-tools-implementation-plan.md (approved MCP-first plan)
- ideas/registry.json (updated with approved MCP tools proposal)

Architech Validation: APPROVED with pivot to MCP-first approach
Human Decision: Approved (pragmatic validation-driven development)

Next: Begin Phase 1 implementation (10-15 hours, 5 core MCP tools)

🤖 Generated with CODEX Research System

Co-Authored-By: The Archivist <archivist@codex.svrnty.io>
Co-Authored-By: The Architech <architech@codex.svrnty.io>
Co-Authored-By: Mathias Beaulieu-Duncan <mat@svrnty.io>
2025-10-22 21:00:34 -04:00

141 lines
4.4 KiB
C#

using Xunit;
using Moq;
using OpenHarbor.MCP.Gateway.Core.Interfaces;
using OpenHarbor.MCP.Gateway.Core.Models;
namespace OpenHarbor.MCP.Gateway.Core.Tests.Interfaces;
/// <summary>
/// Unit tests for IHealthChecker interface contract.
/// Tests health check operations and status tracking.
/// </summary>
public class IHealthCheckerTests
{
[Fact]
public async Task CheckHealthAsync_ReturnsHealthStatus()
{
// Arrange
var mockChecker = new Mock<IHealthChecker>();
var serverConfig = new ServerConfig
{
Id = "server-1",
Name = "Test Server",
TransportType = "Http",
BaseUrl = "http://localhost:5000"
};
var expectedStatus = new ServerHealthStatus
{
ServerId = "server-1",
ServerName = "Test Server",
IsHealthy = true,
LastCheck = DateTime.UtcNow
};
mockChecker.Setup(c => c.CheckHealthAsync(serverConfig, It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedStatus);
// Act
var result = await mockChecker.Object.CheckHealthAsync(serverConfig);
// Assert
Assert.NotNull(result);
Assert.Equal("server-1", result.ServerId);
Assert.True(result.IsHealthy);
}
[Fact]
public async Task CheckHealthAsync_WithUnhealthyServer_ReturnsUnhealthyStatus()
{
// Arrange
var mockChecker = new Mock<IHealthChecker>();
var serverConfig = new ServerConfig
{
Id = "server-2",
Name = "Unhealthy Server",
TransportType = "Http",
BaseUrl = "http://localhost:5001"
};
var expectedStatus = new ServerHealthStatus
{
ServerId = "server-2",
ServerName = "Unhealthy Server",
IsHealthy = false,
LastCheck = DateTime.UtcNow,
ErrorMessage = "Connection timeout"
};
mockChecker.Setup(c => c.CheckHealthAsync(serverConfig, It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedStatus);
// Act
var result = await mockChecker.Object.CheckHealthAsync(serverConfig);
// Assert
Assert.NotNull(result);
Assert.Equal("server-2", result.ServerId);
Assert.False(result.IsHealthy);
Assert.Equal("Connection timeout", result.ErrorMessage);
}
[Fact]
public async Task StartMonitoringAsync_BeginsHealthChecks()
{
// Arrange
var mockChecker = new Mock<IHealthChecker>();
var serverConfigs = new List<ServerConfig>
{
new ServerConfig { Id = "server-1", Name = "Server 1", TransportType = "Http", BaseUrl = "http://localhost:5000" }
};
mockChecker.Setup(c => c.StartMonitoringAsync(serverConfigs, It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
// Act
await mockChecker.Object.StartMonitoringAsync(serverConfigs);
// Assert
mockChecker.Verify(c => c.StartMonitoringAsync(serverConfigs, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task StopMonitoringAsync_EndsHealthChecks()
{
// Arrange
var mockChecker = new Mock<IHealthChecker>();
mockChecker.Setup(c => c.StopMonitoringAsync(It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
// Act
await mockChecker.Object.StopMonitoringAsync();
// Assert
mockChecker.Verify(c => c.StopMonitoringAsync(It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task GetCurrentHealthAsync_ReturnsAllServerHealth()
{
// Arrange
var mockChecker = new Mock<IHealthChecker>();
var expectedHealth = new List<ServerHealthStatus>
{
new ServerHealthStatus { ServerId = "server-1", IsHealthy = true },
new ServerHealthStatus { ServerId = "server-2", IsHealthy = false }
};
mockChecker.Setup(c => c.GetCurrentHealthAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedHealth);
// Act
var result = await mockChecker.Object.GetCurrentHealthAsync();
// Assert
Assert.NotNull(result);
Assert.Equal(2, result.Count());
Assert.Contains(result, s => s.ServerId == "server-1" && s.IsHealthy);
Assert.Contains(result, s => s.ServerId == "server-2" && !s.IsHealthy);
}
}