1 package org.opendaylight.controller.cluster.raft.behaviors;
3 import akka.actor.ActorRef;
4 import akka.actor.Props;
5 import akka.testkit.JavaTestKit;
6 import junit.framework.Assert;
8 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
9 import org.opendaylight.controller.cluster.raft.RaftActorContext;
10 import org.opendaylight.controller.cluster.raft.RaftState;
11 import org.opendaylight.controller.cluster.raft.internal.messages.ElectionTimeout;
12 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
13 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
14 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
15 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
16 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
18 import java.util.Arrays;
19 import java.util.Collections;
21 import static org.junit.Assert.assertEquals;
23 public class CandidateTest extends AbstractRaftActorBehaviorTest {
25 private final ActorRef candidateActor = getSystem().actorOf(Props.create(
26 DoNothingActor.class));
28 private final ActorRef peerActor1 = getSystem().actorOf(Props.create(
29 DoNothingActor.class));
31 private final ActorRef peerActor2 = getSystem().actorOf(Props.create(
32 DoNothingActor.class));
34 private final ActorRef peerActor3 = getSystem().actorOf(Props.create(
35 DoNothingActor.class));
37 private final ActorRef peerActor4 = getSystem().actorOf(Props.create(
38 DoNothingActor.class));
41 public void testWhenACandidateIsCreatedItIncrementsTheCurrentTermAndVotesForItself(){
42 RaftActorContext raftActorContext = createActorContext();
43 long expectedTerm = raftActorContext.getTermInformation().getCurrentTerm().get();
45 new Candidate(raftActorContext, Collections.EMPTY_LIST);
47 assertEquals(expectedTerm+1, raftActorContext.getTermInformation().getCurrentTerm().get());
48 assertEquals(raftActorContext.getId(), raftActorContext.getTermInformation().getVotedFor());
52 public void testThatAnElectionTimeoutIsTriggered(){
53 new JavaTestKit(getSystem()) {{
55 new Within(duration("1 seconds")) {
56 protected void run() {
58 Candidate candidate = new Candidate(createActorContext(getTestActor()), Collections.EMPTY_LIST);
60 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "ElectionTimeout") {
61 // do not put code outside this method, will run afterwards
62 protected Boolean match(Object in) {
63 if (in instanceof ElectionTimeout) {
71 assertEquals(true, out);
78 public void testHandleElectionTimeoutWhenThereAreZeroPeers(){
79 RaftActorContext raftActorContext = createActorContext();
81 new Candidate(raftActorContext, Collections.EMPTY_LIST);
84 candidate.handleMessage(candidateActor, new ElectionTimeout());
86 Assert.assertEquals(RaftState.Leader, raftState);
90 public void testHandleElectionTimeoutWhenThereAreTwoPeers(){
91 RaftActorContext raftActorContext = createActorContext();
93 new Candidate(raftActorContext, Arrays
94 .asList(peerActor1.path().toString(),
95 peerActor2.path().toString()));
98 candidate.handleMessage(candidateActor, new ElectionTimeout());
100 Assert.assertEquals(RaftState.Candidate, raftState);
104 public void testBecomeLeaderOnReceivingMajorityVotesInThreePeerCluster(){
105 RaftActorContext raftActorContext = createActorContext();
106 Candidate candidate =
107 new Candidate(raftActorContext, Arrays
108 .asList(peerActor1.path().toString(),
109 peerActor2.path().toString()));
111 RaftState stateOnFirstVote = candidate.handleMessage(peerActor1, new RequestVoteReply(0, true));
113 Assert.assertEquals(RaftState.Leader, stateOnFirstVote);
118 public void testBecomeLeaderOnReceivingMajorityVotesInFivePeerCluster(){
119 RaftActorContext raftActorContext = createActorContext();
120 Candidate candidate =
121 new Candidate(raftActorContext, Arrays
122 .asList(peerActor1.path().toString(),
123 peerActor2.path().toString(),
124 peerActor3.path().toString()));
126 RaftState stateOnFirstVote = candidate.handleMessage(peerActor1, new RequestVoteReply(0, true));
128 RaftState stateOnSecondVote = candidate.handleMessage(peerActor1, new RequestVoteReply(0, true));
130 Assert.assertEquals(RaftState.Candidate, stateOnFirstVote);
131 Assert.assertEquals(RaftState.Leader, stateOnSecondVote);
136 public void testResponseToAppendEntriesWithLowerTerm(){
137 new JavaTestKit(getSystem()) {{
139 new Within(duration("1 seconds")) {
140 protected void run() {
142 Candidate candidate = new Candidate(createActorContext(getTestActor()), Collections.EMPTY_LIST);
144 candidate.handleMessage(getTestActor(), new AppendEntries(0, "test", 0,0,Collections.EMPTY_LIST, 0));
146 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "AppendEntriesResponse") {
147 // do not put code outside this method, will run afterwards
148 protected Boolean match(Object in) {
149 if (in instanceof AppendEntriesReply) {
150 AppendEntriesReply reply = (AppendEntriesReply) in;
151 return reply.isSuccess();
158 assertEquals(false, out);
165 public void testResponseToRequestVoteWithLowerTerm(){
166 new JavaTestKit(getSystem()) {{
168 new Within(duration("1 seconds")) {
169 protected void run() {
171 Candidate candidate = new Candidate(createActorContext(getTestActor()), Collections.EMPTY_LIST);
173 candidate.handleMessage(getTestActor(), new RequestVote(0, "test", 0, 0));
175 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "AppendEntriesResponse") {
176 // do not put code outside this method, will run afterwards
177 protected Boolean match(Object in) {
178 if (in instanceof RequestVoteReply) {
179 RequestVoteReply reply = (RequestVoteReply) in;
180 return reply.isVoteGranted();
187 assertEquals(false, out);
195 @Override protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
196 return new Candidate(actorContext, Collections.EMPTY_LIST);
199 @Override protected RaftActorContext createActorContext() {
200 return new MockRaftActorContext("test", getSystem(), candidateActor);
203 protected RaftActorContext createActorContext(ActorRef candidateActor) {
204 return new MockRaftActorContext("test", getSystem(), candidateActor);