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.ReplicatedLogImplEntry;
12 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
13 import org.opendaylight.controller.cluster.raft.base.messages.Replicate;
14 import org.opendaylight.controller.cluster.raft.base.messages.SendHeartBeat;
15 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
16 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
18 import java.util.HashMap;
21 import static org.junit.Assert.assertEquals;
23 public class LeaderTest extends AbstractRaftActorBehaviorTest {
25 private ActorRef leaderActor =
26 getSystem().actorOf(Props.create(DoNothingActor.class));
27 private ActorRef senderActor =
28 getSystem().actorOf(Props.create(DoNothingActor.class));
31 public void testHandleMessageForUnknownMessage() throws Exception {
32 new JavaTestKit(getSystem()) {{
34 new Leader(createActorContext());
36 // handle message should return the Leader state when it receives an
38 RaftState state = leader.handleMessage(senderActor, "foo");
39 Assert.assertEquals(RaftState.Leader, state);
45 public void testThatLeaderSendsAHeartbeatMessageToAllFollowers() {
46 new JavaTestKit(getSystem()) {{
48 new Within(duration("1 seconds")) {
49 protected void run() {
51 ActorRef followerActor = getTestActor();
53 MockRaftActorContext actorContext =
54 (MockRaftActorContext) createActorContext();
56 Map<String, String> peerAddresses = new HashMap();
58 peerAddresses.put(followerActor.path().toString(),
59 followerActor.path().toString());
61 actorContext.setPeerAddresses(peerAddresses);
63 Leader leader = new Leader(actorContext);
64 leader.handleMessage(senderActor, new SendHeartBeat());
67 new ExpectMsg<String>(duration("1 seconds"), "match hint") {
68 // do not put code outside this method, will run afterwards
69 protected String match(Object in) {
70 Object msg = fromSerializableMessage(in);
71 if (msg instanceof AppendEntries) {
72 if (((AppendEntries)msg).getTerm() == 0) {
80 }.get(); // this extracts the received message
82 assertEquals("match", out);
92 public void testHandleReplicateMessageSendAppendEntriesToFollower() {
93 new JavaTestKit(getSystem()) {{
95 new Within(duration("1 seconds")) {
96 protected void run() {
98 ActorRef followerActor = getTestActor();
100 MockRaftActorContext actorContext =
101 (MockRaftActorContext) createActorContext();
103 Map<String, String> peerAddresses = new HashMap();
105 peerAddresses.put(followerActor.path().toString(),
106 followerActor.path().toString());
108 actorContext.setPeerAddresses(peerAddresses);
110 Leader leader = new Leader(actorContext);
111 RaftState raftState = leader
112 .handleMessage(senderActor, new Replicate(null, null,
113 new MockRaftActorContext.MockReplicatedLogEntry(1,
115 new MockRaftActorContext.MockPayload("foo"))
118 // State should not change
119 assertEquals(RaftState.Leader, raftState);
122 new ExpectMsg<String>(duration("1 seconds"), "match hint") {
123 // do not put code outside this method, will run afterwards
124 protected String match(Object in) {
125 Object msg = fromSerializableMessage(in);
126 if (msg instanceof AppendEntries) {
127 if (((AppendEntries)msg).getTerm() == 0) {
135 }.get(); // this extracts the received message
137 assertEquals("match", out);
147 public void testHandleReplicateMessageWhenThereAreNoFollowers() {
148 new JavaTestKit(getSystem()) {{
150 new Within(duration("1 seconds")) {
151 protected void run() {
153 ActorRef raftActor = getTestActor();
155 MockRaftActorContext actorContext =
156 new MockRaftActorContext("test", getSystem(), raftActor);
158 actorContext.getReplicatedLog().removeFrom(0);
160 actorContext.getReplicatedLog().append(new ReplicatedLogImplEntry(0, 1,
161 new MockRaftActorContext.MockPayload("foo")));
163 ReplicatedLogImplEntry entry =
164 new ReplicatedLogImplEntry(1, 1,
165 new MockRaftActorContext.MockPayload("foo"));
167 actorContext.getReplicatedLog().append(entry);
169 Leader leader = new Leader(actorContext);
170 RaftState raftState = leader
171 .handleMessage(senderActor, new Replicate(null, "state-id",entry));
173 // State should not change
174 assertEquals(RaftState.Leader, raftState);
176 assertEquals(1, actorContext.getCommitIndex());
179 new ExpectMsg<String>(duration("1 seconds"),
181 // do not put code outside this method, will run afterwards
182 protected String match(Object in) {
183 if (in instanceof ApplyState) {
184 if (((ApplyState) in).getIdentifier().equals("state-id")) {
192 }.get(); // this extracts the received message
194 assertEquals("match", out);
203 @Override protected RaftActorBehavior createBehavior(
204 RaftActorContext actorContext) {
205 return new Leader(actorContext);
208 @Override protected RaftActorContext createActorContext() {
209 return new MockRaftActorContext("test", getSystem(), leaderActor);