Files
natsdotnet/tests/NATS.Server.Auth.Tests/Auth/ImportShadowingTests.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

171 lines
5.4 KiB
C#

// Tests for service import shadowing detection.
// Go reference: accounts.go serviceImportShadowed (~line 2015).
using NATS.Server.Auth;
using NATS.Server.Imports;
using NATS.Server.Subscriptions;
namespace NATS.Server.Auth.Tests.Auth;
public class ImportShadowingTests
{
private static Account CreateAccount(string name) => new(name);
private static Subscription MakeSub(string subject) =>
new() { Subject = subject, Sid = subject };
/// <summary>
/// Adds a service import entry directly to the account's import map (bypassing
/// export/cycle checks) so that shadowing tests can exercise the import map iteration.
/// </summary>
private static void RegisterServiceImport(Account account, string fromSubject)
{
var dest = CreateAccount("Dest");
var si = new ServiceImport
{
DestinationAccount = dest,
From = fromSubject,
To = fromSubject,
};
account.Imports.AddServiceImport(si);
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void ServiceImportShadowed_NoLocalSubs_ReturnsFalse()
{
var account = CreateAccount("A");
var result = account.ServiceImportShadowed("orders.create");
result.ShouldBeFalse();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void ServiceImportShadowed_ExactMatch_ReturnsTrue()
{
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("orders.create"));
var result = account.ServiceImportShadowed("orders.create");
result.ShouldBeTrue();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void ServiceImportShadowed_WildcardMatch_ReturnsTrue()
{
// Local subscription "orders.*" shadows import on "orders.create"
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("orders.*"));
var result = account.ServiceImportShadowed("orders.create");
result.ShouldBeTrue();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void ServiceImportShadowed_GtWildcard_ReturnsTrue()
{
// Local subscription "orders.>" shadows import on "orders.create.new"
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("orders.>"));
var result = account.ServiceImportShadowed("orders.create.new");
result.ShouldBeTrue();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void ServiceImportShadowed_NoMatch_ReturnsFalse()
{
// Local subscription "users.*" does NOT shadow import on "orders.create"
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("users.*"));
var result = account.ServiceImportShadowed("orders.create");
result.ShouldBeFalse();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void GetShadowedServiceImports_ReturnsOnlyShadowed()
{
var account = CreateAccount("A");
// Register two service imports
RegisterServiceImport(account, "orders.create");
RegisterServiceImport(account, "users.profile");
// Only add a local sub that shadows "orders.create"
account.SubList.Insert(MakeSub("orders.create"));
var shadowed = account.GetShadowedServiceImports();
shadowed.Count.ShouldBe(1);
shadowed.ShouldContain("orders.create");
shadowed.ShouldNotContain("users.profile");
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void HasShadowedImports_True_WhenShadowed()
{
var account = CreateAccount("A");
RegisterServiceImport(account, "orders.create");
account.SubList.Insert(MakeSub("orders.create"));
account.HasShadowedImports.ShouldBeTrue();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void HasShadowedImports_False_WhenNone()
{
var account = CreateAccount("A");
RegisterServiceImport(account, "orders.create");
// No local subs — nothing shadows the import
account.HasShadowedImports.ShouldBeFalse();
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void CheckServiceImportShadowing_ReturnsShadowingSubscriptions()
{
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("orders.*"));
account.SubList.Insert(MakeSub("orders.>"));
var result = account.CheckServiceImportShadowing("orders.create");
result.IsShadowed.ShouldBeTrue();
result.ImportSubject.ShouldBe("orders.create");
result.ShadowingSubscriptions.Count.ShouldBeGreaterThan(0);
// Both wildcard subs match "orders.create"
result.ShadowingSubscriptions.ShouldContain("orders.*");
result.ShadowingSubscriptions.ShouldContain("orders.>");
}
// Go reference: accounts.go serviceImportShadowed (~line 2015).
[Fact]
public void CheckServiceImportShadowing_NotShadowed()
{
var account = CreateAccount("A");
account.SubList.Insert(MakeSub("users.*"));
var result = account.CheckServiceImportShadowing("orders.create");
result.IsShadowed.ShouldBeFalse();
result.ImportSubject.ShouldBe("orders.create");
result.ShadowingSubscriptions.Count.ShouldBe(0);
}
}