feat(batch16): port client helper and permission core features

This commit is contained in:
Joseph Doherty
2026-02-28 18:53:59 -05:00
parent 0cc5d89199
commit 46ea749ad0
4 changed files with 364 additions and 11 deletions

View File

@@ -14,8 +14,10 @@
// Adapted from server/client_test.go in the NATS server Go source.
using System.Text;
using System.Linq;
using Shouldly;
using Xunit;
using ZB.MOM.NatsNet.Server.Auth;
using ZB.MOM.NatsNet.Server.Internal;
using ZB.MOM.NatsNet.Server.Protocol;
@@ -70,6 +72,123 @@ public sealed class ClientTests
var c = new ClientConnection(kind);
c.KindString().ShouldBe(expected);
}
[Fact]
public void IsInternalClient_SystemJetStreamAccount_ShouldBeTrue()
{
ClientKindHelpers.IsInternalClient(ClientKind.System).ShouldBeTrue();
ClientKindHelpers.IsInternalClient(ClientKind.JetStream).ShouldBeTrue();
ClientKindHelpers.IsInternalClient(ClientKind.Account).ShouldBeTrue();
ClientKindHelpers.IsInternalClient(ClientKind.Client).ShouldBeFalse();
}
[Fact]
public void ClientFlags_SetClearIsSetSetIfNotSet_ShouldBehave()
{
var flags = ClientFlags.None;
flags = flags.Set(ClientFlags.ConnectReceived);
flags.IsSet(ClientFlags.ConnectReceived).ShouldBeTrue();
ClientFlagExtensions.SetIfNotSet(ref flags, ClientFlags.ConnectReceived).ShouldBeFalse();
ClientFlagExtensions.SetIfNotSet(ref flags, ClientFlags.InfoReceived).ShouldBeTrue();
flags.IsSet(ClientFlags.InfoReceived).ShouldBeTrue();
flags = flags.Clear(ClientFlags.ConnectReceived);
flags.IsSet(ClientFlags.ConnectReceived).ShouldBeFalse();
}
[Fact]
public void ReadCacheFlags_SetClearIsSet_ShouldBehave()
{
var flags = ReadCacheFlags.None;
flags = flags.Set(ReadCacheFlags.HasMappings);
flags.IsSet(ReadCacheFlags.HasMappings).ShouldBeTrue();
flags = flags.Clear(ReadCacheFlags.HasMappings);
flags.IsSet(ReadCacheFlags.HasMappings).ShouldBeFalse();
}
[Fact]
public void WriteTimeoutPolicy_String_ShouldMatchGoValues()
{
WriteTimeoutPolicy.Close.String().ShouldBe("close");
WriteTimeoutPolicy.Retry.String().ShouldBe("retry");
WriteTimeoutPolicy.Default.String().ShouldBe(string.Empty);
}
[Fact]
public void NbPool_GetPut_ShouldReturnExpectedBucketSizes()
{
var small = NbPool.Get(10);
var medium = NbPool.Get(NbPool.SmallSize + 1);
var large = NbPool.Get(NbPool.MediumSize + 1);
small.Length.ShouldBeGreaterThanOrEqualTo(NbPool.SmallSize);
medium.Length.ShouldBeGreaterThanOrEqualTo(NbPool.MediumSize);
large.Length.ShouldBeGreaterThanOrEqualTo(NbPool.LargeSize);
NbPool.Put(small);
NbPool.Put(medium);
NbPool.Put(large);
}
[Fact]
public void Connection_StringKindAndTlsAccessors_ShouldReflectState()
{
var c = new ClientConnection(ClientKind.Router);
c.GetKind().ShouldBe(ClientKind.Router);
c.String().ShouldBe(string.Empty);
c.GetTLSConnectionState().ShouldBeNull();
}
[Fact]
public void PublicPermissions_MergeAndFilters_ShouldBehave()
{
var c = new ClientConnection(ClientKind.Client);
c.RegisterUser(new User
{
Permissions = new Permissions
{
Publish = new SubjectPermission { Allow = ["foo"], Deny = ["deny.once"] },
Subscribe = new SubjectPermission { Allow = ["bar"], Deny = ["sub.deny"] },
Response = new ResponsePermission { MaxMsgs = 10, Expires = TimeSpan.FromSeconds(1) },
},
});
var initial = c.PublicPermissions();
initial.ShouldNotBeNull();
initial!.Publish!.Allow.ShouldContain("foo");
initial.Publish.Deny.ShouldContain("deny.once");
initial.Subscribe!.Allow.ShouldContain("bar");
initial.Subscribe.Deny.ShouldContain("sub.deny");
initial.Response.ShouldNotBeNull();
c.MergeDenyPermissions(DenyType.Pub, ["deny.once", "deny.two"]);
c.MergeDenyPermissionsLocked(DenyType.Sub, ["sub.two"]);
var merged = c.PublicPermissions();
merged.ShouldNotBeNull();
merged!.Publish!.Deny!.Count(s => s == "deny.once").ShouldBe(1);
merged.Publish.Deny.ShouldContain("deny.two");
merged.Subscribe!.Deny.ShouldContain("sub.two");
c.LoadMsgDenyFilter();
c.MPerms.ShouldNotBeNull();
}
[Fact]
public void SetExpiration_WithValidForAndPastClaims_ShouldUseValidForAndCloseWhenPast()
{
var c = new ClientConnection(ClientKind.Client);
c.SetExpiration(0, TimeSpan.FromMilliseconds(30));
c.IsClosed().ShouldBeFalse();
var wait = SpinWait.SpinUntil(c.IsClosed, TimeSpan.FromSeconds(2));
wait.ShouldBeTrue();
var c2 = new ClientConnection(ClientKind.Client);
c2.SetExpiration(DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds(), TimeSpan.Zero);
SpinWait.SpinUntil(c2.IsClosed, TimeSpan.FromSeconds(2)).ShouldBeTrue();
}
}
/// <summary>