Move 28 leaf node test files from NATS.Server.Tests into a dedicated NATS.Server.LeafNodes.Tests project. Update namespaces, add InternalsVisibleTo, register in solution file. Replace all Task.Delay polling loops with PollHelper.WaitUntilAsync/YieldForAsync from TestUtilities. Replace private ReadUntilAsync in LeafProtocolTests with SocketTestHelper.ReadUntilAsync. All 281 tests pass.
143 lines
4.7 KiB
C#
143 lines
4.7 KiB
C#
using Microsoft.Extensions.Logging.Abstractions;
|
|
using NATS.Server.Configuration;
|
|
using NATS.Server.LeafNodes;
|
|
|
|
namespace NATS.Server.LeafNodes.Tests.LeafNodes;
|
|
|
|
/// <summary>
|
|
/// Unit tests for leaf node TLS certificate hot-reload (Gap 12.1).
|
|
/// Verifies that <see cref="LeafNodeManager.UpdateTlsConfig"/> correctly tracks cert/key
|
|
/// paths, increments the reload counter only on genuine changes, and returns accurate
|
|
/// <see cref="LeafTlsReloadResult"/> values.
|
|
/// Go reference: leafnode.go — reloadTLSConfig, TestLeafNodeTLSCertReload.
|
|
/// </summary>
|
|
public class LeafTlsReloadTests
|
|
{
|
|
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<LeafNodeManager>.Instance);
|
|
|
|
// Go: TestLeafNodeTLSCertReload — leafnode_test.go, first reload call
|
|
[Fact]
|
|
public void UpdateTlsConfig_NewCert_ReturnsChanged()
|
|
{
|
|
var manager = CreateManager();
|
|
|
|
var result = manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.NewCertPath.ShouldBe("/certs/leaf.pem");
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — no-op reload when cert unchanged
|
|
[Fact]
|
|
public void UpdateTlsConfig_SameCert_ReturnsUnchanged()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
var result = manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
result.Changed.ShouldBeFalse();
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — cert rotation path
|
|
[Fact]
|
|
public void UpdateTlsConfig_ChangedCert_UpdatesPath()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/old.pem", "/certs/old-key.pem");
|
|
|
|
manager.UpdateTlsConfig("/certs/new.pem", "/certs/new-key.pem");
|
|
|
|
manager.CurrentCertPath.ShouldBe("/certs/new.pem");
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — disabling TLS by passing null cert
|
|
[Fact]
|
|
public void UpdateTlsConfig_ClearCert_ReturnsChanged()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
var result = manager.UpdateTlsConfig(null, null);
|
|
|
|
result.Changed.ShouldBeTrue();
|
|
result.NewCertPath.ShouldBeNull();
|
|
}
|
|
|
|
// Go: TestLeafNodeTLS — IsTlsEnabled when no cert configured
|
|
[Fact]
|
|
public void IsTlsEnabled_NoCert_ReturnsFalse()
|
|
{
|
|
var manager = CreateManager();
|
|
|
|
manager.IsTlsEnabled.ShouldBeFalse();
|
|
}
|
|
|
|
// Go: TestLeafNodeTLS — IsTlsEnabled when cert is configured
|
|
[Fact]
|
|
public void IsTlsEnabled_WithCert_ReturnsTrue()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
manager.IsTlsEnabled.ShouldBeTrue();
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — reload counter increments on each genuine change
|
|
[Fact]
|
|
public void TlsReloadCount_IncrementedOnChange()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.TlsReloadCount.ShouldBe(0);
|
|
|
|
manager.UpdateTlsConfig("/certs/a.pem", "/certs/a-key.pem");
|
|
manager.TlsReloadCount.ShouldBe(1);
|
|
|
|
manager.UpdateTlsConfig("/certs/b.pem", "/certs/b-key.pem");
|
|
manager.TlsReloadCount.ShouldBe(2);
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — reload counter unchanged when config identical
|
|
[Fact]
|
|
public void TlsReloadCount_NotIncrementedOnNoChange()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
manager.TlsReloadCount.ShouldBe(1);
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — result carries previous cert path
|
|
[Fact]
|
|
public void UpdateTlsConfig_ReportsPreviousPath()
|
|
{
|
|
var manager = CreateManager();
|
|
manager.UpdateTlsConfig("/certs/first.pem", "/certs/first-key.pem");
|
|
|
|
var result = manager.UpdateTlsConfig("/certs/second.pem", "/certs/second-key.pem");
|
|
|
|
result.PreviousCertPath.ShouldBe("/certs/first.pem");
|
|
result.NewCertPath.ShouldBe("/certs/second.pem");
|
|
}
|
|
|
|
// Go: TestLeafNodeTLSCertReload — key path tracked alongside cert path
|
|
[Fact]
|
|
public void UpdateTlsConfig_UpdatesKeyPath()
|
|
{
|
|
var manager = CreateManager();
|
|
|
|
manager.UpdateTlsConfig("/certs/leaf.pem", "/certs/leaf-key.pem");
|
|
|
|
manager.CurrentKeyPath.ShouldBe("/certs/leaf-key.pem");
|
|
}
|
|
}
|