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

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.