refactor: extract NATS.Server.JetStream.Tests project
Move 225 JetStream-related test files from NATS.Server.Tests into a dedicated NATS.Server.JetStream.Tests project. This includes root-level JetStream*.cs files, storage test files (FileStore, MemStore, StreamStoreContract), and the full JetStream/ subfolder tree (Api, Cluster, Consumers, MirrorSource, Snapshots, Storage, Streams). Updated all namespaces, added InternalsVisibleTo, registered in the solution file, and added the JETSTREAM_INTEGRATION_MATRIX define.
This commit is contained in:
110
tests/NATS.Server.JetStream.Tests/MirrorSourceRetryTests.cs
Normal file
110
tests/NATS.Server.JetStream.Tests/MirrorSourceRetryTests.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using NSubstitute;
|
||||
using NATS.Server.JetStream.MirrorSource;
|
||||
using NATS.Server.JetStream.Models;
|
||||
using NATS.Server.JetStream.Storage;
|
||||
|
||||
namespace NATS.Server.JetStream.Tests;
|
||||
|
||||
// Go reference: server/stream.go:3478-3505 (calculateRetryBackoff),
|
||||
// server/stream.go:3125-3400 (setupMirrorConsumer retry logic)
|
||||
|
||||
public class MirrorSourceRetryTests
|
||||
{
|
||||
[Fact]
|
||||
public void Mirror_retry_uses_exponential_backoff()
|
||||
{
|
||||
// Go reference: server/stream.go:3478-3505 calculateRetryBackoff
|
||||
var mirror = MirrorCoordinatorTestHelper.Create();
|
||||
|
||||
mirror.RecordFailure();
|
||||
var delay1 = mirror.GetRetryDelay();
|
||||
delay1.ShouldBeGreaterThanOrEqualTo(TimeSpan.FromMilliseconds(250));
|
||||
|
||||
mirror.RecordFailure();
|
||||
var delay2 = mirror.GetRetryDelay();
|
||||
delay2.ShouldBeGreaterThan(delay1);
|
||||
|
||||
// Cap at max
|
||||
for (int i = 0; i < 20; i++) mirror.RecordFailure();
|
||||
var delayMax = mirror.GetRetryDelay();
|
||||
delayMax.ShouldBeLessThanOrEqualTo(TimeSpan.FromSeconds(30));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mirror_success_resets_backoff()
|
||||
{
|
||||
// Go reference: server/stream.go setupMirrorConsumer — success resets retry
|
||||
var mirror = MirrorCoordinatorTestHelper.Create();
|
||||
|
||||
for (int i = 0; i < 5; i++) mirror.RecordFailure();
|
||||
mirror.RecordSuccess();
|
||||
|
||||
var delay = mirror.GetRetryDelay();
|
||||
delay.ShouldBe(TimeSpan.FromMilliseconds(250));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mirror_tracks_sequence_gap()
|
||||
{
|
||||
// Go reference: server/stream.go:2863-3014 processInboundMirrorMsg — gap detection
|
||||
var mirror = MirrorCoordinatorTestHelper.Create();
|
||||
|
||||
mirror.RecordSourceSeq(1);
|
||||
mirror.RecordSourceSeq(2);
|
||||
mirror.RecordSourceSeq(5); // gap: 3, 4 missing
|
||||
|
||||
mirror.HasGap.ShouldBeTrue();
|
||||
mirror.GapStart.ShouldBe(3UL);
|
||||
mirror.GapEnd.ShouldBe(4UL);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mirror_tracks_error_state()
|
||||
{
|
||||
// Go reference: server/stream.go mirror error state tracking
|
||||
var mirror = MirrorCoordinatorTestHelper.Create();
|
||||
|
||||
mirror.SetError("connection refused");
|
||||
mirror.HasError.ShouldBeTrue();
|
||||
mirror.ErrorMessage.ShouldBe("connection refused");
|
||||
|
||||
mirror.ClearError();
|
||||
mirror.HasError.ShouldBeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Source_dedup_window_prunes_expired()
|
||||
{
|
||||
// Go reference: server/stream.go duplicate window pruning
|
||||
var source = SourceCoordinatorTestHelper.Create();
|
||||
|
||||
source.RecordMsgId("msg-1");
|
||||
source.RecordMsgId("msg-2");
|
||||
|
||||
source.IsDuplicate("msg-1").ShouldBeTrue();
|
||||
source.IsDuplicate("msg-3").ShouldBeFalse();
|
||||
|
||||
// Simulate time passing beyond dedup window
|
||||
source.PruneDedupWindow(DateTimeOffset.UtcNow.AddMinutes(5));
|
||||
source.IsDuplicate("msg-1").ShouldBeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MirrorCoordinatorTestHelper
|
||||
{
|
||||
public static MirrorCoordinator Create()
|
||||
{
|
||||
var store = Substitute.For<IStreamStore>();
|
||||
return new MirrorCoordinator(store);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SourceCoordinatorTestHelper
|
||||
{
|
||||
public static SourceCoordinator Create()
|
||||
{
|
||||
var store = Substitute.For<IStreamStore>();
|
||||
var config = new StreamSourceConfig { Name = "test-source", DuplicateWindowMs = 60_000 };
|
||||
return new SourceCoordinator(store, config);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user