import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class CandidateTest extends AbstractRaftActorBehaviorTest {
+public class CandidateTest extends AbstractRaftActorBehaviorTest<Candidate> {
static final Logger LOG = LoggerFactory.getLogger(CandidateTest.class);
private final TestActorRef<MessageCollectorActor> candidateActor = actorFactory.createTestActor(
candidate = new Candidate(raftActorContext);
RaftActorBehavior newBehavior =
- candidate.handleMessage(candidateActor, new ElectionTimeout());
+ candidate.handleMessage(candidateActor, ElectionTimeout.INSTANCE);
assertEquals("Behavior", RaftState.Leader, newBehavior.state());
}
raftActorContext.setPeerAddresses(setupPeers(1));
candidate = new Candidate(raftActorContext);
- candidate = candidate.handleMessage(candidateActor, new ElectionTimeout());
+ candidate = candidate.handleMessage(candidateActor, ElectionTimeout.INSTANCE);
assertEquals("Behavior", RaftState.Candidate, candidate.state());
}
@Test
public void testBecomeLeaderOnReceivingMajorityVotesInThreeNodeCluster(){
MockRaftActorContext raftActorContext = createActorContext();
+ raftActorContext.setLastApplied(raftActorContext.getReplicatedLog().lastIndex());
raftActorContext.setPeerAddresses(setupPeers(2));
candidate = new Candidate(raftActorContext);
assertEquals("Behavior", RaftState.Leader, candidate.state());
}
+ @Test
+ public void testBecomePreLeaderOnReceivingMajorityVotesInThreeNodeCluster(){
+ MockRaftActorContext raftActorContext = createActorContext();
+ raftActorContext.setPeerAddresses(setupPeers(2));
+ candidate = new Candidate(raftActorContext);
+
+ candidate = candidate.handleMessage(peerActors[0], new RequestVoteReply(1, true));
+
+ // LastApplied is -1 and behind the last index.
+ assertEquals("Behavior", RaftState.PreLeader, candidate.state());
+ }
+
@Test
public void testBecomeLeaderOnReceivingMajorityVotesInFiveNodeCluster(){
MockRaftActorContext raftActorContext = createActorContext();
raftActorContext.getTermInformation().update(2L, "other");
raftActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().
createEntries(0, 5, 1).build());
+ raftActorContext.setCommitIndex(raftActorContext.getReplicatedLog().lastIndex());
+ raftActorContext.setLastApplied(raftActorContext.getReplicatedLog().lastIndex());
raftActorContext.setPeerAddresses(setupPeers(4));
candidate = new Candidate(raftActorContext);
context.getTermInformation().update(2, "test");
// Send an unknown message so that the state of the RaftActor remains unchanged
- RaftActorBehavior expected = behavior.handleMessage(candidateActor, "unknown");
+ behavior.handleMessage(candidateActor, "unknown");
RaftActorBehavior raftBehavior = behavior.handleMessage(candidateActor, appendEntries);
}
@Override
- protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
+ protected Candidate createBehavior(final RaftActorContext actorContext) {
return new Candidate(actorContext);
}
return new MockRaftActorContext("candidate", getSystem(), candidateActor);
}
- private Map<String, String> setupPeers(int count) {
+ @SuppressWarnings("unchecked")
+ private Map<String, String> setupPeers(final int count) {
Map<String, String> peerMap = new HashMap<>();
peerActors = new TestActorRef[count];
for(int i = 0; i < count; i++) {
}
@Override
- protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
- ActorRef actorRef, RaftRPC rpc) throws Exception {
+ protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(final MockRaftActorContext actorContext,
+ final ActorRef actorRef, final RaftRPC rpc) throws Exception {
super.assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, actorRef, rpc);
- assertEquals("New votedFor", null, actorContext.getTermInformation().getVotedFor());
+ if(rpc instanceof RequestVote) {
+ assertEquals("New votedFor", ((RequestVote)rpc).getCandidateId(), actorContext.getTermInformation().getVotedFor());
+ } else {
+ assertEquals("New votedFor", null, actorContext.getTermInformation().getVotedFor());
+ }
}
}