76ef5f6228a37509a067f67c0e5858ca8d5191c2
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / LeadershipTransferIntegrationTest.java
1 /*
2  * Copyright (c) 2015 Brocade Communications 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;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNull;
12 import static org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor.clearMessages;
13 import static org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor.expectFirstMatching;
14
15 import akka.actor.ActorRef;
16 import akka.actor.Props;
17 import akka.pattern.Patterns;
18 import akka.testkit.TestActorRef;
19 import com.google.common.collect.ImmutableMap;
20 import java.util.concurrent.TimeUnit;
21 import org.junit.Test;
22 import org.opendaylight.controller.cluster.notifications.LeaderStateChanged;
23 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
24 import org.opendaylight.controller.cluster.raft.client.messages.Shutdown;
25 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
26 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
27 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
28 import scala.concurrent.Await;
29 import scala.concurrent.Future;
30 import scala.concurrent.duration.FiniteDuration;
31
32 /**
33  * Tests leadership transfer end-to-end.
34  *
35  * @author Thomas Pantelis
36  */
37 public class LeadershipTransferIntegrationTest extends AbstractRaftActorIntegrationTest {
38
39     private final String follower3Id = factory.generateActorId("follower");
40     private TestActorRef<MessageCollectorActor> leaderNotifierActor;
41     private TestActorRef<MessageCollectorActor> follower1NotifierActor;
42     private TestActorRef<MessageCollectorActor> follower2NotifierActor;
43     private TestActorRef<MessageCollectorActor> follower3NotifierActor;
44     private TestActorRef<TestRaftActor> follower3Actor;
45     private ActorRef follower3CollectorActor;
46
47     @Test
48     public void testLeaderTransferOnShutDown() throws Exception {
49         testLog.info("testLeaderTransferOnShutDown starting");
50
51         createRaftActors();
52
53         sendPayloadWithFollower2Lagging();
54
55         sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1();
56
57         sendShutDown(follower2Actor);
58
59         testLog.info("testLeaderTransferOnShutDown ending");
60     }
61
62     private void sendShutDown(ActorRef actor) throws Exception {
63         testLog.info("sendShutDown for {} starting", actor.path());
64
65         FiniteDuration duration = FiniteDuration.create(5, TimeUnit.SECONDS);
66         Future<Boolean> stopFuture = Patterns.gracefulStop(actor, duration, Shutdown.INSTANCE);
67
68         Boolean stopped = Await.result(stopFuture, duration);
69         assertEquals("Stopped", Boolean.TRUE, stopped);
70
71         testLog.info("sendShutDown for {} ending", actor.path());
72     }
73
74     private void sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1() throws Exception {
75         testLog.info("sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1 starting");
76
77         clearMessages(leaderNotifierActor);
78         clearMessages(follower1NotifierActor);
79         clearMessages(follower2NotifierActor);
80         clearMessages(follower3NotifierActor);
81
82         FiniteDuration duration = FiniteDuration.create(5, TimeUnit.SECONDS);
83         final Future<Boolean> stopFuture = Patterns.gracefulStop(leaderActor, duration, Shutdown.INSTANCE);
84
85         assertNullLeaderIdChange(leaderNotifierActor);
86         assertNullLeaderIdChange(follower1NotifierActor);
87         assertNullLeaderIdChange(follower2NotifierActor);
88         assertNullLeaderIdChange(follower3NotifierActor);
89
90         verifyRaftState(follower1Actor, RaftState.Leader);
91
92         Boolean stopped = Await.result(stopFuture, duration);
93         assertEquals("Stopped", Boolean.TRUE, stopped);
94
95         follower2Actor.underlyingActor().stopDropMessages(AppendEntries.class);
96         ApplyState applyState = expectFirstMatching(follower2CollectorActor, ApplyState.class);
97         assertEquals("Apply sate index", 0, applyState.getReplicatedLogEntry().getIndex());
98
99         testLog.info("sendShutDownToLeaderAndVerifyLeadershipTransferToFollower1 ending");
100     }
101
102     private void sendPayloadWithFollower2Lagging() {
103         testLog.info("sendPayloadWithFollower2Lagging starting");
104
105         follower2Actor.underlyingActor().startDropMessages(AppendEntries.class);
106
107         sendPayloadData(leaderActor, "zero");
108
109         expectFirstMatching(leaderCollectorActor, ApplyState.class);
110         expectFirstMatching(follower1CollectorActor, ApplyState.class);
111         expectFirstMatching(follower3CollectorActor, ApplyState.class);
112
113         testLog.info("sendPayloadWithFollower2Lagging ending");
114     }
115
116     private void createRaftActors() {
117         testLog.info("createRaftActors starting");
118
119         follower1NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
120                 factory.generateActorId(follower1Id + "-notifier"));
121         follower1Actor = newTestRaftActor(follower1Id, TestRaftActor.newBuilder().peerAddresses(
122                 ImmutableMap.of(leaderId, testActorPath(leaderId), follower2Id, testActorPath(follower2Id),
123                         follower3Id, testActorPath(follower3Id)))
124                 .config(newFollowerConfigParams()).roleChangeNotifier(follower1NotifierActor));
125
126         follower2NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
127                 factory.generateActorId(follower2Id + "-notifier"));
128         follower2Actor = newTestRaftActor(follower2Id,TestRaftActor.newBuilder().peerAddresses(
129                 ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString(),
130                         follower3Id, testActorPath(follower3Id)))
131                 .config(newFollowerConfigParams()).roleChangeNotifier(follower2NotifierActor));
132
133         follower3NotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
134                 factory.generateActorId(follower3Id + "-notifier"));
135         follower3Actor = newTestRaftActor(follower3Id,TestRaftActor.newBuilder().peerAddresses(
136                 ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString(),
137                         follower2Id, follower2Actor.path().toString()))
138                 .config(newFollowerConfigParams()).roleChangeNotifier(follower3NotifierActor));
139
140         peerAddresses = ImmutableMap.<String, String>builder()
141                 .put(follower1Id, follower1Actor.path().toString())
142                 .put(follower2Id, follower2Actor.path().toString())
143                 .put(follower3Id, follower3Actor.path().toString()).build();
144
145         leaderConfigParams = newLeaderConfigParams();
146         leaderConfigParams.setElectionTimeoutFactor(3);
147         leaderNotifierActor = factory.createTestActor(Props.create(MessageCollectorActor.class),
148                 factory.generateActorId(leaderId + "-notifier"));
149         leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses)
150                 .config(leaderConfigParams).roleChangeNotifier(leaderNotifierActor));
151
152         follower1CollectorActor = follower1Actor.underlyingActor().collectorActor();
153         follower2CollectorActor = follower2Actor.underlyingActor().collectorActor();
154         follower3CollectorActor = follower3Actor.underlyingActor().collectorActor();
155         leaderCollectorActor = leaderActor.underlyingActor().collectorActor();
156
157         leaderContext = leaderActor.underlyingActor().getRaftActorContext();
158         leaderContext.getPeerInfo(follower3Id).setVotingState(VotingState.NON_VOTING);
159
160         waitUntilLeader(leaderActor);
161
162         testLog.info("createRaftActors starting");
163     }
164
165     private static void verifyRaftState(ActorRef raftActor, final RaftState expState) {
166         verifyRaftState(raftActor, rs -> assertEquals("getRaftState", expState.toString(), rs.getRaftState()));
167     }
168
169     private static void assertNullLeaderIdChange(TestActorRef<MessageCollectorActor> notifierActor) {
170         LeaderStateChanged change = expectFirstMatching(notifierActor, LeaderStateChanged.class);
171         assertNull("Expected null leader Id", change.getLeaderId());
172     }
173
174     @Test
175     public void testLeaderTransferAborted() throws Exception {
176         testLog.info("testLeaderTransferAborted starting");
177
178         createRaftActors();
179
180         leaderActor.underlyingActor().startDropMessages(AppendEntriesReply.class);
181
182         sendShutDown(leaderActor);
183
184         verifyRaftState(follower1Actor, RaftState.Follower);
185         verifyRaftState(follower2Actor, RaftState.Follower);
186         verifyRaftState(follower3Actor, RaftState.Follower);
187
188         testLog.info("testLeaderTransferOnShutDown ending");
189     }
190
191     @Test
192     public void testLeaderTransferSkippedOnShutdownWithNoFollowers() throws Exception {
193         testLog.info("testLeaderTransferSkippedOnShutdownWithNoFollowers starting");
194
195         leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().config(newLeaderConfigParams()));
196         waitUntilLeader(leaderActor);
197
198         sendShutDown(leaderActor);
199
200         testLog.info("testLeaderTransferSkippedOnShutdownWithNoFollowers ending");
201     }
202 }