From 1a9d3f06e6542b89da6e41abbed726f154741efa Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Wed, 25 Feb 2026 12:24:03 -0500 Subject: [PATCH] feat: add leaf cluster registration and topology tracking (Gap 12.6) --- .../LeafNodes/LeafClusterRegistrationTests.cs | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 tests/NATS.Server.Tests/LeafNodes/LeafClusterRegistrationTests.cs diff --git a/tests/NATS.Server.Tests/LeafNodes/LeafClusterRegistrationTests.cs b/tests/NATS.Server.Tests/LeafNodes/LeafClusterRegistrationTests.cs new file mode 100644 index 0000000..b49b0ad --- /dev/null +++ b/tests/NATS.Server.Tests/LeafNodes/LeafClusterRegistrationTests.cs @@ -0,0 +1,149 @@ +using Microsoft.Extensions.Logging.Abstractions; +using NATS.Server.Configuration; +using NATS.Server.LeafNodes; + +namespace NATS.Server.Tests.LeafNodes; + +/// +/// Unit tests for leaf cluster topology registration (Gap 12.6). +/// Verifies that , +/// , +/// , +/// , +/// , +/// , and +/// +/// correctly manage leaf cluster entries. +/// Go reference: leafnode.go registerLeafNodeCluster. +/// +public class LeafClusterRegistrationTests +{ + private static LeafNodeManager CreateManager() => + new( + options: new LeafNodeOptions { Host = "127.0.0.1", Port = 0 }, + stats: new ServerStats(), + serverId: "test-server", + remoteSubSink: _ => { }, + messageSink: _ => { }, + logger: NullLogger.Instance); + + // Go: leafnode.go registerLeafNodeCluster — first registration succeeds + [Fact] + public void RegisterLeafNodeCluster_NewCluster_ReturnsTrue() + { + var manager = CreateManager(); + + var result = manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 3); + + result.ShouldBeTrue(); + } + + // Go: leafnode.go registerLeafNodeCluster — duplicate name returns false + [Fact] + public void RegisterLeafNodeCluster_Duplicate_ReturnsFalse() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 3); + + var result = manager.RegisterLeafNodeCluster("cluster-A", "nats://other:7222", 1); + + result.ShouldBeFalse(); + } + + // Go: leafnode.go — cluster removal for existing entry returns true + [Fact] + public void UnregisterLeafNodeCluster_Existing_ReturnsTrue() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 3); + + var result = manager.UnregisterLeafNodeCluster("cluster-A"); + + result.ShouldBeTrue(); + } + + // Go: leafnode.go — cluster removal for absent entry returns false + [Fact] + public void UnregisterLeafNodeCluster_NonExistent_ReturnsFalse() + { + var manager = CreateManager(); + + var result = manager.UnregisterLeafNodeCluster("cluster-X"); + + result.ShouldBeFalse(); + } + + // Go: leafnode.go — HasLeafNodeCluster true after registration + [Fact] + public void HasLeafNodeCluster_Registered_ReturnsTrue() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 3); + + manager.HasLeafNodeCluster("cluster-A").ShouldBeTrue(); + } + + // Go: leafnode.go — HasLeafNodeCluster false when not registered + [Fact] + public void HasLeafNodeCluster_NotRegistered_ReturnsFalse() + { + var manager = CreateManager(); + + manager.HasLeafNodeCluster("cluster-X").ShouldBeFalse(); + } + + // Go: leafnode.go — GetLeafNodeCluster returns registered info + [Fact] + public void GetLeafNodeCluster_Found_ReturnsInfo() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 5); + + var info = manager.GetLeafNodeCluster("cluster-A"); + + info.ShouldNotBeNull(); + info.ClusterName.ShouldBe("cluster-A"); + info.GatewayUrl.ShouldBe("nats://gateway:7222"); + info.ConnectionCount.ShouldBe(5); + } + + // Go: leafnode.go — GetLeafNodeCluster returns null for absent cluster + [Fact] + public void GetLeafNodeCluster_NotFound_ReturnsNull() + { + var manager = CreateManager(); + + var info = manager.GetLeafNodeCluster("cluster-X"); + + info.ShouldBeNull(); + } + + // Go: leafnode.go — GetAllLeafClusters returns all registered entries + [Fact] + public void GetAllLeafClusters_ReturnsAll() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gw-a:7222", 2); + manager.RegisterLeafNodeCluster("cluster-B", "nats://gw-b:7222", 4); + + var all = manager.GetAllLeafClusters(); + + all.Count.ShouldBe(2); + all.Select(c => c.ClusterName).ShouldContain("cluster-A"); + all.Select(c => c.ClusterName).ShouldContain("cluster-B"); + } + + // Go: leafnode.go — UpdateLeafClusterConnectionCount updates the count on existing entry + [Fact] + public void UpdateLeafClusterConnectionCount_UpdatesCount() + { + var manager = CreateManager(); + manager.RegisterLeafNodeCluster("cluster-A", "nats://gateway:7222", 1); + + manager.UpdateLeafClusterConnectionCount("cluster-A", 7); + + var info = manager.GetLeafNodeCluster("cluster-A"); + info.ShouldNotBeNull(); + info.ConnectionCount.ShouldBe(7); + } +}