X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fmd-sal%2Fsal-akka-raft%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fraft%2FNonVotingFollowerIntegrationTest.java;h=660d7914382a4e774b43ff98621ab971953342f6;hb=f33beecf2a10955a9219757529ba3017079816cc;hp=adbc5e8eb7a81a9cb056c0e81f2063a320a085d3;hpb=bef65394c7f540b601ce4bd360d7d7648f289bd1;p=controller.git diff --git a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/NonVotingFollowerIntegrationTest.java b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/NonVotingFollowerIntegrationTest.java index adbc5e8eb7..660d791438 100644 --- a/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/NonVotingFollowerIntegrationTest.java +++ b/opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/NonVotingFollowerIntegrationTest.java @@ -8,19 +8,28 @@ package org.opendaylight.controller.cluster.raft; import static org.junit.Assert.assertEquals; + +import akka.actor.ActorRef; import com.google.common.base.Optional; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import java.util.Arrays; +import java.util.concurrent.TimeUnit; import org.junit.Test; -import org.opendaylight.controller.cluster.raft.ServerConfigurationPayload.ServerInfo; +import org.opendaylight.controller.cluster.notifications.LeaderStateChanged; +import org.opendaylight.controller.cluster.raft.AbstractRaftActorIntegrationTest.TestRaftActor.Builder; import org.opendaylight.controller.cluster.raft.base.messages.ApplyState; +import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout; import org.opendaylight.controller.cluster.raft.base.messages.SnapshotComplete; -import org.opendaylight.controller.cluster.raft.base.messages.UpdateElectionTerm; import org.opendaylight.controller.cluster.raft.messages.AppendEntries; +import org.opendaylight.controller.cluster.raft.persisted.ServerConfigurationPayload; +import org.opendaylight.controller.cluster.raft.persisted.ServerInfo; +import org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry; +import org.opendaylight.controller.cluster.raft.persisted.UpdateElectionTerm; import org.opendaylight.controller.cluster.raft.policy.DisableElectionsRaftPolicy; import org.opendaylight.controller.cluster.raft.utils.InMemoryJournal; import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor; +import scala.concurrent.duration.FiniteDuration; /** * Integration test for various scenarios involving non-voting followers. @@ -30,6 +39,7 @@ import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor; public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrationTest { private TestRaftActor followerInstance; private TestRaftActor leaderInstance; + private final Builder follower1Builder = TestRaftActor.newBuilder(); /** * Tests non-voting follower re-sync after the non-persistent leader restarts with an empty log. In this @@ -284,7 +294,7 @@ public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrati ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList( new ServerInfo(leaderId, true), new ServerInfo(follower1Id, false), new ServerInfo(follower2Id, true), new ServerInfo("downPeer", false))); - ReplicatedLogImplEntry persistedServerConfigEntry = new ReplicatedLogImplEntry(0, currentTerm, + SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, currentTerm, persistedServerConfig); InMemoryJournal.clear(); @@ -295,8 +305,8 @@ public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrati DefaultConfigParamsImpl follower2ConfigParams = newFollowerConfigParams(); follower2ConfigParams.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName()); follower2Actor = newTestRaftActor(follower2Id, TestRaftActor.newBuilder().peerAddresses( - ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString())). - config(follower2ConfigParams).persistent(Optional.of(false))); + ImmutableMap.of(leaderId, testActorPath(leaderId), follower1Id, follower1Actor.path().toString())) + .config(follower2ConfigParams).persistent(Optional.of(false))); TestRaftActor follower2Instance = follower2Actor.underlyingActor(); follower2Instance.waitForRecoveryComplete(); follower2CollectorActor = follower2Instance.collectorActor(); @@ -343,10 +353,40 @@ public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrati testLog.info("testFollowerResyncWithMoreLeaderLogEntriesAndDownPeerAfterNonPersistentLeaderRestart ending"); } + @Test + public void testFollowerLeaderStateChanges() { + testLog.info("testFollowerLeaderStateChanges"); + + ActorRef roleChangeNotifier = factory.createActor( + MessageCollectorActor.props(), factory.generateActorId("roleChangeNotifier")); + follower1Builder.roleChangeNotifier(roleChangeNotifier); + + setupLeaderAndNonVotingFollower(); + + ((DefaultConfigParamsImpl)follower1Context.getConfigParams()).setElectionTimeoutFactor(2); + ((DefaultConfigParamsImpl)follower1Context.getConfigParams()) + .setHeartBeatInterval(FiniteDuration.apply(100, TimeUnit.MILLISECONDS)); + + MessageCollectorActor.clearMessages(roleChangeNotifier); + follower1Actor.tell(ElectionTimeout.INSTANCE, ActorRef.noSender()); + followerInstance.startDropMessages(AppendEntries.class); + + LeaderStateChanged leaderStateChanged = MessageCollectorActor.expectFirstMatching(roleChangeNotifier, + LeaderStateChanged.class); + assertEquals("getLeaderId", null, leaderStateChanged.getLeaderId()); + + MessageCollectorActor.clearMessages(roleChangeNotifier); + followerInstance.stopDropMessages(AppendEntries.class); + + leaderStateChanged = MessageCollectorActor.expectFirstMatching(roleChangeNotifier, + LeaderStateChanged.class); + assertEquals("getLeaderId", leaderId, leaderStateChanged.getLeaderId()); + } + private void createNewLeaderActor() { expSnapshotState.clear(); - leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses). - config(leaderConfigParams).persistent(Optional.of(false))); + leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses) + .config(leaderConfigParams).persistent(Optional.of(false))); leaderInstance = leaderActor.underlyingActor(); leaderCollectorActor = leaderInstance.collectorActor(); waitUntilLeader(leaderActor); @@ -355,31 +395,31 @@ public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrati private void setupLeaderAndNonVotingFollower() { snapshotBatchCount = 100; - int initialTerm = 1; + int persistedTerm = 1; // Set up a persisted ServerConfigurationPayload with the leader voting and the follower non-voting. ServerConfigurationPayload persistedServerConfig = new ServerConfigurationPayload(Arrays.asList( new ServerInfo(leaderId, true), new ServerInfo(follower1Id, false))); - ReplicatedLogImplEntry persistedServerConfigEntry = new ReplicatedLogImplEntry(0, initialTerm, + SimpleReplicatedLogEntry persistedServerConfigEntry = new SimpleReplicatedLogEntry(0, persistedTerm, persistedServerConfig); - InMemoryJournal.addEntry(leaderId, 1, new UpdateElectionTerm(initialTerm, leaderId)); + InMemoryJournal.addEntry(leaderId, 1, new UpdateElectionTerm(persistedTerm, leaderId)); InMemoryJournal.addEntry(leaderId, 2, persistedServerConfigEntry); - InMemoryJournal.addEntry(follower1Id, 1, new UpdateElectionTerm(initialTerm, leaderId)); + InMemoryJournal.addEntry(follower1Id, 1, new UpdateElectionTerm(persistedTerm, leaderId)); InMemoryJournal.addEntry(follower1Id, 2, persistedServerConfigEntry); DefaultConfigParamsImpl followerConfigParams = newFollowerConfigParams(); - follower1Actor = newTestRaftActor(follower1Id, TestRaftActor.newBuilder().peerAddresses( - ImmutableMap.of(leaderId, testActorPath(leaderId))).config(followerConfigParams). - persistent(Optional.of(false))); + follower1Actor = newTestRaftActor(follower1Id, follower1Builder.peerAddresses( + ImmutableMap.of(leaderId, testActorPath(leaderId))).config(followerConfigParams) + .persistent(Optional.of(false))); - peerAddresses = ImmutableMap.builder(). - put(follower1Id, follower1Actor.path().toString()).build(); + peerAddresses = ImmutableMap.builder() + .put(follower1Id, follower1Actor.path().toString()).build(); leaderConfigParams = newLeaderConfigParams(); - leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses). - config(leaderConfigParams).persistent(Optional.of(false))); + leaderActor = newTestRaftActor(leaderId, TestRaftActor.newBuilder().peerAddresses(peerAddresses) + .config(leaderConfigParams).persistent(Optional.of(false))); followerInstance = follower1Actor.underlyingActor(); follower1CollectorActor = followerInstance.collectorActor(); @@ -394,7 +434,7 @@ public class NonVotingFollowerIntegrationTest extends AbstractRaftActorIntegrati // Verify leader's context after startup - currentTerm = initialTerm + 1; + currentTerm = persistedTerm + 1; assertEquals("Leader term", currentTerm, leaderContext.getTermInformation().getCurrentTerm()); assertEquals("Leader server config", Sets.newHashSet(persistedServerConfig.getServerConfig()), Sets.newHashSet(leaderContext.getPeerServerInfo(true).getServerConfig()));