BUG-9028: make NonPersistentDataProvider schedule invocation
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / RaftActorServerConfigurationSupportTest.java
index 71412f3e052394e506cab3df3b0a8585a5aa2370..c22a0e567e592dabbf7461ac8b9fe3af0992578f 100644 (file)
@@ -42,7 +42,6 @@ import org.opendaylight.controller.cluster.NonPersistentDataProvider;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
-import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
 import org.opendaylight.controller.cluster.raft.base.messages.InitiateCaptureSnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.TimeoutNow;
 import org.opendaylight.controller.cluster.raft.behaviors.AbstractLeader;
@@ -850,48 +849,68 @@ public class RaftActorServerConfigurationSupportTest extends AbstractActorTest {
     }
 
     @Test
-    public void testRemoveServer() {
+    public void testRemoveServer() throws Exception {
         LOG.info("testRemoveServer starting");
 
         DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
         configParams.setHeartBeatInterval(new FiniteDuration(1, TimeUnit.DAYS));
         configParams.setCustomRaftPolicyImplementationClass(DisableElectionsRaftPolicy.class.getName());
 
-        final String followerActorId = actorFactory.generateActorId(FOLLOWER_ID);
-        final String followerActorPath = actorFactory.createTestActorPath(followerActorId);
+        final String follower1ActorId = actorFactory.generateActorId(FOLLOWER_ID);
+        final String follower1ActorPath = actorFactory.createTestActorPath(follower1ActorId);
+        final String follower2ActorId = actorFactory.generateActorId(FOLLOWER_ID2);
+        final String follower2ActorPath = actorFactory.createTestActorPath(follower2ActorId);
         RaftActorContext initialActorContext = new MockRaftActorContext();
 
-        TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(
-                MockLeaderRaftActor.props(ImmutableMap.of(FOLLOWER_ID, followerActorPath),
+        final String downNodeId = "downNode";
+        TestActorRef<MockLeaderRaftActor> leaderActor = actorFactory.createTestActor(MockLeaderRaftActor.props(
+                ImmutableMap.of(FOLLOWER_ID, follower1ActorPath, FOLLOWER_ID2, follower2ActorPath, downNodeId, ""),
                         initialActorContext).withDispatcher(Dispatchers.DefaultDispatcherId()),
                 actorFactory.generateActorId(LEADER_ID));
 
         final TestActorRef<MessageCollectorActor> leaderCollector =
                 newLeaderCollectorActor(leaderActor.underlyingActor());
 
-        TestActorRef<MessageCollectorActor> collector = actorFactory.createTestActor(MessageCollectorActor.props()
-                .withDispatcher(Dispatchers.DefaultDispatcherId()),
+        TestActorRef<MessageCollectorActor> follower1Collector = actorFactory.createTestActor(
+                MessageCollectorActor.props().withDispatcher(Dispatchers.DefaultDispatcherId()),
                         actorFactory.generateActorId("collector"));
-        actorFactory.createTestActor(
-                CollectingMockRaftActor.props(FOLLOWER_ID, ImmutableMap.of(LEADER_ID, leaderActor.path().toString()),
-                        configParams, NO_PERSISTENCE, collector).withDispatcher(Dispatchers.DefaultDispatcherId()),
-                followerActorId);
+        final TestActorRef<CollectingMockRaftActor> follower1Actor = actorFactory.createTestActor(
+                CollectingMockRaftActor.props(FOLLOWER_ID, ImmutableMap.of(LEADER_ID, leaderActor.path().toString(),
+                        FOLLOWER_ID2, follower2ActorPath, downNodeId, ""), configParams, NO_PERSISTENCE,
+                        follower1Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), follower1ActorId);
+
+        TestActorRef<MessageCollectorActor> follower2Collector = actorFactory.createTestActor(
+                MessageCollectorActor.props().withDispatcher(Dispatchers.DefaultDispatcherId()),
+                        actorFactory.generateActorId("collector"));
+        final TestActorRef<CollectingMockRaftActor> follower2Actor = actorFactory.createTestActor(
+                CollectingMockRaftActor.props(FOLLOWER_ID2, ImmutableMap.of(LEADER_ID, leaderActor.path().toString(),
+                        FOLLOWER_ID, follower1ActorPath, downNodeId, ""), configParams, NO_PERSISTENCE,
+                        follower2Collector).withDispatcher(Dispatchers.DefaultDispatcherId()), follower2ActorId);
+
+        leaderActor.underlyingActor().waitForInitializeBehaviorComplete();
+        follower1Actor.underlyingActor().waitForInitializeBehaviorComplete();
+        follower2Actor.underlyingActor().waitForInitializeBehaviorComplete();
 
         leaderActor.tell(new RemoveServer(FOLLOWER_ID), testKit.getRef());
         RemoveServerReply removeServerReply = testKit.expectMsgClass(JavaTestKit.duration("5 seconds"),
                 RemoveServerReply.class);
         assertEquals("getStatus", ServerChangeStatus.OK, removeServerReply.getStatus());
 
-        final ApplyState applyState = MessageCollectorActor.expectFirstMatching(leaderCollector, ApplyState.class);
+        ApplyState applyState = MessageCollectorActor.expectFirstMatching(leaderCollector, ApplyState.class);
+        assertEquals(0L, applyState.getReplicatedLogEntry().getIndex());
+        verifyServerConfigurationPayloadEntry(leaderActor.underlyingActor().getRaftActorContext().getReplicatedLog(),
+                votingServer(LEADER_ID), votingServer(FOLLOWER_ID2), votingServer(downNodeId));
+
+        applyState = MessageCollectorActor.expectFirstMatching(follower2Collector, ApplyState.class);
         assertEquals(0L, applyState.getReplicatedLogEntry().getIndex());
         verifyServerConfigurationPayloadEntry(leaderActor.underlyingActor().getRaftActorContext().getReplicatedLog(),
-                votingServer(LEADER_ID));
+                votingServer(LEADER_ID), votingServer(FOLLOWER_ID2), votingServer(downNodeId));
 
         RaftActorBehavior currentBehavior = leaderActor.underlyingActor().getCurrentBehavior();
         assertTrue("Expected Leader", currentBehavior instanceof Leader);
-        assertEquals("Follower ids size", 0, ((Leader)currentBehavior).getFollowerIds().size());
+        assertEquals("Follower ids size", 2, ((Leader)currentBehavior).getFollowerIds().size());
 
-        MessageCollectorActor.expectFirstMatching(collector, ServerRemoved.class);
+        MessageCollectorActor.expectFirstMatching(follower1Collector, ServerRemoved.class);
 
         LOG.info("testRemoveServer ending");
     }
@@ -1185,19 +1204,19 @@ public class RaftActorServerConfigurationSupportTest extends AbstractActorTest {
         node1RaftActorRef.tell(changeServers, testKit.getRef());
         ServerChangeReply reply = testKit.expectMsgClass(JavaTestKit.duration("5 seconds"), ServerChangeReply.class);
         assertEquals("getStatus", ServerChangeStatus.NO_LEADER, reply.getStatus());
+        assertEquals("getRaftState", RaftState.Follower, node1RaftActor.getRaftState());
 
         // Send an AppendEntries so node1 has a leaderId
 
-        MessageCollectorActor.clearMessages(node1Collector);
-
         long term = node1RaftActor.getRaftActorContext().getTermInformation().getCurrentTerm();
         node1RaftActorRef.tell(new AppendEntries(term, "downNode1", -1L, -1L,
                 Collections.<ReplicatedLogEntry>emptyList(), 0, -1, (short)1), ActorRef.noSender());
 
-        // Wait for the ElectionTimeout to clear the leaderId. he leaderId must be null so on the
+        // Wait for the ElectionTimeout to clear the leaderId. The leaderId must be null so on the next
         // ChangeServersVotingStatus message, it will try to elect a leader.
 
-        MessageCollectorActor.expectFirstMatching(node1Collector, ElectionTimeout.class);
+        AbstractRaftActorIntegrationTest.verifyRaftState(node1RaftActorRef,
+            rs -> assertEquals("getLeader", null, rs.getLeader()));
 
         // Update node2's peer address and send the message again
 
@@ -1475,7 +1494,7 @@ public class RaftActorServerConfigurationSupportTest extends AbstractActorTest {
         DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
         configParams.setHeartBeatInterval(new FiniteDuration(100, TimeUnit.MILLISECONDS));
         configParams.setElectionTimeoutFactor(100000);
-        NonPersistentDataProvider noPersistence = new NonPersistentDataProvider();
+        NonPersistentDataProvider noPersistence = new NonPersistentDataProvider(Runnable::run);
         ElectionTermImpl termInfo = new ElectionTermImpl(noPersistence, id, LOG);
         termInfo.update(1, LEADER_ID);
         return new RaftActorContextImpl(actor, actor.underlyingActor().getContext(),