using System.Numerics; using Shouldly; using ZB.MOM.NatsNet.Server; namespace ZB.MOM.NatsNet.Server.Tests.JetStream; public sealed class NatsStreamMessageHeadersTests { [Fact] public void ParseMessageTTL_NeverValue_ReturnsMinusOne() { var (ttl, error) = NatsStream.ParseMessageTTL("never"); error.ShouldBeNull(); ttl.ShouldBe(-1); } [Fact] public void GetMessageIncr_ValidHeader_ReturnsParsedValue() { var hdr = NatsMessageHeaders.GenHeader(null, NatsHeaderConstants.JsMessageIncr, "42"); var (value, ok) = NatsStream.GetMessageIncr(hdr); ok.ShouldBeTrue(); value.ShouldBe(new BigInteger(42)); } [Fact] public void GetMessageSchedule_InvalidPattern_ReturnsNotOk() { var hdr = NatsMessageHeaders.GenHeader(null, NatsHeaderConstants.JsSchedulePattern, "invalid"); var (schedule, ok) = NatsStream.GetMessageSchedule(hdr); ok.ShouldBeFalse(); schedule.ShouldBe(default); } [Fact] public void SetupStore_MemoryStorage_CreatesMemStore() { var stream = CreateStream(duplicates: TimeSpan.FromSeconds(1)); var error = stream.SetupStore(null); error.ShouldBeNull(); stream.Store.ShouldNotBeNull(); stream.Store!.Type().ShouldBe(StorageType.MemoryStorage); } [Fact] public void StoreMsgIdAndPurge_ExpiredEntry_RemovesEntry() { var stream = CreateStream(duplicates: TimeSpan.FromMilliseconds(50)); var oldTs = (DateTimeOffset.UtcNow - TimeSpan.FromSeconds(1)).ToUnixTimeMilliseconds() * 1_000_000L; stream.StoreMsgId(new NatsStream.DedupeEntry { Id = "id-1", Seq = 1, TimestampNanos = oldTs }); stream.NumMsgIds().ShouldBe(1); stream.CheckMsgId("id-1").ShouldNotBeNull(); stream.PurgeMsgIds(); stream.NumMsgIds().ShouldBe(0); stream.CheckMsgId("id-1").ShouldBeNull(); } private static NatsStream CreateStream(TimeSpan duplicates) { var account = new Account { Name = "A" }; var config = new StreamConfig { Name = "S", Storage = StorageType.MemoryStorage, Duplicates = duplicates, }; return new NatsStream(account, config, DateTime.UtcNow); } }