import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import akka.actor.ActorRef;
-import akka.actor.Props;
import akka.dispatch.Dispatchers;
-import akka.testkit.JavaTestKit;
+import akka.protobuf.ByteString;
import akka.testkit.TestActorRef;
+import akka.testkit.javadsl.TestKit;
import com.google.common.base.Optional;
import com.google.common.base.Stopwatch;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteSource;
import com.google.common.util.concurrent.Uninterruptibles;
-import com.google.protobuf.ByteString;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
public class FollowerTest extends AbstractRaftActorBehaviorTest<Follower> {
- private final TestActorRef<MessageCollectorActor> followerActor = actorFactory.createTestActor(
- Props.create(MessageCollectorActor.class), actorFactory.generateActorId("follower"));
+ private final ActorRef followerActor = actorFactory.createActor(
+ MessageCollectorActor.props(), actorFactory.generateActorId("follower"));
- private final TestActorRef<MessageCollectorActor> leaderActor = actorFactory.createTestActor(
- Props.create(MessageCollectorActor.class), actorFactory.generateActorId("leader"));
+ private final ActorRef leaderActor = actorFactory.createActor(
+ MessageCollectorActor.props(), actorFactory.generateActorId("leader"));
private Follower follower;
@Test
public void testHandleFirstAppendEntriesWithPrevIndexMinusOneAndReplicatedToAllIndexPresentInLog() {
- logStart("testHandleFirstAppendEntries");
+ logStart("testHandleFirstAppendEntriesWithPrevIndexMinusOneAndReplicatedToAllIndexPresentInLog");
MockRaftActorContext context = createActorContext();
context.getReplicatedLog().clear(0,2);
@Test
public void testHandleFirstAppendEntriesWithPrevIndexMinusOneAndReplicatedToAllIndexPresentInSnapshot() {
- logStart("testHandleFirstAppendEntries");
+ logStart("testHandleFirstAppendEntriesWithPrevIndexMinusOneAndReplicatedToAllIndexPresentInSnapshot");
MockRaftActorContext context = createActorContext();
context.getReplicatedLog().clear(0,2);
assertFalse(syncStatus.isInitialSyncDone());
// Clear all the messages
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
context.setLastApplied(101);
context.setCommitIndex(101);
assertTrue(syncStatus.isInitialSyncDone());
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
// Sending the same message again should not generate another message
assertFalse(syncStatus.isInitialSyncDone());
// Clear all the messages
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
context.setLastApplied(100);
setLastLogEntry(context, 1, 100,
assertFalse(syncStatus.isInitialSyncDone());
// Clear all the messages
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
context.setLastApplied(101);
context.setCommitIndex(101);
assertTrue(syncStatus.isInitialSyncDone());
// Clear all the messages
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
context.setLastApplied(100);
setLastLogEntry(context, 1, 100,
}
/**
- * This test verifies that when an AppendEntries is received a specific prevLogTerm
+ * This test verifies that when an AppendEntries is received with a prevLogTerm
* which does not match the term that is in RaftActors log entry at prevLogIndex
* then the RaftActor does not change it's state and it returns a failure.
*/
MockRaftActorContext context = createActorContext();
- // First set the receivers term to lower number
- context.getTermInformation().update(95, "test");
-
- // AppendEntries is now sent with a bigger term
- // this will set the receivers term to be the same as the sender's term
- AppendEntries appendEntries = new AppendEntries(100, "leader", 0, 0, Collections.emptyList(), 101, -1,
- (short)0);
+ AppendEntries appendEntries = new AppendEntries(2, "leader", 0, 2, Collections.emptyList(), 101, -1, (short)0);
follower = createBehavior(context);
assertEquals("isSuccess", false, reply.isSuccess());
}
+ @Test
+ public void testHandleAppendEntriesSenderPrevLogIndexIsInTheSnapshot() {
+ logStart("testHandleAppendEntriesSenderPrevLogIndexIsInTheSnapshot");
+
+ MockRaftActorContext context = createActorContext();
+ context.setReplicatedLog(new MockRaftActorContext.MockReplicatedLogBuilder().createEntries(5, 8, 3).build());
+ context.getReplicatedLog().setSnapshotIndex(4);
+ context.getReplicatedLog().setSnapshotTerm(3);
+
+ AppendEntries appendEntries = new AppendEntries(3, "leader", 1, 3, Collections.emptyList(), 8, -1, (short)0);
+
+ follower = createBehavior(context);
+
+ RaftActorBehavior newBehavior = follower.handleMessage(leaderActor, appendEntries);
+
+ Assert.assertSame(follower, newBehavior);
+
+ AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(leaderActor, AppendEntriesReply.class);
+
+ assertEquals("isSuccess", true, reply.isSuccess());
+ }
+
/**
* This test verifies that when a new AppendEntries message is received with
* new entries and the logs of the sender and receiver match that the new
entries = Arrays.asList(newReplicatedLogEntry(1, 1, "one"), newReplicatedLogEntry(1, 2, "two"));
- leaderActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(leaderActor);
follower.handleMessage(leaderActor, new AppendEntries(1, "leader", 0, 1, entries, 2, -1, (short)0));
assertEquals("Next index", 3, log.last().getIndex() + 1);
assertFalse(syncStatus.isInitialSyncDone());
// Clear all the messages
- followerActor.underlyingActor().clear();
+ MessageCollectorActor.clearMessages(followerActor);
context.setLastApplied(101);
context.setCommitIndex(101);
// Reinstate the actor from persistence
- actorFactory.killActor(followerActorRef, new JavaTestKit(getSystem()));
+ actorFactory.killActor(followerActorRef, new TestKit(getSystem()));
followerActorRef = actorFactory.createTestActor(builder.props()
.withDispatcher(Dispatchers.DefaultDispatcherId()), id);
}
@Override
- protected void handleAppendEntriesAddSameEntryToLogReply(final TestActorRef<MessageCollectorActor> replyActor) {
+ protected void handleAppendEntriesAddSameEntryToLogReply(final ActorRef replyActor) {
AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(replyActor, AppendEntriesReply.class);
assertEquals("isSuccess", true, reply.isSuccess());
}