Cleanup warnings
[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 static org.junit.Assert.assertEquals;
11
12 import akka.actor.ActorRef;
13 import akka.actor.Props;
14 import akka.testkit.TestActorRef;
15 import java.util.HashMap;
16 import java.util.Map;
17 import org.junit.After;
18 import org.junit.Test;
19 import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
20 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
21 import org.opendaylight.controller.cluster.raft.RaftActorContext;
22 import org.opendaylight.controller.cluster.raft.RaftState;
23 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
24 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
25
26 public class IsolatedLeaderTest extends AbstractLeaderTest<IsolatedLeader> {
27
28     private final TestActorRef<MessageCollectorActor> leaderActor = actorFactory.createTestActor(
29             Props.create(MessageCollectorActor.class), actorFactory.generateActorId("leader"));
30
31     private final TestActorRef<MessageCollectorActor> senderActor = actorFactory.createTestActor(
32             Props.create(MessageCollectorActor.class), actorFactory.generateActorId("sender"));
33
34     private AbstractLeader isolatedLeader;
35
36     @Override
37     @After
38     public void tearDown() {
39         if (isolatedLeader != null) {
40             isolatedLeader.close();
41         }
42
43         super.tearDown();
44     }
45
46     @Override
47     protected IsolatedLeader createBehavior(final RaftActorContext actorContext) {
48         return new IsolatedLeader(actorContext);
49     }
50
51     @Override
52     protected MockRaftActorContext createActorContext() {
53         return createActorContext(leaderActor);
54     }
55
56     @Override
57     protected MockRaftActorContext createActorContext(final ActorRef actor) {
58         DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
59         configParams.setElectionTimeoutFactor(100000);
60         MockRaftActorContext context = new MockRaftActorContext("isolated-leader", getSystem(), actor);
61         context.setConfigParams(configParams);
62         return context;
63     }
64
65     @Test
66     public void testHandleMessageWithThreeMembers() throws Exception {
67         String followerAddress1 = "akka://test/user/$a";
68         String followerAddress2 = "akka://test/user/$b";
69
70         MockRaftActorContext leaderActorContext = createActorContext();
71         Map<String, String> peerAddresses = new HashMap<>();
72         peerAddresses.put("follower-1", followerAddress1);
73         peerAddresses.put("follower-2", followerAddress2);
74         leaderActorContext.setPeerAddresses(peerAddresses);
75
76         isolatedLeader = new IsolatedLeader(leaderActorContext);
77         leaderActorContext.setCurrentBehavior(isolatedLeader);
78         assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
79
80         // in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
81         RaftActorBehavior newBehavior = isolatedLeader.handleMessage(senderActor,
82                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
83                         isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short)0));
84
85         assertEquals("Raft state", RaftState.Leader, newBehavior.state());
86
87         isolatedLeader.close();
88         isolatedLeader = (AbstractLeader) newBehavior;
89
90         newBehavior = isolatedLeader.handleMessage(senderActor,
91                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
92                         isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
93
94         assertEquals("Raft state", RaftState.Leader, newBehavior.state());
95     }
96
97     @Test
98     public void testHandleMessageWithFiveMembers() throws Exception {
99         String followerAddress1 = "akka://test/user/$a";
100         String followerAddress2 = "akka://test/user/$b";
101         String followerAddress3 = "akka://test/user/$c";
102         String followerAddress4 = "akka://test/user/$d";
103
104         final MockRaftActorContext leaderActorContext = createActorContext();
105         Map<String, String> peerAddresses = new HashMap<>();
106         peerAddresses.put("follower-1", followerAddress1);
107         peerAddresses.put("follower-2", followerAddress2);
108         peerAddresses.put("follower-3", followerAddress3);
109         peerAddresses.put("follower-4", followerAddress4);
110         leaderActorContext.setPeerAddresses(peerAddresses);
111
112         isolatedLeader = new IsolatedLeader(leaderActorContext);
113         leaderActorContext.setCurrentBehavior(isolatedLeader);
114         assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
115
116         // in a 5 member cluster, atleast 2 followers need to be active and return a reply
117         RaftActorBehavior newBehavior = isolatedLeader.handleMessage(senderActor,
118                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
119                         isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
120
121         assertEquals("Raft state", RaftState.IsolatedLeader, newBehavior.state());
122
123         newBehavior = isolatedLeader.handleMessage(senderActor,
124                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
125                         isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
126
127         assertEquals("Raft state", RaftState.Leader, newBehavior.state());
128
129         isolatedLeader.close();
130         isolatedLeader = (AbstractLeader) newBehavior;
131
132         newBehavior = isolatedLeader.handleMessage(senderActor,
133                 new AppendEntriesReply("follower-3", isolatedLeader.lastTerm() - 1, true,
134                         isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1, (short) 0));
135
136         assertEquals("Raft state", RaftState.Leader, newBehavior.state());
137     }
138
139     @Test
140     public void testHandleMessageFromAnotherLeader() throws Exception {
141         String followerAddress1 = "akka://test/user/$a";
142         String followerAddress2 = "akka://test/user/$b";
143
144         MockRaftActorContext leaderActorContext = createActorContext();
145         Map<String, String> peerAddresses = new HashMap<>();
146         peerAddresses.put("follower-1", followerAddress1);
147         peerAddresses.put("follower-2", followerAddress2);
148         leaderActorContext.setPeerAddresses(peerAddresses);
149
150         isolatedLeader = new IsolatedLeader(leaderActorContext);
151         assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
152
153         // if an append-entries reply is received by the isolated-leader, and that reply
154         // has a term  > than its own term, then IsolatedLeader switches to Follower
155         // bowing itself to another leader in the cluster
156         RaftActorBehavior newBehavior = isolatedLeader.handleMessage(senderActor,
157                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() + 1, true,
158                         isolatedLeader.lastIndex() + 1, isolatedLeader.lastTerm() + 1, (short)0));
159
160         assertEquals("Raft state", RaftState.Follower, newBehavior.state());
161
162         newBehavior.close();
163     }
164 }