Move TLS, OCSP, WebSocket, Networking, and IO test files from NATS.Server.Tests into a dedicated NATS.Server.Transport.Tests project. Update namespaces, replace private GetFreePort/ReadUntilAsync with shared TestUtilities helpers, extract TestCertHelper to TestUtilities, and replace Task.Delay polling loops with PollHelper.WaitUntilAsync/YieldForAsync for proper synchronization.
120 lines
3.9 KiB
C#
120 lines
3.9 KiB
C#
// Go reference: server/websocket.go — wsTLSConfig and related TLS handling.
|
|
|
|
using NATS.Server.WebSocket;
|
|
using Shouldly;
|
|
|
|
namespace NATS.Server.Transport.Tests.WebSocket;
|
|
|
|
/// <summary>
|
|
/// Tests for <see cref="WebSocketTlsConfig"/> — WebSocket-specific TLS configuration
|
|
/// with separate cert/key from the main NATS listener (Gap 15.1).
|
|
/// </summary>
|
|
public class WebSocketTlsTests
|
|
{
|
|
// ── IsConfigured ──────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void IsConfigured_WithCert_ReturnsTrue()
|
|
{
|
|
var cfg = new WebSocketTlsConfig { CertFile = "server.pem", KeyFile = "server-key.pem" };
|
|
cfg.IsConfigured.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void IsConfigured_WithoutCert_ReturnsFalse()
|
|
{
|
|
var cfg = new WebSocketTlsConfig();
|
|
cfg.IsConfigured.ShouldBeFalse();
|
|
}
|
|
|
|
// ── Validate ──────────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void Validate_ValidConfig_NoErrors()
|
|
{
|
|
var cfg = new WebSocketTlsConfig { CertFile = "server.pem", KeyFile = "server-key.pem" };
|
|
var result = cfg.Validate();
|
|
result.IsValid.ShouldBeTrue();
|
|
result.Errors.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_KeyWithoutCert_HasError()
|
|
{
|
|
var cfg = new WebSocketTlsConfig { KeyFile = "server-key.pem" };
|
|
var result = cfg.Validate();
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldNotBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_CertWithoutKey_HasError()
|
|
{
|
|
var cfg = new WebSocketTlsConfig { CertFile = "server.pem" };
|
|
var result = cfg.Validate();
|
|
result.IsValid.ShouldBeFalse();
|
|
result.Errors.ShouldNotBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public void Validate_EmptyConfig_Valid()
|
|
{
|
|
// An empty configuration means "no TLS" — that is a valid state.
|
|
var cfg = new WebSocketTlsConfig();
|
|
var result = cfg.Validate();
|
|
result.IsValid.ShouldBeTrue();
|
|
result.Errors.ShouldBeEmpty();
|
|
}
|
|
|
|
// ── HasChangedFrom ────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void HasChangedFrom_SameConfig_ReturnsFalse()
|
|
{
|
|
var a = new WebSocketTlsConfig
|
|
{
|
|
CertFile = "server.pem",
|
|
KeyFile = "server-key.pem",
|
|
CaFile = "ca.pem",
|
|
RequireClientCert = true,
|
|
InsecureSkipVerify = false,
|
|
};
|
|
|
|
var b = new WebSocketTlsConfig
|
|
{
|
|
CertFile = "server.pem",
|
|
KeyFile = "server-key.pem",
|
|
CaFile = "ca.pem",
|
|
RequireClientCert = true,
|
|
InsecureSkipVerify = false,
|
|
};
|
|
|
|
a.HasChangedFrom(b).ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void HasChangedFrom_DifferentCert_ReturnsTrue()
|
|
{
|
|
var a = new WebSocketTlsConfig { CertFile = "old.pem", KeyFile = "old-key.pem" };
|
|
var b = new WebSocketTlsConfig { CertFile = "new.pem", KeyFile = "new-key.pem" };
|
|
|
|
a.HasChangedFrom(b).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void HasChangedFrom_NullOther_ReturnsTrue()
|
|
{
|
|
var cfg = new WebSocketTlsConfig { CertFile = "server.pem", KeyFile = "server-key.pem" };
|
|
cfg.HasChangedFrom(null).ShouldBeTrue();
|
|
}
|
|
|
|
// ── Defaults ──────────────────────────────────────────────────────────────
|
|
|
|
[Fact]
|
|
public void RequireClientCert_Default_False()
|
|
{
|
|
var cfg = new WebSocketTlsConfig();
|
|
cfg.RequireClientCert.ShouldBeFalse();
|
|
}
|
|
}
|