Refactor AbstractRaftActorBehaviorTest and IsolatedLeaderTest 46/15446/3
authortpantelis <tpanteli@brocade.com>
Wed, 18 Feb 2015 02:26:21 +0000 (21:26 -0500)
committertpantelis <tpanteli@brocade.com>
Thu, 19 Feb 2015 08:16:27 +0000 (03:16 -0500)
Removed the Within blocks in tests.

Used TestActorFactory to create and cleanup actors.

Added some more assertions in some tests.

Change-Id: Idd790b97dd396c75676843779ceab192b848aa17
Signed-off-by: tpantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/AbstractRaftActorBehaviorTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/CandidateTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/FollowerTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/IsolatedLeaderTest.java
opendaylight/md-sal/sal-akka-raft/src/test/java/org/opendaylight/controller/cluster/raft/behaviors/LeaderTest.java

index 4cfcc3fb9e57b98f9868f3497b5e797c90315b6b..f56755b447d347981b687cf017eded1caa059ea6 100644 (file)
@@ -1,10 +1,9 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import akka.actor.ActorRef;
 import akka.actor.Props;
-import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import com.google.protobuf.ByteString;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -12,25 +11,42 @@ import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import org.junit.After;
+import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.raft.AbstractActorTest;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
+import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.SerializationUtils;
+import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload;
-import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 import org.slf4j.LoggerFactory;
 
 public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
 
-    private final ActorRef behaviorActor = getSystem().actorOf(Props.create(
-        DoNothingActor.class));
+    protected final TestActorFactory actorFactory = new TestActorFactory(getSystem());
+
+    private final TestActorRef<MessageCollectorActor> behaviorActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("behavior"));
+
+    RaftActorBehavior behavior;
+
+    @After
+    public void tearDown() throws Exception {
+        if(behavior != null) {
+            behavior.close();
+        }
+
+        actorFactory.close();
+    }
 
     /**
      * This test checks that when a new Raft RPC message is received with a newer
@@ -40,22 +56,19 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      */
     @Test
     public void testHandleRaftRPCWithNewerTerm() throws Exception {
-        new JavaTestKit(getSystem()) {{
+        RaftActorContext actorContext = createActorContext();
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createAppendEntriesWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createAppendEntriesReplyWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createRequestVoteWithNewerTerm());
 
-            assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(getTestActor(),
+        assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, behaviorActor,
                 createRequestVoteReplyWithNewerTerm());
-
-
-        }};
     }
 
 
@@ -67,145 +80,95 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      * @throws Exception
      */
     @Test
