Files
natsdotnet/tests/NATS.Server.Auth.Tests/Auth/WildcardExportTests.cs
Joseph Doherty 36b9dfa654 refactor: extract NATS.Server.Auth.Tests project
Move 50 auth/accounts/permissions/JWT/NKey test files from
NATS.Server.Tests into a dedicated NATS.Server.Auth.Tests project.
Update namespaces, replace private GetFreePort/ReadUntilAsync helpers
with TestUtilities calls, replace Task.Delay with TaskCompletionSource
in test doubles, and add InternalsVisibleTo.

690 tests pass.
2026-03-12 15:54:07 -04:00

170 lines
7.6 KiB
C#

// Tests for wildcard service export matching on Account.
// Go reference: accounts_test.go — getWildcardServiceExport, getServiceExport (accounts.go line 2849).
using NATS.Server.Auth;
using NATS.Server.Imports;
namespace NATS.Server.Auth.Tests.Auth;
public class WildcardExportTests
{
private static Account CreateAccount(string name = "TestAccount") => new(name);
// ──────────────────────────────────────────────────────────────────────────
// GetWildcardServiceExport
// ──────────────────────────────────────────────────────────────────────────
[Fact]
public void GetWildcardServiceExport_ExactMatch_ReturnsExport()
{
// Go ref: accounts.go getWildcardServiceExport — exact key in exports.services map
var acct = CreateAccount();
acct.AddServiceExport("orders.create", ServiceResponseType.Singleton, null);
var result = acct.GetWildcardServiceExport("orders.create");
result.ShouldNotBeNull();
result.Subject.ShouldBe("orders.create");
result.ResponseType.ShouldBe(ServiceResponseType.Singleton);
}
[Fact]
public void GetWildcardServiceExport_StarWildcard_ReturnsExport()
{
// Go ref: accounts.go getWildcardServiceExport — isSubsetMatch with '*' wildcard
var acct = CreateAccount();
acct.AddServiceExport("orders.*", ServiceResponseType.Streamed, null);
var result = acct.GetWildcardServiceExport("orders.create");
result.ShouldNotBeNull();
result.Subject.ShouldBe("orders.*");
result.ResponseType.ShouldBe(ServiceResponseType.Streamed);
result.IsWildcard.ShouldBeTrue();
}
[Fact]
public void GetWildcardServiceExport_GtWildcard_ReturnsExport()
{
// Go ref: accounts.go getWildcardServiceExport — isSubsetMatch with '>' wildcard
var acct = CreateAccount();
acct.AddServiceExport("orders.>", ServiceResponseType.Chunked, null);
var result = acct.GetWildcardServiceExport("orders.create.new");
result.ShouldNotBeNull();
result.Subject.ShouldBe("orders.>");
result.ResponseType.ShouldBe(ServiceResponseType.Chunked);
result.IsWildcard.ShouldBeTrue();
}
[Fact]
public void GetWildcardServiceExport_NoMatch_ReturnsNull()
{
// Go ref: accounts.go getWildcardServiceExport — returns nil when no pattern matches
var acct = CreateAccount();
acct.AddServiceExport("payments.*", ServiceResponseType.Singleton, null);
var result = acct.GetWildcardServiceExport("orders.create");
result.ShouldBeNull();
}
// ──────────────────────────────────────────────────────────────────────────
// GetAllServiceExports
// ──────────────────────────────────────────────────────────────────────────
[Fact]
public void GetAllServiceExports_ReturnsAll()
{
// Go ref: accounts.go — exports.services map contains all registered exports
var acct = CreateAccount();
acct.AddServiceExport("svc.a", ServiceResponseType.Singleton, null);
acct.AddServiceExport("svc.b.*", ServiceResponseType.Streamed, null);
acct.AddServiceExport("svc.>", ServiceResponseType.Chunked, null);
var all = acct.GetAllServiceExports();
all.Count.ShouldBe(3);
all.Select(e => e.Subject).ShouldContain("svc.a");
all.Select(e => e.Subject).ShouldContain("svc.b.*");
all.Select(e => e.Subject).ShouldContain("svc.>");
}
// ──────────────────────────────────────────────────────────────────────────
// GetExactServiceExport
// ──────────────────────────────────────────────────────────────────────────
[Fact]
public void GetExactServiceExport_Found()
{
// Go ref: accounts.go getServiceExport — direct map lookup, no wildcard scan
var acct = CreateAccount();
acct.AddServiceExport("orders.create", ServiceResponseType.Singleton, null);
var result = acct.GetExactServiceExport("orders.create");
result.ShouldNotBeNull();
result.Subject.ShouldBe("orders.create");
}
[Fact]
public void GetExactServiceExport_NotFound_ReturnsNull()
{
// Go ref: accounts.go getServiceExport — map lookup misses wildcard patterns
var acct = CreateAccount();
acct.AddServiceExport("orders.*", ServiceResponseType.Singleton, null);
// "orders.create" is not an exact key in the map — only "orders.*" is
var result = acct.GetExactServiceExport("orders.create");
result.ShouldBeNull();
}
// ──────────────────────────────────────────────────────────────────────────
// HasServiceExport
// ──────────────────────────────────────────────────────────────────────────
[Fact]
public void HasServiceExport_ExactMatch_ReturnsTrue()
{
// Go ref: accounts.go — exact subject registered as an export
var acct = CreateAccount();
acct.AddServiceExport("orders.create", ServiceResponseType.Singleton, null);
acct.HasServiceExport("orders.create").ShouldBeTrue();
}
[Fact]
public void HasServiceExport_WildcardMatch_ReturnsTrue()
{
// Go ref: accounts.go — wildcard pattern covers the queried literal subject
var acct = CreateAccount();
acct.AddServiceExport("orders.>", ServiceResponseType.Singleton, null);
acct.HasServiceExport("orders.create.urgent").ShouldBeTrue();
}
// ──────────────────────────────────────────────────────────────────────────
// IsWildcard flag
// ──────────────────────────────────────────────────────────────────────────
[Theory]
[InlineData("orders.*", true)]
[InlineData("orders.>", true)]
[InlineData("orders.*.create", true)]
[InlineData("orders.create", false)]
[InlineData("svc", false)]
public void IsWildcard_DetectsWildcardSubjects(string subject, bool expectedWildcard)
{
// Go ref: accounts.go — wildcard subjects contain '*' or '>'
var acct = CreateAccount();
acct.AddServiceExport(subject, ServiceResponseType.Singleton, null);
var result = acct.GetExactServiceExport(subject);
result.ShouldNotBeNull();
result.IsWildcard.ShouldBe(expectedWildcard);
}
}