135 lines
4.1 KiB
C#
135 lines
4.1 KiB
C#
using NATS.Server;
|
|
using NATS.Server.Auth;
|
|
using NATS.Server.Imports;
|
|
|
|
namespace NATS.Server.Tests;
|
|
|
|
public class ImportExportTests
|
|
{
|
|
[Fact]
|
|
public void ExportAuth_public_export_authorizes_any_account()
|
|
{
|
|
var auth = new ExportAuth();
|
|
var account = new Account("test");
|
|
auth.IsAuthorized(account).ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void ExportAuth_approved_accounts_restricts_access()
|
|
{
|
|
var auth = new ExportAuth { ApprovedAccounts = ["allowed"] };
|
|
var allowed = new Account("allowed");
|
|
var denied = new Account("denied");
|
|
auth.IsAuthorized(allowed).ShouldBeTrue();
|
|
auth.IsAuthorized(denied).ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void ExportAuth_revoked_account_denied()
|
|
{
|
|
var auth = new ExportAuth
|
|
{
|
|
ApprovedAccounts = ["test"],
|
|
RevokedAccounts = new() { ["test"] = DateTimeOffset.UtcNow.ToUnixTimeSeconds() },
|
|
};
|
|
var account = new Account("test");
|
|
auth.IsAuthorized(account).ShouldBeFalse();
|
|
}
|
|
|
|
[Fact]
|
|
public void ServiceResponseType_defaults_to_singleton()
|
|
{
|
|
var import = new ServiceImport
|
|
{
|
|
DestinationAccount = new Account("dest"),
|
|
From = "requests.>",
|
|
To = "api.>",
|
|
};
|
|
import.ResponseType.ShouldBe(ServiceResponseType.Singleton);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExportMap_stores_and_retrieves_exports()
|
|
{
|
|
var map = new ExportMap();
|
|
map.Services["api.>"] = new ServiceExport { Account = new Account("svc") };
|
|
map.Streams["events.>"] = new StreamExport();
|
|
|
|
map.Services.ShouldContainKey("api.>");
|
|
map.Streams.ShouldContainKey("events.>");
|
|
}
|
|
|
|
[Fact]
|
|
public void ImportMap_stores_service_imports()
|
|
{
|
|
var map = new ImportMap();
|
|
var si = new ServiceImport
|
|
{
|
|
DestinationAccount = new Account("dest"),
|
|
From = "requests.>",
|
|
To = "api.>",
|
|
};
|
|
map.AddServiceImport(si);
|
|
map.Services.ShouldContainKey("requests.>");
|
|
map.Services["requests.>"].Count.ShouldBe(1);
|
|
}
|
|
|
|
[Fact]
|
|
public void Account_add_service_export_and_import()
|
|
{
|
|
var exporter = new Account("exporter");
|
|
var importer = new Account("importer");
|
|
|
|
exporter.AddServiceExport("api.>", ServiceResponseType.Singleton, null);
|
|
exporter.Exports.Services.ShouldContainKey("api.>");
|
|
|
|
var si = importer.AddServiceImport(exporter, "requests.>", "api.>");
|
|
si.ShouldNotBeNull();
|
|
si.From.ShouldBe("requests.>");
|
|
si.To.ShouldBe("api.>");
|
|
si.DestinationAccount.ShouldBe(exporter);
|
|
importer.Imports.Services.ShouldContainKey("requests.>");
|
|
}
|
|
|
|
[Fact]
|
|
public void Account_add_stream_export_and_import()
|
|
{
|
|
var exporter = new Account("exporter");
|
|
var importer = new Account("importer");
|
|
|
|
exporter.AddStreamExport("events.>", null);
|
|
exporter.Exports.Streams.ShouldContainKey("events.>");
|
|
|
|
importer.AddStreamImport(exporter, "events.>", "imported.events.>");
|
|
importer.Imports.Streams.Count.ShouldBe(1);
|
|
importer.Imports.Streams[0].From.ShouldBe("events.>");
|
|
importer.Imports.Streams[0].To.ShouldBe("imported.events.>");
|
|
}
|
|
|
|
[Fact]
|
|
public void Account_service_import_auth_rejected()
|
|
{
|
|
var exporter = new Account("exporter");
|
|
var importer = new Account("importer");
|
|
|
|
exporter.AddServiceExport("api.>", ServiceResponseType.Singleton, [new Account("other")]);
|
|
|
|
Should.Throw<UnauthorizedAccessException>(() =>
|
|
importer.AddServiceImport(exporter, "requests.>", "api.>"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Account_lazy_creates_internal_client()
|
|
{
|
|
var account = new Account("test");
|
|
var client = account.GetOrCreateInternalClient(99);
|
|
client.ShouldNotBeNull();
|
|
client.Kind.ShouldBe(ClientKind.Account);
|
|
client.Account.ShouldBe(account);
|
|
|
|
// Second call returns same instance
|
|
var client2 = account.GetOrCreateInternalClient(100);
|
|
client2.ShouldBeSameAs(client);
|
|
}
|
|
}
|