- Rename tests/NATS.Server.Tests -> tests/NATS.Server.Core.Tests - Update solution file, InternalsVisibleTo, and csproj references - Remove JETSTREAM_INTEGRATION_MATRIX and NATS.NKeys from csproj (moved to JetStream.Tests and Auth.Tests) - Update all namespaces from NATS.Server.Tests.* to NATS.Server.Core.Tests.* - Replace private GetFreePort/ReadUntilAsync helpers with TestUtilities calls - Fix stale namespace in Transport.Tests/NetworkingGoParityTests.cs
131 lines
4.4 KiB
C#
131 lines
4.4 KiB
C#
using NATS.Server;
|
|
using NATS.Server.Auth;
|
|
using NATS.Server.Protocol;
|
|
using NATS.Server.Subscriptions;
|
|
|
|
namespace NATS.Server.Core.Tests.Subscriptions;
|
|
|
|
public class SubListParityBatch2Tests
|
|
{
|
|
[Fact]
|
|
public void RegisterQueueNotification_tracks_first_and_last_exact_queue_interest()
|
|
{
|
|
var subList = new SubList();
|
|
var notifications = new List<bool>();
|
|
Action<bool> callback = hasInterest => notifications.Add(hasInterest);
|
|
|
|
subList.RegisterQueueNotification("foo.bar", "q", callback).ShouldBeTrue();
|
|
notifications.ShouldBe([false]);
|
|
|
|
var sub1 = new Subscription { Subject = "foo.bar", Queue = "q", Sid = "1" };
|
|
var sub2 = new Subscription { Subject = "foo.bar", Queue = "q", Sid = "2" };
|
|
|
|
subList.Insert(sub1);
|
|
subList.Insert(sub2);
|
|
notifications.ShouldBe([false, true]);
|
|
|
|
subList.Remove(sub1);
|
|
notifications.ShouldBe([false, true]);
|
|
|
|
subList.Remove(sub2);
|
|
notifications.ShouldBe([false, true, false]);
|
|
|
|
subList.ClearQueueNotification("foo.bar", "q", callback).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void UpdateRemoteQSub_updates_queue_weight_for_match_remote()
|
|
{
|
|
var subList = new SubList();
|
|
var original = new RemoteSubscription("foo.bar", "q", "R1", Account: "A", QueueWeight: 1);
|
|
subList.ApplyRemoteSub(original);
|
|
subList.MatchRemote("A", "foo.bar").Count.ShouldBe(1);
|
|
|
|
subList.UpdateRemoteQSub(original with { QueueWeight = 3 });
|
|
subList.MatchRemote("A", "foo.bar").Count.ShouldBe(3);
|
|
}
|
|
|
|
[Fact]
|
|
public void SubListStats_Add_aggregates_stats_like_go()
|
|
{
|
|
var stats = new SubListStats
|
|
{
|
|
NumSubs = 1,
|
|
NumCache = 2,
|
|
NumInserts = 3,
|
|
NumRemoves = 4,
|
|
NumMatches = 10,
|
|
MaxFanout = 5,
|
|
TotalFanout = 8,
|
|
CacheEntries = 2,
|
|
CacheHits = 6,
|
|
};
|
|
|
|
stats.Add(new SubListStats
|
|
{
|
|
NumSubs = 2,
|
|
NumCache = 3,
|
|
NumInserts = 4,
|
|
NumRemoves = 5,
|
|
NumMatches = 30,
|
|
MaxFanout = 9,
|
|
TotalFanout = 12,
|
|
CacheEntries = 3,
|
|
CacheHits = 15,
|
|
});
|
|
|
|
stats.NumSubs.ShouldBe((uint)3);
|
|
stats.NumCache.ShouldBe((uint)5);
|
|
stats.NumInserts.ShouldBe((ulong)7);
|
|
stats.NumRemoves.ShouldBe((ulong)9);
|
|
stats.NumMatches.ShouldBe((ulong)40);
|
|
stats.MaxFanout.ShouldBe((uint)9);
|
|
stats.AvgFanout.ShouldBe(4.0);
|
|
stats.CacheHitRate.ShouldBe(0.525);
|
|
}
|
|
|
|
[Fact]
|
|
public void NumLevels_returns_max_trie_depth()
|
|
{
|
|
var subList = new SubList();
|
|
subList.Insert(new Subscription { Subject = "foo.bar.baz", Sid = "1" });
|
|
subList.Insert(new Subscription { Subject = "foo.bar", Sid = "2" });
|
|
|
|
subList.NumLevels().ShouldBe(3);
|
|
}
|
|
|
|
[Fact]
|
|
public void LocalSubs_filters_non_local_kinds_and_optionally_includes_leaf()
|
|
{
|
|
var subList = new SubList();
|
|
subList.Insert(new Subscription { Subject = "foo.a", Sid = "1", Client = new TestClient(ClientKind.Client) });
|
|
subList.Insert(new Subscription { Subject = "foo.b", Sid = "2", Client = new TestClient(ClientKind.Router) });
|
|
subList.Insert(new Subscription { Subject = "foo.c", Sid = "3", Client = new TestClient(ClientKind.System) });
|
|
subList.Insert(new Subscription { Subject = "foo.d", Sid = "4", Client = new TestClient(ClientKind.Leaf) });
|
|
|
|
var local = subList.LocalSubs(includeLeafHubs: false).Select(s => s.Sid).OrderBy(x => x).ToArray();
|
|
local.ShouldBe(["1", "3"]);
|
|
|
|
var withLeaf = subList.LocalSubs(includeLeafHubs: true).Select(s => s.Sid).OrderBy(x => x).ToArray();
|
|
withLeaf.ShouldBe(["1", "3", "4"]);
|
|
}
|
|
|
|
private sealed class TestClient(ClientKind kind) : INatsClient
|
|
{
|
|
public ulong Id => 1;
|
|
public ClientKind Kind => kind;
|
|
public Account? Account => null;
|
|
public ClientOptions? ClientOpts => null;
|
|
public ClientPermissions? Permissions => null;
|
|
public void SendMessage(string subject, string sid, string? replyTo, ReadOnlyMemory<byte> headers, ReadOnlyMemory<byte> payload)
|
|
{
|
|
}
|
|
|
|
public bool QueueOutbound(ReadOnlyMemory<byte> data) => true;
|
|
|
|
public void RemoveSubscription(string sid)
|
|
{
|
|
}
|
|
}
|
|
}
|