feat(batch6-task7): port t2 leaf route websocket tls tests

This commit is contained in:
Joseph Doherty
2026-02-28 10:10:27 -05:00
parent 62169c82d9
commit b336fa4519
5 changed files with 282 additions and 4 deletions

View File

@@ -6,6 +6,175 @@ namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed partial class LeafNodeHandlerTests
{
[Fact] // T:1918
public void LeafNodeCloseTLSConnection_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseLeafNodes(
new Dictionary<string, object?>
{
["tls"] = new Dictionary<string, object?>
{
["verify"] = true,
["map"] = true,
["timeout"] = 0.25d,
},
["write_deadline"] = "2s",
["write_timeout"] = "close",
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.LeafNode.TlsConfig.ShouldNotBeNull();
options.LeafNode.TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
options.LeafNode.TlsMap.ShouldBeTrue();
options.LeafNode.TlsTimeout.ShouldBe(0.25d);
options.LeafNode.WriteDeadline.ShouldBe(TimeSpan.FromSeconds(2));
options.LeafNode.WriteTimeout.ShouldBe(WriteTimeoutPolicy.Close);
}
[Fact] // T:1919
public void LeafNodeTLSSaveName_ShouldSucceed()
{
var errors = new List<Exception>();
var warnings = new List<Exception>();
var remotes = ServerOptions.ParseRemoteLeafNodes(
new List<object?>
{
new Dictionary<string, object?>
{
["url"] = "nats://localhost:7422",
["tls"] = new Dictionary<string, object?>
{
["verify"] = true,
["timeout"] = 1,
},
},
},
errors,
warnings);
errors.ShouldBeEmpty();
remotes.Count.ShouldBe(1);
remotes[0].Urls.Count.ShouldBe(1);
remotes[0].Urls[0].Host.ShouldBe("localhost");
remotes[0].TlsConfig.ShouldNotBeNull();
remotes[0].TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
remotes[0].TlsTimeout.ShouldBe(1d);
}
[Fact] // T:1929
public void LeafNodeTLSVerifyAndMap_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseLeafNodes(
new Dictionary<string, object?>
{
["authorization"] = new Dictionary<string, object?>
{
["users"] = new List<object?>
{
new Dictionary<string, object?>
{
["user"] = "CN=example.com,OU=NATS.io",
["pass"] = "pw",
["account"] = "MyAccount",
},
},
},
["tls"] = new Dictionary<string, object?>
{
["verify"] = true,
["map"] = true,
["timeout"] = 0.5d,
},
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.LeafNode.TlsConfig.ShouldNotBeNull();
options.LeafNode.TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
options.LeafNode.TlsMap.ShouldBeTrue();
options.LeafNode.Users.ShouldNotBeNull();
options.LeafNode.Users!.Count.ShouldBe(1);
options.LeafNode.Users[0].Username.ShouldBe("CN=example.com,OU=NATS.io");
options.LeafNode.Users[0].Account.ShouldNotBeNull();
options.LeafNode.Users[0].Account!.Name.ShouldBe("MyAccount");
}
[Fact] // T:1942
public void LeafNodeWSBasic_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseLeafNodes(
new Dictionary<string, object?>
{
["remotes"] = new List<object?>
{
new Dictionary<string, object?>
{
["url"] = "ws://127.0.0.1:7422/some/path",
["ws_compression"] = true,
["ws_no_masking"] = true,
["compression"] = true,
},
},
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.LeafNode.Remotes.Count.ShouldBe(1);
options.LeafNode.Remotes[0].Urls.Count.ShouldBe(1);
options.LeafNode.Remotes[0].Urls[0].Scheme.ShouldBe("ws");
options.LeafNode.Remotes[0].Websocket.Compression.ShouldBeTrue();
options.LeafNode.Remotes[0].Websocket.NoMasking.ShouldBeTrue();
options.LeafNode.Remotes[0].Compression.Mode.ShouldBe(CompressionModes.S2Auto);
}
[Fact] // T:1950
public void LeafNodeWSRemoteNoTLSBlockWithWSSProto_ShouldSucceed()
{
var errors = new List<Exception>();
var warnings = new List<Exception>();
var remotes = ServerOptions.ParseRemoteLeafNodes(
new List<object?>
{
new Dictionary<string, object?>
{
["url"] = "wss://127.0.0.1:7422/some/path",
},
},
errors,
warnings);
errors.ShouldBeEmpty();
remotes.Count.ShouldBe(1);
remotes[0].Urls.Count.ShouldBe(1);
remotes[0].Urls[0].Scheme.ShouldBe("wss");
remotes[0].Tls.ShouldBeFalse();
remotes[0].TlsConfig.ShouldBeNull();
}
[Fact] // T:1907
public void LeafNodeRandomRemotes_ShouldSucceed()
{

View File

@@ -6,6 +6,87 @@ namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed partial class RouteHandlerTests
{
[Fact] // T:2817
public void RouteCloseTLSConnection_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var (tlsOptions, tlsParseError) = ServerOptions.ParseTLS(
new Dictionary<string, object?>
{
["verify"] = true,
["timeout"] = 0.1d,
},
isClientCtx: false);
tlsParseError.ShouldBeNull();
tlsOptions.ShouldNotBeNull();
var (tlsConfig, tlsGenError) = ServerOptions.GenTLSConfig(tlsOptions!);
tlsGenError.ShouldBeNull();
tlsConfig.ShouldNotBeNull();
options.Cluster.TlsConfig = tlsConfig;
options.Cluster.TlsTimeout = tlsOptions!.Timeout;
var parseError = ServerOptions.ParseCluster(
new Dictionary<string, object?>
{
["name"] = "A",
["write_deadline"] = "3s",
["write_timeout"] = "close",
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.Cluster.TlsConfig.ShouldNotBeNull();
options.Cluster.TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
options.Cluster.TlsTimeout.ShouldBe(0.1d);
options.Cluster.WriteDeadline.ShouldBe(TimeSpan.FromSeconds(3));
options.Cluster.WriteTimeout.ShouldBe(WriteTimeoutPolicy.Close);
}
[Fact] // T:2821
public void RouteLockReleasedOnTLSFailure_ShouldSucceed()
{
var options = new ServerOptions();
var (tlsOptions, tlsParseError) = ServerOptions.ParseTLS(
new Dictionary<string, object?>
{
["cipher_suites"] = new List<object?> { "TLS_RSA_WITH_RC4_128_SHA" },
},
isClientCtx: false);
tlsOptions.ShouldBeNull();
tlsParseError.ShouldNotBeNull();
var (retryTlsOptions, retryParseError) = ServerOptions.ParseTLS(
new Dictionary<string, object?>
{
["verify"] = true,
["timeout"] = 0.25d,
},
isClientCtx: false);
retryParseError.ShouldBeNull();
retryTlsOptions.ShouldNotBeNull();
var (tlsConfig, tlsGenError) = ServerOptions.GenTLSConfig(retryTlsOptions!);
tlsGenError.ShouldBeNull();
tlsConfig.ShouldNotBeNull();
options.Cluster.TlsTimeout = retryTlsOptions!.Timeout;
options.Cluster.TlsConfig = tlsConfig;
options.Cluster.TlsConfig.ShouldNotBeNull();
options.Cluster.TlsTimeout.ShouldBe(0.25d);
}
[Fact] // T:2808
public void RouteUseIPv6_ShouldSucceed()
{

View File

@@ -6,6 +6,34 @@ namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed partial class WebSocketHandlerTests
{
[Fact] // T:3109
public void WSHandshakeTimeout_ShouldSucceed()
{
var options = new ServerOptions();
var errors = new List<Exception>();
var warnings = new List<Exception>();
var parseError = ServerOptions.ParseWebsocket(
new Dictionary<string, object?>
{
["handshake_timeout"] = "1ms",
["tls"] = new Dictionary<string, object?>
{
["verify_and_map"] = true,
},
},
options,
errors,
warnings);
parseError.ShouldBeNull();
errors.ShouldBeEmpty();
options.Websocket.HandshakeTimeout.ShouldBe(TimeSpan.FromMilliseconds(1));
options.Websocket.TlsConfig.ShouldNotBeNull();
options.Websocket.TlsMap.ShouldBeTrue();
options.Websocket.TlsConfig!.ClientCertificateRequired.ShouldBeTrue();
}
[Fact] // T:3105
public void WSPubSub_ShouldSucceed()
{