-    public void testHandleAppendEntriesSenderTermLessThanReceiverTerm()
-        throws Exception {
-        new JavaTestKit(getSystem()) {{
-
+    public void testHandleAppendEntriesSenderTermLessThanReceiverTerm() throws Exception {
             MockRaftActorContext context = createActorContext();
 
             // First set the receivers term to a high number (1000)
             context.getTermInformation().update(1000, "test");
 
-            AppendEntries appendEntries =
-                new AppendEntries(100, "leader-1", 0, 0, null, 101, -1);
+            AppendEntries appendEntries = new AppendEntries(100, "leader-1", 0, 0, null, 101, -1);
 
-            RaftActorBehavior behavior = createBehavior(context);
+            behavior = createBehavior(context);
 
             // Send an unknown message so that the state of the RaftActor remains unchanged
-            RaftActorBehavior expected = behavior.handleMessage(getRef(), "unknown");
+            RaftActorBehavior expected = behavior.handleMessage(behaviorActor, "unknown");
 
-            RaftActorBehavior raftBehavior =
-                behavior.handleMessage(getRef(), appendEntries);
+            RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
 
-            assertEquals(expected, raftBehavior);
+            assertEquals("Raft state", expected.state(), raftBehavior.state());
 
             // Also expect an AppendEntriesReply to be sent where success is false
-            final Boolean out = new ExpectMsg<Boolean>(duration("1 seconds"),
-                "AppendEntriesReply") {
-                // do not put code outside this method, will run afterwards
-                @Override
-                protected Boolean match(Object in) {
-                    if (in instanceof AppendEntriesReply) {
-                        AppendEntriesReply reply = (AppendEntriesReply) in;
-                        return reply.isSuccess();
-                    } else {
-                        throw noMatch();
-                    }
-                }
-            }.get();
-
-            assertEquals(false, out);
-
-
-        }};
-    }
 
+            AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(
+                    behaviorActor, AppendEntriesReply.class);
 
-    @Test
-    public void testHandleAppendEntriesAddSameEntryToLog(){
-        new JavaTestKit(getSystem()) {
-            {
+            assertEquals("isSuccess", false, reply.isSuccess());
+    }
 
-                MockRaftActorContext context = createActorContext();
 
-                // First set the receivers term to lower number
-                context.getTermInformation().update(2, "test");
+    @Test
+    public void testHandleAppendEntriesAddSameEntryToLog() throws Exception {
+        MockRaftActorContext context = createActorContext();
 
-                // Prepare the receivers log
-                MockRaftActorContext.SimpleReplicatedLog log =
-                    new MockRaftActorContext.SimpleReplicatedLog();
-                log.append(
-                    new MockRaftActorContext.MockReplicatedLogEntry(1, 0, new MockRaftActorContext.MockPayload("zero")));
+        context.getTermInformation().update(2, "test");
 
-                context.setReplicatedLog(log);
+        // Prepare the receivers log
+        MockRaftActorContext.MockPayload payload = new MockRaftActorContext.MockPayload("zero");
+        setLastLogEntry(context, 2, 0, payload);
 
-                List<ReplicatedLogEntry> entries = new ArrayList<>();
-                entries.add(
-                    new MockRaftActorContext.MockReplicatedLogEntry(1, 0, new MockRaftActorContext.MockPayload("zero")));
+        List<ReplicatedLogEntry> entries = new ArrayList<>();
+        entries.add(new MockRaftActorContext.MockReplicatedLogEntry(2, 0, payload));
 
-                AppendEntries appendEntries =
-                    new AppendEntries(2, "leader-1", -1, 1, entries, 0, -1);
+        AppendEntries appendEntries = new AppendEntries(2, "leader-1", -1, -1, entries, 2, -1);
 
-                RaftActorBehavior behavior = createBehavior(context);
+        behavior = createBehavior(context);
 
-                if (AbstractRaftActorBehaviorTest.this instanceof CandidateTest) {
-                    // Resetting the Candidates term to make sure it will match
-                    // the term sent by AppendEntries. If this was not done then
-                    // the test will fail because the Candidate will assume that
-                    // the message was sent to it from a lower term peer and will
-                    // thus respond with a failure
-                    context.getTermInformation().update(2, "test");
-                }
+        if (behavior instanceof Candidate) {
+            // Resetting the Candidates term to make sure it will match
+            // the term sent by AppendEntries. If this was not done then
+            // the test will fail because the Candidate will assume that
+            // the message was sent to it from a lower term peer and will
+            // thus respond with a failure
+            context.getTermInformation().update(2, "test");
+        }
 
-                // Send an unknown message so that the state of the RaftActor remains unchanged
-                RaftActorBehavior expected = behavior.handleMessage(getRef(), "unknown");
+        // Send an unknown message so that the state of the RaftActor remains unchanged
+        RaftActorBehavior expected = behavior.handleMessage(behaviorActor, "unknown");
 
-                RaftActorBehavior raftBehavior =
-                    behavior.handleMessage(getRef(), appendEntries);
+        RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
 
-                assertEquals(expected, raftBehavior);
+        assertEquals("Raft state", expected.state(), raftBehavior.state());
 
-                assertEquals(1, log.size());
+        assertEquals("ReplicatedLog size", 1, context.getReplicatedLog().size());
 
+        handleAppendEntriesAddSameEntryToLogReply(behaviorActor);
+    }
 
-            }};
+    protected void handleAppendEntriesAddSameEntryToLogReply(TestActorRef<MessageCollectorActor> replyActor)
+            throws Exception {
+        AppendEntriesReply reply = MessageCollectorActor.getFirstMatching(replyActor, AppendEntriesReply.class);
+        Assert.assertNull("Expected no AppendEntriesReply", reply);
     }
 
     /**
      * This test verifies that when a RequestVote is received by the RaftActor
-     * with a term which is greater than the RaftActors' currentTerm and the
-     * senders' log is more upto date than the receiver that the receiver grants
-     * the vote to the sender
+     * with the senders' log is more up to date than the receiver that the receiver grants
+     * the vote to the sender.
      */
     @Test
-    public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermAndSenderLogMoreUpToDate() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                @Override
-                protected void run() {
-
-                    RaftActorBehavior behavior = createBehavior(
-                        createActorContext(behaviorActor));
-
-                    RaftActorBehavior raftBehavior = behavior.handleMessage(getTestActor(),
-                        new RequestVote(1000, "test", 10000, 999));
-
-                    if(!(behavior instanceof Follower)){
-                        assertTrue(raftBehavior instanceof Follower);
-                    } else {
-
-                        final Boolean out =
-                            new ExpectMsg<Boolean>(duration("1 seconds"),
-                                "RequestVoteReply") {
-                                // do not put code outside this method, will run afterwards
-                                @Override
-                                protected Boolean match(Object in) {
-                                    if (in instanceof RequestVoteReply) {
-                                        RequestVoteReply reply =
-                                            (RequestVoteReply) in;
-                                        return reply.isVoteGranted();
-                                    } else {
-                                        throw noMatch();
-                                    }
-                                }
-                            }.get();
-
-                        assertEquals(true, out);
-                    }
-                }
-            };
-        }};
+    public void testHandleRequestVoteWhenSenderLogMoreUpToDate() {
+        MockRaftActorContext context = createActorContext();
+
+        behavior = createBehavior(context);
+
+        context.getTermInformation().update(1, "test");
+
+        behavior.handleMessage(behaviorActor, new RequestVote(context.getTermInformation().getCurrentTerm(),
+                "test", 10000, 999));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", true, reply.isVoteGranted());
     }
 
     /**
@@ -214,53 +177,24 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      * log then the receiving RaftActor will not grant the vote to the sender
      */
     @Test
