2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.cluster.raft;
11 import static org.junit.Assert.assertArrayEquals;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Matchers.any;
16 import static org.mockito.Matchers.anyLong;
17 import static org.mockito.Mockito.doReturn;
18 import static org.mockito.Mockito.doThrow;
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.never;
21 import static org.mockito.Mockito.reset;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
25 import akka.actor.ActorRef;
26 import akka.persistence.SnapshotSelectionCriteria;
27 import akka.testkit.TestActorRef;
28 import java.util.Arrays;
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.Mock;
34 import org.mockito.MockitoAnnotations;
35 import org.opendaylight.controller.cluster.DataPersistenceProvider;
36 import org.opendaylight.controller.cluster.raft.SnapshotManager.LastAppliedTermInformationReader;
37 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
38 import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot;
39 import org.opendaylight.controller.cluster.raft.base.messages.SnapshotComplete;
40 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
41 import org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry;
42 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
43 import org.slf4j.LoggerFactory;
45 public class SnapshotManagerTest extends AbstractActorTest {
48 private RaftActorContext mockRaftActorContext;
51 private ConfigParams mockConfigParams;
54 private ReplicatedLog mockReplicatedLog;
57 private DataPersistenceProvider mockDataPersistenceProvider;
60 private RaftActorBehavior mockRaftActorBehavior;
63 private Runnable mockProcedure;
66 private ElectionTerm mockElectionTerm;
68 private SnapshotManager snapshotManager;
70 private TestActorFactory factory;
72 private TestActorRef<MessageCollectorActor> actorRef;
76 MockitoAnnotations.initMocks(this);
78 doReturn(false).when(mockRaftActorContext).hasFollowers();
79 doReturn(mockConfigParams).when(mockRaftActorContext).getConfigParams();
80 doReturn(10L).when(mockConfigParams).getSnapshotBatchCount();
81 doReturn(70).when(mockConfigParams).getSnapshotDataThresholdPercentage();
82 doReturn(mockReplicatedLog).when(mockRaftActorContext).getReplicatedLog();
83 doReturn("123").when(mockRaftActorContext).getId();
84 doReturn(mockDataPersistenceProvider).when(mockRaftActorContext).getPersistenceProvider();
85 doReturn(mockRaftActorBehavior).when(mockRaftActorContext).getCurrentBehavior();
86 doReturn("123").when(mockRaftActorBehavior).getLeaderId();
88 doReturn(mockElectionTerm).when(mockRaftActorContext).getTermInformation();
89 doReturn(5L).when(mockElectionTerm).getCurrentTerm();
90 doReturn("member5").when(mockElectionTerm).getVotedFor();
92 snapshotManager = new SnapshotManager(mockRaftActorContext, LoggerFactory.getLogger(this.getClass()));
93 factory = new TestActorFactory(getSystem());
95 actorRef = factory.createTestActor(MessageCollectorActor.props(), factory.generateActorId("test-"));
96 doReturn(actorRef).when(mockRaftActorContext).getActor();
98 snapshotManager.setCreateSnapshotRunnable(mockProcedure);
102 public void tearDown() {
107 public void testConstruction() {
108 assertEquals(false, snapshotManager.isCapturing());
112 public void testCaptureToInstall() throws Exception {
114 // Force capturing toInstall = true
115 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(0, 1,
116 new MockRaftActorContext.MockPayload()), 0, "follower-1");
118 assertEquals(true, snapshotManager.isCapturing());
120 verify(mockProcedure).run();
122 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
124 // LastIndex and LastTerm are picked up from the lastLogEntry
125 assertEquals(0L, captureSnapshot.getLastIndex());
126 assertEquals(1L, captureSnapshot.getLastTerm());
128 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
129 assertEquals(0L, captureSnapshot.getLastAppliedIndex());
130 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
133 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
134 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
135 actorRef.underlyingActor().clear();
139 public void testCapture() throws Exception {
140 boolean capture = snapshotManager.capture(new SimpleReplicatedLogEntry(9, 1,
141 new MockRaftActorContext.MockPayload()), 9);
145 assertEquals(true, snapshotManager.isCapturing());
147 verify(mockProcedure).run();
149 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
151 // LastIndex and LastTerm are picked up from the lastLogEntry
152 assertEquals(9L, captureSnapshot.getLastIndex());
153 assertEquals(1L, captureSnapshot.getLastTerm());
155 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
156 assertEquals(9L, captureSnapshot.getLastAppliedIndex());
157 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
160 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
161 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
163 actorRef.underlyingActor().clear();
168 public void testCaptureWithNullLastLogEntry() throws Exception {
169 boolean capture = snapshotManager.capture(null, 1);
173 assertEquals(true, snapshotManager.isCapturing());
175 verify(mockProcedure).run();
177 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
179 // LastIndex and LastTerm are picked up from the lastLogEntry
180 assertEquals(-1L, captureSnapshot.getLastIndex());
181 assertEquals(-1L, captureSnapshot.getLastTerm());
183 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
184 assertEquals(-1L, captureSnapshot.getLastAppliedIndex());
185 assertEquals(-1L, captureSnapshot.getLastAppliedTerm());
188 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
189 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
190 actorRef.underlyingActor().clear();
195 public void testCaptureWithCreateProcedureError() throws Exception {
196 doThrow(new RuntimeException("mock")).when(mockProcedure).run();
198 boolean capture = snapshotManager.capture(new SimpleReplicatedLogEntry(9, 1,
199 new MockRaftActorContext.MockPayload()), 9);
201 assertFalse(capture);
203 assertEquals(false, snapshotManager.isCapturing());
205 verify(mockProcedure).run();
209 public void testIllegalCapture() throws Exception {
210 boolean capture = snapshotManager.capture(new SimpleReplicatedLogEntry(9, 1,
211 new MockRaftActorContext.MockPayload()), 9);
215 verify(mockProcedure).run();
217 reset(mockProcedure);
219 // This will not cause snapshot capture to start again
220 capture = snapshotManager.capture(new SimpleReplicatedLogEntry(9, 1,
221 new MockRaftActorContext.MockPayload()), 9);
223 assertFalse(capture);
225 verify(mockProcedure, never()).run();
229 public void testPersistWhenReplicatedToAllIndexMinusOne() {
230 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
231 doReturn(1L).when(mockReplicatedLog).getSnapshotTerm();
233 doReturn(true).when(mockRaftActorContext).hasFollowers();
235 doReturn(8L).when(mockRaftActorContext).getLastApplied();
237 ReplicatedLogEntry lastLogEntry = new SimpleReplicatedLogEntry(9L, 3L, new MockRaftActorContext.MockPayload());
239 ReplicatedLogEntry lastAppliedEntry = new SimpleReplicatedLogEntry(
240 8L, 2L, new MockRaftActorContext.MockPayload());
242 doReturn(lastAppliedEntry).when(mockReplicatedLog).get(8L);
243 doReturn(Arrays.asList(lastLogEntry)).when(mockReplicatedLog).getFrom(9L);
245 // when replicatedToAllIndex = -1
246 snapshotManager.capture(lastLogEntry, -1);
248 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
249 snapshotManager.persist(bytes, Runtime.getRuntime().totalMemory());
251 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
252 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
254 Snapshot snapshot = snapshotArgumentCaptor.getValue();
256 assertEquals("getLastTerm", 3L, snapshot.getLastTerm());
257 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
258 assertEquals("getLastAppliedTerm", 2L, snapshot.getLastAppliedTerm());
259 assertEquals("getLastAppliedIndex", 8L, snapshot.getLastAppliedIndex());
260 assertArrayEquals("getState", bytes, snapshot.getState());
261 assertEquals("getUnAppliedEntries", Arrays.asList(lastLogEntry), snapshot.getUnAppliedEntries());
262 assertEquals("electionTerm", mockElectionTerm.getCurrentTerm(), snapshot.getElectionTerm());
263 assertEquals("electionVotedFor", mockElectionTerm.getVotedFor(), snapshot.getElectionVotedFor());
265 verify(mockReplicatedLog).snapshotPreCommit(7L, 1L);
269 public void testPersistWhenReplicatedToAllIndexNotMinus() {
270 doReturn(45L).when(mockReplicatedLog).getSnapshotIndex();
271 doReturn(6L).when(mockReplicatedLog).getSnapshotTerm();
272 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
273 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(9);
274 doReturn(6L).when(replicatedLogEntry).getTerm();
275 doReturn(9L).when(replicatedLogEntry).getIndex();
277 // when replicatedToAllIndex != -1
278 snapshotManager.capture(new SimpleReplicatedLogEntry(9, 6, new MockRaftActorContext.MockPayload()), 9);
280 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
281 snapshotManager.persist(bytes, Runtime.getRuntime().totalMemory());
283 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
284 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
286 Snapshot snapshot = snapshotArgumentCaptor.getValue();
288 assertEquals("getLastTerm", 6L, snapshot.getLastTerm());
289 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
290 assertEquals("getLastAppliedTerm", 6L, snapshot.getLastAppliedTerm());
291 assertEquals("getLastAppliedIndex", 9L, snapshot.getLastAppliedIndex());
292 assertArrayEquals("getState", bytes, snapshot.getState());
293 assertEquals("getUnAppliedEntries size", 0, snapshot.getUnAppliedEntries().size());
295 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
297 verify(mockRaftActorBehavior).setReplicatedToAllIndex(9);
301 public void testPersistWhenReplicatedLogDataSizeGreaterThanThreshold() {
302 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
304 // when replicatedToAllIndex = -1
305 snapshotManager.capture(new SimpleReplicatedLogEntry(9, 6, new MockRaftActorContext.MockPayload()), -1);
307 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
309 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
311 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
313 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
317 public void testPersistWhenReplicatedLogSizeExceedsSnapshotBatchCount() {
318 doReturn(10L).when(mockReplicatedLog).size(); // matches snapshotBatchCount
319 doReturn(100).when(mockReplicatedLog).dataSize();
321 doReturn(5L).when(mockReplicatedLog).getSnapshotIndex();
322 doReturn(5L).when(mockReplicatedLog).getSnapshotTerm();
324 long replicatedToAllIndex = 1;
325 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
326 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(replicatedToAllIndex);
327 doReturn(6L).when(replicatedLogEntry).getTerm();
328 doReturn(replicatedToAllIndex).when(replicatedLogEntry).getIndex();
330 snapshotManager.capture(new SimpleReplicatedLogEntry(9, 6,
331 new MockRaftActorContext.MockPayload()), replicatedToAllIndex);
333 snapshotManager.persist(new byte[]{}, 2000000L);
335 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
337 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
339 verify(mockRaftActorBehavior).setReplicatedToAllIndex(replicatedToAllIndex);
343 public void testPersistSendInstallSnapshot() {
344 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
346 // when replicatedToAllIndex = -1
347 boolean capture = snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
348 new MockRaftActorContext.MockPayload()), -1, "follower-1");
352 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
354 snapshotManager.persist(bytes, Runtime.getRuntime().totalMemory());
356 assertEquals(true, snapshotManager.isCapturing());
358 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
360 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
362 ArgumentCaptor<SendInstallSnapshot> sendInstallSnapshotArgumentCaptor
363 = ArgumentCaptor.forClass(SendInstallSnapshot.class);
365 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), sendInstallSnapshotArgumentCaptor.capture());
367 SendInstallSnapshot sendInstallSnapshot = sendInstallSnapshotArgumentCaptor.getValue();
369 assertTrue(Arrays.equals(bytes, sendInstallSnapshot.getSnapshot().getState()));
373 public void testCallingPersistWithoutCaptureWillDoNothing() {
374 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
376 verify(mockDataPersistenceProvider, never()).saveSnapshot(any(Snapshot.class));
378 verify(mockReplicatedLog, never()).snapshotPreCommit(9L, 6L);
380 verify(mockRaftActorBehavior, never()).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
384 public void testCallingPersistTwiceWillDoNoHarm() {
385 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
387 // when replicatedToAllIndex = -1
388 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
389 new MockRaftActorContext.MockPayload()), -1, "follower-1");
391 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
393 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
395 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
397 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
399 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
403 public void testCommit() {
404 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
406 // when replicatedToAllIndex = -1
407 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
408 new MockRaftActorContext.MockPayload()), -1, "follower-1");
410 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
412 assertEquals(true, snapshotManager.isCapturing());
414 snapshotManager.commit(100L, 1234L);
416 assertEquals(false, snapshotManager.isCapturing());
418 verify(mockReplicatedLog).snapshotCommit();
420 verify(mockDataPersistenceProvider).deleteMessages(50L);
422 ArgumentCaptor<SnapshotSelectionCriteria> criteriaCaptor =
423 ArgumentCaptor.forClass(SnapshotSelectionCriteria.class);
425 verify(mockDataPersistenceProvider).deleteSnapshots(criteriaCaptor.capture());
427 assertEquals(100L, criteriaCaptor.getValue().maxSequenceNr());
428 assertEquals(1233L, criteriaCaptor.getValue().maxTimestamp());
430 MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
434 public void testCommitBeforePersist() {
435 // when replicatedToAllIndex = -1
436 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
437 new MockRaftActorContext.MockPayload()), -1, "follower-1");
439 snapshotManager.commit(100L, 0);
441 verify(mockReplicatedLog, never()).snapshotCommit();
443 verify(mockDataPersistenceProvider, never()).deleteMessages(100L);
445 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
450 public void testCommitBeforeCapture() {
451 snapshotManager.commit(100L, 0);
453 verify(mockReplicatedLog, never()).snapshotCommit();
455 verify(mockDataPersistenceProvider, never()).deleteMessages(anyLong());
457 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
462 public void testCallingCommitMultipleTimesCausesNoHarm() {
463 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
465 // when replicatedToAllIndex = -1
466 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
467 new MockRaftActorContext.MockPayload()), -1, "follower-1");
469 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
471 snapshotManager.commit(100L, 0);
473 snapshotManager.commit(100L, 0);
475 verify(mockReplicatedLog, times(1)).snapshotCommit();
477 verify(mockDataPersistenceProvider, times(1)).deleteMessages(50L);
479 verify(mockDataPersistenceProvider, times(1)).deleteSnapshots(any(SnapshotSelectionCriteria.class));
483 public void testRollback() {
484 // when replicatedToAllIndex = -1
485 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
486 new MockRaftActorContext.MockPayload()), -1, "follower-1");
488 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
490 snapshotManager.rollback();
492 verify(mockReplicatedLog).snapshotRollback();
494 MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
499 public void testRollbackBeforePersist() {
500 // when replicatedToAllIndex = -1
501 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
502 new MockRaftActorContext.MockPayload()), -1, "follower-1");
504 snapshotManager.rollback();
506 verify(mockReplicatedLog, never()).snapshotRollback();
510 public void testRollbackBeforeCapture() {
511 snapshotManager.rollback();
513 verify(mockReplicatedLog, never()).snapshotRollback();
517 public void testCallingRollbackMultipleTimesCausesNoHarm() {
518 // when replicatedToAllIndex = -1
519 snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 6,
520 new MockRaftActorContext.MockPayload()), -1, "follower-1");
522 snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
524 snapshotManager.rollback();
526 snapshotManager.rollback();
528 verify(mockReplicatedLog, times(1)).snapshotRollback();
532 public void testTrimLogWhenTrimIndexLessThanLastApplied() {
533 doReturn(20L).when(mockRaftActorContext).getLastApplied();
535 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
536 doReturn(true).when(mockReplicatedLog).isPresent(10);
537 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
538 doReturn(5L).when(replicatedLogEntry).getTerm();
540 long retIndex = snapshotManager.trimLog(10);
541 assertEquals("return index", 10L, retIndex);
543 verify(mockReplicatedLog).snapshotPreCommit(10, 5);
544 verify(mockReplicatedLog).snapshotCommit();
546 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
550 public void testTrimLogWhenLastAppliedNotSet() {
551 doReturn(-1L).when(mockRaftActorContext).getLastApplied();
553 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
554 doReturn(true).when(mockReplicatedLog).isPresent(10);
555 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
556 doReturn(5L).when(replicatedLogEntry).getTerm();
558 long retIndex = snapshotManager.trimLog(10);
559 assertEquals("return index", -1L, retIndex);
561 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
562 verify(mockReplicatedLog, never()).snapshotCommit();
564 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
568 public void testTrimLogWhenLastAppliedZero() {
569 doReturn(0L).when(mockRaftActorContext).getLastApplied();
571 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
572 doReturn(true).when(mockReplicatedLog).isPresent(10);
573 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
574 doReturn(5L).when(replicatedLogEntry).getTerm();
576 long retIndex = snapshotManager.trimLog(10);
577 assertEquals("return index", -1L, retIndex);
579 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
580 verify(mockReplicatedLog, never()).snapshotCommit();
582 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
586 public void testTrimLogWhenTrimIndexNotPresent() {
587 doReturn(20L).when(mockRaftActorContext).getLastApplied();
589 doReturn(false).when(mockReplicatedLog).isPresent(10);
591 long retIndex = snapshotManager.trimLog(10);
592 assertEquals("return index", -1L, retIndex);
594 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
595 verify(mockReplicatedLog, never()).snapshotCommit();
597 // Trim index is greater than replicatedToAllIndex so should update it.
598 verify(mockRaftActorBehavior).setReplicatedToAllIndex(10L);
602 public void testTrimLogAfterCapture() {
603 boolean capture = snapshotManager.capture(new SimpleReplicatedLogEntry(9, 1,
604 new MockRaftActorContext.MockPayload()), 9);
608 assertEquals(true, snapshotManager.isCapturing());
610 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
611 doReturn(20L).when(mockRaftActorContext).getLastApplied();
612 doReturn(true).when(mockReplicatedLog).isPresent(10);
613 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
614 doReturn(5L).when(replicatedLogEntry).getTerm();
616 snapshotManager.trimLog(10);
618 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
619 verify(mockReplicatedLog, never()).snapshotCommit();
624 public void testTrimLogAfterCaptureToInstall() {
625 boolean capture = snapshotManager.captureToInstall(new SimpleReplicatedLogEntry(9, 1,
626 new MockRaftActorContext.MockPayload()), 9, "follower-1");
630 assertEquals(true, snapshotManager.isCapturing());
632 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
633 doReturn(20L).when(mockRaftActorContext).getLastApplied();
634 doReturn(true).when(mockReplicatedLog).isPresent(10);
635 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
636 doReturn(5L).when(replicatedLogEntry).getTerm();
638 snapshotManager.trimLog(10);
640 verify(mockReplicatedLog, never()).snapshotPreCommit(10, 5);
641 verify(mockReplicatedLog, never()).snapshotCommit();
646 public void testLastAppliedTermInformationReader() {
648 LastAppliedTermInformationReader reader = new LastAppliedTermInformationReader();
650 doReturn(4L).when(mockReplicatedLog).getSnapshotTerm();
651 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
653 ReplicatedLogEntry lastLogEntry = new SimpleReplicatedLogEntry(9L, 6L,
654 new MockRaftActorContext.MockPayload());
656 // No followers and valid lastLogEntry
657 reader.init(mockReplicatedLog, 1L, lastLogEntry, false);
659 assertEquals("getTerm", 6L, reader.getTerm());
660 assertEquals("getIndex", 9L, reader.getIndex());
662 // No followers and null lastLogEntry
663 reader.init(mockReplicatedLog, 1L, null, false);
665 assertEquals("getTerm", -1L, reader.getTerm());
666 assertEquals("getIndex", -1L, reader.getIndex());
668 // Followers and valid originalIndex entry
669 doReturn(new SimpleReplicatedLogEntry(8L, 5L,
670 new MockRaftActorContext.MockPayload())).when(mockReplicatedLog).get(8L);
671 reader.init(mockReplicatedLog, 8L, lastLogEntry, true);
673 assertEquals("getTerm", 5L, reader.getTerm());
674 assertEquals("getIndex", 8L, reader.getIndex());
676 // Followers and null originalIndex entry and valid snapshot index
677 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
679 assertEquals("getTerm", 4L, reader.getTerm());
680 assertEquals("getIndex", 7L, reader.getIndex());
682 // Followers and null originalIndex entry and invalid snapshot index
683 doReturn(-1L).when(mockReplicatedLog).getSnapshotIndex();
684 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
686 assertEquals("getTerm", -1L, reader.getTerm());
687 assertEquals("getIndex", -1L, reader.getIndex());