feat(batch30): implement raft group-b snapshot helpers
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
// Copyright 2012-2026 The NATS Authors
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
|
||||
using Shouldly;
|
||||
|
||||
namespace ZB.MOM.NatsNet.Server.Tests.JetStream;
|
||||
|
||||
public sealed class RaftNodeCoreTests
|
||||
{
|
||||
[Fact]
|
||||
public void SnapshotHelpers_WhenEncodedAndLoaded_ShouldRoundTrip()
|
||||
{
|
||||
var storeDir = Path.Combine(Path.GetTempPath(), $"raft-node-core-{Guid.NewGuid():N}");
|
||||
var raft = new Raft
|
||||
{
|
||||
StoreDir = storeDir,
|
||||
Term_ = 3,
|
||||
Applied_ = 9,
|
||||
PApplied = 7,
|
||||
Wps = [1, 2, 3],
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var checkpoint = raft.CreateSnapshotCheckpointLocked(force: true);
|
||||
checkpoint.ShouldNotBeNull();
|
||||
|
||||
var snapshot = new Snapshot
|
||||
{
|
||||
LastTerm = 3,
|
||||
LastIndex = 9,
|
||||
PeerState = [7, 8],
|
||||
Data = [9, 10, 11],
|
||||
};
|
||||
|
||||
raft.InstallSnapshotInternal(snapshot).ShouldBeNull();
|
||||
var (loaded, error) = raft.LoadLastSnapshot();
|
||||
error.ShouldBeNull();
|
||||
loaded.ShouldNotBeNull();
|
||||
loaded!.LastTerm.ShouldBe(3UL);
|
||||
loaded.LastIndex.ShouldBe(9UL);
|
||||
loaded.PeerState.ShouldBe([7, 8]);
|
||||
loaded.Data.ShouldBe([9, 10, 11]);
|
||||
|
||||
raft.SetupLastSnapshot().ShouldBeNull();
|
||||
raft.PIndex.ShouldBe(9UL);
|
||||
raft.PTerm.ShouldBe(3UL);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (Directory.Exists(storeDir))
|
||||
{
|
||||
Directory.Delete(storeDir, recursive: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LeadershipHelpers_WhenSteppingDownAndSelectingLeader_ShouldUpdateState()
|
||||
{
|
||||
var raft = new Raft
|
||||
{
|
||||
Id = "N1",
|
||||
StateValue = (int)RaftState.Candidate,
|
||||
Peers_ = new Dictionary<string, Lps>
|
||||
{
|
||||
["N2"] = new() { Li = 3 },
|
||||
["N3"] = new() { Li = 7 },
|
||||
},
|
||||
};
|
||||
|
||||
raft.StepdownLocked("N3");
|
||||
raft.State().ShouldBe(RaftState.Follower);
|
||||
raft.LeaderId.ShouldBe("N3");
|
||||
raft.SelectNextLeader().ShouldBe("N3");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CampaignHelpers_WhenLeaderOrFollower_ShouldReturnExpectedOutcome()
|
||||
{
|
||||
var raft = new Raft
|
||||
{
|
||||
StateValue = (int)RaftState.Leader,
|
||||
};
|
||||
|
||||
raft.CampaignInternal(TimeSpan.FromMilliseconds(200)).ShouldNotBeNull();
|
||||
raft.XferCampaign().ShouldNotBeNull();
|
||||
|
||||
raft.StateValue = (int)RaftState.Follower;
|
||||
raft.CampaignInternal(TimeSpan.FromMilliseconds(200)).ShouldBeNull();
|
||||
raft.State().ShouldBe(RaftState.Candidate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressHelpers_WhenCatchupAndKnownPeersChange_ShouldTrackFlags()
|
||||
{
|
||||
var raft = new Raft
|
||||
{
|
||||
Commit = 10,
|
||||
Applied_ = 8,
|
||||
Catchup = new CatchupState(),
|
||||
};
|
||||
|
||||
raft.IsCatchingUp().ShouldBeTrue();
|
||||
raft.IsCurrent(includeForwardProgress: true).ShouldBeFalse();
|
||||
raft.Catchup = null;
|
||||
raft.UpdateKnownPeersLocked(["N2", "N3"]);
|
||||
raft.Peers_.Count.ShouldBe(2);
|
||||
raft.RandCampaignTimeout().ShouldBeGreaterThan(TimeSpan.Zero);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user