@@ -219,6 +219,41 @@ class RaftActorCandidateSpec extends TestKit(ActorSystem()) with RaftActorSpecBa
219219 state.stateData.leaderMember should be(None )
220220 }
221221
222+ " not become the leader by duplicated votes from the same follower" in {
223+ val selfMemberIndex = createUniqueMemberIndex()
224+ val follower1MemberIndex = createUniqueMemberIndex()
225+ val follower2MemberIndex = createUniqueMemberIndex()
226+ val candidate = createRaftActor(
227+ selfMemberIndex = selfMemberIndex,
228+ otherMemberIndexes = Set (follower1MemberIndex, follower2MemberIndex),
229+ )
230+ val currentTerm = Term (1 )
231+ setState(candidate, Candidate , createCandidateData(currentTerm))
232+ inside(getState(candidate)) { state =>
233+ state.stateData.acceptedMembers should be(Set .empty)
234+ }
235+
236+ // For simplicity, this test skips that the candidate votes for itself.
237+
238+ // The first vote from follower1
239+ candidate ! RequestVoteAccepted (currentTerm, follower1MemberIndex)
240+ inside(getState(candidate)) { state =>
241+ state.stateName should be(Candidate )
242+ state.stateData.currentTerm should be(currentTerm)
243+ state.stateData.acceptedMembers should be(Set (follower1MemberIndex))
244+ }
245+
246+ // The second duplicated vote from follower1.
247+ // The candidate shouldn't become the leader
248+ // since it doesn't receive votes from the majority of the members.
249+ candidate ! RequestVoteAccepted (currentTerm, follower1MemberIndex)
250+ inside(getState(candidate)) { state =>
251+ state.stateName should be(Candidate )
252+ state.stateData.currentTerm should be(currentTerm)
253+ state.stateData.acceptedMembers should be(Set (follower1MemberIndex))
254+ }
255+ }
256+
222257 " AppendEntries が古い Term を持っているときは拒否" in {
223258 val candidateMemberIndex = createUniqueMemberIndex()
224259 val candidate = createRaftActor(
0 commit comments