// Copyright 2012-2026 The NATS Authors // Licensed under the Apache License, Version 2.0 using Shouldly; using ZB.MOM.NatsNet.Server; namespace ZB.MOM.NatsNet.Server.Tests.JetStream; public sealed class WaitQueueTests { [Fact] public void Add_Peek_Pop_IsFull_ShouldBehaveAsFifo() { var q = new WaitQueue(); q.Peek().ShouldBeNull(); q.Pop().ShouldBeNull(); q.Add(new WaitingRequest { Subject = "A", N = 1 }); q.Add(new WaitingRequest { Subject = "B", N = 2 }); q.Len.ShouldBe(2); q.IsFull(2).ShouldBeTrue(); q.Peek()!.Subject.ShouldBe("A"); q.Pop()!.Subject.ShouldBe("A"); q.Pop()!.Subject.ShouldBe("B"); q.Len.ShouldBe(1); q.Pop()!.Subject.ShouldBe("B"); q.Len.ShouldBe(0); q.IsFull(1).ShouldBeFalse(); } [Fact] public void AddPrioritized_AndCycle_ShouldPreserveStableOrder() { var q = new WaitQueue(max: 10); q.AddPrioritized(new WaitingRequest { Reply = "2a", N = 1, PriorityGroup = new PriorityGroup { Priority = 2 } }) .ShouldBeTrue(); q.AddPrioritized(new WaitingRequest { Reply = "1a", N = 1, PriorityGroup = new PriorityGroup { Priority = 1 } }) .ShouldBeTrue(); q.AddPrioritized(new WaitingRequest { Reply = "1b", N = 1, PriorityGroup = new PriorityGroup { Priority = 1 } }) .ShouldBeTrue(); q.Peek()!.Reply.ShouldBe("1a"); q.Cycle(); q.Peek()!.Reply.ShouldBe("1b"); } [Fact] public void WaitingRequestRecycle_AndWaitQueueFactory_ShouldBehave() { var request = new WaitingRequest { Subject = "s", Reply = "r", N = 0, D = 1, MaxBytes = 10, B = 10, PriorityGroup = new PriorityGroup { Group = "g", Priority = 1 }, }; request.RecycleIfDone().ShouldBeTrue(); request.Subject.ShouldBe(string.Empty); request.Reply.ShouldBeNull(); var q = WaitQueue.NewWaitQueue(max: 3); q.ShouldNotBeNull(); q.IsFull(3).ShouldBeFalse(); } [Fact] public void WaitingDeliveryRecycle_ShouldClearState() { var wd = new WaitingDelivery { Reply = "r", Sequence = 42, Created = DateTime.UtcNow }; wd.Recycle(); wd.Reply.ShouldBe(string.Empty); wd.Sequence.ShouldBe(0UL); wd.Created.ShouldBe(DateTime.UnixEpoch); } }