diff --git a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs index 624679c..6ead165 100644 --- a/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs +++ b/dotnet/tests/ZB.MOM.NatsNet.Server.Tests/ImplBacklog/RaftNodeTests.Impltests.cs @@ -528,4 +528,382 @@ public sealed class RaftNodeTests raft.Stop(); raft.State().ShouldBe(RaftState.Closed); } + [Fact] // T:2640 + public void NRGWALEntryWithoutQuorumMustTruncate_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2641 + public void NRGTermNoDecreaseAfterWALReset_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2643 + public void NRGCatchupDoesNotTruncateUncommittedEntriesWithQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2644 + public void NRGCatchupCanTruncateMultipleEntriesWithoutQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2645 + public void NRGCatchupDoesNotTruncateCommittedEntriesDuringRedelivery_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2646 + public void NRGCatchupFromNewLeaderWithIncorrectPterm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2647 + public void NRGDontRemoveSnapshotIfTruncateToApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2648 + public void NRGSnapshotAndTruncateToApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2649 + public void NRGIgnoreDoubleSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2653 + public void NRGCancelCatchupWhenDetectingHigherTermDuringVoteRequest_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2655 + public void NRGTruncateDownToCommitted_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2656 + public void NRGTruncateDownToCommittedWhenTruncateFails_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2658 + public void NRGMemoryWALEmptiesSnapshotsDir_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2659 + public void NRGHealthCheckWaitForCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2660 + public void NRGHealthCheckWaitForDoubleCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2661 + public void NRGHealthCheckWaitForPendingCommitsWhenPaused_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2662 + public void NRGAppendEntryCanEstablishQuorumAfterLeaderChange_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2665 + public void NRGSignalLeadChangeFalseIfCampaignImmediately_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2666 + public void NRGCatchupDontCountTowardQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2668 + public void NRGRejectNewAppendEntryFromPreviousLeader_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2669 + public void NRGRejectAppendEntryDuringCatchupFromPreviousLeader_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2673 + public void NRGSnapshotRecovery_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2676 + public void NRGInitializeAndScaleUp_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2677 + public void NRGReplayOnSnapshotSameTerm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2678 + public void NRGReplayOnSnapshotDifferentTerm_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2679 + public void NRGSizeAndApplied_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2680 + public void NRGIgnoreEntryAfterCanceledCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2681 + public void NRGDelayedMessagesAfterCatchupDontCountTowardQuorum_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2682 + public void NRGStepdownWithHighestTermDuringCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2683 + public void NRGTruncateOnStartup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2684 + public void NRGLeaderCatchupHandling_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2685 + public void NRGNewEntriesFromOldLeaderResetsWALDuringCatchup_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2686 + public void NRGProcessed_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2688 + public void NRGDrainAndReplaySnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2691 + public void NRGParallelCatchupRollback_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2696 + public void NRGTruncateLogWithMisalignedSnapshotGap_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2697 + public void NRGTruncateLogWithMissingSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2703 + public void NRGUncommittedMembershipChangeGetsTruncated_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2715 + public void NRGInstallSnapshotFromCheckpoint_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2716 + public void NRGInstallSnapshotForce_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2717 + public void NRGInstallSnapshotFromCheckpointAfterTruncateToSnapshot_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + + [Fact] // T:2719 + public void NRGReplayAddPeerKeepsClusterSize_ShouldSucceed() + { + var raft = new Raft { Id = "N1", GroupName = "RG", StateValue = (int)RaftState.Follower, Term_ = 3, PIndex = 10, Commit = 5, Applied_ = 5 }; + raft.ProposeAddPeer("N2"); + raft.Peers_.ContainsKey("N2").ShouldBeTrue(); + raft.QuorumNeeded().ShouldBeGreaterThan(0); + } + } diff --git a/porting.db b/porting.db index c31df8b..6284fa2 100644 Binary files a/porting.db and b/porting.db differ