using FluentAssertions; using StellaOps.Router.Common.Enums; using StellaOps.Router.Common.Models; using StellaOps.Router.Gateway.State; using Xunit; namespace StellaOps.Router.Gateway.Tests; public sealed class InMemoryRoutingStateTests { [Fact] public void ResolveEndpoint_WhenExactMatch_ReturnsEndpointDescriptor() { var routingState = new InMemoryRoutingState(); var connection = CreateConnection("conn-1", "inventory", "1.0.0", region: "test"); connection.Endpoints[("GET", "/items")] = new EndpointDescriptor { ServiceName = "inventory", Version = "1.0.0", Method = "GET", Path = "/items" }; routingState.AddConnection(connection); var resolved = routingState.ResolveEndpoint("GET", "/items"); resolved.Should().NotBeNull(); resolved!.ServiceName.Should().Be("inventory"); resolved.Version.Should().Be("1.0.0"); resolved.Method.Should().Be("GET"); resolved.Path.Should().Be("/items"); } [Fact] public void ResolveEndpoint_WhenTemplateMatch_ReturnsEndpointDescriptor() { var routingState = new InMemoryRoutingState(); var connection = CreateConnection("conn-1", "inventory", "1.0.0", region: "test"); connection.Endpoints[("GET", "/items/{sku}")] = new EndpointDescriptor { ServiceName = "inventory", Version = "1.0.0", Method = "GET", Path = "/items/{sku}" }; routingState.AddConnection(connection); var resolved = routingState.ResolveEndpoint("GET", "/items/SKU-001"); resolved.Should().NotBeNull(); resolved!.Path.Should().Be("/items/{sku}"); } [Fact] public void RemoveConnection_RemovesEndpointsFromIndex() { var routingState = new InMemoryRoutingState(); var connection = CreateConnection("conn-1", "inventory", "1.0.0", region: "test"); connection.Endpoints[("GET", "/items")] = new EndpointDescriptor { ServiceName = "inventory", Version = "1.0.0", Method = "GET", Path = "/items" }; routingState.AddConnection(connection); routingState.ResolveEndpoint("GET", "/items").Should().NotBeNull(); routingState.RemoveConnection("conn-1"); routingState.ResolveEndpoint("GET", "/items").Should().BeNull(); routingState.GetAllConnections().Should().BeEmpty(); } [Fact] public void GetConnectionsFor_FiltersByServiceAndVersion() { var routingState = new InMemoryRoutingState(); var inventoryV1 = CreateConnection("inv-v1", "inventory", "1.0.0", region: "test"); inventoryV1.Endpoints[("GET", "/items")] = new EndpointDescriptor { ServiceName = "inventory", Version = "1.0.0", Method = "GET", Path = "/items" }; var inventoryV2 = CreateConnection("inv-v2", "inventory", "2.0.0", region: "test"); inventoryV2.Endpoints[("GET", "/items")] = new EndpointDescriptor { ServiceName = "inventory", Version = "2.0.0", Method = "GET", Path = "/items" }; routingState.AddConnection(inventoryV1); routingState.AddConnection(inventoryV2); var connections = routingState.GetConnectionsFor( serviceName: "inventory", version: "1.0.0", method: "GET", path: "/items"); connections.Should().HaveCount(1); connections[0].ConnectionId.Should().Be("inv-v1"); } private static ConnectionState CreateConnection( string connectionId, string serviceName, string version, string region) { return new ConnectionState { ConnectionId = connectionId, Instance = new InstanceDescriptor { InstanceId = connectionId, ServiceName = serviceName, Version = version, Region = region }, Status = InstanceHealthStatus.Healthy, LastHeartbeatUtc = DateTime.UtcNow, TransportType = TransportType.InMemory }; } }