1e7aa6a1d5fe40e2fd57e3088e80dc0dcbe1d653
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / behaviors / AbstractRaftActorBehaviorTest.java
1 package org.opendaylight.controller.cluster.raft.behaviors;
2
3 import akka.actor.ActorRef;
4 import akka.actor.Props;
5 import akka.testkit.JavaTestKit;
6 import org.junit.Test;
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;
17
18 import java.util.concurrent.atomic.AtomicLong;
19
20 import static org.junit.Assert.assertEquals;
21
22 public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest{
23
24     private final ActorRef behaviorActor = getSystem().actorOf(Props.create(
25         DoNothingActor.class));
26
27    @Test
28     public void testHandlingOfRaftRPCWithNewerTerm() throws Exception {
29         new JavaTestKit(getSystem()) {{
30
31             assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
32                 createAppendEntriesWithNewerTerm());
33
34             assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
35                 createAppendEntriesReplyWithNewerTerm());
36
37             assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
38                 createRequestVoteWithNewerTerm());
39
40             assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
41                 createRequestVoteReplyWithNewerTerm());
42
43
44         }};
45     }
46
47     @Test
48     public void testHandlingOfAppendEntriesWithNewerCommitIndex() throws Exception{
49         new JavaTestKit(getSystem()) {{
50
51             RaftActorContext context =
52                 createActorContext();
53
54             ((MockRaftActorContext) context).setLastApplied(100);
55
56             AppendEntries appendEntries =
57                 new AppendEntries(100, "leader-1", 0, 0, null, 101);
58
59             RaftState raftState =
60                 createBehavior(context).handleMessage(getRef(), appendEntries);
61
62             assertEquals(new AtomicLong(101).get(), context.getLastApplied());
63
64         }};
65     }
66
67     @Test
68     public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermAndSenderLogMoreUpToDate(){
69         new JavaTestKit(getSystem()) {{
70
71             new Within(duration("1 seconds")) {
72                 protected void run() {
73
74                     RaftActorBehavior follower = createBehavior(
75                         createActorContext(behaviorActor));
76
77                     follower.handleMessage(getTestActor(), new RequestVote(1000, "test", 10000, 999));
78
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();
85                             } else {
86                                 throw noMatch();
87                             }
88                         }
89                     }.get();
90
91                     assertEquals(true, out);
92                 }
93             };
94         }};
95     }
96
97     @Test
98     public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermButSenderLogLessUptoDate(){
99         new JavaTestKit(getSystem()) {{
100
101             new Within(duration("1 seconds")) {
102                 protected void run() {
103
104                     RaftActorContext actorContext =
105                         createActorContext(behaviorActor);
106
107                     MockRaftActorContext.MockReplicatedLog log = new MockRaftActorContext.MockReplicatedLog();
108                     log.setReplicatedLogEntry(new MockRaftActorContext.MockReplicatedLogEntry(20000, 1000000, ""));
109                     log.setLast(
110                         new MockRaftActorContext.MockReplicatedLogEntry(20000,
111                             1000000, ""));
112
113                     ((MockRaftActorContext) actorContext).setReplicatedLog(log);
114
115                     RaftActorBehavior follower = createBehavior(actorContext);
116
117                     follower.handleMessage(getTestActor(), new RequestVote(1000, "test", 10000, 999));
118
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();
125                             } else {
126                                 throw noMatch();
127                             }
128                         }
129                     }.get();
130
131                     assertEquals(false, out);
132                 }
133             };
134         }};
135     }
136
137
138
139
140     @Test
141     public void testHandleRequestVoteWhenSenderTermLessThanCurrentTerm(){
142         new JavaTestKit(getSystem()) {{
143
144             new Within(duration("1 seconds")) {
145                 protected void run() {
146
147                     RaftActorContext context = createActorContext(behaviorActor);
148
149                     context.getTermInformation().update(1000, null);
150
151                     RaftActorBehavior follower = createBehavior(context);
152
153                     follower.handleMessage(getTestActor(), new RequestVote(999, "test", 10000, 999));
154
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();
161                             } else {
162                                 throw noMatch();
163                             }
164                         }
165                     }.get();
166
167                     assertEquals(false, out);
168                 }
169             };
170         }};
171     }
172
173     protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(
174         ActorRef actorRef, RaftRPC rpc){
175         RaftState raftState = createBehavior()
176             .handleMessage(actorRef, rpc);
177
178         assertEquals(RaftState.Follower, raftState);
179     }
180
181     protected abstract RaftActorBehavior createBehavior(RaftActorContext actorContext);
182
183     protected RaftActorBehavior createBehavior(){
184         return createBehavior(createActorContext());
185     }
186
187     protected RaftActorContext createActorContext(){
188         return new MockRaftActorContext();
189     }
190
191     protected RaftActorContext createActorContext(ActorRef actor) {
192         return new MockRaftActorContext("test", getSystem(), actor);
193     }
194
195     protected AppendEntries createAppendEntriesWithNewerTerm(){
196         return new AppendEntries(100, "leader-1", 0, 0, null, 1);
197     }
198
199     protected AppendEntriesReply createAppendEntriesReplyWithNewerTerm(){
200         return new AppendEntriesReply(100, false);
201     }
202
203     protected RequestVote createRequestVoteWithNewerTerm(){
204         return new RequestVote(100, "candidate-1", 10, 100);
205     }
206
207     protected RequestVoteReply createRequestVoteReplyWithNewerTerm(){
208         return new RequestVoteReply(100, false);
209     }
210
211
212
213 }