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;
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
*/
@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());
-
-
- }};
}
* @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());
}
/**
* 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());
}
*/
@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
}
- 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(
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);
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);
}
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();
}
}