-    public void testHandleRequestVoteWhenSenderTermGreaterThanCurrentTermButSenderLogLessUptoDate() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                @Override
-                protected void run() {
-
-                    RaftActorContext actorContext =
-                        createActorContext(behaviorActor);
-
-                    MockRaftActorContext.SimpleReplicatedLog
-                        log = new MockRaftActorContext.SimpleReplicatedLog();
-                    log.append(
-                        new MockRaftActorContext.MockReplicatedLogEntry(20000,
-                            1000000, new MockRaftActorContext.MockPayload("")));
-
-                    ((MockRaftActorContext) actorContext).setReplicatedLog(log);
-
-                    RaftActorBehavior behavior = createBehavior(actorContext);
-
-                    RaftActorBehavior raftBehavior = behavior.handleMessage(getTestActor(),
-                        new RequestVote(1000, "test", 10000, 999));
-
-                    if(!(behavior instanceof Follower)){
-                        assertTrue(raftBehavior instanceof Follower);
-                    } else {
-                        final Boolean out =
-                            new ExpectMsg<Boolean>(duration("1 seconds"),
-                                "RequestVoteReply") {
-                                // do not put code outside this method, will run afterwards
-                                @Override
-                                protected Boolean match(Object in) {
-                                    if (in instanceof RequestVoteReply) {
-                                        RequestVoteReply reply =
-                                            (RequestVoteReply) in;
-                                        return reply.isVoteGranted();
-                                    } else {
-                                        throw noMatch();
-                                    }
-                                }
-                            }.get();
-
-                        assertEquals(false, out);
-                    }
-                }
-            };
-        }};
+    public void testHandleRequestVoteWhenSenderLogLessUptoDate() {
+        MockRaftActorContext context = createActorContext();
+
+        behavior = createBehavior(context);
+
+        context.getTermInformation().update(1, "test");
+
+        int index = 2000;
+        setLastLogEntry(context, context.getTermInformation().getCurrentTerm(), index,
+                new MockRaftActorContext.MockPayload(""));
+
+        behavior.handleMessage(behaviorActor, new RequestVote(
+                context.getTermInformation().getCurrentTerm(), "test",
+                index - 1, context.getTermInformation().getCurrentTerm()));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
     }
 
 
