Files
natsdotnet/tests/NATS.Server.Core.Tests/Subscriptions/SubListParityBatch2Tests.cs
Joseph Doherty 7fbffffd05 refactor: rename remaining tests to NATS.Server.Core.Tests
- 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
2026-03-12 16:14:02 -04:00

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)
{
}
}
}