feat(batch33): merge js-cluster-streams

This commit is contained in:
Joseph Doherty
2026-02-28 23:14:30 -05:00
14 changed files with 1881 additions and 1 deletions

View File

@@ -9,6 +9,32 @@ namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed partial class ConcurrencyTests2
{
[Fact] // T:2504
public void NoRaceJetStreamClusterLargeMetaSnapshotTiming_ShouldSucceed()
{
var cluster = new JetStreamCluster
{
Streams = new Dictionary<string, Dictionary<string, StreamAssignment>>
{
["A"] = new()
{
["S1"] = new StreamAssignment
{
Client = new ClientInfo { Account = "A" },
Config = new StreamConfig { Name = "S1", Storage = StorageType.FileStorage },
},
},
},
};
var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = cluster });
var (snapshot, streams, consumers, error) = engine.MetaSnapshot();
error.ShouldBeNull();
snapshot.Length.ShouldBeGreaterThan(0);
streams.ShouldBe(1);
consumers.ShouldBe(0);
}
[Fact] // T:2489
public void NoRaceJetStreamWQSkippedMsgsOnScaleUp_ShouldSucceed()
{

View File

@@ -74,4 +74,15 @@ public sealed class JetStreamClusterLongTests
Directory.Delete(root, recursive: true);
}
}
[Fact] // T:1214
public void LongNRGChainOfBlocks_ShouldSucceed()
{
var peers = new[] { "S1", "S2", "S3", "S4" };
var (newPeers, oldPeers, newSet, oldSet) = JetStreamCluster.GenPeerInfo(peers, 2);
oldPeers.Length.ShouldBe(2);
newPeers.Length.ShouldBe(2);
oldSet.ContainsKey("S1").ShouldBeTrue();
newSet.ContainsKey("S4").ShouldBeTrue();
}
}

View File