@@ -272,42 +206,17 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
      */
     @Test
     public void testHandleRequestVoteWhenSenderTermLessThanCurrentTerm() {
-        new JavaTestKit(getSystem()) {{
-
-            new Within(duration("1 seconds")) {
-                @Override
-                protected void run() {
-
-                    RaftActorContext context =
-                        createActorContext(behaviorActor);
-
-                    context.getTermInformation().update(1000, null);
-
-                    RaftActorBehavior follower = createBehavior(context);
-
-                    follower.handleMessage(getTestActor(),
-                        new RequestVote(999, "test", 10000, 999));
-
-                    final Boolean out =
-                        new ExpectMsg<Boolean>(duration("1 seconds"),
-                            "RequestVoteReply") {
-                            // do not put code outside this method, will run afterwards
-                            @Override
-                            protected Boolean match(Object in) {
-                                if (in instanceof RequestVoteReply) {
-                                    RequestVoteReply reply =
-                                        (RequestVoteReply) in;
-                                    return reply.isVoteGranted();
-                                } else {
-                                    throw noMatch();
-                                }
-                            }
-                        }.get();
-
-                    assertEquals(false, out);
-                }
-            };
-        }};
+        RaftActorContext context = createActorContext();
+
+        context.getTermInformation().update(1000, null);
+
+        behavior = createBehavior(context);
+
+        behavior.handleMessage(behaviorActor, new RequestVote(999, "test", 10000, 999));
+
+        RequestVoteReply reply = MessageCollectorActor.expectFirstMatching(behaviorActor,
+                RequestVoteReply.class);
+        assertEquals("isVoteGranted", false, reply.isVoteGranted());
     }
 
     @Test
@@ -357,18 +266,21 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
     }
 
 
-    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(
-        ActorRef actorRef, RaftRPC rpc) {
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
 
-        RaftActorContext actorContext = createActorContext();
         Payload p = new MockRaftActorContext.MockPayload("");
-        setLastLogEntry(
-            (MockRaftActorContext) actorContext, 0, 0, p);
+        setLastLogEntry((MockRaftActorContext) actorContext, 1, 0, p);
+        actorContext.getTermInformation().update(1, "test");
 
-        RaftActorBehavior raftBehavior = createBehavior(actorContext)
-            .handleMessage(actorRef, rpc);
+        RaftActorBehavior origBehavior = createBehavior(actorContext);
+        RaftActorBehavior raftBehavior = origBehavior.handleMessage(actorRef, rpc);
 
-        assertTrue(raftBehavior instanceof Follower);
+        assertEquals("New raft state", RaftState.Follower, raftBehavior.state());
+        assertEquals("New election term", rpc.getTerm(), actorContext.getTermInformation().getCurrentTerm());
+
+        origBehavior.close();
+        raftBehavior.close();
     }
 
     protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(
@@ -377,10 +289,9 @@ public abstract class AbstractRaftActorBehaviorTest extends AbstractActorTest {
             new MockRaftActorContext.MockReplicatedLogEntry(term, index, data));
     }
 
