Merge changes Ic434bf4a,I05a3fb18,I47a3783d,I8234bbfd
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / behaviors / IsolatedLeaderTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.raft.behaviors;
9
10 import akka.actor.ActorRef;
11 import akka.actor.Props;
12 import akka.testkit.JavaTestKit;
13 import java.util.HashMap;
14 import java.util.Map;
15 import org.junit.Test;
16 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
17 import org.opendaylight.controller.cluster.raft.RaftActorContext;
18 import org.opendaylight.controller.cluster.raft.RaftState;
19 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
20 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23
24 public class IsolatedLeaderTest  extends AbstractRaftActorBehaviorTest {
25
26     private ActorRef leaderActor =
27         getSystem().actorOf(Props.create(DoNothingActor.class));
28
29     private ActorRef senderActor =
30         getSystem().actorOf(Props.create(DoNothingActor.class));
31
32     @Override
33     protected RaftActorBehavior createBehavior(
34         RaftActorContext actorContext) {
35         return new Leader(actorContext);
36     }
37
38     @Override
39     protected RaftActorContext createActorContext() {
40         return createActorContext(leaderActor);
41     }
42
43
44     @Test
45     public void testHandleMessageWithThreeMembers() {
46         new JavaTestKit(getSystem()) {{
47             String followerAddress1 = "akka://test/user/$a";
48             String followerAddress2 = "akka://test/user/$b";
49
50             MockRaftActorContext leaderActorContext = (MockRaftActorContext) createActorContext();
51             Map<String, String> peerAddresses = new HashMap<>();
52             peerAddresses.put("follower-1", followerAddress1);
53             peerAddresses.put("follower-2", followerAddress2);
54             leaderActorContext.setPeerAddresses(peerAddresses);
55
56             IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
57             assertTrue(isolatedLeader.state() == RaftState.IsolatedLeader);
58
59             // in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
60             RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
61                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
62                     isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1));
63
64             assertEquals(RaftState.Leader, behavior.state());
65
66             behavior = isolatedLeader.handleMessage(senderActor,
67                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
68                     isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
69
70             assertEquals(RaftState.Leader, behavior.state());
71         }};
72     }
73
74     @Test
75     public void testHandleMessageWithFiveMembers() {
76         new JavaTestKit(getSystem()) {{
77
78             String followerAddress1 = "akka://test/user/$a";
79             String followerAddress2 = "akka://test/user/$b";
80             String followerAddress3 = "akka://test/user/$c";
81             String followerAddress4 = "akka://test/user/$d";
82
83             MockRaftActorContext leaderActorContext = (MockRaftActorContext) createActorContext();
84             Map<String, String> peerAddresses = new HashMap<>();
85             peerAddresses.put("follower-1", followerAddress1);
86             peerAddresses.put("follower-2", followerAddress2);
87             peerAddresses.put("follower-3", followerAddress3);
88             peerAddresses.put("follower-4", followerAddress4);
89             leaderActorContext.setPeerAddresses(peerAddresses);
90
91             IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
92             assertEquals(RaftState.IsolatedLeader, isolatedLeader.state());
93
94             // in a 5 member cluster, atleast 2 followers need to be active and return a reply
95             RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
96                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
97                     isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
98
99             assertEquals(RaftState.IsolatedLeader, behavior.state());
100
101             behavior = isolatedLeader.handleMessage(senderActor,
102                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
103                     isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
104
105             assertEquals(RaftState.Leader, behavior.state());
106
107             behavior = isolatedLeader.handleMessage(senderActor,
108                 new AppendEntriesReply("follower-3", isolatedLeader.lastTerm() - 1, true,
109                     isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
110
111             assertEquals(RaftState.Leader, behavior.state());
112         }};
113     }
114
115     @Test
116     public void testHandleMessageFromAnotherLeader() {
117         new JavaTestKit(getSystem()) {{
118             String followerAddress1 = "akka://test/user/$a";
119             String followerAddress2 = "akka://test/user/$b";
120
121             MockRaftActorContext leaderActorContext = (MockRaftActorContext) createActorContext();
122             Map<String, String> peerAddresses = new HashMap<>();
123             peerAddresses.put("follower-1", followerAddress1);
124             peerAddresses.put("follower-2", followerAddress2);
125             leaderActorContext.setPeerAddresses(peerAddresses);
126
127             IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
128             assertTrue(isolatedLeader.state() == RaftState.IsolatedLeader);
129
130             // if an append-entries reply is received by the isolated-leader, and that reply
131             // has a term  > than its own term, then IsolatedLeader switches to Follower
132             // bowing itself to another leader in the cluster
133             RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
134                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() + 1, true,
135                     isolatedLeader.lastIndex() + 1, isolatedLeader.lastTerm() + 1));
136
137             assertEquals(RaftState.Follower, behavior.state());
138         }};
139
140     }
141 }