+ }
+
+
+ /**
+ * This test verifies that when an AppendEntries is received with a term that
+ * is less that the currentTerm of the RaftActor then the RaftActor does not
+ * change it's state and it responds back with a failure.
+ */
+ @Test
+ public void testHandleAppendEntriesSenderTermLessThanReceiverTerm() throws Exception {
+ MockRaftActorContext context = createActorContext();
+ short payloadVersion = 5;
+ context.setPayloadVersion(payloadVersion);
+
+ // 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, (short)4);
+
+ behavior = createBehavior(context);
+
+ RaftState expected = behavior.state();
+
+ RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
+
+ assertEquals("Raft state", expected, raftBehavior.state());
+
+ // Also expect an AppendEntriesReply to be sent where success is false
+
+ AppendEntriesReply reply = MessageCollectorActor.expectFirstMatching(
+ behaviorActor, AppendEntriesReply.class);
+
+ assertEquals("isSuccess", false, reply.isSuccess());
+ assertEquals("getPayloadVersion", payloadVersion, reply.getPayloadVersion());
+ }
+
+
+ @Test
+ public void testHandleAppendEntriesAddSameEntryToLog() throws Exception {
+ MockRaftActorContext context = createActorContext();
+
+ context.getTermInformation().update(2, "test");
+
+ // Prepare the receivers log
+ MockRaftActorContext.MockPayload payload = new MockRaftActorContext.MockPayload("zero");
+ setLastLogEntry(context, 2, 0, payload);
+
+ List<ReplicatedLogEntry> entries = new ArrayList<>();
+ entries.add(new SimpleReplicatedLogEntry(0, 2, payload));
+
+ final AppendEntries appendEntries = new AppendEntries(2, "leader-1", -1, -1, entries, 2, -1, (short)0);
+
+ behavior = createBehavior(context);
+
+ assertFalse("This test should be overridden when testing Candidate", behavior instanceof Candidate);
+
+ RaftState expected = behavior.state();
+
+ // Check that the behavior does not handle unknwon message
+ assertNull(behavior.handleMessage(behaviorActor, "unknown"));
+
+ RaftActorBehavior raftBehavior = behavior.handleMessage(behaviorActor, appendEntries);
+
+ assertEquals("Raft state", expected, raftBehavior.state());
+
+ 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 the senders' log is more up to date than the receiver that the receiver grants
+ * the vote to the sender.
+ */
+ @Test
+ public void testHandleRequestVoteWhenSenderLogMoreUpToDate() {
+ MockRaftActorContext context = createActorContext();