-    protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(
-        MockRaftActorContext actorContext, ReplicatedLogEntry logEntry) {
-        MockRaftActorContext.SimpleReplicatedLog
-            log = new MockRaftActorContext.SimpleReplicatedLog();
+    protected MockRaftActorContext.SimpleReplicatedLog setLastLogEntry(MockRaftActorContext actorContext,
+            ReplicatedLogEntry logEntry) {
+        MockRaftActorContext.SimpleReplicatedLog log = new MockRaftActorContext.SimpleReplicatedLog();
         log.append(logEntry);
         actorContext.setReplicatedLog(log);
 
index 9d323b6ab1e2213718a6d25ebbdec14cca5102e2..60f45523cf204d5d246fb14ac01eddc4dcc760ba 100644 (file)
@@ -1,6 +1,7 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import static org.junit.Assert.assertEquals;
+import akka.actor.ActorRef;
 import akka.actor.Props;
 import akka.testkit.TestActorRef;
 import java.util.Collections;
@@ -13,18 +14,16 @@ import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
+import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
 public class CandidateTest extends AbstractRaftActorBehaviorTest {
 
-    private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
-
     private final TestActorRef<MessageCollectorActor> candidateActor = actorFactory.createTestActor(
             Props.create(MessageCollectorActor.class), actorFactory.generateActorId("candidate"));
 
@@ -36,13 +35,14 @@ public class CandidateTest extends AbstractRaftActorBehaviorTest {
     public void setUp(){
     }
 
+    @Override
     @After
     public void tearDown() throws Exception {
         if(candidate != null) {
             candidate.close();
         }
 
-        actorFactory.close();
+        super.tearDown();
     }
 
     @Test
@@ -206,4 +206,11 @@ public class CandidateTest extends AbstractRaftActorBehaviorTest {
 
         return peerMap;
     }
+
+    @Override
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
+        super.assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, actorRef, rpc);
+        assertEquals("New votedFor", null, actorContext.getTermInformation().getVotedFor());
+    }
 }
index 34cdd5b67ef3e31af457b6ab554bf3e72275a2f3..4e8e7fe11bad4fdeb085ffc1ac60450cbbfeda11 100644 (file)
@@ -17,21 +17,19 @@ import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogEntry;
 import org.opendaylight.controller.cluster.raft.Snapshot;
-import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
 import org.opendaylight.controller.cluster.raft.base.messages.ElectionTimeout;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVote;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
 public class FollowerTest extends AbstractRaftActorBehaviorTest {
 
-    private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
-
     private final TestActorRef<MessageCollectorActor> followerActor = actorFactory.createTestActor(
             Props.create(MessageCollectorActor.class), actorFactory.generateActorId("follower"));
 
@@ -40,13 +38,14 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
 
     private RaftActorBehavior follower;
 
+    @Override
     @After
     public void tearDown() throws Exception {
         if(follower != null) {
             follower.close();
         }
 
-        actorFactory.close();
+        super.tearDown();
     }
 
     @Override
@@ -514,4 +513,20 @@ public class FollowerTest extends AbstractRaftActorBehaviorTest {
         return new MockRaftActorContext.MockReplicatedLogEntry(term, index,
                 new MockRaftActorContext.MockPayload(data));
     }
+
+    @Override
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
+        super.assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, actorRef, rpc);
+
+        String expVotedFor = RequestVote.class.isInstance(rpc) ? ((RequestVote)rpc).getCandidateId() : null;
+        assertEquals("New votedFor", expVotedFor, actorContext.getTermInformation().getVotedFor());
+    }
+
+    @Override
+    protected void handleAppendEntriesAddSameEntryToLogReply(TestActorRef<MessageCollectorActor> replyActor)
+            throws Exception {
+        AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(replyActor, AppendEntriesReply.class);
+        assertEquals("isSuccess", true, reply.isSuccess());
+    }
 }
