Files
natsdotnet/tests/NATS.E2E.Tests/AccountIsolationTests.cs
Joseph Doherty 88a82ee860 docs: add XML doc comments to server types and fix flaky test timings
Add XML doc comments to public properties across EventTypes, Connz, Varz,
NatsOptions, StreamConfig, IStreamStore, FileStore, MqttListener,
MqttSessionStore, MessageTraceContext, and JetStreamApiResponse. Fix flaky
tests by increasing timing margins (ResponseTracker expiry 1ms→50ms,
sleep 50ms→200ms) and document known flaky test patterns in tests.md.
2026-03-13 18:47:48 -04:00

99 lines
3.7 KiB
C#

using NATS.Client.Core;
using NATS.E2E.Tests.Infrastructure;
namespace NATS.E2E.Tests;
[Collection("E2E-Accounts")]
public class AccountIsolationTests(AccountServerFixture fixture)
{
[Fact]
public async Task Accounts_SameAccount_MessageDelivered()
{
await using var pub = fixture.CreateClientA();
await using var sub = fixture.CreateClientA();
await pub.ConnectAsync();
await sub.ConnectAsync();
await using var subscription = await sub.SubscribeCoreAsync<string>("acct.test");
await sub.PingAsync();
await pub.PublishAsync("acct.test", "intra-account");
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var msg = await subscription.Msgs.ReadAsync(cts.Token);
msg.Data.ShouldBe("intra-account");
}
[Fact]
public async Task Accounts_CrossAccount_MessageNotDelivered()
{
await using var pub = fixture.CreateClientA();
await using var sub = fixture.CreateClientB();
await pub.ConnectAsync();
await sub.ConnectAsync();
await using var subscription = await sub.SubscribeCoreAsync<string>("cross.test");
await sub.PingAsync();
await pub.PublishAsync("cross.test", "cross-account");
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var readTask = subscription.Msgs.ReadAsync(cts.Token).AsTask();
var completed = await Task.WhenAny(readTask, Task.Delay(3000));
completed.ShouldNotBe(readTask);
}
[Fact]
public async Task Accounts_EachAccountHasOwnNamespace()
{
await using var pubA = fixture.CreateClientA();
await using var subA = fixture.CreateClientA();
await using var pubB = fixture.CreateClientB();
await using var subB = fixture.CreateClientB();
await pubA.ConnectAsync();
await subA.ConnectAsync();
await pubB.ConnectAsync();
await subB.ConnectAsync();
await using var subscriptionA = await subA.SubscribeCoreAsync<string>("shared.topic");
await using var subscriptionB = await subB.SubscribeCoreAsync<string>("shared.topic");
await subA.PingAsync();
await subB.PingAsync();
// Publish from ACCT_A — only ACCT_A subscriber should receive
await pubA.PublishAsync("shared.topic", "from-a");
using var ctA = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var msgA = await subscriptionA.Msgs.ReadAsync(ctA.Token);
msgA.Data.ShouldBe("from-a");
using var ctsBNoMsg = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var readBTask = subscriptionB.Msgs.ReadAsync(ctsBNoMsg.Token).AsTask();
var completedB = await Task.WhenAny(readBTask, Task.Delay(3000));
completedB.ShouldNotBe(readBTask);
// Cancel the abandoned read so it doesn't consume the next message
await ctsBNoMsg.CancelAsync();
try { await readBTask; } catch (OperationCanceledException) { }
// Publish from ACCT_B — only ACCT_B subscriber should receive
await pubB.PublishAsync("shared.topic", "from-b");
using var ctB = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var msgB = await subscriptionB.Msgs.ReadAsync(ctB.Token);
msgB.Data.ShouldBe("from-b");
using var ctsANoMsg = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var readATask2 = subscriptionA.Msgs.ReadAsync(ctsANoMsg.Token).AsTask();
var completedA2 = await Task.WhenAny(readATask2, Task.Delay(3000));
completedA2.ShouldNotBe(readATask2);
await ctsANoMsg.CancelAsync();
try { await readATask2; } catch (OperationCanceledException) { }
}
}