svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Core.Tests/Interfaces/IGatewayRouterTests.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

140 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 IGatewayRouter interface following TDD approach.
/// Tests routing behavior and contract compliance.
/// </summary>
public class IGatewayRouterTests
{
[Fact]
public async Task RouteAsync_WithValidRequest_ReturnsResponse()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var request = new GatewayRequest
{
ToolName = "test_tool",
Arguments = new Dictionary<string, object> { { "key", "value" } }
};
var expectedResponse = new GatewayResponse
{
Success = true,
Result = new Dictionary<string, object> { { "data", "result" } }
};
mockRouter
.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expectedResponse);
// Act
var response = await mockRouter.Object.RouteAsync(request, CancellationToken.None);
// Assert
Assert.NotNull(response);
Assert.True(response.Success);
Assert.NotNull(response.Result);
mockRouter.Verify(r => r.RouteAsync(request, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task RouteAsync_WithCancellationToken_PropagatesToken()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var request = new GatewayRequest { ToolName = "cancel_test" };
var cts = new CancellationTokenSource();
mockRouter
.Setup(r => r.RouteAsync(It.IsAny<GatewayRequest>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new GatewayResponse { Success = true });
// Act
await mockRouter.Object.RouteAsync(request, cts.Token);
// Assert
mockRouter.Verify(r => r.RouteAsync(request, cts.Token), Times.Once);
}
[Fact]
public async Task GetServerHealthAsync_ReturnsHealthStatuses()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var healthStatuses = new List<ServerHealthStatus>
{
new ServerHealthStatus
{
ServerId = "server-1",
IsHealthy = true,
ResponseTime = TimeSpan.FromMilliseconds(25)
},
new ServerHealthStatus
{
ServerId = "server-2",
IsHealthy = false,
ErrorMessage = "Timeout"
}
};
mockRouter
.Setup(r => r.GetServerHealthAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(healthStatuses);
// Act
var result = await mockRouter.Object.GetServerHealthAsync(CancellationToken.None);
// 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);
}
[Fact]
public async Task RegisterServerAsync_AddsServerConfiguration()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var serverConfig = new ServerConfig
{
Id = "new-server",
Name = "New MCP Server",
TransportType = "Stdio"
};
mockRouter
.Setup(r => r.RegisterServerAsync(It.IsAny<ServerConfig>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
// Act
await mockRouter.Object.RegisterServerAsync(serverConfig, CancellationToken.None);
// Assert
mockRouter.Verify(r => r.RegisterServerAsync(serverConfig, It.IsAny<CancellationToken>()), Times.Once);
}
[Fact]
public async Task UnregisterServerAsync_RemovesServerConfiguration()
{
// Arrange
var mockRouter = new Mock<IGatewayRouter>();
var serverId = "remove-server";
mockRouter
.Setup(r => r.UnregisterServerAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
// Act
var result = await mockRouter.Object.UnregisterServerAsync(serverId, CancellationToken.None);
// Assert
Assert.True(result);
mockRouter.Verify(r => r.UnregisterServerAsync(serverId, It.IsAny<CancellationToken>()), Times.Once);
}
}