+ 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);
+
+ RequestVote requestVote = MessageCollectorActor.expectFirstMatching(peerActors[0], RequestVote.class);
+ assertEquals("getTerm", 3L, requestVote.getTerm());
+ assertEquals("getCandidateId", raftActorContext.getId(), requestVote.getCandidateId());
+ assertEquals("getLastLogTerm", 1L, requestVote.getLastLogTerm());
+ assertEquals("getLastLogIndex", 4L, requestVote.getLastLogIndex());
+
+ MessageCollectorActor.expectFirstMatching(peerActors[1], RequestVote.class);
+ MessageCollectorActor.expectFirstMatching(peerActors[2], RequestVote.class);
+ MessageCollectorActor.expectFirstMatching(peerActors[3], RequestVote.class);
+
+ // First peers denies the vote.
+ candidate = candidate.handleMessage(peerActors[0], new RequestVoteReply(1, false));
+
+ assertEquals("Behavior", RaftState.Candidate, candidate.state());
+
+ candidate = candidate.handleMessage(peerActors[1], new RequestVoteReply(1, true));
+
+ assertEquals("Behavior", RaftState.Candidate, candidate.state());
+
+ candidate = candidate.handleMessage(peerActors[2], new RequestVoteReply(1, true));
+
+ assertEquals("Behavior", RaftState.Leader, candidate.state());
+ }
+
+ @Test
+ public void testBecomeLeaderOnReceivingMajorityVotesWithNonVotingPeers() {
+ ElectionTerm mockElectionTerm = Mockito.mock(ElectionTerm.class);
+ Mockito.doReturn(1L).when(mockElectionTerm).getCurrentTerm();
+ RaftActorContext raftActorContext = new RaftActorContextImpl(candidateActor, candidateActor.actorContext(),
+ "candidate", mockElectionTerm, -1, -1, setupPeers(4), new DefaultConfigParamsImpl(),
+ new NonPersistentDataProvider(Runnable::run), applyState -> { }, LOG, MoreExecutors.directExecutor());
+ raftActorContext.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().build());
+ raftActorContext.getPeerInfo("peer1").setVotingState(VotingState.NON_VOTING);
+ raftActorContext.getPeerInfo("peer4").setVotingState(VotingState.NON_VOTING);
+ candidate = new Candidate(raftActorContext);
+
+ MessageCollectorActor.expectFirstMatching(peerActors[1], RequestVote.class);
+ MessageCollectorActor.expectFirstMatching(peerActors[2], RequestVote.class);
+ MessageCollectorActor.assertNoneMatching(peerActors[0], RequestVote.class, 300);
+ MessageCollectorActor.assertNoneMatching(peerActors[3], RequestVote.class, 100);
+
+ candidate = candidate.handleMessage(peerActors[1], new RequestVoteReply(1, false));
+
+ assertEquals("Behavior", RaftState.Candidate, candidate.state());
+
+ candidate = candidate.handleMessage(peerActors[2], new RequestVoteReply(1, true));
+
+ assertEquals("Behavior", RaftState.Leader, candidate.state());
+ }