index 6197f980ea51dbcbf38c424a13b4e9259240d4a7..b37ace9560b4bfa46984cb030f310541717a2d63 100644 (file)
@@ -8,30 +8,42 @@
 package org.opendaylight.controller.cluster.raft.behaviors;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import akka.actor.ActorRef;
 import akka.actor.Props;
-import akka.testkit.JavaTestKit;
+import akka.testkit.TestActorRef;
 import java.util.HashMap;
 import java.util.Map;
+import org.junit.After;
 import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.DefaultConfigParamsImpl;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
-import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
+import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 
 public class IsolatedLeaderTest  extends AbstractRaftActorBehaviorTest {
 
-    private final ActorRef leaderActor =
-        getSystem().actorOf(Props.create(DoNothingActor.class));
+    private final TestActorRef<MessageCollectorActor> leaderActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("leader"));
 
-    private final ActorRef senderActor =
-        getSystem().actorOf(Props.create(DoNothingActor.class));
+    private final TestActorRef<MessageCollectorActor> senderActor = actorFactory.createTestActor(
+            Props.create(MessageCollectorActor.class), actorFactory.generateActorId("sender"));
+
+    private AbstractLeader isolatedLeader;
+
+    @Override
+    @After
+    public void tearDown() throws Exception {
+        if(isolatedLeader != null) {
+            isolatedLeader.close();
+        }
+
+        super.tearDown();
+    }
 
     @Override
-    protected RaftActorBehavior createBehavior(
-        RaftActorContext actorContext) {
+    protected RaftActorBehavior createBehavior(RaftActorContext actorContext) {
         return new Leader(actorContext);
     }
 
@@ -40,102 +52,110 @@ public class IsolatedLeaderTest  extends AbstractRaftActorBehaviorTest {
         return createActorContext(leaderActor);
     }
 
+    @Override
+    protected MockRaftActorContext createActorContext(ActorRef actor) {
+        DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
+        configParams.setElectionTimeoutFactor(100000);
+        MockRaftActorContext context = new MockRaftActorContext("isolated-leader", getSystem(), actor);
+        context.setConfigParams(configParams);
+        return context;
+    }
 
     @Test
-    public void testHandleMessageWithThreeMembers() {
-        new JavaTestKit(getSystem()) {{
-            String followerAddress1 = "akka://test/user/$a";
-            String followerAddress2 = "akka://test/user/$b";
-
-            MockRaftActorContext leaderActorContext = createActorContext();
-            Map<String, String> peerAddresses = new HashMap<>();
-            peerAddresses.put("follower-1", followerAddress1);
-            peerAddresses.put("follower-2", followerAddress2);
-            leaderActorContext.setPeerAddresses(peerAddresses);
-
-            IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
-            assertTrue(isolatedLeader.state() == RaftState.IsolatedLeader);
-
-            // in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
-            RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
+    public void testHandleMessageWithThreeMembers() throws Exception {
+        String followerAddress1 = "akka://test/user/$a";
+        String followerAddress2 = "akka://test/user/$b";
+
+        MockRaftActorContext leaderActorContext = createActorContext();
+        Map<String, String> peerAddresses = new HashMap<>();
+        peerAddresses.put("follower-1", followerAddress1);
+        peerAddresses.put("follower-2", followerAddress2);
+        leaderActorContext.setPeerAddresses(peerAddresses);
+
+        isolatedLeader = new IsolatedLeader(leaderActorContext);
+        assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
+
+        // in a 3 node cluster, even if 1 follower is returns a reply, the isolatedLeader is not isolated
+        RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
-                    isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1));
+                        isolatedLeader.lastIndex() - 1, isolatedLeader.lastTerm() - 1));
+
+        assertEquals("Raft state", RaftState.Leader, behavior.state());
 
-            assertEquals(RaftState.Leader, behavior.state());
+        isolatedLeader.close();
+        isolatedLeader = (AbstractLeader) behavior;
 
-            behavior = isolatedLeader.handleMessage(senderActor,
+        behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
-                    isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
+                        isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
 
-            assertEquals(RaftState.Leader, behavior.state());
-        }};
+        assertEquals("Raft state", RaftState.Leader, behavior.state());
     }
 
     @Test
