Files
natsnet/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/JetStreamClusterTests3.Impltests.cs

153 lines
5.3 KiB
C#

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<bool>();
(state.Cluster as JetStreamCluster)!.Stopped = System.Threading.Channels.Channel.CreateUnbounded<bool>();
engine.ClusterQuitC().ShouldNotBeNull();
engine.ClusterStoppedC().ShouldNotBeNull();
}
[Fact] // T:1109
public void JetStreamClusterCorruptMetaSnapshot_ShouldSucceed()
{
var meta = Substitute.For<IRaftNode>();
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<string, Dictionary<string, StreamAssignment>>
{
["A"] = new Dictionary<string, StreamAssignment>
{
["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<string, Dictionary<string, StreamAssignment>>
{
["A"] = new Dictionary<string, StreamAssignment>
{
["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);
}
}