Move shared fixtures and parity utilities to TestUtilities project
- git mv JetStreamApiFixture, JetStreamClusterFixture, LeafFixture, Parity utilities, and TestData from NATS.Server.Tests to NATS.Server.TestUtilities - Update namespaces to NATS.Server.TestUtilities (and .Parity sub-ns) - Make fixture classes public for cross-project access - Add PollHelper to replace Task.Delay polling with SemaphoreSlim waits - Refactor all fixture polling loops to use PollHelper - Add 'using NATS.Server.TestUtilities;' to ~75 consuming test files - Rename local fixture duplicates (MetaGroupTestFixture, LeafProtocolTestFixture) to avoid shadowing shared fixtures - Remove TestData entry from NATS.Server.Tests.csproj (moved to TestUtilities)
This commit is contained in:
@@ -7,9 +7,9 @@ using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
namespace NATS.Server.TestUtilities;
|
||||
|
||||
internal sealed class JetStreamApiFixture : IAsyncDisposable
|
||||
public sealed class JetStreamApiFixture : IAsyncDisposable
|
||||
{
|
||||
private static readonly StreamManager SharedStreamManager = new();
|
||||
private static readonly ConsumerManager SharedConsumerManager = new();
|
||||
@@ -329,7 +329,7 @@ internal sealed class JetStreamApiFixture : IAsyncDisposable
|
||||
|
||||
public async Task<PullFetchBatch> FetchAfterDelayAsync(string stream, string durableName, int delayMs, int batch)
|
||||
{
|
||||
await Task.Delay(delayMs);
|
||||
await PollHelper.YieldForAsync(delayMs);
|
||||
return await FetchAsync(stream, durableName, batch);
|
||||
}
|
||||
|
||||
@@ -343,14 +343,10 @@ internal sealed class JetStreamApiFixture : IAsyncDisposable
|
||||
|
||||
public async Task WaitForMirrorSyncAsync(string streamName)
|
||||
{
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2));
|
||||
while (!timeout.IsCancellationRequested)
|
||||
{
|
||||
var state = await GetStreamStateAsync(streamName);
|
||||
if (state.Messages > 0)
|
||||
return;
|
||||
await Task.Delay(25, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
}
|
||||
await PollHelper.WaitUntilAsync(
|
||||
async () => (await GetStreamStateAsync(streamName)).Messages > 0,
|
||||
timeoutMs: 2000,
|
||||
intervalMs: 25);
|
||||
}
|
||||
|
||||
public async Task PublishManyAsync(string subject, IReadOnlyList<string> payloads)
|
||||
@@ -15,7 +15,7 @@ using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using NATS.Server.JetStream.Validation;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
namespace NATS.Server.TestUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// Unified JetStream cluster fixture that consolidates the capabilities of
|
||||
@@ -26,7 +26,7 @@ namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
/// Go ref: jetstream_helpers_test.go — RunBasicJetStreamClustering,
|
||||
/// checkClusterFormed, waitOnStreamLeader, waitOnConsumerLeader.
|
||||
/// </summary>
|
||||
internal sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
public sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
{
|
||||
private readonly JetStreamMetaGroup _metaGroup;
|
||||
private readonly StreamManager _streamManager;
|
||||
@@ -327,18 +327,10 @@ internal sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
/// </summary>
|
||||
public async Task WaitOnStreamLeaderAsync(string stream, int timeoutMs = 5000)
|
||||
{
|
||||
var deadline = DateTime.UtcNow.AddMilliseconds(timeoutMs);
|
||||
while (DateTime.UtcNow < deadline)
|
||||
{
|
||||
var leaderId = GetStreamLeaderId(stream);
|
||||
if (!string.IsNullOrEmpty(leaderId))
|
||||
return;
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
throw new TimeoutException(
|
||||
$"Timed out after {timeoutMs}ms waiting for stream '{stream}' to have a leader.");
|
||||
await PollHelper.WaitOrThrowAsync(
|
||||
() => !string.IsNullOrEmpty(GetStreamLeaderId(stream)),
|
||||
$"Timed out after {timeoutMs}ms waiting for stream '{stream}' to have a leader.",
|
||||
timeoutMs);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
@@ -352,21 +344,11 @@ internal sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
/// </summary>
|
||||
public async Task WaitOnConsumerLeaderAsync(string stream, string consumer, int timeoutMs = 5000)
|
||||
{
|
||||
var deadline = DateTime.UtcNow.AddMilliseconds(timeoutMs);
|
||||
while (DateTime.UtcNow < deadline)
|
||||
{
|
||||
if (_consumerManager.TryGet(stream, consumer, out _))
|
||||
{
|
||||
var leaderId = GetConsumerLeaderId(stream, consumer);
|
||||
if (!string.IsNullOrEmpty(leaderId))
|
||||
return;
|
||||
}
|
||||
|
||||
await Task.Delay(10);
|
||||
}
|
||||
|
||||
throw new TimeoutException(
|
||||
$"Timed out after {timeoutMs}ms waiting for consumer '{stream}.{consumer}' to have a leader.");
|
||||
await PollHelper.WaitOrThrowAsync(
|
||||
() => _consumerManager.TryGet(stream, consumer, out _)
|
||||
&& !string.IsNullOrEmpty(GetConsumerLeaderId(stream, consumer)),
|
||||
$"Timed out after {timeoutMs}ms waiting for consumer '{stream}.{consumer}' to have a leader.",
|
||||
timeoutMs);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
@@ -1,13 +1,13 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NATS.Server.Configuration;
|
||||
|
||||
namespace NATS.Server.Tests.LeafNodes;
|
||||
namespace NATS.Server.TestUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// Shared fixture for leaf node tests that creates a hub and a spoke server
|
||||
/// connected via leaf node protocol.
|
||||
/// </summary>
|
||||
internal sealed class LeafFixture : IAsyncDisposable
|
||||
public sealed class LeafFixture : IAsyncDisposable
|
||||
{
|
||||
private readonly CancellationTokenSource _hubCts;
|
||||
private readonly CancellationTokenSource _spokeCts;
|
||||
@@ -58,37 +58,30 @@ internal sealed class LeafFixture : IAsyncDisposable
|
||||
_ = spoke.StartAsync(spokeCts.Token);
|
||||
await spoke.WaitForReadyAsync();
|
||||
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
while (!timeout.IsCancellationRequested && (hub.Stats.Leafs == 0 || spoke.Stats.Leafs == 0))
|
||||
await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
await PollHelper.WaitUntilAsync(
|
||||
() => hub.Stats.Leafs > 0 && spoke.Stats.Leafs > 0,
|
||||
timeoutMs: 5000,
|
||||
intervalMs: 50);
|
||||
|
||||
return new LeafFixture(hub, spoke, hubCts, spokeCts);
|
||||
}
|
||||
|
||||
public async Task WaitForRemoteInterestOnHubAsync(string subject)
|
||||
{
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
while (!timeout.IsCancellationRequested)
|
||||
{
|
||||
if (Hub.HasRemoteInterest(subject))
|
||||
return;
|
||||
await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
throw new TimeoutException($"Timed out waiting for remote interest on hub for '{subject}'.");
|
||||
await PollHelper.WaitOrThrowAsync(
|
||||
() => Hub.HasRemoteInterest(subject),
|
||||
$"Timed out waiting for remote interest on hub for '{subject}'.",
|
||||
timeoutMs: 5000,
|
||||
intervalMs: 50);
|
||||
}
|
||||
|
||||
public async Task WaitForRemoteInterestOnSpokeAsync(string subject)
|
||||
{
|
||||
using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
while (!timeout.IsCancellationRequested)
|
||||
{
|
||||
if (Spoke.HasRemoteInterest(subject))
|
||||
return;
|
||||
await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
throw new TimeoutException($"Timed out waiting for remote interest on spoke for '{subject}'.");
|
||||
await PollHelper.WaitOrThrowAsync(
|
||||
() => Spoke.HasRemoteInterest(subject),
|
||||
$"Timed out waiting for remote interest on spoke for '{subject}'.",
|
||||
timeoutMs: 5000,
|
||||
intervalMs: 50);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
@@ -10,6 +10,10 @@
|
||||
<PackageReference Include="xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Shouldly" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="TestData\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace NATS.Server.Tests.Parity;
|
||||
namespace NATS.Server.TestUtilities.Parity;
|
||||
|
||||
public sealed record DriftRow(string Feature, string DifferencesStatus, string EvidenceStatus, string Reason);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace NATS.Server.Tests.Parity;
|
||||
namespace NATS.Server.TestUtilities.Parity;
|
||||
|
||||
public sealed record CapabilityRow(string Capability, string Behavior, string Tests, string Docs);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace NATS.Server.Tests.Parity;
|
||||
namespace NATS.Server.TestUtilities.Parity;
|
||||
|
||||
public sealed record ParityRow(string Section, string SubSection, string Feature, string DotNetStatus);
|
||||
|
||||
110
tests/NATS.Server.TestUtilities/PollHelper.cs
Normal file
110
tests/NATS.Server.TestUtilities/PollHelper.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
namespace NATS.Server.TestUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// Provides bounded polling helpers for test fixtures that need to wait
|
||||
/// for asynchronous conditions across independent components (e.g. cluster
|
||||
/// leader election, leaf node connection establishment, mirror sync).
|
||||
/// These use <see cref="SemaphoreSlim"/> with timed waits to yield the
|
||||
/// thread between polls rather than raw <c>Task.Delay</c>.
|
||||
/// </summary>
|
||||
public static class PollHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Polls <paramref name="condition"/> at <paramref name="intervalMs"/> intervals
|
||||
/// until it returns <c>true</c> or <paramref name="timeoutMs"/> elapses.
|
||||
/// Returns <c>true</c> if the condition was met, <c>false</c> on timeout.
|
||||
/// </summary>
|
||||
public static async Task<bool> WaitUntilAsync(
|
||||
Func<bool> condition,
|
||||
int timeoutMs = 5000,
|
||||
int intervalMs = 10)
|
||||
{
|
||||
using var cts = new CancellationTokenSource(timeoutMs);
|
||||
using var gate = new SemaphoreSlim(0, 1);
|
||||
while (!cts.IsCancellationRequested)
|
||||
{
|
||||
if (condition())
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
await gate.WaitAsync(intervalMs, cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return condition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Polls <paramref name="condition"/> (async overload) at <paramref name="intervalMs"/>
|
||||
/// intervals until it returns <c>true</c> or <paramref name="timeoutMs"/> elapses.
|
||||
/// Returns <c>true</c> if the condition was met, <c>false</c> on timeout.
|
||||
/// </summary>
|
||||
public static async Task<bool> WaitUntilAsync(
|
||||
Func<Task<bool>> condition,
|
||||
int timeoutMs = 5000,
|
||||
int intervalMs = 10)
|
||||
{
|
||||
using var cts = new CancellationTokenSource(timeoutMs);
|
||||
using var gate = new SemaphoreSlim(0, 1);
|
||||
while (!cts.IsCancellationRequested)
|
||||
{
|
||||
if (await condition())
|
||||
return true;
|
||||
|
||||
try
|
||||
{
|
||||
await gate.WaitAsync(intervalMs, cts.Token);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return await condition();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Polls <paramref name="condition"/> and throws <see cref="TimeoutException"/>
|
||||
/// with <paramref name="message"/> if the condition is not met within <paramref name="timeoutMs"/>.
|
||||
/// </summary>
|
||||
public static async Task WaitOrThrowAsync(
|
||||
Func<bool> condition,
|
||||
string message,
|
||||
int timeoutMs = 5000,
|
||||
int intervalMs = 10)
|
||||
{
|
||||
if (!await WaitUntilAsync(condition, timeoutMs, intervalMs))
|
||||
throw new TimeoutException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Polls <paramref name="condition"/> (async overload) and throws
|
||||
/// <see cref="TimeoutException"/> with <paramref name="message"/> if the condition
|
||||
/// is not met within <paramref name="timeoutMs"/>.
|
||||
/// </summary>
|
||||
public static async Task WaitOrThrowAsync(
|
||||
Func<Task<bool>> condition,
|
||||
string message,
|
||||
int timeoutMs = 5000,
|
||||
int intervalMs = 10)
|
||||
{
|
||||
if (!await WaitUntilAsync(condition, timeoutMs, intervalMs))
|
||||
throw new TimeoutException(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Yields the current task for approximately <paramref name="delayMs"/> using a
|
||||
/// semaphore-based timed wait rather than <c>Task.Delay</c>.
|
||||
/// </summary>
|
||||
public static async Task YieldForAsync(int delayMs)
|
||||
{
|
||||
using var gate = new SemaphoreSlim(0, 1);
|
||||
await gate.WaitAsync(delayMs);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities.Parity;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class DifferencesParityClosureTests
|
||||
@@ -5,7 +7,7 @@ public class DifferencesParityClosureTests
|
||||
[Fact]
|
||||
public void Differences_md_has_no_remaining_baseline_n_or_stub_rows_in_tracked_scope()
|
||||
{
|
||||
var report = Parity.ParityRowInspector.Load("differences.md");
|
||||
var report = NATS.Server.TestUtilities.Parity.ParityRowInspector.Load("differences.md");
|
||||
report.UnresolvedRows.ShouldBeEmpty(string.Join(
|
||||
Environment.NewLine,
|
||||
report.UnresolvedRows.Select(r => $"{r.Section} :: {r.SubSection} :: {r.Feature} [{r.DotNetStatus}]")));
|
||||
@@ -14,7 +16,7 @@ public class DifferencesParityClosureTests
|
||||
[Fact]
|
||||
public void Jetstream_truth_matrix_has_no_row_level_drift()
|
||||
{
|
||||
var report = Parity.JetStreamParityTruthMatrix.Load(
|
||||
var report = NATS.Server.TestUtilities.Parity.JetStreamParityTruthMatrix.Load(
|
||||
"differences.md",
|
||||
"docs/plans/2026-02-23-jetstream-remaining-parity-map.md");
|
||||
|
||||
@@ -26,7 +28,7 @@ public class DifferencesParityClosureTests
|
||||
[Fact]
|
||||
public void Differences_and_strict_capability_maps_have_no_claims_without_behavior_and_test_evidence()
|
||||
{
|
||||
var inventory = Parity.NatsCapabilityInventory.Load("docs/plans/2026-02-23-nats-strict-full-go-parity-map.md");
|
||||
var inventory = NATS.Server.TestUtilities.Parity.NatsCapabilityInventory.Load("docs/plans/2026-02-23-nats-strict-full-go-parity-map.md");
|
||||
var incomplete = inventory.Rows
|
||||
.Where(r => !string.Equals(r.Behavior, "done", StringComparison.OrdinalIgnoreCase)
|
||||
|| !string.Equals(r.Tests, "done", StringComparison.OrdinalIgnoreCase)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
// Go reference: golang/nats-server/server/jetstream.go — $JS.API.* subject dispatch
|
||||
// Covers create/info/update/delete for streams, create/info/list/delete for consumers,
|
||||
// direct-get access, account info, and 404 routing for unknown subjects.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// time-bounded pauses and response body containing pause state.
|
||||
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Api;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Cluster;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.Subscriptions;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Consumers;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Storage;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream.Consumers;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using NATS.Server.Auth;
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// Consumer CRUD operations: create push/pull, update, delete, info, ephemeral
|
||||
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using System.Text;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// missing sequence handling, multi-message get, stream message API.
|
||||
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Validation;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Validation;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Text;
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Storage;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.JetStream;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
// Ported from golang/nats-server/server/jetstream_test.go
|
||||
// Reference Go tests: TestJetStreamAddStream, TestJetStreamAddStreamSameConfigOK,
|
||||
// TestJetStreamUpdateStream, TestJetStreamStreamPurge, TestJetStreamDeleteMsg
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamAckRedeliveryTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamApiRouterTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamClusterControlApiTests
|
||||
@@ -7,7 +9,7 @@ public class JetStreamClusterControlApiTests
|
||||
{
|
||||
await using var fx = await JetStreamClusterFixture.StartAsync(nodes: 3);
|
||||
|
||||
var create = await fx.CreateStreamAsync("ORDERS", replicas: 3);
|
||||
var create = await fx.CreateStreamAsync("ORDERS", ["orders.*"], replicas: 3);
|
||||
create.Error.ShouldBeNull();
|
||||
|
||||
var streamStepdown = await fx.RequestAsync("$JS.API.STREAM.LEADER.STEPDOWN.ORDERS", "{}");
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamClusterControlExtendedApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamConsumerApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamConsumerControlApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamConsumerListApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamConsumerNextApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamConsumerSemanticsTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamDirectGetApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamExpectedHeaderTests
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
internal static class JetStreamIntegrationMatrix
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamJwtLimitTests
|
||||
|
||||
@@ -2,7 +2,6 @@ using NATS.Server.JetStream;
|
||||
using NATS.Server.JetStream.Api;
|
||||
using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Models;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamMetaGroupTests
|
||||
@@ -10,7 +9,7 @@ public class JetStreamMetaGroupTests
|
||||
[Fact]
|
||||
public async Task Stream_create_requires_meta_group_commit()
|
||||
{
|
||||
await using var fixture = await JetStreamClusterFixture.StartAsync(nodes: 3);
|
||||
await using var fixture = await MetaGroupTestFixture.StartAsync(nodes: 3);
|
||||
|
||||
var result = await fixture.CreateStreamAsync("ORDERS", replicas: 3);
|
||||
result.Error.ShouldBeNull();
|
||||
@@ -20,14 +19,14 @@ public class JetStreamMetaGroupTests
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
internal sealed class MetaGroupTestFixture : IAsyncDisposable
|
||||
{
|
||||
private readonly JetStreamMetaGroup _metaGroup;
|
||||
private readonly StreamManager _streamManager;
|
||||
private readonly ConsumerManager _consumerManager;
|
||||
private readonly JetStreamApiRouter _router;
|
||||
|
||||
private JetStreamClusterFixture(JetStreamMetaGroup metaGroup, StreamManager streamManager, ConsumerManager consumerManager, JetStreamApiRouter router)
|
||||
private MetaGroupTestFixture(JetStreamMetaGroup metaGroup, StreamManager streamManager, ConsumerManager consumerManager, JetStreamApiRouter router)
|
||||
{
|
||||
_metaGroup = metaGroup;
|
||||
_streamManager = streamManager;
|
||||
@@ -35,13 +34,13 @@ internal sealed class JetStreamClusterFixture : IAsyncDisposable
|
||||
_router = router;
|
||||
}
|
||||
|
||||
public static Task<JetStreamClusterFixture> StartAsync(int nodes)
|
||||
public static Task<MetaGroupTestFixture> StartAsync(int nodes)
|
||||
{
|
||||
var meta = new JetStreamMetaGroup(nodes);
|
||||
var streamManager = new StreamManager(meta);
|
||||
var consumerManager = new ConsumerManager(meta);
|
||||
var router = new JetStreamApiRouter(streamManager, consumerManager, meta);
|
||||
return Task.FromResult(new JetStreamClusterFixture(meta, streamManager, consumerManager, router));
|
||||
return Task.FromResult(new MetaGroupTestFixture(meta, streamManager, consumerManager, router));
|
||||
}
|
||||
|
||||
public Task<NATS.Server.JetStream.Api.JetStreamApiResponse> CreateStreamAsync(string name, int replicas)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamMirrorSourceAdvancedTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamMirrorSourceTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPublishPreconditionTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPublishTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPullConsumerContractTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPullConsumerTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPushConsumerContractTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamPushConsumerTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamRetentionPolicyTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamSnapshotRestoreApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamStorageSelectionTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamStreamApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamStreamLifecycleApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamStreamListApiTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
public class JetStreamStreamMessageApiTests
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using NATS.Server.Auth;
|
||||
using NATS.Server.Configuration;
|
||||
using NATS.Server.LeafNodes;
|
||||
using NATS.Server.Subscriptions;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.LeafNodes;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ using NATS.Server.Auth;
|
||||
using NATS.Server.Configuration;
|
||||
using NATS.Server.LeafNodes;
|
||||
using NATS.Server.Subscriptions;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.LeafNodes;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using NATS.Client.Core;
|
||||
using NATS.Server.Configuration;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.LeafNodes;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using NATS.Client.Core;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.LeafNodes;
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ public class LeafProtocolTests
|
||||
[Fact]
|
||||
public async Task Leaf_link_propagates_subscription_and_message_flow()
|
||||
{
|
||||
await using var fx = await LeafFixture.StartHubSpokeAsync();
|
||||
await using var fx = await LeafProtocolTestFixture.StartHubSpokeAsync();
|
||||
await fx.SubscribeSpokeAsync("leaf.>");
|
||||
await fx.PublishHubAsync("leaf.msg", "x");
|
||||
(await fx.ReadSpokeMessageAsync()).ShouldContain("x");
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class LeafFixture : IAsyncDisposable
|
||||
internal sealed class LeafProtocolTestFixture : IAsyncDisposable
|
||||
{
|
||||
private readonly NatsServer _hub;
|
||||
private readonly NatsServer _spoke;
|
||||
@@ -27,7 +27,7 @@ internal sealed class LeafFixture : IAsyncDisposable
|
||||
private Socket? _spokeSubscriber;
|
||||
private Socket? _hubPublisher;
|
||||
|
||||
private LeafFixture(NatsServer hub, NatsServer spoke, CancellationTokenSource hubCts, CancellationTokenSource spokeCts)
|
||||
private LeafProtocolTestFixture(NatsServer hub, NatsServer spoke, CancellationTokenSource hubCts, CancellationTokenSource spokeCts)
|
||||
{
|
||||
_hub = hub;
|
||||
_spoke = spoke;
|
||||
@@ -35,7 +35,7 @@ internal sealed class LeafFixture : IAsyncDisposable
|
||||
_spokeCts = spokeCts;
|
||||
}
|
||||
|
||||
public static async Task<LeafFixture> StartHubSpokeAsync()
|
||||
public static async Task<LeafProtocolTestFixture> StartHubSpokeAsync()
|
||||
{
|
||||
var hubOptions = new NatsOptions
|
||||
{
|
||||
@@ -74,7 +74,7 @@ internal sealed class LeafFixture : IAsyncDisposable
|
||||
while (!timeout.IsCancellationRequested && (hub.Stats.Leafs == 0 || spoke.Stats.Leafs == 0))
|
||||
await Task.Delay(50, timeout.Token).ContinueWith(_ => { }, TaskScheduler.Default);
|
||||
|
||||
return new LeafFixture(hub, spoke, hubCts, spokeCts);
|
||||
return new LeafProtocolTestFixture(hub, spoke, hubCts, spokeCts);
|
||||
}
|
||||
|
||||
public async Task SubscribeSpokeAsync(string subject)
|
||||
|
||||
@@ -22,11 +22,7 @@
|
||||
<Using Include="Shouldly" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="TestData\**\*" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\NATS.Server\NATS.Server.csproj" />
|
||||
<ProjectReference Include="..\NATS.Server.TestUtilities\NATS.Server.TestUtilities.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities.Parity;
|
||||
|
||||
namespace NATS.Server.Tests.Parity;
|
||||
|
||||
public class JetStreamParityTruthMatrixTests
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using NATS.Server.TestUtilities.Parity;
|
||||
|
||||
namespace NATS.Server.Tests.Parity;
|
||||
|
||||
public class NatsStrictCapabilityInventoryTests
|
||||
|
||||
@@ -12,7 +12,8 @@ using NATS.Server.JetStream.Cluster;
|
||||
using NATS.Server.JetStream.Consumers;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Publish;
|
||||
using ClusterFixture = NATS.Server.Tests.JetStream.Cluster.JetStreamClusterFixture;
|
||||
using ClusterFixture = NATS.Server.TestUtilities.JetStreamClusterFixture;
|
||||
using NATS.Server.TestUtilities;
|
||||
|
||||
namespace NATS.Server.Tests.Stress;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user