1 package org.opendaylight.controller.cluster.raft;
3 import static org.junit.Assert.assertArrayEquals;
4 import static org.junit.Assert.assertEquals;
5 import static org.junit.Assert.assertFalse;
6 import static org.junit.Assert.assertTrue;
7 import static org.mockito.Matchers.any;
8 import static org.mockito.Matchers.anyLong;
9 import static org.mockito.Mockito.doReturn;
10 import static org.mockito.Mockito.doThrow;
11 import static org.mockito.Mockito.mock;
12 import static org.mockito.Mockito.never;
13 import static org.mockito.Mockito.reset;
14 import static org.mockito.Mockito.times;
15 import static org.mockito.Mockito.verify;
16 import akka.actor.ActorRef;
17 import akka.japi.Procedure;
18 import akka.persistence.SnapshotSelectionCriteria;
19 import akka.testkit.TestActorRef;
20 import com.google.common.collect.ImmutableMap;
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import org.junit.After;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.mockito.ArgumentCaptor;
27 import org.mockito.Mock;
28 import org.mockito.MockitoAnnotations;
29 import org.opendaylight.controller.cluster.DataPersistenceProvider;
30 import org.opendaylight.controller.cluster.raft.SnapshotManager.LastAppliedTermInformationReader;
31 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
32 import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot;
33 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
34 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
35 import org.slf4j.LoggerFactory;
37 public class SnapshotManagerTest extends AbstractActorTest {
40 private RaftActorContext mockRaftActorContext;
43 private ConfigParams mockConfigParams;
46 private ReplicatedLog mockReplicatedLog;
49 private DataPersistenceProvider mockDataPersistenceProvider;
52 private RaftActorBehavior mockRaftActorBehavior;
55 private Procedure<Void> mockProcedure;
57 private SnapshotManager snapshotManager;
59 private TestActorFactory factory;
61 private TestActorRef<MessageCollectorActor> actorRef;
65 MockitoAnnotations.initMocks(this);
67 doReturn(new HashMap<>()).when(mockRaftActorContext).getPeerAddresses();
68 doReturn(mockConfigParams).when(mockRaftActorContext).getConfigParams();
69 doReturn(10L).when(mockConfigParams).getSnapshotBatchCount();
70 doReturn(mockReplicatedLog).when(mockRaftActorContext).getReplicatedLog();
71 doReturn("123").when(mockRaftActorContext).getId();
72 doReturn(mockDataPersistenceProvider).when(mockRaftActorContext).getPersistenceProvider();
73 doReturn("123").when(mockRaftActorBehavior).getLeaderId();
75 ElectionTerm mockElectionTerm = mock(ElectionTerm.class);
76 doReturn(mockElectionTerm).when(mockRaftActorContext).getTermInformation();
77 doReturn(5L).when(mockElectionTerm).getCurrentTerm();
79 snapshotManager = new SnapshotManager(mockRaftActorContext, LoggerFactory.getLogger(this.getClass()));
80 factory = new TestActorFactory(getSystem());
82 actorRef = factory.createTestActor(MessageCollectorActor.props(), factory.generateActorId("test-"));
83 doReturn(actorRef).when(mockRaftActorContext).getActor();
85 snapshotManager.setCreateSnapshotCallable(mockProcedure);
89 public void tearDown(){
94 public void testConstruction(){
95 assertEquals(false, snapshotManager.isCapturing());
99 public void testCaptureToInstall() throws Exception {
101 // Force capturing toInstall = true
102 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1, 0,
103 new MockRaftActorContext.MockPayload()), 0, "follower-1");
105 assertEquals(true, snapshotManager.isCapturing());
107 verify(mockProcedure).apply(null);
109 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
111 // LastIndex and LastTerm are picked up from the lastLogEntry
112 assertEquals(0L, captureSnapshot.getLastIndex());
113 assertEquals(1L, captureSnapshot.getLastTerm());
115 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
116 assertEquals(0L, captureSnapshot.getLastAppliedIndex());
117 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
120 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
121 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
122 actorRef.underlyingActor().clear();
126 public void testCapture() throws Exception {
127 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
128 new MockRaftActorContext.MockPayload()), 9);
132 assertEquals(true, snapshotManager.isCapturing());
134 verify(mockProcedure).apply(null);
136 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
138 // LastIndex and LastTerm are picked up from the lastLogEntry
139 assertEquals(9L, captureSnapshot.getLastIndex());
140 assertEquals(1L, captureSnapshot.getLastTerm());
142 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
143 assertEquals(9L, captureSnapshot.getLastAppliedIndex());
144 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
147 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
148 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
150 actorRef.underlyingActor().clear();
155 public void testCaptureWithCreateProcedureError () throws Exception {
156 doThrow(new Exception("mock")).when(mockProcedure).apply(null);
158 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
159 new MockRaftActorContext.MockPayload()), 9);
161 assertFalse(capture);
163 assertEquals(false, snapshotManager.isCapturing());
165 verify(mockProcedure).apply(null);
169 public void testIllegalCapture() throws Exception {
170 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
171 new MockRaftActorContext.MockPayload()), 9);
175 verify(mockProcedure).apply(null);
177 reset(mockProcedure);
179 // This will not cause snapshot capture to start again
180 capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
181 new MockRaftActorContext.MockPayload()), 9);
183 assertFalse(capture);
185 verify(mockProcedure, never()).apply(null);
189 public void testPersistWhenReplicatedToAllIndexMinusOne(){
190 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
191 doReturn(1L).when(mockReplicatedLog).getSnapshotTerm();
193 doReturn(ImmutableMap.builder().put("follower-1", "").build()).when(mockRaftActorContext).getPeerAddresses();
195 doReturn(8L).when(mockRaftActorContext).getLastApplied();
197 MockRaftActorContext.MockReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(
198 3L, 9L, new MockRaftActorContext.MockPayload());
200 MockRaftActorContext.MockReplicatedLogEntry lastAppliedEntry = new MockRaftActorContext.MockReplicatedLogEntry(
201 2L, 8L, new MockRaftActorContext.MockPayload());
203 doReturn(lastAppliedEntry).when(mockReplicatedLog).get(8L);
204 doReturn(Arrays.asList(lastLogEntry)).when(mockReplicatedLog).getFrom(9L);
206 // when replicatedToAllIndex = -1
207 snapshotManager.capture(lastLogEntry, -1);
209 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
210 snapshotManager.persist(mockDataPersistenceProvider, bytes, mockRaftActorBehavior
211 , Runtime.getRuntime().totalMemory());
213 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
214 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
216 Snapshot snapshot = snapshotArgumentCaptor.getValue();
218 assertEquals("getLastTerm", 3L, snapshot.getLastTerm());
219 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
220 assertEquals("getLastAppliedTerm", 2L, snapshot.getLastAppliedTerm());
221 assertEquals("getLastAppliedIndex", 8L, snapshot.getLastAppliedIndex());
222 assertArrayEquals("getState", bytes, snapshot.getState());
223 assertEquals("getUnAppliedEntries", Arrays.asList(lastLogEntry), snapshot.getUnAppliedEntries());
225 verify(mockReplicatedLog).snapshotPreCommit(7L, 1L);
229 public void testPersistWhenReplicatedToAllIndexNotMinus(){
230 doReturn(45L).when(mockReplicatedLog).getSnapshotIndex();
231 doReturn(6L).when(mockReplicatedLog).getSnapshotTerm();
232 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
233 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(9);
234 doReturn(6L).when(replicatedLogEntry).getTerm();
235 doReturn(9L).when(replicatedLogEntry).getIndex();
237 // when replicatedToAllIndex != -1
238 snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
239 new MockRaftActorContext.MockPayload()), 9);
241 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
242 snapshotManager.persist(mockDataPersistenceProvider, bytes, mockRaftActorBehavior
243 , Runtime.getRuntime().totalMemory());
245 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
246 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
248 Snapshot snapshot = snapshotArgumentCaptor.getValue();
250 assertEquals("getLastTerm", 6L, snapshot.getLastTerm());
251 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
252 assertEquals("getLastAppliedTerm", 6L, snapshot.getLastAppliedTerm());
253 assertEquals("getLastAppliedIndex", 9L, snapshot.getLastAppliedIndex());
254 assertArrayEquals("getState", bytes, snapshot.getState());
255 assertEquals("getUnAppliedEntries size", 0, snapshot.getUnAppliedEntries().size());
257 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
259 verify(mockRaftActorBehavior).setReplicatedToAllIndex(9);
264 public void testPersistWhenReplicatedLogDataSizeGreaterThanThreshold(){
265 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
267 // when replicatedToAllIndex = -1
268 snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
269 new MockRaftActorContext.MockPayload()), -1);
271 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
272 , Runtime.getRuntime().totalMemory());
274 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
276 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
280 public void testPersistSendInstallSnapshot(){
281 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
283 // when replicatedToAllIndex = -1
284 boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
285 new MockRaftActorContext.MockPayload()), -1, "follower-1");
289 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
291 snapshotManager.persist(mockDataPersistenceProvider, bytes, mockRaftActorBehavior
292 , Runtime.getRuntime().totalMemory());
294 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
296 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
298 ArgumentCaptor<SendInstallSnapshot> sendInstallSnapshotArgumentCaptor
299 = ArgumentCaptor.forClass(SendInstallSnapshot.class);
301 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), sendInstallSnapshotArgumentCaptor.capture());
303 SendInstallSnapshot sendInstallSnapshot = sendInstallSnapshotArgumentCaptor.getValue();
305 assertTrue(Arrays.equals(bytes, sendInstallSnapshot.getSnapshot().toByteArray()));
309 public void testCallingPersistWithoutCaptureWillDoNothing(){
310 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
311 , Runtime.getRuntime().totalMemory());
313 verify(mockDataPersistenceProvider, never()).saveSnapshot(any(Snapshot.class));
315 verify(mockReplicatedLog, never()).snapshotPreCommit(9L, 6L);
317 verify(mockRaftActorBehavior, never()).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
320 public void testCallingPersistTwiceWillDoNoHarm(){
321 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
323 // when replicatedToAllIndex = -1
324 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
325 new MockRaftActorContext.MockPayload()), -1, "follower-1");
327 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
328 , Runtime.getRuntime().totalMemory());
330 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
331 , Runtime.getRuntime().totalMemory());
333 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
335 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
337 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
341 public void testCommit(){
342 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
344 // when replicatedToAllIndex = -1
345 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
346 new MockRaftActorContext.MockPayload()), -1, "follower-1");
348 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
349 , Runtime.getRuntime().totalMemory());
351 snapshotManager.commit(mockDataPersistenceProvider, 100L);
353 verify(mockReplicatedLog).snapshotCommit();
355 verify(mockDataPersistenceProvider).deleteMessages(50L);
357 ArgumentCaptor<SnapshotSelectionCriteria> criteriaCaptor = ArgumentCaptor.forClass(SnapshotSelectionCriteria.class);
359 verify(mockDataPersistenceProvider).deleteSnapshots(criteriaCaptor.capture());
361 assertEquals(90, criteriaCaptor.getValue().maxSequenceNr()); // sequenceNumber = 100
362 // config snapShotBatchCount = 10
363 // therefore maxSequenceNumber = 90
367 public void testCommitBeforePersist(){
368 // when replicatedToAllIndex = -1
369 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
370 new MockRaftActorContext.MockPayload()), -1, "follower-1");
372 snapshotManager.commit(mockDataPersistenceProvider, 100L);
374 verify(mockReplicatedLog, never()).snapshotCommit();
376 verify(mockDataPersistenceProvider, never()).deleteMessages(100L);
378 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
383 public void testCommitBeforeCapture(){
384 snapshotManager.commit(mockDataPersistenceProvider, 100L);
386 verify(mockReplicatedLog, never()).snapshotCommit();
388 verify(mockDataPersistenceProvider, never()).deleteMessages(anyLong());
390 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
395 public void testCallingCommitMultipleTimesCausesNoHarm(){
396 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
398 // when replicatedToAllIndex = -1
399 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
400 new MockRaftActorContext.MockPayload()), -1, "follower-1");
402 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
403 , Runtime.getRuntime().totalMemory());
405 snapshotManager.commit(mockDataPersistenceProvider, 100L);
407 snapshotManager.commit(mockDataPersistenceProvider, 100L);
409 verify(mockReplicatedLog, times(1)).snapshotCommit();
411 verify(mockDataPersistenceProvider, times(1)).deleteMessages(50L);
413 verify(mockDataPersistenceProvider, times(1)).deleteSnapshots(any(SnapshotSelectionCriteria.class));
417 public void testRollback(){
418 // when replicatedToAllIndex = -1
419 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
420 new MockRaftActorContext.MockPayload()), -1, "follower-1");
422 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
423 , Runtime.getRuntime().totalMemory());
425 snapshotManager.rollback();
427 verify(mockReplicatedLog).snapshotRollback();
432 public void testRollbackBeforePersist(){
433 // when replicatedToAllIndex = -1
434 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
435 new MockRaftActorContext.MockPayload()), -1, "follower-1");
437 snapshotManager.rollback();
439 verify(mockReplicatedLog, never()).snapshotRollback();
443 public void testRollbackBeforeCapture(){
444 snapshotManager.rollback();
446 verify(mockReplicatedLog, never()).snapshotRollback();
450 public void testCallingRollbackMultipleTimesCausesNoHarm(){
451 // when replicatedToAllIndex = -1
452 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
453 new MockRaftActorContext.MockPayload()), -1, "follower-1");
455 snapshotManager.persist(mockDataPersistenceProvider, new byte[]{}, mockRaftActorBehavior
456 , Runtime.getRuntime().totalMemory());
458 snapshotManager.rollback();
460 snapshotManager.rollback();
462 verify(mockReplicatedLog, times(1)).snapshotRollback();
466 public void testTrimLogWhenTrimIndexLessThanLastApplied() {
467 doReturn(20L).when(mockRaftActorContext).getLastApplied();
469 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
470 doReturn(true).when(mockReplicatedLog).isPresent(10);
471 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
472 doReturn(5L).when(replicatedLogEntry).getTerm();
474 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
475 assertEquals("return index", 10L, retIndex);
477 verify(mockReplicatedLog).snapshotPreCommit(10, 5);
478 verify(mockReplicatedLog).snapshotCommit();
480 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
484 public void testTrimLogWhenLastAppliedNotSet() {
485 doReturn(-1L).when(mockRaftActorContext).getLastApplied();
487 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
488 doReturn(true).when(mockReplicatedLog).isPresent(10);
489 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
490 doReturn(5L).when(replicatedLogEntry).getTerm();
492 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
493 assertEquals("return index", -1L, retIndex);
495 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
496 verify(mockReplicatedLog, never()).snapshotCommit();
498 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
502 public void testTrimLogWhenLastAppliedZero() {
503 doReturn(0L).when(mockRaftActorContext).getLastApplied();
505 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
506 doReturn(true).when(mockReplicatedLog).isPresent(10);
507 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
508 doReturn(5L).when(replicatedLogEntry).getTerm();
510 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
511 assertEquals("return index", -1L, retIndex);
513 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
514 verify(mockReplicatedLog, never()).snapshotCommit();
516 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
520 public void testTrimLogWhenTrimIndexNotPresent() {
521 doReturn(20L).when(mockRaftActorContext).getLastApplied();
523 doReturn(false).when(mockReplicatedLog).isPresent(10);
525 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
526 assertEquals("return index", -1L, retIndex);
528 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
529 verify(mockReplicatedLog, never()).snapshotCommit();
531 // Trim index is greater than replicatedToAllIndex so should update it.
532 verify(mockRaftActorBehavior).setReplicatedToAllIndex(10L);
536 public void testTrimLogAfterCapture(){
537 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
538 new MockRaftActorContext.MockPayload()), 9);
542 assertEquals(true, snapshotManager.isCapturing());
544 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
545 doReturn(20L).when(mockRaftActorContext).getLastApplied();
546 doReturn(true).when(mockReplicatedLog).isPresent(10);
547 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
548 doReturn(5L).when(replicatedLogEntry).getTerm();
550 snapshotManager.trimLog(10, mockRaftActorBehavior);
552 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
553 verify(mockReplicatedLog, never()).snapshotCommit();
558 public void testTrimLogAfterCaptureToInstall(){
559 boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
560 new MockRaftActorContext.MockPayload()), 9, "follower-1");
564 assertEquals(true, snapshotManager.isCapturing());
566 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
567 doReturn(20L).when(mockRaftActorContext).getLastApplied();
568 doReturn(true).when(mockReplicatedLog).isPresent(10);
569 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
570 doReturn(5L).when(replicatedLogEntry).getTerm();
572 snapshotManager.trimLog(10, mockRaftActorBehavior);
574 verify(mockReplicatedLog, never()).snapshotPreCommit(10, 5);
575 verify(mockReplicatedLog, never()).snapshotCommit();
580 public void testLastAppliedTermInformationReader() {
582 LastAppliedTermInformationReader reader = new LastAppliedTermInformationReader();
584 doReturn(4L).when(mockReplicatedLog).getSnapshotTerm();
585 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
587 ReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(6L, 9L,
588 new MockRaftActorContext.MockPayload());
590 // No followers and valid lastLogEntry
591 reader.init(mockReplicatedLog, 1L, lastLogEntry, false);
593 assertEquals("getTerm", 6L, reader.getTerm());
594 assertEquals("getIndex", 9L, reader.getIndex());
596 // No followers and null lastLogEntry
597 reader.init(mockReplicatedLog, 1L, null, false);
599 assertEquals("getTerm", -1L, reader.getTerm());
600 assertEquals("getIndex", -1L, reader.getIndex());
602 // Followers and valid originalIndex entry
603 doReturn(new MockRaftActorContext.MockReplicatedLogEntry(5L, 8L,
604 new MockRaftActorContext.MockPayload())).when(mockReplicatedLog).get(8L);
605 reader.init(mockReplicatedLog, 8L, lastLogEntry, true);
607 assertEquals("getTerm", 5L, reader.getTerm());
608 assertEquals("getIndex", 8L, reader.getIndex());
610 // Followers and null originalIndex entry and valid snapshot index
611 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
613 assertEquals("getTerm", 4L, reader.getTerm());
614 assertEquals("getIndex", 7L, reader.getIndex());
616 // Followers and null originalIndex entry and invalid snapshot index
617 doReturn(-1L).when(mockReplicatedLog).getSnapshotIndex();
618 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
620 assertEquals("getTerm", -1L, reader.getTerm());
621 assertEquals("getIndex", -1L, reader.getIndex());