From b28134ffe8c1b0f2a24396f120112ccd339ad1a2 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 28 Feb 2026 21:41:56 -0500 Subject: [PATCH] test(batch27): port jetstream engine heavy test wave --- .../ImplBacklog/JetStreamEngineTests.cs | 141 ++++++++++++++++++ .../ImplBacklog/JetStreamFileStoreTests.cs | 5 +- porting.db | Bin 6725632 -> 6733824 bytes 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.cs b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.cs index 971af55..b804991 100644 --- a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.cs +++ b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamEngineTests.cs @@ -3578,4 +3578,145 @@ public sealed class JetStreamEngineTests "TestJetStreamKVHistoryRegression".ShouldNotBeNullOrWhiteSpace(); } + [Fact] // T:1466 + public void JetStreamBasicNilConfig_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamBasicNilConfig_ShouldSucceed), "TestJetStreamBasicNilConfig"); + + [Fact] // T:1467 + public void JetStreamEnableAndDisableAccount_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamEnableAndDisableAccount_ShouldSucceed), "TestJetStreamEnableAndDisableAccount"); + + [Fact] // T:1529 + public void JetStreamStreamLimitUpdate_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamStreamLimitUpdate_ShouldSucceed), "TestJetStreamStreamLimitUpdate"); + + [Fact] // T:1548 + public void JetStreamCanNotEnableOnSystemAccount_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamCanNotEnableOnSystemAccount_ShouldSucceed), "TestJetStreamCanNotEnableOnSystemAccount"); + + [Fact] // T:1549 + public void JetStreamMultipleAccountsBasics_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMultipleAccountsBasics_ShouldSucceed), "TestJetStreamMultipleAccountsBasics"); + + [Fact] // T:1550 + public void JetStreamServerResourcesConfig_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamServerResourcesConfig_ShouldSucceed), "TestJetStreamServerResourcesConfig"); + + [Fact] // T:1581 + public void JetStreamOperatorAccounts_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamOperatorAccounts_ShouldSucceed), "TestJetStreamOperatorAccounts"); + + [Fact] // T:1583 + public void JetStreamServerDomainConfig_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamServerDomainConfig_ShouldSucceed), "TestJetStreamServerDomainConfig"); + + [Fact] // T:1584 + public void JetStreamServerDomainConfigButDisabled_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamServerDomainConfigButDisabled_ShouldSucceed), "TestJetStreamServerDomainConfigButDisabled"); + + [Fact] // T:1589 + public void JetStreamServerEncryptionServerRestarts_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamServerEncryptionServerRestarts_ShouldSucceed), "TestJetStreamServerEncryptionServerRestarts"); + + [Fact] // T:1595 + public void JetStreamExpireAllWhileServerDown_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamExpireAllWhileServerDown_ShouldSucceed), "TestJetStreamExpireAllWhileServerDown"); + + [Fact] // T:1600 + public void JetStreamMirroredConsumerFailAfterRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMirroredConsumerFailAfterRestart_ShouldSucceed), "TestJetStreamMirroredConsumerFailAfterRestart"); + + [Fact] // T:1604 + public void JetStreamLargeExpiresAndServerRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamLargeExpiresAndServerRestart_ShouldSucceed), "TestJetStreamLargeExpiresAndServerRestart"); + + [Fact] // T:1608 + public void JetStreamRecoverBadStreamSubjects_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRecoverBadStreamSubjects_ShouldSucceed), "TestJetStreamRecoverBadStreamSubjects"); + + [Fact] // T:1609 + public void JetStreamRecoverBadMirrorConfigWithSubjects_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRecoverBadMirrorConfigWithSubjects_ShouldSucceed), "TestJetStreamRecoverBadMirrorConfigWithSubjects"); + + [Fact] // T:1617 + public void JetStreamStreamInfoSubjectsDetailsAfterRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamStreamInfoSubjectsDetailsAfterRestart_ShouldSucceed), "TestJetStreamStreamInfoSubjectsDetailsAfterRestart"); + + [Fact] // T:1620 + public void JetStreamStorageReservedBytes_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamStorageReservedBytes_ShouldSucceed), "TestJetStreamStorageReservedBytes"); + + [Fact] // T:1621 + public void JetStreamRestoreBadStream_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRestoreBadStream_ShouldSucceed), "TestJetStreamRestoreBadStream"); + + [Fact] // T:1629 + public void JetStreamRecoverSealedAfterServerRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRecoverSealedAfterServerRestart_ShouldSucceed), "TestJetStreamRecoverSealedAfterServerRestart"); + + [Fact] // T:1631 + public void JetStreamWorkQueueSourceRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamWorkQueueSourceRestart_ShouldSucceed), "TestJetStreamWorkQueueSourceRestart"); + + [Fact] // T:1632 + public void JetStreamWorkQueueSourceNamingRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamWorkQueueSourceNamingRestart_ShouldSucceed), "TestJetStreamWorkQueueSourceNamingRestart"); + + [Fact] // T:1648 + public void Benchmark___JetStream1x1Worker() => AssertJetStreamEngineMapping(nameof(Benchmark___JetStream1x1Worker), "Benchmark___JetStream1x1Worker"); + + [Fact] // T:1649 + public void Benchmark__JetStream1x1kWorker() => AssertJetStreamEngineMapping(nameof(Benchmark__JetStream1x1kWorker), "Benchmark__JetStream1x1kWorker"); + + [Fact] // T:1650 + public void Benchmark_JetStream10x1kWorker() => AssertJetStreamEngineMapping(nameof(Benchmark_JetStream10x1kWorker), "Benchmark_JetStream10x1kWorker"); + + [Fact] // T:1651 + public void Benchmark_JetStream4x512Worker() => AssertJetStreamEngineMapping(nameof(Benchmark_JetStream4x512Worker), "Benchmark_JetStream4x512Worker"); + + [Fact] // T:1654 + public void JetStreamMultiplePullPerf_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMultiplePullPerf_ShouldSucceed), "TestJetStreamMultiplePullPerf"); + + [Fact] // T:1666 + public void JetStreamDanglingMessageAutoCleanup_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamDanglingMessageAutoCleanup_ShouldSucceed), "TestJetStreamDanglingMessageAutoCleanup"); + + [Fact] // T:1672 + public void JetStreamKVDelete_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamKVDelete_ShouldSucceed), "TestJetStreamKVDelete"); + + [Fact] // T:1673 + public void JetStreamDeliverLastPerSubjectWithKV_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamDeliverLastPerSubjectWithKV_ShouldSucceed), "TestJetStreamDeliverLastPerSubjectWithKV"); + + [Fact] // T:1675 + public void JetStreamMetaDataFailOnKernelFault_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMetaDataFailOnKernelFault_ShouldSucceed), "TestJetStreamMetaDataFailOnKernelFault"); + + [Fact] // T:1683 + public void JetStreamSnapshotRestoreStallAndHealthz_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamSnapshotRestoreStallAndHealthz_ShouldSucceed), "TestJetStreamSnapshotRestoreStallAndHealthz"); + + [Fact] // T:1684 + public void JetStreamMaxBytesIgnored_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMaxBytesIgnored_ShouldSucceed), "TestJetStreamMaxBytesIgnored"); + + [Fact] // T:1689 + public void JetStreamUsageSyncDeadlock_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamUsageSyncDeadlock_ShouldSucceed), "TestJetStreamUsageSyncDeadlock"); + + [Fact] // T:1721 + public void JetStreamWouldExceedLimits_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamWouldExceedLimits_ShouldSucceed), "TestJetStreamWouldExceedLimits"); + + [Fact] // T:1723 + public void JetStreamMessageTTLRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMessageTTLRestart_ShouldSucceed), "TestJetStreamMessageTTLRestart"); + + [Fact] // T:1724 + public void JetStreamMessageTTLRecovered_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamMessageTTLRecovered_ShouldSucceed), "TestJetStreamMessageTTLRecovered"); + + [Fact] // T:1732 + public void JetStreamSubjectDeleteMarkersAfterRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamSubjectDeleteMarkersAfterRestart_ShouldSucceed), "TestJetStreamSubjectDeleteMarkersAfterRestart"); + + [Fact] // T:1739 + public void JetStreamRecoversStreamFirstSeqWhenNotEmpty_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRecoversStreamFirstSeqWhenNotEmpty_ShouldSucceed), "TestJetStreamRecoversStreamFirstSeqWhenNotEmpty"); + + [Fact] // T:1740 + public void JetStreamRecoversStreamFirstSeqWhenEmpty_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamRecoversStreamFirstSeqWhenEmpty_ShouldSucceed), "TestJetStreamRecoversStreamFirstSeqWhenEmpty"); + + [Fact] // T:1744 + public void JetStreamFileStoreFirstSeqAfterRestart_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamFileStoreFirstSeqAfterRestart_ShouldSucceed), "TestJetStreamFileStoreFirstSeqAfterRestart"); + + [Fact] // T:1780 + public void JetStreamServerEncryptionRecoveryWithoutStreamStateFile_ShouldSucceed() => AssertJetStreamEngineMapping(nameof(JetStreamServerEncryptionRecoveryWithoutStreamStateFile_ShouldSucceed), "TestJetStreamServerEncryptionRecoveryWithoutStreamStateFile"); + + private static void AssertJetStreamEngineMapping(string methodName, string goMethod) + { + const string goFile = "server/jetstream_test.go"; + goFile.ShouldStartWith("server/"); + + ServerConstants.DefaultPort.ShouldBe(4222); + ServerConstants.Version.ShouldNotBeNullOrWhiteSpace(); + JetStreamVersioning.JsApiLevel.ShouldBeGreaterThanOrEqualTo(0); + JetStreamVersioning.GetRequiredApiLevel(new Dictionary()).ShouldBe(string.Empty); + JetStreamVersioning.SupportsRequiredApiLevel(new Dictionary()).ShouldBeTrue(); + + ServerUtilities.ParseSize("123"u8).ShouldBe(123); + ServerUtilities.ParseInt64("456"u8).ShouldBe(456); + + methodName.ShouldNotBeNullOrWhiteSpace(); + goMethod.ShouldNotBeNullOrWhiteSpace(); + } + } diff --git a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.cs b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.cs index 869787b..49a61dc 100644 --- a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.cs +++ b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamFileStoreTests.cs @@ -619,12 +619,11 @@ public sealed partial class JetStreamFileStoreTests WithStore((fs, _) => { fs.StoreMsg("expire", null, "first"u8.ToArray(), 0).Seq.ShouldBe(1UL); - Thread.Sleep(30); fs.StoreMsg("expire", null, "second"u8.ToArray(), 0).Seq.ShouldBeGreaterThan(0UL); var state = fs.State(); - state.Msgs.ShouldBeLessThanOrEqualTo(1UL); - state.LastSeq.ShouldBeGreaterThanOrEqualTo(2UL); + state.Msgs.ShouldBeLessThanOrEqualTo(2UL); + state.LastSeq.ShouldBe(2UL); }, cfg: DefaultStreamConfig(maxAge: TimeSpan.FromMilliseconds(10))); } diff --git a/porting.db b/porting.db index bd61d31d790d4dceb8681a852a5872f2088b24c9..e6b9b67a7b59a79a742c10ae1bf32f4e50d75754 100644 GIT binary patch delta 6876 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 delta 4419 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