-    public void testHandleMessageWithFiveMembers() {
-        new JavaTestKit(getSystem()) {{
-
-            String followerAddress1 = "akka://test/user/$a";
-            String followerAddress2 = "akka://test/user/$b";
-            String followerAddress3 = "akka://test/user/$c";
-            String followerAddress4 = "akka://test/user/$d";
-
-            MockRaftActorContext leaderActorContext = createActorContext();
-            Map<String, String> peerAddresses = new HashMap<>();
-            peerAddresses.put("follower-1", followerAddress1);
-            peerAddresses.put("follower-2", followerAddress2);
-            peerAddresses.put("follower-3", followerAddress3);
-            peerAddresses.put("follower-4", followerAddress4);
-            leaderActorContext.setPeerAddresses(peerAddresses);
-
-            IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
-            assertEquals(RaftState.IsolatedLeader, isolatedLeader.state());
-
-            // in a 5 member cluster, atleast 2 followers need to be active and return a reply
-            RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
+    public void testHandleMessageWithFiveMembers() throws Exception {
+        String followerAddress1 = "akka://test/user/$a";
+        String followerAddress2 = "akka://test/user/$b";
+        String followerAddress3 = "akka://test/user/$c";
+        String followerAddress4 = "akka://test/user/$d";
+
+        MockRaftActorContext leaderActorContext = createActorContext();
+        Map<String, String> peerAddresses = new HashMap<>();
+        peerAddresses.put("follower-1", followerAddress1);
+        peerAddresses.put("follower-2", followerAddress2);
+        peerAddresses.put("follower-3", followerAddress3);
+        peerAddresses.put("follower-4", followerAddress4);
+        leaderActorContext.setPeerAddresses(peerAddresses);
+
+        isolatedLeader = new IsolatedLeader(leaderActorContext);
+        assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
+
+        // in a 5 member cluster, atleast 2 followers need to be active and return a reply
+        RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() - 1, true,
-                    isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
+                        isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
 
-            assertEquals(RaftState.IsolatedLeader, behavior.state());
+        assertEquals("Raft state", RaftState.IsolatedLeader, behavior.state());
 
-            behavior = isolatedLeader.handleMessage(senderActor,
+        behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-2", isolatedLeader.lastTerm() - 1, true,
-                    isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
+                        isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
+
+        assertEquals("Raft state", RaftState.Leader, behavior.state());
 
-            assertEquals(RaftState.Leader, behavior.state());
+        isolatedLeader.close();
+        isolatedLeader = (AbstractLeader) behavior;
 
-            behavior = isolatedLeader.handleMessage(senderActor,
+        behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-3", isolatedLeader.lastTerm() - 1, true,
-                    isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
+                        isolatedLeader.lastIndex() -1, isolatedLeader.lastTerm() -1 ));
 
-            assertEquals(RaftState.Leader, behavior.state());
-        }};
+        assertEquals("Raft state", RaftState.Leader, behavior.state());
     }
 
     @Test
-    public void testHandleMessageFromAnotherLeader() {
-        new JavaTestKit(getSystem()) {{
-            String followerAddress1 = "akka://test/user/$a";
-            String followerAddress2 = "akka://test/user/$b";
-
-            MockRaftActorContext leaderActorContext = createActorContext();
-            Map<String, String> peerAddresses = new HashMap<>();
-            peerAddresses.put("follower-1", followerAddress1);
-            peerAddresses.put("follower-2", followerAddress2);
-            leaderActorContext.setPeerAddresses(peerAddresses);
-
-            IsolatedLeader isolatedLeader = new IsolatedLeader(leaderActorContext);
-            assertTrue(isolatedLeader.state() == RaftState.IsolatedLeader);
-
-            // if an append-entries reply is received by the isolated-leader, and that reply
-            // has a term  > than its own term, then IsolatedLeader switches to Follower
-            // bowing itself to another leader in the cluster
-            RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
+    public void testHandleMessageFromAnotherLeader() throws Exception {
+        String followerAddress1 = "akka://test/user/$a";
+        String followerAddress2 = "akka://test/user/$b";
+
+        MockRaftActorContext leaderActorContext = createActorContext();
+        Map<String, String> peerAddresses = new HashMap<>();
+        peerAddresses.put("follower-1", followerAddress1);
+        peerAddresses.put("follower-2", followerAddress2);
+        leaderActorContext.setPeerAddresses(peerAddresses);
+
+        isolatedLeader = new IsolatedLeader(leaderActorContext);
+        assertEquals("Raft state", RaftState.IsolatedLeader, isolatedLeader.state());
+
+        // if an append-entries reply is received by the isolated-leader, and that reply
+        // has a term  > than its own term, then IsolatedLeader switches to Follower
+        // bowing itself to another leader in the cluster
+        RaftActorBehavior behavior = isolatedLeader.handleMessage(senderActor,
                 new AppendEntriesReply("follower-1", isolatedLeader.lastTerm() + 1, true,
-                    isolatedLeader.lastIndex() + 1, isolatedLeader.lastTerm() + 1));
+                        isolatedLeader.lastIndex() + 1, isolatedLeader.lastTerm() + 1));
 
-            assertEquals(RaftState.Follower, behavior.state());
-        }};
+        assertEquals("Raft state", RaftState.Follower, behavior.state());
 
+        behavior.close();
     }
 }
