feat(batch14): complete group2 lifecycle checks and wave2 tests

This commit is contained in:
Joseph Doherty
2026-02-28 15:27:32 -05:00
parent 4f0a7f40fc
commit 9a35e2dfc5
5 changed files with 856 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Reflection;
using Shouldly;
using ZB.MOM.NatsNet.Server;
@@ -59,6 +60,38 @@ public sealed partial class ConcurrencyTests2
}
}
[Fact] // T:2476
public void NoRaceFilestoreBinaryStreamSnapshotEncodingLargeGaps_ShouldSucceed()
{
WithStore((fs, _) =>
{
const int numMsgs = 5000;
var payload = new byte[128];
fs.StoreMsg("zzz", null, payload, 0).Seq.ShouldBe(1UL);
for (var i = 2; i < numMsgs; i++)
{
var (seq, _) = fs.StoreMsg("zzz", null, null, 0);
seq.ShouldBeGreaterThan(1UL);
fs.RemoveMsg(seq).Removed.ShouldBeTrue();
}
fs.StoreMsg("zzz", null, payload, 0).Seq.ShouldBe((ulong)numMsgs);
Should.NotThrow(() => InvokePrivate(fs, "SyncBlocks"));
var (snapshot, err) = fs.EncodedStreamState(0);
err.ShouldBeNull();
StoreParity.IsEncodedStreamState(snapshot).ShouldBeTrue();
snapshot.Length.ShouldBeLessThan(2048);
var state = fs.State();
state.FirstSeq.ShouldBe(1UL);
state.LastSeq.ShouldBe((ulong)numMsgs);
state.Msgs.ShouldBe(2UL);
state.NumDeleted.ShouldBe(numMsgs - 2);
});
}
private static void WithStore(Action<JetStreamFileStore, string> action, StreamConfig? cfg = null)
{
var root = NewRoot();
@@ -94,5 +127,12 @@ public sealed partial class ConcurrencyTests2
};
}
private static void InvokePrivate(object target, string methodName, params object[] args)
{
var method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
method!.Invoke(target, args);
}
private static string NewRoot() => Path.Combine(Path.GetTempPath(), $"impl-fs-c2-{Guid.NewGuid():N}");
}