660 lines
21 KiB
C#
660 lines
21 KiB
C#
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);
|
|
}
|
|
|
|
[Fact] // T:333
|
|
public void GatewayNameClientInfo_ShouldSucceed()
|
|
=> ServerEventsConnectDisconnectForGlobalAcc_ShouldSucceed();
|
|
|
|
[Fact] // T:314
|
|
public void AccountReqMonitoring_ShouldSucceed()
|
|
{
|
|
var acc = Account.NewAccount("ACC-MON");
|
|
var id1 = acc.NextEventId();
|
|
var id2 = acc.NextEventId();
|
|
|
|
id1.ShouldNotBeNullOrWhiteSpace();
|
|
id2.ShouldNotBeNullOrWhiteSpace();
|
|
id1.ShouldNotBe(id2);
|
|
}
|
|
|
|
[Fact] // T:345
|
|
public void ServerEventsStatsZJetStreamApiLevel_ShouldSucceed()
|
|
{
|
|
var (server, err) = NatsServer.NewServer(new ServerOptions { JetStream = true });
|
|
err.ShouldBeNull();
|
|
server.ShouldNotBeNull();
|
|
|
|
JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0);
|
|
server!.GetOpts().JetStream.ShouldBeTrue();
|
|
}
|
|
|
|
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++;
|
|
}
|
|
}
|