using System.Net; using System.Net.Sockets; using Microsoft.Extensions.Logging.Abstractions; using NATS.Server.Configuration; using NATS.Server.Protocol; using NATS.Server.Routes; namespace NATS.Server.Clustering.Tests.Routes; public class RouteParityHelpersBatch1Tests { [Fact] public void BuildConnectInfoJson_includes_connectinfo_compat_fields() { var json = RouteConnection.BuildConnectInfoJson("S1", ["A"], "topo-v1"); json.ShouldContain("\"verbose\":false"); json.ShouldContain("\"pedantic\":false"); json.ShouldContain("\"echo\":false"); json.ShouldContain("\"tls_required\":false"); json.ShouldContain("\"headers\":true"); json.ShouldContain("\"name\":\"S1\""); json.ShouldContain("\"cluster\":\"\""); json.ShouldContain("\"dynamic\":false"); json.ShouldContain("\"lnoc\":false"); json.ShouldContain("\"lnocu\":false"); } [Fact] public void HasThisRouteConfigured_matches_explicit_routes_with_scheme_normalization() { var manager = CreateManager(new ClusterOptions { Host = "127.0.0.1", Port = 0, Routes = ["127.0.0.1:7222"], }); manager.HasThisRouteConfigured("127.0.0.1:7222").ShouldBeTrue(); manager.HasThisRouteConfigured("nats-route://127.0.0.1:7222").ShouldBeTrue(); manager.HasThisRouteConfigured("nats://127.0.0.1:7222").ShouldBeTrue(); manager.HasThisRouteConfigured("127.0.0.1:7999").ShouldBeFalse(); } [Fact] public void ProcessImplicitRoute_skips_configured_routes_and_tracks_new_routes() { var manager = CreateManager(new ClusterOptions { Host = "127.0.0.1", Port = 0, Routes = ["127.0.0.1:7222"], }); var serverInfo = new ServerInfo { ServerId = "S2", ServerName = "S2", Version = NatsProtocol.Version, Host = "127.0.0.1", Port = 7222, ConnectUrls = ["127.0.0.1:7222", "nats-route://127.0.0.1:7444"], }; manager.ProcessImplicitRoute(serverInfo); manager.DiscoveredRoutes.ShouldNotContain("127.0.0.1:7222"); manager.DiscoveredRoutes.ShouldContain("nats-route://127.0.0.1:7444"); } [Fact] public void RouteStillValid_checks_configured_and_discovered_routes() { var manager = CreateManager(new ClusterOptions { Host = "127.0.0.1", Port = 0, Routes = ["127.0.0.1:7222"], }); manager.RouteStillValid("nats://127.0.0.1:7222").ShouldBeTrue(); manager.RouteStillValid("127.0.0.1:7555").ShouldBeFalse(); manager.ProcessImplicitRoute(new ServerInfo { ServerId = "S2", ServerName = "S2", Version = NatsProtocol.Version, Host = "127.0.0.1", Port = 7444, ConnectUrls = ["127.0.0.1:7444"], }); manager.RouteStillValid("nats-route://127.0.0.1:7444").ShouldBeTrue(); } [Fact] public async Task Solicited_route_helpers_upgrade_and_query_status() { var manager = CreateManager(); await using var connection = MakeRouteConnection(); manager.RegisterRoute("S2", connection); manager.HasSolicitedRoute("S2").ShouldBeFalse(); manager.UpgradeRouteToSolicited("S2").ShouldBeTrue(); connection.IsSolicitedRoute().ShouldBeTrue(); manager.HasSolicitedRoute("S2").ShouldBeTrue(); manager.IsDuplicateServerName("S2").ShouldBeTrue(); } [Fact] public async Task RemoveRoute_cleans_hash_and_account_route_indexes() { var manager = CreateManager(); var connection = MakeRouteConnection(); manager.RegisterRoute("S2", connection); manager.RegisterRouteByHash("S2", connection); manager.RegisterAccountRoute("A", connection); manager.HashedRouteCount.ShouldBe(1); manager.DedicatedRouteCount.ShouldBe(1); manager.RemoveRoute("S2").ShouldBeTrue(); manager.HashedRouteCount.ShouldBe(0); manager.DedicatedRouteCount.ShouldBe(0); } [Fact] public async Task TryParseRemoteUnsub_parses_rs_minus_and_ls_minus() { RouteConnection.TryParseRemoteUnsub("RS- ACCT_A foo.bar q1", out var account1, out var subject1, out var queue1).ShouldBeTrue(); account1.ShouldBe("ACCT_A"); subject1.ShouldBe("foo.bar"); queue1.ShouldBe("q1"); RouteConnection.TryParseRemoteUnsub("LS- ACCT_B foo.>", out var account2, out var subject2, out var queue2).ShouldBeTrue(); account2.ShouldBe("ACCT_B"); subject2.ShouldBe("foo.>"); queue2.ShouldBeNull(); RouteConnection.TryParseRemoteUnsub("RS+ ACCT_A foo.bar", out _, out _, out _).ShouldBeFalse(); } private static RouteManager CreateManager(ClusterOptions? options = null) => new( options ?? new ClusterOptions { Host = "127.0.0.1", Port = 0 }, new ServerStats(), "S1", _ => { }, _ => { }, NullLogger.Instance); private static RouteConnection MakeRouteConnection() { var listener = new TcpListener(IPAddress.Loopback, 0); listener.Start(); var endpoint = (IPEndPoint)listener.LocalEndpoint; var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); client.Connect(endpoint); var server = listener.AcceptSocket(); server.Dispose(); listener.Stop(); return new RouteConnection(client); } }