using Microsoft.Extensions.Logging.Abstractions; using NATS.Server.Configuration; using NATS.Server.Gateways; using Shouldly; namespace NATS.Server.Tests.Gateways; /// /// Tests for gateway connection registration and state tracking (Gap 11.7). /// Go reference: server/gateway.go srvGateway / outboundGateway struct and gwConnState transitions. /// public class GatewayRegistrationTests { // Go: server/gateway.go solicitGateway creates an outbound entry before dialling. [Fact] public void RegisterGateway_creates_registration() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.GetRegistration("gw-east").ShouldNotBeNull(); } // Go: server/gateway.go initial gwConnState is gwConnecting before the dial completes. [Fact] public void RegisterGateway_starts_in_connecting_state() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); var reg = manager.GetRegistration("gw-east")!; reg.State.ShouldBe(GatewayConnectionState.Connecting); } // Go: server/gateway.go gwConnState transitions (Connecting → Connected, Connected → Disconnected, etc.). [Fact] public void UpdateState_changes_state() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.UpdateState("gw-east", GatewayConnectionState.Connected); manager.GetRegistration("gw-east")!.State.ShouldBe(GatewayConnectionState.Connected); } // Go: server/gateway.go getOutboundGatewayConnection returns nil for unknown names. [Fact] public void GetRegistration_returns_null_for_unknown() { var manager = BuildManager(); manager.GetRegistration("does-not-exist").ShouldBeNull(); } // Go: server/gateway.go server.gateways map stores all configured outbound gateways. [Fact] public void GetAllRegistrations_returns_all() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.RegisterGateway("gw-west"); var all = manager.GetAllRegistrations(); all.Count.ShouldBe(2); all.Select(r => r.Name).ShouldContain("gw-east"); all.Select(r => r.Name).ShouldContain("gw-west"); } // Go: server/gateway.go outboundGateway teardown removes entry from server.gateways. [Fact] public void UnregisterGateway_removes_registration() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.UnregisterGateway("gw-east"); manager.GetRegistration("gw-east").ShouldBeNull(); } // Go: server/gateway.go numOutboundGatewayConnections counts only fully-connected entries. [Fact] public void GetConnectedGatewayCount_counts_connected_only() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); // Connecting manager.RegisterGateway("gw-west"); // Connecting manager.RegisterGateway("gw-south"); // → Connected manager.UpdateState("gw-south", GatewayConnectionState.Connected); manager.GetConnectedGatewayCount().ShouldBe(1); } // Go: server/gateway.go outboundGateway.msgs.outMsgs incremented per forwarded message. [Fact] public void IncrementMessagesSent_increments() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.IncrementMessagesSent("gw-east"); manager.IncrementMessagesSent("gw-east"); manager.IncrementMessagesSent("gw-east"); manager.GetRegistration("gw-east")!.MessagesSent.ShouldBe(3L); } // Go: server/gateway.go inboundGateway.msgs.inMsgs incremented per received message. [Fact] public void IncrementMessagesReceived_increments() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); manager.IncrementMessagesReceived("gw-east"); manager.IncrementMessagesReceived("gw-east"); manager.GetRegistration("gw-east")!.MessagesReceived.ShouldBe(2L); } // Go: server/gateway.go outboundGateway.remoteName / remoteIP stored for monitoring. [Fact] public void Registration_stores_remote_address() { var manager = BuildManager(); manager.RegisterGateway("gw-east", remoteAddress: "10.0.0.1:7222"); manager.GetRegistration("gw-east")!.RemoteAddress.ShouldBe("10.0.0.1:7222"); } // Go: server/gateway.go gwConnState Connected transition stamps connected-at time. [Fact] public void UpdateState_to_connected_stamps_ConnectedAtUtc() { var manager = BuildManager(); manager.RegisterGateway("gw-east"); var before = DateTime.UtcNow; manager.UpdateState("gw-east", GatewayConnectionState.Connected); var after = DateTime.UtcNow; var stamp = manager.GetRegistration("gw-east")!.ConnectedAtUtc; stamp.ShouldBeGreaterThanOrEqualTo(before); stamp.ShouldBeLessThanOrEqualTo(after); } // ── Helpers ────────────────────────────────────────────────────────────── private static GatewayManager BuildManager() => new GatewayManager( new GatewayOptions { Name = "TEST", Host = "127.0.0.1", Port = 0 }, new ServerStats(), "S1", _ => { }, _ => { }, NullLogger.Instance); }