index 02c391f146630277c9fc60233193bb8108cd6961..853ed5867d4395d460be0692966b1abee92b2fdf 100644 (file)
@@ -27,7 +27,6 @@ import org.opendaylight.controller.cluster.raft.RaftActorContext;
 import org.opendaylight.controller.cluster.raft.RaftState;
 import org.opendaylight.controller.cluster.raft.ReplicatedLogImplEntry;
 import org.opendaylight.controller.cluster.raft.SerializationUtils;
-import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyLogEntries;
 import org.opendaylight.controller.cluster.raft.base.messages.ApplyState;
 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
@@ -40,6 +39,7 @@ import org.opendaylight.controller.cluster.raft.messages.AppendEntries;
 import org.opendaylight.controller.cluster.raft.messages.AppendEntriesReply;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshot;
 import org.opendaylight.controller.cluster.raft.messages.InstallSnapshotReply;
+import org.opendaylight.controller.cluster.raft.messages.RaftRPC;
 import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
 import org.opendaylight.controller.protobuff.messages.cluster.raft.InstallSnapshotMessages;
@@ -49,8 +49,6 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
     static final String FOLLOWER_ID = "follower";
 
-    private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
-
     private final TestActorRef<ForwardMessageToBehaviorActor> leaderActor = actorFactory.createTestActor(
             Props.create(ForwardMessageToBehaviorActor.class), actorFactory.generateActorId("leader"));
 
@@ -59,13 +57,14 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
 
     private Leader leader;
 
+    @Override
     @After
     public void tearDown() throws Exception {
         if(leader != null) {
             leader.close();
         }
 
-        actorFactory.close();
+        super.tearDown();
     }
 
     @Test
@@ -1136,6 +1135,13 @@ public class LeaderTest extends AbstractRaftActorBehaviorTest {
         follower.close();
     }
 
+    @Override
+    protected void assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(RaftActorContext actorContext,
+            ActorRef actorRef, RaftRPC rpc) throws Exception {
+        super.assertStateChangesToFollowerWhenRaftRPCHasNewerTerm(actorContext, actorRef, rpc);
+        assertEquals("New votedFor", null, actorContext.getTermInformation().getVotedFor());
+    }
+
     private class MockConfigParamsImpl extends DefaultConfigParamsImpl {
 
         private final long electionTimeOutIntervalMillis;