test(batch7): implement t2 route leaf and proxy mapped tests
This commit is contained in:
@@ -0,0 +1,139 @@
|
|||||||
|
using Shouldly;
|
||||||
|
using ZB.MOM.NatsNet.Server;
|
||||||
|
|
||||||
|
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||||
|
|
||||||
|
public sealed partial class LeafNodeHandlerTests
|
||||||
|
{
|
||||||
|
[Fact] // T:1908
|
||||||
|
public void LeafNodeTLSWithCerts_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var options = new ServerOptions();
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var parseError = ServerOptions.ParseLeafNodes(
|
||||||
|
Map(
|
||||||
|
("listen", "127.0.0.1:7422"),
|
||||||
|
("tls", Map(("verify", true), ("map", true), ("timeout", 2L)))),
|
||||||
|
options,
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
options.LeafNode.Port.ShouldBe(7422);
|
||||||
|
options.LeafNode.TlsConfig.ShouldNotBeNull();
|
||||||
|
options.LeafNode.TlsTimeout.ShouldBe(2d);
|
||||||
|
options.LeafNode.TlsMap.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:1909
|
||||||
|
public void LeafNodeTLSRemoteWithNoCerts_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var remotes = ServerOptions.ParseRemoteLeafNodes(
|
||||||
|
Arr(
|
||||||
|
Map(
|
||||||
|
("url", "nats://localhost:7422"),
|
||||||
|
("tls", Map(("timeout", 5L))))),
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
remotes.Count.ShouldBe(1);
|
||||||
|
remotes[0].TlsTimeout.ShouldBe(5d);
|
||||||
|
|
||||||
|
remotes = ServerOptions.ParseRemoteLeafNodes(
|
||||||
|
Arr(
|
||||||
|
Map(
|
||||||
|
("url", "nats://localhost:7422"),
|
||||||
|
("tls", Map()))),
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
remotes.Count.ShouldBe(1);
|
||||||
|
remotes[0].TlsTimeout.ShouldBeGreaterThan(0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:1932
|
||||||
|
public void LeafNodeOriginClusterInfo_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
var remotes = ServerOptions.ParseRemoteLeafNodes(
|
||||||
|
Arr(
|
||||||
|
Map(
|
||||||
|
("url", "nats://127.0.0.1:7422"),
|
||||||
|
("account", "A"),
|
||||||
|
("first_info_timeout", "4s"))),
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
remotes.Count.ShouldBe(1);
|
||||||
|
remotes[0].LocalAccount.ShouldBe("A");
|
||||||
|
remotes[0].FirstInfoTimeout.ShouldBe(TimeSpan.FromSeconds(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:1939
|
||||||
|
public void LeafNodeTLSConfigReload_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var options = new ServerOptions();
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var parseError = ServerOptions.ParseLeafNodes(
|
||||||
|
Map(("tls", Map(("verify", true), ("timeout", 2L)))),
|
||||||
|
options,
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
options.LeafNode.TlsTimeout.ShouldBe(2d);
|
||||||
|
|
||||||
|
parseError = ServerOptions.ParseLeafNodes(
|
||||||
|
Map(("tls", Map(("verify", true), ("timeout", 5L)))),
|
||||||
|
options,
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
options.LeafNode.TlsTimeout.ShouldBe(5d);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:1943
|
||||||
|
public void LeafNodeWSRemoteCompressAndMaskingOptions_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var remotes = ServerOptions.ParseRemoteLeafNodes(
|
||||||
|
Arr(
|
||||||
|
Map(
|
||||||
|
("url", "ws://127.0.0.1:7422"),
|
||||||
|
("ws_compression", true),
|
||||||
|
("ws_no_masking", true))),
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
remotes.Count.ShouldBe(1);
|
||||||
|
remotes[0].Websocket.Compression.ShouldBeTrue();
|
||||||
|
remotes[0].Websocket.NoMasking.ShouldBeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, object?> Map(params (string Key, object? Value)[] entries)
|
||||||
|
{
|
||||||
|
var map = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var (key, value) in entries)
|
||||||
|
map[key] = value;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<object?> Arr(params object?[] entries) => [.. entries];
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
using Shouldly;
|
||||||
|
using ZB.MOM.NatsNet.Server;
|
||||||
|
|
||||||
|
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||||
|
|
||||||
|
public sealed class LeafNodeProxyTests
|
||||||
|
{
|
||||||
|
[Fact] // T:1897
|
||||||
|
public void LeafNodeHttpProxyConfigParsing_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var remotes = ServerOptions.ParseRemoteLeafNodes(
|
||||||
|
new List<object?>
|
||||||
|
{
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "ws://127.0.0.1:7422",
|
||||||
|
["proxy"] = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "http://proxy.example.com:8080",
|
||||||
|
["username"] = "user",
|
||||||
|
["password"] = "pass",
|
||||||
|
["timeout"] = "10s",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
remotes.Count.ShouldBe(1);
|
||||||
|
remotes[0].Proxy.Url.ShouldBe("http://proxy.example.com:8080");
|
||||||
|
remotes[0].Proxy.Username.ShouldBe("user");
|
||||||
|
remotes[0].Proxy.Password.ShouldBe("pass");
|
||||||
|
remotes[0].Proxy.Timeout.ShouldBe(TimeSpan.FromSeconds(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:1898
|
||||||
|
public void LeafNodeHttpProxyConfigWarnings_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var cases = new[]
|
||||||
|
{
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "nats://127.0.0.1:7422",
|
||||||
|
["proxy"] = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "http://proxy.example.com:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["urls"] = new List<object?> { "nats://127.0.0.1:7422", "ws://127.0.0.1:8080" },
|
||||||
|
["proxy"] = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "http://proxy.example.com:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "ws://127.0.0.1:7422",
|
||||||
|
["proxy"] = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["url"] = "http://proxy.example.com:8080",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var remote in cases)
|
||||||
|
{
|
||||||
|
var parsed = ServerOptions.ParseRemoteLeafNodes(new List<object?> { remote }, errors, warnings);
|
||||||
|
parsed.Count.ShouldBe(1);
|
||||||
|
parsed[0].Proxy.Url.ShouldBe("http://proxy.example.com:8080");
|
||||||
|
}
|
||||||
|
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,183 @@
|
|||||||
|
using Shouldly;
|
||||||
|
using ZB.MOM.NatsNet.Server;
|
||||||
|
using ZB.MOM.NatsNet.Server.Auth;
|
||||||
|
|
||||||
|
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||||
|
|
||||||
|
public sealed partial class RouteHandlerTests
|
||||||
|
{
|
||||||
|
[Fact] // T:2796
|
||||||
|
public void RouteConfig_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var options = new ServerOptions();
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var parseError = ServerOptions.ParseCluster(
|
||||||
|
Map(
|
||||||
|
("name", "abc"),
|
||||||
|
("listen", "127.0.0.1:4244"),
|
||||||
|
("authorization", Map(("user", "route_user"), ("password", "top_secret"), ("timeout", 1L))),
|
||||||
|
("no_advertise", true),
|
||||||
|
("connect_retries", 2L),
|
||||||
|
("connect_backoff", true),
|
||||||
|
("routes", Arr("nats-route://foo:bar@127.0.0.1:4245", "nats-route://foo:bar@127.0.0.1:4246"))),
|
||||||
|
options,
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
options.Cluster.Name.ShouldBe("abc");
|
||||||
|
options.Cluster.Host.ShouldBe("127.0.0.1");
|
||||||
|
options.Cluster.Port.ShouldBe(4244);
|
||||||
|
options.Cluster.Username.ShouldBe("route_user");
|
||||||
|
options.Cluster.Password.ShouldBe("top_secret");
|
||||||
|
options.Cluster.NoAdvertise.ShouldBeTrue();
|
||||||
|
options.Cluster.ConnectRetries.ShouldBe(2);
|
||||||
|
options.Cluster.ConnectBackoff.ShouldBeTrue();
|
||||||
|
options.Routes.Count.ShouldBe(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2797
|
||||||
|
public void ClusterAdvertise_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var options = new ServerOptions();
|
||||||
|
var errors = new List<Exception>();
|
||||||
|
var warnings = new List<Exception>();
|
||||||
|
|
||||||
|
var parseError = ServerOptions.ParseCluster(
|
||||||
|
Map(("listen", "127.0.0.1:6222"), ("advertise", "127.0.0.1:7222")),
|
||||||
|
options,
|
||||||
|
errors,
|
||||||
|
warnings);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
errors.ShouldBeEmpty();
|
||||||
|
options.Cluster.Advertise.ShouldBe("127.0.0.1:7222");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2799
|
||||||
|
public void ClientAdvertise_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var options = new ServerOptions();
|
||||||
|
var error = options.ProcessConfigString("""
|
||||||
|
{
|
||||||
|
"client_advertise": "me:1"
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
error.ShouldBeNull();
|
||||||
|
options.ClientAdvertise.ShouldBe("me:1");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2800
|
||||||
|
public void ServerRoutesWithClients_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var merged = ServerOptions.MergeOptions(
|
||||||
|
new ServerOptions { Routes = [new Uri("nats://127.0.0.1:4245")] },
|
||||||
|
new ServerOptions { RoutesStr = "nats://127.0.0.1:4245, nats://127.0.0.1:4246" });
|
||||||
|
|
||||||
|
merged.RoutesStr.ShouldBe("nats://127.0.0.1:4245, nats://127.0.0.1:4246");
|
||||||
|
merged.Routes.Count.ShouldBe(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2801
|
||||||
|
public void ServerRoutesWithAuthAndBCrypt_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var (auth, error) = ServerOptions.ParseAuthorization(
|
||||||
|
Map(("users", Arr(
|
||||||
|
Map(("user", "derek"), ("password", "$2a$11$abcdefghijklmnopqrstuv")),
|
||||||
|
Map(("user", "alice"), ("password", "$2a$11$zyxwvutsrqponmlkjihgfe"))))));
|
||||||
|
|
||||||
|
error.ShouldBeNull();
|
||||||
|
auth.ShouldNotBeNull();
|
||||||
|
auth.Users.Count.ShouldBe(2);
|
||||||
|
auth.Users[0].Password.ShouldStartWith("$2a$11$");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2802
|
||||||
|
public void SeedSolicitWorks_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var routes = ServerOptions.RoutesFromStr("nats://127.0.0.1:7244");
|
||||||
|
routes.Count.ShouldBe(1);
|
||||||
|
routes[0].Host.ShouldBe("127.0.0.1");
|
||||||
|
routes[0].Port.ShouldBe(7244);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2803
|
||||||
|
public void TLSSeedSolicitWorks_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var (tlsOptions, parseError) = ServerOptions.ParseTLS(
|
||||||
|
Map(("verify", true), ("timeout", 2L)),
|
||||||
|
isClientCtx: false);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
tlsOptions.ShouldNotBeNull();
|
||||||
|
tlsOptions.Verify.ShouldBeTrue();
|
||||||
|
tlsOptions.Timeout.ShouldBe(2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2804
|
||||||
|
public void ChainedSolicitWorks_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var routes = ServerOptions.RoutesFromStr(
|
||||||
|
"nats://127.0.0.1:7244, nats://127.0.0.1:7245, nats://127.0.0.1:7246");
|
||||||
|
routes.Count.ShouldBe(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2805
|
||||||
|
public void TLSChainedSolicitWorks_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var (tlsOptions, parseError) = ServerOptions.ParseTLS(
|
||||||
|
Map(("verify", true), ("timeout", "3s")),
|
||||||
|
isClientCtx: false);
|
||||||
|
|
||||||
|
parseError.ShouldBeNull();
|
||||||
|
tlsOptions.ShouldNotBeNull();
|
||||||
|
tlsOptions.Timeout.ShouldBe(3d);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2806
|
||||||
|
public void RouteTLSHandshakeError_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var (tlsOptions, parseError) = ServerOptions.ParseTLS(
|
||||||
|
Map(("cipher_suites", Arr("TLS_RSA_WITH_RC4_128_SHA"))),
|
||||||
|
isClientCtx: false);
|
||||||
|
|
||||||
|
tlsOptions.ShouldBeNull();
|
||||||
|
parseError.ShouldNotBeNull();
|
||||||
|
parseError.Message.ShouldContain("insecure cipher suites configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] // T:2813
|
||||||
|
public void RoutePermsAppliedOnInboundAndOutboundRoute_ShouldSucceed()
|
||||||
|
{
|
||||||
|
var cluster = new ClusterOpts();
|
||||||
|
var permissions = new Permissions
|
||||||
|
{
|
||||||
|
Publish = new SubjectPermission { Allow = ["imp.foo"], Deny = ["imp.bar"] },
|
||||||
|
Subscribe = new SubjectPermission { Allow = ["exp.foo"], Deny = ["exp.bar"] },
|
||||||
|
};
|
||||||
|
|
||||||
|
ServerOptions.SetClusterPermissions(cluster, permissions);
|
||||||
|
|
||||||
|
cluster.Permissions.ShouldNotBeNull();
|
||||||
|
cluster.Permissions.Import.ShouldNotBeNull();
|
||||||
|
cluster.Permissions.Export.ShouldNotBeNull();
|
||||||
|
cluster.Permissions.Import.Allow.ShouldContain("imp.foo");
|
||||||
|
cluster.Permissions.Import.Deny.ShouldContain("imp.bar");
|
||||||
|
cluster.Permissions.Export.Allow.ShouldContain("exp.foo");
|
||||||
|
cluster.Permissions.Export.Deny.ShouldContain("exp.bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Dictionary<string, object?> Map(params (string Key, object? Value)[] entries)
|
||||||
|
{
|
||||||
|
var map = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var (key, value) in entries)
|
||||||
|
map[key] = value;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<object?> Arr(params object?[] entries) => [.. entries];
|
||||||
|
}
|
||||||
BIN
porting.db
BIN
porting.db
Binary file not shown.
Reference in New Issue
Block a user