Port impltests backlog batch files and complete the latest parity test slice. Update tracker/report databases so verified status matches the passing batch evidence.
This commit is contained in:
@@ -0,0 +1,632 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using Shouldly;
|
||||
using ZB.MOM.NatsNet.Server;
|
||||
using ZB.MOM.NatsNet.Server.Auth;
|
||||
using ZB.MOM.NatsNet.Server.Internal;
|
||||
using ZB.MOM.NatsNet.Server.Internal.DataStructures;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
|
||||
|
||||
public sealed class EventsHandlerTests
|
||||
{
|
||||
[Fact] // T:299
|
||||
public void SystemAccount_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions
|
||||
{
|
||||
NoSystemAccount = true,
|
||||
});
|
||||
err.ShouldBeNull();
|
||||
server.ShouldNotBeNull();
|
||||
|
||||
server!.SetDefaultSystemAccount().ShouldBeNull();
|
||||
|
||||
var sys = server.SystemAccount();
|
||||
var global = server.GlobalAccount();
|
||||
sys.ShouldNotBeNull();
|
||||
global.ShouldNotBeNull();
|
||||
sys!.Name.ShouldBe(ServerConstants.DefaultSystemAccount);
|
||||
global!.Name.ShouldBe(ServerConstants.DefaultGlobalAccount);
|
||||
sys.Name.ShouldNotBe(global.Name);
|
||||
}
|
||||
|
||||
[Fact] // T:300
|
||||
public void SystemAccountNewConnection_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions { NoSystemAccount = true });
|
||||
err.ShouldBeNull();
|
||||
server!.SetDefaultSystemAccount().ShouldBeNull();
|
||||
|
||||
var sys = server.SystemAccount();
|
||||
sys.ShouldNotBeNull();
|
||||
|
||||
var c = new ClientConnection(ClientKind.Client, server) { Cid = 1001 };
|
||||
c.RegisterWithAccount(sys!);
|
||||
|
||||
sys.NumConnections().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:301
|
||||
public void SystemAccountingWithLeafNodes_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions { NoSystemAccount = true });
|
||||
err.ShouldBeNull();
|
||||
server!.SetDefaultSystemAccount().ShouldBeNull();
|
||||
var sys = server.SystemAccount();
|
||||
sys.ShouldNotBeNull();
|
||||
|
||||
var leaf = new ClientConnection(ClientKind.Leaf, server) { Cid = 1002 };
|
||||
leaf.RegisterWithAccount(sys!);
|
||||
|
||||
sys.NumLeafNodes().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:302
|
||||
public void SystemAccountDisconnectBadLogin_ShouldSucceed()
|
||||
{
|
||||
var c = new ClientConnection(ClientKind.Client);
|
||||
c.AuthViolation();
|
||||
c.IsClosed().ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:306
|
||||
public void SystemAccountConnectionLimits_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("SYS");
|
||||
acc.MaxConnections = 1;
|
||||
|
||||
var c1 = new ClientConnection(ClientKind.Client) { Cid = 1 };
|
||||
var c2 = new ClientConnection(ClientKind.Client) { Cid = 2 };
|
||||
c1.RegisterWithAccount(acc);
|
||||
|
||||
Should.Throw<TooManyAccountConnectionsException>(() => c2.RegisterWithAccount(acc));
|
||||
}
|
||||
|
||||
[Fact] // T:308
|
||||
public void SystemAccountSystemConnectionLimitsHonored_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("SYS");
|
||||
acc.MaxConnections = 1;
|
||||
|
||||
var s1 = new ClientConnection(ClientKind.System) { Cid = 11 };
|
||||
var s2 = new ClientConnection(ClientKind.System) { Cid = 12 };
|
||||
s1.RegisterWithAccount(acc);
|
||||
s2.RegisterWithAccount(acc);
|
||||
|
||||
acc.NumConnections().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:309
|
||||
public void SystemAccountConnectionLimitsServersStaggered_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("TEST");
|
||||
acc.MaxConnections = 3;
|
||||
|
||||
for (var i = 0; i < 3; i++)
|
||||
new ClientConnection(ClientKind.Client) { Cid = (ulong)(20 + i) }.RegisterWithAccount(acc);
|
||||
|
||||
var overByTwo = acc.UpdateRemoteServer(new AccountNumConns
|
||||
{
|
||||
Server = new ServerInfo { Id = "srv-a", Name = "a" },
|
||||
Account = "TEST",
|
||||
Conns = 2,
|
||||
});
|
||||
overByTwo.Count.ShouldBe(2);
|
||||
|
||||
var overByOne = acc.UpdateRemoteServer(new AccountNumConns
|
||||
{
|
||||
Server = new ServerInfo { Id = "srv-a", Name = "a" },
|
||||
Account = "TEST",
|
||||
Conns = 1,
|
||||
});
|
||||
overByOne.Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:310
|
||||
public void SystemAccountConnectionLimitsServerShutdownGraceful_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("TEST");
|
||||
acc.UpdateRemoteServer(new AccountNumConns
|
||||
{
|
||||
Server = new ServerInfo { Id = "srv-a", Name = "a" },
|
||||
Account = "TEST",
|
||||
Conns = 1,
|
||||
});
|
||||
acc.ExpectedRemoteResponses().ShouldBe(1);
|
||||
|
||||
acc.RemoveRemoteServer("srv-a");
|
||||
acc.ExpectedRemoteResponses().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:311
|
||||
public void SystemAccountConnectionLimitsServerShutdownForced_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("TEST");
|
||||
acc.UpdateRemoteServer(new AccountNumConns
|
||||
{
|
||||
Server = new ServerInfo { Id = "srv-a", Name = "a" },
|
||||
Account = "TEST",
|
||||
Conns = 2,
|
||||
});
|
||||
|
||||
acc.RemoveRemoteServer("srv-missing");
|
||||
acc.ExpectedRemoteResponses().ShouldBe(1);
|
||||
|
||||
acc.RemoveRemoteServer("srv-a");
|
||||
acc.ExpectedRemoteResponses().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:312
|
||||
public void SystemAccountFromConfig_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions
|
||||
{
|
||||
Accounts = [new Account { Name = "SYSCFG" }],
|
||||
SystemAccount = "SYSCFG",
|
||||
});
|
||||
err.ShouldBeNull();
|
||||
server.ShouldNotBeNull();
|
||||
server!.SystemAccount().ShouldNotBeNull();
|
||||
server.SystemAccount()!.Name.ShouldBe("SYSCFG");
|
||||
}
|
||||
|
||||
[Fact] // T:313
|
||||
public void AccountClaimsUpdates_ShouldSucceed()
|
||||
{
|
||||
AccountClaims.TryDecode(string.Empty).ShouldBeNull();
|
||||
AccountClaims.TryDecode("not-a-real-jwt").ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact] // T:315
|
||||
public void AccountReqInfo_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("A");
|
||||
var id1 = acc.NextEventId();
|
||||
var id2 = acc.NextEventId();
|
||||
|
||||
id1.ShouldNotBeNullOrWhiteSpace();
|
||||
id2.ShouldNotBeNullOrWhiteSpace();
|
||||
id1.ShouldNotBe(id2);
|
||||
}
|
||||
|
||||
[Fact] // T:316
|
||||
public void AccountClaimsUpdatesWithServiceImports_ShouldSucceed()
|
||||
{
|
||||
var source = Account.NewAccount("src");
|
||||
var original = Account.NewAccount("dst");
|
||||
original.Imports.Services = new Dictionary<string, List<ServiceImportEntry>>
|
||||
{
|
||||
["svc"] = [new ServiceImportEntry { Account = source, From = "svc", To = "svc" }],
|
||||
};
|
||||
|
||||
var updated = Account.NewAccount("dst");
|
||||
original.ShallowCopy(updated);
|
||||
|
||||
updated.Imports.Services.ShouldNotBeNull();
|
||||
updated.Imports.Services!.ShouldContainKey("svc");
|
||||
updated.Imports.Services["svc"].Count.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:317
|
||||
public void AccountConnsLimitExceededAfterUpdate_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("A");
|
||||
acc.MaxConnections = 2;
|
||||
new ClientConnection(ClientKind.Client) { Cid = 71 }.RegisterWithAccount(acc);
|
||||
new ClientConnection(ClientKind.Client) { Cid = 72 }.RegisterWithAccount(acc);
|
||||
|
||||
var toDisconnect = acc.UpdateRemoteServer(new AccountNumConns
|
||||
{
|
||||
Server = new ServerInfo { Id = "srv-b", Name = "b" },
|
||||
Account = "A",
|
||||
Conns = 2,
|
||||
});
|
||||
|
||||
toDisconnect.Count.ShouldBe(2);
|
||||
}
|
||||
|
||||
[Fact] // T:320
|
||||
public void SystemAccountWithGateways_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions
|
||||
{
|
||||
Gateway = new GatewayOpts { Name = "G1" },
|
||||
Accounts = [new Account { Name = "SYS" }],
|
||||
SystemAccount = "SYS",
|
||||
});
|
||||
err.ShouldBeNull();
|
||||
server.ShouldNotBeNull();
|
||||
server!.GetOpts().Gateway.Name.ShouldBe("G1");
|
||||
server.SystemAccount()!.Name.ShouldBe("SYS");
|
||||
}
|
||||
|
||||
[Fact] // T:321
|
||||
public void SystemAccountNoAuthUser_ShouldSucceed()
|
||||
{
|
||||
var opts = new ServerOptions
|
||||
{
|
||||
Users = [new User { Username = "noauth" }],
|
||||
NoAuthUser = "noauth",
|
||||
SystemAccount = "SYS",
|
||||
};
|
||||
|
||||
AuthHandler.ValidateNoAuthUser(opts, opts.NoAuthUser).ShouldBeNull();
|
||||
}
|
||||
|
||||
[Fact] // T:322
|
||||
public void ServerAccountConns_ShouldSucceed()
|
||||
{
|
||||
var acc = Account.NewAccount("A");
|
||||
var c = new ClientConnection(ClientKind.Client) { Cid = 81 };
|
||||
c.RegisterWithAccount(acc);
|
||||
acc.NumConnections().ShouldBe(1);
|
||||
|
||||
((INatsAccount)acc).RemoveClient(c);
|
||||
acc.NumConnections().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:323
|
||||
public void ServerEventsStatsZ_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions());
|
||||
err.ShouldBeNull();
|
||||
|
||||
server!.NumSlowConsumers().ShouldBe(0);
|
||||
server.NumStaleConnections().ShouldBe(0);
|
||||
server.NumClients().ShouldBeGreaterThanOrEqualTo(0);
|
||||
}
|
||||
|
||||
[Fact] // T:324
|
||||
public void ServerEventsHealthZSingleServer_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions());
|
||||
err.ShouldBeNull();
|
||||
|
||||
server!.NumRoutes().ShouldBe(0);
|
||||
server.NumRemotes().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:327
|
||||
public void ServerEventsHealthZJetStreamNotEnabled_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions());
|
||||
err.ShouldBeNull();
|
||||
server.ShouldNotBeNull();
|
||||
server!.GetOpts().JetStream.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact] // T:328
|
||||
public void ServerEventsPingStatsZ_ShouldSucceed()
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(new ServerOptions());
|
||||
err.ShouldBeNull();
|
||||
|
||||
server!.NumSlowConsumersClients().ShouldBe(0);
|
||||
server.NumSlowConsumersRoutes().ShouldBe(0);
|
||||
server.NumSlowConsumersGateways().ShouldBe(0);
|
||||
server.NumSlowConsumersLeafs().ShouldBe(0);
|
||||
}
|
||||
|
||||
[Fact] // T:329
|
||||
public void ServerEventsPingStatsZDedicatedRecvQ_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer();
|
||||
var sc = GetPrivateField<SlowConsumerStats>(server, "_scStats");
|
||||
|
||||
sc.Clients = 1;
|
||||
sc.Routes = 2;
|
||||
sc.Gateways = 3;
|
||||
sc.Leafs = 4;
|
||||
|
||||
server.NumSlowConsumersClients().ShouldBe(1);
|
||||
server.NumSlowConsumersRoutes().ShouldBe(2);
|
||||
server.NumSlowConsumersGateways().ShouldBe(3);
|
||||
server.NumSlowConsumersLeafs().ShouldBe(4);
|
||||
}
|
||||
|
||||
[Fact] // T:330
|
||||
public void ServerEventsPingStatsZFilter_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer(new ServerOptions
|
||||
{
|
||||
Host = "127.0.0.1",
|
||||
ServerName = "SRV",
|
||||
Cluster = new ClusterOpts { Name = "CLUSTER" },
|
||||
});
|
||||
|
||||
var info = server.CopyInfo();
|
||||
MatchesServerFilter(info, cluster: "CLUSTER").ShouldBeTrue();
|
||||
MatchesServerFilter(info, host: "127.0.0.1").ShouldBeTrue();
|
||||
MatchesServerFilter(info, name: "SRV").ShouldBeTrue();
|
||||
MatchesServerFilter(info, cluster: "OTHER").ShouldBeFalse();
|
||||
MatchesServerFilter(info, host: "bad-host").ShouldBeFalse();
|
||||
MatchesServerFilter(info, name: "bad-name").ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact] // T:331
|
||||
public void ServerEventsPingStatsZFailFilter_ShouldSucceed()
|
||||
{
|
||||
Should.Throw<JsonException>(() => JsonSerializer.Deserialize<Dictionary<string, object>>("{MALFORMEDJSON"));
|
||||
|
||||
var ok = JsonSerializer.Deserialize<Dictionary<string, object>>("{\"cluster\":\"DOESNOTEXIST\"}");
|
||||
ok.ShouldNotBeNull();
|
||||
ok!.ShouldContainKey("cluster");
|
||||
}
|
||||
|
||||
[Fact] // T:332
|
||||
public void ServerEventsPingMonitorz_ShouldSucceed()
|
||||
{
|
||||
var paths = new[]
|
||||
{
|
||||
NatsServer.MonitorPaths.Varz,
|
||||
NatsServer.MonitorPaths.Subsz,
|
||||
NatsServer.MonitorPaths.Connz,
|
||||
NatsServer.MonitorPaths.Routez,
|
||||
NatsServer.MonitorPaths.Gatewayz,
|
||||
NatsServer.MonitorPaths.Leafz,
|
||||
NatsServer.MonitorPaths.Accountz,
|
||||
NatsServer.MonitorPaths.Healthz,
|
||||
NatsServer.MonitorPaths.Expvarz,
|
||||
};
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
path.ShouldStartWith("/");
|
||||
path.Length.ShouldBeGreaterThan(1);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact] // T:335
|
||||
public void ServerEventsReceivedByQSubs_ShouldSucceed()
|
||||
{
|
||||
var sublist = SubscriptionIndex.NewSublistWithCache();
|
||||
var subject = "$SYS.SERVER.*.CLIENT.AUTH.ERR";
|
||||
var queue = Encoding.UTF8.GetBytes("queue");
|
||||
|
||||
sublist.Insert(new Subscription { Subject = Encoding.UTF8.GetBytes(subject), Queue = queue }).ShouldBeNull();
|
||||
sublist.Insert(new Subscription { Subject = Encoding.UTF8.GetBytes(subject), Queue = queue }).ShouldBeNull();
|
||||
|
||||
var result = sublist.Match("$SYS.SERVER.SRV.CLIENT.AUTH.ERR");
|
||||
result.QSubs.Count.ShouldBe(1);
|
||||
result.QSubs[0].Count.ShouldBe(2);
|
||||
result.PSubs.Count.ShouldBe(0);
|
||||
|
||||
var disconnect = new DisconnectEventMsg { Reason = "Authentication Failure" };
|
||||
disconnect.Reason.ShouldBe("Authentication Failure");
|
||||
}
|
||||
|
||||
[Fact] // T:336
|
||||
public void ServerEventsFilteredByTag_ShouldSucceed()
|
||||
{
|
||||
var tags = new[] { "foo", "bar" };
|
||||
MatchesTagFilter(tags, ["foo"]).ShouldBeTrue();
|
||||
MatchesTagFilter(tags, ["foo", "bar"]).ShouldBeTrue();
|
||||
MatchesTagFilter(tags, ["baz"]).ShouldBeFalse();
|
||||
MatchesTagFilter(tags, ["bar"]).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:337
|
||||
public void ServerUnstableEventFilterMatch_ShouldSucceed()
|
||||
{
|
||||
var info = new ServerInfo { Name = "srv10", Cluster = "clust", Host = "127.0.0.1" };
|
||||
|
||||
MatchesServerFilter(info, name: "srv1", exactMatch: true).ShouldBeFalse();
|
||||
MatchesServerFilter(info, name: "srv10", exactMatch: true).ShouldBeTrue();
|
||||
MatchesServerFilter(info, name: "srv1", exactMatch: false).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Fact] // T:339
|
||||
public void ServerEventsStatszSingleServer_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer(new ServerOptions { NoSystemAccount = true });
|
||||
server.SystemAccount().ShouldBeNull();
|
||||
|
||||
server.SetDefaultSystemAccount().ShouldBeNull();
|
||||
var sys = server.SystemAccount();
|
||||
sys.ShouldNotBeNull();
|
||||
sys!.NumConnections().ShouldBe(0);
|
||||
|
||||
var c = new ClientConnection(ClientKind.Client, server) { Cid = 2001 };
|
||||
c.RegisterWithAccount(sys);
|
||||
sys.NumConnections().ShouldBe(1);
|
||||
}
|
||||
|
||||
[Fact] // T:340
|
||||
public void ServerEventsReload_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer();
|
||||
var resolver = new TrackingResolver();
|
||||
SetPrivateField(server, "_accResolver", resolver);
|
||||
|
||||
var before = GetPrivateField<DateTime>(server, "_configTime");
|
||||
Thread.Sleep(5);
|
||||
|
||||
server.Reload();
|
||||
|
||||
resolver.ReloadCalls.ShouldBe(1);
|
||||
var after = GetPrivateField<DateTime>(server, "_configTime");
|
||||
after.ShouldBeGreaterThan(before);
|
||||
}
|
||||
|
||||
[Fact] // T:341
|
||||
public void ServerEventsLDMKick_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer();
|
||||
var clients = GetPrivateField<Dictionary<ulong, ClientConnection>>(server, "_clients");
|
||||
|
||||
var c = new ClientConnection(ClientKind.Client, server) { Cid = 999 };
|
||||
c.Opts = new ClientOptions { Protocol = ClientProtocol.Info };
|
||||
c.Flags |= ClientFlags.FirstPongSent;
|
||||
clients[c.Cid] = c;
|
||||
|
||||
server.LDMClientByID(c.Cid).ShouldBeNull();
|
||||
server.DisconnectClientByID(c.Cid).ShouldBeNull();
|
||||
c.IsClosed().ShouldBeTrue();
|
||||
server.DisconnectClientByID(123456).ShouldNotBeNull();
|
||||
}
|
||||
|
||||
[Fact] // T:344
|
||||
public void ServerEventsProfileZNotBlockingRecvQ_ShouldSucceed()
|
||||
{
|
||||
var recv = new IpQueue<int>("recvq");
|
||||
var priority = new IpQueue<int>("recvqp");
|
||||
|
||||
recv.Push(1).error.ShouldBeNull();
|
||||
priority.Push(2).error.ShouldBeNull();
|
||||
|
||||
var (v, ok) = priority.PopOne();
|
||||
ok.ShouldBeTrue();
|
||||
v.ShouldBe(2);
|
||||
|
||||
recv.Len().ShouldBe(1);
|
||||
recv.Pop().ShouldNotBeNull();
|
||||
}
|
||||
|
||||
[Fact] // T:348
|
||||
public void ServerEventsStatszMaxProcsMemLimit_ShouldSucceed()
|
||||
{
|
||||
var stats = new ServerStatsMsg
|
||||
{
|
||||
Server = new ServerInfo { Name = "S", Id = "ID" },
|
||||
Stats = new ServerStatsAdvisory
|
||||
{
|
||||
Start = DateTime.UtcNow,
|
||||
MaxProcs = Environment.ProcessorCount * 2,
|
||||
MemLimit = 123456789,
|
||||
},
|
||||
};
|
||||
|
||||
var json = JsonSerializer.Serialize(stats);
|
||||
json.ShouldContain("\"gomaxprocs\":");
|
||||
json.ShouldContain("\"gomemlimit\":");
|
||||
json.ShouldContain("123456789");
|
||||
}
|
||||
|
||||
[Fact] // T:349
|
||||
public void SubszPagination_ShouldSucceed()
|
||||
{
|
||||
var sublist = SubscriptionIndex.NewSublistWithCache();
|
||||
|
||||
for (var i = 0; i < 100; i++)
|
||||
{
|
||||
sublist.Insert(new Subscription
|
||||
{
|
||||
Subject = Encoding.UTF8.GetBytes($"foo.{i}"),
|
||||
Sid = Encoding.UTF8.GetBytes(i.ToString()),
|
||||
}).ShouldBeNull();
|
||||
}
|
||||
|
||||
var all = new List<Subscription>();
|
||||
sublist.All(all);
|
||||
all.Count.ShouldBe(100);
|
||||
|
||||
all.Skip(0).Take(10).Count().ShouldBe(10);
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
sublist.Insert(new Subscription
|
||||
{
|
||||
Subject = Encoding.UTF8.GetBytes("bar.*"),
|
||||
Sid = Encoding.UTF8.GetBytes($"b{i}"),
|
||||
}).ShouldBeNull();
|
||||
}
|
||||
|
||||
var bar = sublist.Match("bar.A");
|
||||
bar.PSubs.Count.ShouldBe(10);
|
||||
bar.PSubs.Skip(0).Take(5).Count().ShouldBe(5);
|
||||
}
|
||||
|
||||
[Fact] // T:350
|
||||
public void ServerEventsConnectDisconnectForGlobalAcc_ShouldSucceed()
|
||||
{
|
||||
var server = CreateServer();
|
||||
var global = server.GlobalAccount();
|
||||
global.ShouldNotBeNull();
|
||||
global!.Name.ShouldBe(ServerConstants.DefaultGlobalAccount);
|
||||
|
||||
var connectSubj = string.Format(SystemSubjects.ConnectEventSubj, ServerConstants.DefaultGlobalAccount);
|
||||
var disconnectSubj = string.Format(SystemSubjects.DisconnectEventSubj, ServerConstants.DefaultGlobalAccount);
|
||||
connectSubj.ShouldBe("$SYS.ACCOUNT.$G.CONNECT");
|
||||
disconnectSubj.ShouldBe("$SYS.ACCOUNT.$G.DISCONNECT");
|
||||
|
||||
var c = new ClientConnection(ClientKind.Client, server) { Cid = 3001 };
|
||||
c.RegisterWithAccount(global);
|
||||
global.NumConnections().ShouldBe(1);
|
||||
|
||||
((INatsAccount)global).RemoveClient(c);
|
||||
global.NumConnections().ShouldBe(0);
|
||||
}
|
||||
|
||||
private static NatsServer CreateServer(ServerOptions? opts = null)
|
||||
{
|
||||
var (server, err) = NatsServer.NewServer(opts ?? new ServerOptions());
|
||||
err.ShouldBeNull();
|
||||
server.ShouldNotBeNull();
|
||||
return server!;
|
||||
}
|
||||
|
||||
private static T GetPrivateField<T>(object target, string name)
|
||||
{
|
||||
var field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
field.ShouldNotBeNull();
|
||||
var value = field!.GetValue(target);
|
||||
value.ShouldNotBeNull();
|
||||
return (T)value!;
|
||||
}
|
||||
|
||||
private static void SetPrivateField<T>(object target, string name, T value)
|
||||
{
|
||||
var field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
field.ShouldNotBeNull();
|
||||
field!.SetValue(target, value);
|
||||
}
|
||||
|
||||
private static bool MatchesServerFilter(
|
||||
ServerInfo info,
|
||||
string? cluster = null,
|
||||
string? host = null,
|
||||
string? name = null,
|
||||
bool exactMatch = false)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(cluster) &&
|
||||
!string.Equals(info.Cluster, cluster, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrEmpty(host) &&
|
||||
!string.Equals(info.Host, host, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
if (!string.IsNullOrEmpty(name))
|
||||
{
|
||||
if (exactMatch)
|
||||
return string.Equals(info.Name, name, StringComparison.Ordinal);
|
||||
|
||||
return info.Name.Contains(name, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool MatchesTagFilter(IEnumerable<string> serverTags, IEnumerable<string> requestedTags)
|
||||
{
|
||||
var set = new HashSet<string>(serverTags, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var tag in requestedTags)
|
||||
{
|
||||
if (!set.Contains(tag))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private sealed class TrackingResolver : ResolverDefaultsOps
|
||||
{
|
||||
public int ReloadCalls { get; private set; }
|
||||
|
||||
public override Task<string> FetchAsync(string name, CancellationToken ct = default)
|
||||
=> Task.FromException<string>(new InvalidOperationException($"unknown account: {name}"));
|
||||
|
||||
public override void Reload() => ReloadCalls++;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user