using NSubstitute; using Shouldly; using ZB.MOM.NatsNet.Server; namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog; public sealed class JetStreamClusterTests3 { [Fact] // T:1060 public void JetStreamClusterLostConsumers_ShouldSucceed() { var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = new JetStreamCluster(), }); engine.IsConsumerHealthy(null, "C1", new ConsumerAssignment()).ShouldBeFalse(); } [Fact] // T:1088 public void JetStreamClusterPurgeExReplayAfterRestart_ShouldSucceed() { var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = new JetStreamCluster() }); engine.SubjectsOverlap("A", ["foo.*"], null).ShouldBeFalse(); } [Fact] // T:1098 public void JetStreamClusterDurableConsumerInactiveThresholdLeaderSwitch_ShouldSucceed() { var state = new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = new JetStreamCluster() }; var engine = new JetStreamEngine(state); engine.SetMetaRecovering(); engine.IsMetaRecovering().ShouldBeTrue(); engine.ClearMetaRecovering(); engine.IsMetaRecovering().ShouldBeFalse(); } [Fact] // T:1106 public void JetStreamClusterDomainAdvisory_ShouldSucceed() { var state = new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = new JetStreamCluster() }; var engine = new JetStreamEngine(state); (state.Cluster as JetStreamCluster)!.Qch = System.Threading.Channels.Channel.CreateUnbounded(); (state.Cluster as JetStreamCluster)!.Stopped = System.Threading.Channels.Channel.CreateUnbounded(); engine.ClusterQuitC().ShouldNotBeNull(); engine.ClusterStoppedC().ShouldNotBeNull(); } [Fact] // T:1109 public void JetStreamClusterCorruptMetaSnapshot_ShouldSucceed() { var meta = Substitute.For(); meta.Leaderless().Returns(true); var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = new JetStreamCluster { Meta = meta }, }); engine.IsLeaderless().ShouldBeTrue(); } [Fact] // T:1122 public void JetStreamClusterConcurrentStreamUpdate_ShouldSucceed() { var cluster = new JetStreamCluster { Streams = new Dictionary> { ["A"] = new Dictionary { ["S1"] = new() { Config = new StreamConfig { Name = "S1", Subjects = ["orders.*"] }, }, }, }, }; var state = new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = cluster }; var engine = new JetStreamEngine(state); engine.SubjectsOverlap("A", ["orders.created"]).ShouldBeTrue(); } [Fact] // T:1118 public void JetStreamClusterStreamRescaleCatchup_ShouldSucceed() { var cluster = new JetStreamCluster { Streams = new Dictionary> { ["A"] = new Dictionary { ["ORDERS"] = new() { Client = new ClientInfo { Account = "A" }, Config = new StreamConfig { Name = "ORDERS", Replicas = 3 }, Group = new RaftGroup { Name = "RG-ORDERS", Peers = ["S1", "S2"] }, }, }, }, }; var state = new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = cluster }; var engine = new JetStreamEngine(state); var assignment = engine.StreamAssignment("A", "ORDERS"); assignment.ShouldNotBeNull(); assignment!.MissingPeers().ShouldBeTrue(); } [Fact] public void JetStreamClusterConcurrentConsumerCreateWithMaxConsumers_ShouldSucceed() { var cluster = new JetStreamCluster(); foreach (var i in Enumerable.Range(0, 64)) { cluster.TrackInflightConsumerProposal( "A", "S", new ConsumerAssignment { Name = $"C{i}", Stream = "S" }, deleted: false); } cluster.InflightConsumers["A"]["S"].Count.ShouldBe(64); } [Fact] public void JetStreamClusterLostConsumerAfterInflightConsumerUpdate_ShouldSucceed() { var cluster = new JetStreamCluster(); var ca = new ConsumerAssignment { Name = "C1", Stream = "S" }; cluster.TrackInflightConsumerProposal("A", "S", ca, deleted: false); cluster.TrackInflightConsumerProposal("A", "S", ca, deleted: true); cluster.InflightConsumers["A"]["S"]["C1"].Deleted.ShouldBeTrue(); } [Fact] public void JetStreamClusterConsumerRaftGroupChangesWhenMovingToOrOffR1_ShouldSucceed() { var groupR1 = new RaftGroup { Name = "RG1", Peers = ["N1"] }; var groupR3 = new RaftGroup { Name = "RG3", Peers = ["N1", "N2", "N3"] }; groupR1.IsMember("N1").ShouldBeTrue(); groupR3.IsMember("N3").ShouldBeTrue(); groupR1.Peers.Length.ShouldBe(1); groupR3.Peers.Length.ShouldBe(3); } }