1 package org.opendaylight.controller.cluster.raft.behaviors;
3 import akka.actor.ActorRef;
4 import akka.actor.Props;
5 import akka.testkit.JavaTestKit;
7 import org.opendaylight.controller.cluster.raft.AbstractActorTest;
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.messages.AppendEntries;
12 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
13 import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
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.concurrent.atomic.AtomicLong;
20 import static org.junit.Assert.assertEquals;
22 public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest{
24 private final ActorRef behaviorActor = getSystem().actorOf(Props.create(
25 DoNothingActor.class));
28 public void testHandlingOfRaftRPCWithNewerTerm() throws Exception {
29 new JavaTestKit(getSystem()) {{
31 assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
32 createAppendEntriesWithNewerTerm());
34 assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
35 createAppendEntriesReplyWithNewerTerm());
37 assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
38 createRequestVoteWithNewerTerm());
40 assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
41 createRequestVoteReplyWithNewerTerm());
48 public void testHandlingOfAppendEntriesWithNewerCommitIndex() throws Exception{
49 new JavaTestKit(getSystem()) {{
51 RaftActorContext context =
54 ((MockRaftActorContext) context).setLastApplied(100);
56 AppendEntries appendEntries =
57 new AppendEntries(100, "leader-1", 0, 0, null, 101);
60 createBehavior(context).handleMessage(getRef(), appendEntries);
62 assertEquals(new AtomicLong(101).get(), context.getLastApplied());
68 public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermAndSenderLogMoreUpToDate(){
69 new JavaTestKit(getSystem()) {{
71 new Within(duration("1 seconds")) {
72 protected void run() {
74 RaftActorBehavior follower = createBehavior(
75 createActorContext(behaviorActor));
77 follower.handleMessage(getTestActor(), new RequestVote(1000, "test", 10000, 999));
79 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
80 // do not put code outside this method, will run afterwards
81 protected Boolean match(Object in) {
82 if (in instanceof RequestVoteReply) {
83 RequestVoteReply reply = (RequestVoteReply) in;
84 return reply.isVoteGranted();
91 assertEquals(true, out);
98 public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermButSenderLogLessUptoDate(){
99 new JavaTestKit(getSystem()) {{
101 new Within(duration("1 seconds")) {
102 protected void run() {
104 RaftActorContext actorContext =
105 createActorContext(behaviorActor);
107 MockRaftActorContext.MockReplicatedLog log = new MockRaftActorContext.MockReplicatedLog();
108 log.setReplicatedLogEntry(new MockRaftActorContext.MockReplicatedLogEntry(20000, 1000000, ""));
110 new MockRaftActorContext.MockReplicatedLogEntry(20000,
113 ((MockRaftActorContext) actorContext).setReplicatedLog(log);
115 RaftActorBehavior follower = createBehavior(actorContext);
117 follower.handleMessage(getTestActor(), new RequestVote(1000, "test", 10000, 999));
119 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
120 // do not put code outside this method, will run afterwards
121 protected Boolean match(Object in) {
122 if (in instanceof RequestVoteReply) {
123 RequestVoteReply reply = (RequestVoteReply) in;
124 return reply.isVoteGranted();
131 assertEquals(false, out);
141 public void testHandleRequestVoteWhenSenderTermLessThanCurrentTerm(){
142 new JavaTestKit(getSystem()) {{
144 new Within(duration("1 seconds")) {
145 protected void run() {
147 RaftActorContext context = createActorContext(behaviorActor);
149 context.getTermInformation().update(1000, null);
151 RaftActorBehavior follower = createBehavior(context);
153 follower.handleMessage(getTestActor(), new RequestVote(999, "test", 10000, 999));
155 final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"), "RequestVoteReply") {
156 // do not put code outside this method, will run afterwards
157 protected Boolean match(Object in) {
158 if (in instanceof RequestVoteReply) {
159 RequestVoteReply reply = (RequestVoteReply) in;
160 return reply.isVoteGranted();
167 assertEquals(false, out);
173 protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(
174 ActorRef actorRef, RaftRPC rpc){
175 RaftState raftState = createBehavior()
176 .handleMessage(actorRef, rpc);
178 assertEquals(RaftState.Follower, raftState);
181 protected abstract RaftActorBehavior createBehavior(RaftActorContext actorContext);
183 protected RaftActorBehavior createBehavior(){
184 return createBehavior(createActorContext());
187 protected RaftActorContext createActorContext(){
188 return new MockRaftActorContext();
191 protected RaftActorContext createActorContext(ActorRef actor) {
192 return new MockRaftActorContext("test", getSystem(), actor);
195 protected AppendEntries createAppendEntriesWithNewerTerm(){
196 return new AppendEntries(100, "leader-1", 0, 0, null, 1);
199 protected AppendEntriesReply createAppendEntriesReplyWithNewerTerm(){
200 return new AppendEntriesReply(100, false);
203 protected RequestVote createRequestVoteWithNewerTerm(){
204 return new RequestVote(100, "candidate-1", 10, 100);
207 protected RequestVoteReply createRequestVoteReplyWithNewerTerm(){
208 return new RequestVoteReply(100, false);