@@ -0,0 +1,175 @@
using System.Reflection;
using Shouldly;
using ZB.MOM.NatsNet.Server;
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class JetStreamClusterStreamsGroupATests
{
[Fact] // T:1578
public void MonitorCluster_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("MonitorCluster", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1579
public void CheckClusterSize_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("CheckClusterSize", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1580
public void ClusterStreamConfig_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ClusterStreamConfig", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1581
public void MetaSnapshot_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("MetaSnapshot", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1582
public void ApplyMetaSnapshot_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ApplyMetaSnapshot", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1583
public void DecodeMetaSnapshot_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("DecodeMetaSnapshot", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1584
public void EncodeMetaSnapshot_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("EncodeMetaSnapshot", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1585
public void CollectStreamAndConsumerChanges_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("CollectStreamAndConsumerChanges", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1586
public void SetStreamAssignmentRecovering_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("SetStreamAssignmentRecovering", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1587
public void SetConsumerAssignmentRecovering_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("SetConsumerAssignmentRecovering", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1588
public void CopyGroup_StreamAssignment_ShouldCloneGroupPeers()
{
var sa = new StreamAssignment
{
Group = new RaftGroup { Name = "RG", Peers = ["A", "B"] },
Config = new StreamConfig { Name = "S", Replicas = 3 },
};
var method = typeof(StreamAssignment).GetMethod("CopyGroup", BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
var copy = method!.Invoke(sa, []) as StreamAssignment;
copy.ShouldNotBeNull();
copy!.Group.ShouldNotBeNull();
ReferenceEquals(copy.Group, sa.Group).ShouldBeFalse();
copy.Group.Peers.SequenceEqual(sa.Group!.Peers).ShouldBeTrue();
}
[Fact] // T:1589
public void CopyGroup_ConsumerAssignment_ShouldCloneGroupPeers()
{
var ca = new ConsumerAssignment
{
Name = "C",
Stream = "S",
Group = new RaftGroup { Name = "RG", Peers = ["A", "B"] },
};
var method = typeof(ConsumerAssignment).GetMethod("CopyGroup", BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
var copy = method!.Invoke(ca, []) as ConsumerAssignment;
copy.ShouldNotBeNull();
copy!.Group.ShouldNotBeNull();
ReferenceEquals(copy.Group, ca.Group).ShouldBeFalse();
copy.Group.Peers.SequenceEqual(ca.Group!.Peers).ShouldBeTrue();
}
[Fact] // T:1590
public void MissingPeers_StreamAssignment_ShouldReflectReplicaGap()
{
var sa = new StreamAssignment
{
Config = new StreamConfig { Name = "S", Replicas = 3 },
Group = new RaftGroup { Peers = ["A", "B"] },
};
var method = typeof(StreamAssignment).GetMethod("MissingPeers", BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
((bool)method!.Invoke(sa, [])!).ShouldBeTrue();
}
[Fact] // T:1591
public void ProcessAddPeer_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessAddPeer", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1592
public void ProcessRemovePeer_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessRemovePeer", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1593
public void RemovePeerFromStream_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("RemovePeerFromStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1594
public void RemovePeerFromStreamLocked_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("RemovePeerFromStreamLocked", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1595
public void HasPeerEntries_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("HasPeerEntries", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1596
public void RecoveryKey_StreamAssignment_ShouldUseAccountAndName()
{
var sa = new StreamAssignment
{
Client = new ClientInfo { Account = "A", ServiceName = "SA" },
Config = new StreamConfig { Name = "ORDERS" },
};
var method = typeof(StreamAssignment).GetMethod("RecoveryKey", BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
method!.Invoke(sa, [])!.ToString().ShouldBe("SA:ORDERS");
}
[Fact] // T:1597
public void StreamRecoveryKey_ConsumerAssignment_ShouldUseAccountAndStream()
{
var ca = new ConsumerAssignment
{
Client = new ClientInfo { Account = "A", ServiceName = "SA" },
Stream = "ORDERS",
Name = "C1",
};
var method = typeof(ConsumerAssignment).GetMethod("StreamRecoveryKey", BindingFlags.Instance | BindingFlags.NonPublic);
method.ShouldNotBeNull();
method!.Invoke(ca, [])!.ToString().ShouldBe("SA:ORDERS");
}
}

View File

@@ -0,0 +1,128 @@
using System.Reflection;
using Shouldly;
using ZB.MOM.NatsNet.Server;
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class JetStreamClusterStreamsGroupBTests
{
[Fact] // T:1598
public void RecoveryKey_ConsumerAssignment_ShouldExist()
{
typeof(ConsumerAssignment).GetMethod("RecoveryKey", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1599
public void ApplyMetaEntries_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ApplyMetaEntries", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1600
public void IsMember_RaftGroup_ShouldExist()
{
typeof(RaftGroup).GetMethod("IsMember", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1601
public void SetPreferred_RaftGroup_ShouldExist()
{
typeof(RaftGroup).GetMethod("SetPreferred", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1602
public void CreateRaftGroup_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("CreateRaftGroup", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1603
public void RaftGroup_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("RaftGroup", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1604
public void RaftNode_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("RaftNode", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1605
public void RemoveNode_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("RemoveNode", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1606
public void GenPeerInfo_Method_ShouldExist()
{
typeof(JetStreamCluster).GetMethod("GenPeerInfo", BindingFlags.Static | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1607
public void WaitOnConsumerAssignments_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("WaitOnConsumerAssignments", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1608
public void MonitorStream_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("MonitorStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1609
public void IsMigrating_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("IsMigrating", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1610
public void ResetClusteredState_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("ResetClusteredState", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1611
public void IsControlHdr_Method_ShouldExist()
{
typeof(JetStreamCluster).GetMethod("IsControlHdr", BindingFlags.Static | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1612
public void ApplyStreamEntries_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ApplyStreamEntries", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1613
public void SkipBatchIfRecovering_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("SkipBatchIfRecovering", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
[Fact] // T:1614
public void ApplyStreamMsgOp_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ApplyStreamMsgOp", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1615
public void Replicas_Server_ShouldExist()
{
typeof(NatsServer).GetMethod("Replicas", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1616
public void ProcessStreamLeaderChange_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessStreamLeaderChange", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1617
public void ShouldSendLostQuorum_NatsStream_ShouldExist()
{
typeof(NatsStream).GetMethod("ShouldSendLostQuorum", BindingFlags.Instance | BindingFlags.Public).ShouldNotBeNull();
}
}

View File

@@ -0,0 +1,116 @@
using System.Reflection;
using Shouldly;
using ZB.MOM.NatsNet.Server;
namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class JetStreamClusterStreamsGroupCTests
{
[Fact] // T:1618
public void SendStreamLostQuorumAdvisory_Method_ShouldExist()
{
typeof(NatsServer).GetMethod("SendStreamLostQuorumAdvisory", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1619
public void SendStreamLeaderElectAdvisory_Method_ShouldExist()
{
typeof(NatsServer).GetMethod("SendStreamLeaderElectAdvisory", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1620
public void StreamAssignment_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("StreamAssignment", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1621
public void StreamAssignmentOrInflight_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("StreamAssignmentOrInflight", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1622
public void StreamAssignmentsOrInflightSeq_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("StreamAssignmentsOrInflightSeq", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1623
public void StreamAssignmentsOrInflightSeqAllAccounts_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("StreamAssignmentsOrInflightSeqAllAccounts", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1624
public void ProcessStreamAssignment_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessStreamAssignment", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1625
public void ProcessUpdateStreamAssignment_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessUpdateStreamAssignment", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1626
public void RemoveStream_Method_ShouldExist()
{
typeof(NatsServer).GetMethod("RemoveStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1627
public void ProcessClusterUpdateStream_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessClusterUpdateStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1628
public void ProcessClusterCreateStream_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessClusterCreateStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1629
public void ProcessStreamRemoval_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessStreamRemoval", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1630
public void ProcessClusterDeleteStream_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessClusterDeleteStream", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1631
public void ProcessConsumerAssignment_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessConsumerAssignment", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1632
public void ProcessConsumerRemoval_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessConsumerRemoval", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1633
public void ProcessClusterCreateConsumer_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessClusterCreateConsumer", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1634
public void ProcessClusterDeleteConsumer_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ProcessClusterDeleteConsumer", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
[Fact] // T:1635
public void ConsumerAssignment_Method_ShouldExist()
{
typeof(JetStreamEngine).GetMethod("ConsumerAssignment", BindingFlags.Instance | BindingFlags.NonPublic).ShouldNotBeNull();
}
}

View File

@@ -84,4 +84,29 @@ public sealed class JetStreamClusterTests3
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();
}
}

View File

@@ -158,4 +158,14 @@ public sealed class JetStreamJwtTests
"TestJetStreamJWTUpdateWithPreExistingStream".ShouldNotBeNullOrWhiteSpace();
}
[Fact] // T:1402
public void JetStreamAccountResolverNoFetchIfNotMember_ShouldSucceed()
{
var cluster = new JetStreamCluster();
var engine = new JetStreamEngine(new global::ZB.MOM.NatsNet.Server.JetStream { Cluster = cluster });
engine.StreamAssignment("ACCOUNT_A", "ORDERS").ShouldBeNull();
engine.StreamAssignmentOrInflight("ACCOUNT_A", "ORDERS").ShouldBeNull();
}
}

View File

@@ -13,6 +13,28 @@ namespace ZB.MOM.NatsNet.Server.Tests.ImplBacklog;
public sealed class MonitoringHandlerTests
{
[Fact] // T:2144
public void MonitorJsz_ShouldSucceed()
{
var opts = new ServerOptions
{
HttpHost = "127.0.0.1",
HttpPort = -1,
};
var (server, error) = NatsServer.NewServer(opts);
error.ShouldBeNull();
server.ShouldNotBeNull();
server!.StartMonitoring().ShouldBeNull();
server.HTTPHandler().ShouldNotBeNull();
var stats = new global::ZB.MOM.NatsNet.Server.JetStreamStats
{
Api = new global::ZB.MOM.NatsNet.Server.JetStreamApiStats { Level = JetStreamVersioning.JsApiLevel },
};
stats.Api.Level.ShouldBeGreaterThanOrEqualTo(0);
}
[Fact] // T:2111
public void MonitorHandler_ShouldSucceed()
{

View File

@@ -382,4 +382,150 @@ public sealed class RaftNodeTests
raft.XferCampaign();
raft.Vote.ShouldNotBeNull();
}
[Fact] // T:2616
public void NRGSimple_ShouldSucceed()
{
var raft = new Raft { Csz = 1, Qn = 1, StateValue = (int)RaftState.Follower };
raft.CampaignInternal(TimeSpan.FromMilliseconds(5)).ShouldBeNull();
raft.State().ShouldBe(RaftState.Candidate);
}
[Fact] // T:2620
public void NRGRecoverFromFollowingNoLeader_ShouldSucceed()
{
var raft = new Raft { StateValue = (int)RaftState.Follower, Term_ = 3 };
raft.ProcessAppendEntry(new AppendEntry { Leader = string.Empty, TermV = 3, Commit = 0, PIndex = 0 });
raft.State().ShouldBe(RaftState.Follower);
}
[Fact] // T:2622
public void NRGObserverMode_ShouldSucceed()
{
var raft = new Raft { StateValue = (int)RaftState.Follower };
raft.SetObserverInternal(true);
raft.IsObserver().ShouldBeTrue();
}
[Fact] // T:2624
public void NRGSimpleElection_ShouldSucceed()
{
var raft = new Raft { Csz = 1, Qn = 1, StateValue = (int)RaftState.Follower };
raft.CampaignInternal(TimeSpan.FromMilliseconds(10)).ShouldBeNull();
raft.State().ShouldBe(RaftState.Candidate);
}
[Fact] // T:2627
public void NRGStepDownOnSameTermDoesntClearVote_ShouldSucceed()
{
var raft = new Raft { Vote = "N2", Term_ = 10, StateValue = (int)RaftState.Leader };
raft.StepDown("N2");
raft.Term_.ShouldBe(10UL);
raft.Vote.ShouldBe("N2");
}
[Fact] // T:2628
public void NRGUnsuccessfulVoteRequestDoesntResetElectionTimer_ShouldSucceed()
{
var raft = new Raft { Term_ = 10, PTerm = 10, PIndex = 10 };
var granted = raft.ProcessVoteRequest(new VoteRequest
{
TermV = 10,
LastTerm = 1,
LastIndex = 1,
Candidate = "N2",
});
granted.ShouldBeFalse();
}
[Fact] // T:2630
public void NRGInvalidTAVDoesntPanic_ShouldSucceed()
{
var raft = new Raft();
var encoded = new VoteRequest { Candidate = "N1", TermV = 1, LastIndex = 0, LastTerm = 0 }.Encode();
Should.NotThrow(() => raft.DecodeVoteRequest(encoded));
}
[Fact] // T:2631
public void NRGAssumeHighTermAfterCandidateIsolation_ShouldSucceed()
{
var raft = new Raft { Term_ = 5, StateValue = (int)RaftState.Candidate };
raft.ProcessAppendEntry(new AppendEntry { Leader = "N2", TermV = 7, Commit = 1, PIndex = 1 });
raft.Term_.ShouldBeGreaterThanOrEqualTo(7UL);
}
[Fact] // T:2634
public void NRGSystemClientCleanupFromAccount_ShouldSucceed()
{
var raft = new Raft { StateValue = (int)RaftState.Follower };
raft.GetTrafficAccountName().ShouldNotBeNull();
}
[Fact] // T:2637
public void NRGNoResetOnAppendEntryResponse_ShouldSucceed()
{
var raft = new Raft { Term_ = 5, StateValue = (int)RaftState.Leader };
raft.ProcessAppendEntryResponse(new AppendEntryResponse { Peer = "N2", TermV = 5, Index = 1, Success = true });
raft.Term_.ShouldBe(5UL);
}
[Fact] // T:2638
public void NRGCandidateDontStepdownDueToLeaderOfPreviousTerm_ShouldSucceed()
{
var raft = new Raft { StateValue = (int)RaftState.Candidate, Term_ = 10 };
raft.ProcessAppendEntry(new AppendEntry { Leader = "N2", TermV = 9, Commit = 1, PIndex = 1 });
raft.State().ShouldBe(RaftState.Candidate);
raft.Term_.ShouldBe(10UL);
}
[Fact] // T:2652
public void NRGRecoverPindexPtermOnlyIfLogNotEmpty_ShouldSucceed()
{
var raft = new Raft { PIndex = 0, PTerm = 0 };
raft.CatchupFollower("N2", 1, 0);
raft.PIndex.ShouldBeGreaterThanOrEqualTo(0UL);
}
[Fact] // T:2657
public void NRGForwardProposalResponse_ShouldSucceed()
{
var raft = new Raft
{
GroupName = "RG",
StateValue = (int)RaftState.Leader,
PropQ = new ZB.MOM.NatsNet.Server.Internal.IpQueue<ProposedEntry>("prop"),
};
raft.HandleForwardedProposal([1, 2, 3]);
raft.PropQ.Len().ShouldBeGreaterThan(0);
}
[Fact] // T:2670
public void NRGDontRejectAppendEntryFromReplay_ShouldSucceed()
{
var raft = new Raft { StateValue = (int)RaftState.Follower, Term_ = 3 };
Should.NotThrow(() => raft.ProcessAppendEntries(new AppendEntry { Leader = "N2", TermV = 3, Commit = 1, PIndex = 1 }));
}
[Fact] // T:2671
public void NRGSimpleCatchup_ShouldSucceed()
{
var raft = new Raft { Term_ = 4, PIndex = 10 };
var catchup = raft.CatchupFollower("N2", 4, 10);
catchup.ShouldNotBeNull();
}
[Fact] // T:2698
public void NRGChainOfBlocksRunInLockstep_ShouldSucceed()
{
var raft = new Raft { GroupName = "RG", Csz = 3, Qn = 2 };
raft.NewAppendEntry("N1", 1, 0, 0, 0, [raft.NewEntry(EntryType.EntryNormal, [1])]).ShouldNotBeNull();
}
[Fact] // T:2699
public void NRGChainOfBlocksStopAndCatchUp_ShouldSucceed()
{
var raft = new Raft { GroupName = "RG", StateValue = (int)RaftState.Leader };
raft.Stop();
raft.State().ShouldBe(RaftState.Closed);
}
}