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.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.doThrow;
20 import static org.mockito.Mockito.mock;
21 import static org.mockito.Mockito.never;
22 import static org.mockito.Mockito.reset;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import akka.actor.ActorRef;
26 import akka.japi.Procedure;
27 import akka.persistence.SnapshotSelectionCriteria;
28 import akka.testkit.TestActorRef;
29 import java.util.Arrays;
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.mockito.ArgumentCaptor;
34 import org.mockito.Mock;
35 import org.mockito.MockitoAnnotations;
36 import org.opendaylight.controller.cluster.DataPersistenceProvider;
37 import org.opendaylight.controller.cluster.raft.SnapshotManager.LastAppliedTermInformationReader;
38 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
39 import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot;
40 import org.opendaylight.controller.cluster.raft.base.messages.SnapshotComplete;
41 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
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 Procedure<Void> mockProcedure;
66 private ElectionTerm mockElectionTerm;
68 private SnapshotManager snapshotManager;
70 private TestActorFactory factory;
72 private TestActorRef<MessageCollectorActor> actorRef;
75 public void setUp() throws Exception {
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("123").when(mockRaftActorBehavior).getLeaderId();
86 doReturn(null).when(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(Object.class));
87 doReturn(0L).when(mockRaftActorBehavior).getReplicatedToAllIndex();
89 doReturn(mockElectionTerm).when(mockRaftActorContext).getTermInformation();
90 doReturn(5L).when(mockElectionTerm).getCurrentTerm();
91 doReturn("member5").when(mockElectionTerm).getVotedFor();
93 snapshotManager = new SnapshotManager(mockRaftActorContext, LoggerFactory.getLogger(this.getClass()));
94 factory = new TestActorFactory(getSystem());
96 actorRef = factory.createTestActor(MessageCollectorActor.props(), factory.generateActorId("test-"));
97 doReturn(actorRef).when(mockRaftActorContext).getActor();
98 doReturn(0L).when(mockRaftActorContext).getLastApplied();
99 doReturn(null).when(mockRaftActorContext).getPeerServerInfo(any(boolean.class));
100 doReturn(null).when(mockReplicatedLog).get(any(long.class));
101 doReturn(null).when(mockReplicatedLog).getFrom(any(long.class));
102 doReturn(0).when(mockReplicatedLog).dataSize();
103 doReturn(0L).when(mockReplicatedLog).size();
104 doReturn(0L).when(mockReplicatedLog).getSnapshotIndex();
105 doReturn(0L).when(mockReplicatedLog).getSnapshotTerm();
106 doNothing().when(mockReplicatedLog).snapshotPreCommit(any(long.class), any(long.class));
107 doNothing().when(mockReplicatedLog).snapshotRollback();
108 doNothing().when(mockReplicatedLog).snapshotCommit();
109 doNothing().when(mockRaftActorBehavior).setReplicatedToAllIndex(any(long.class));
111 doReturn(0L).when(mockDataPersistenceProvider).getLastSequenceNumber();
112 doNothing().when(mockDataPersistenceProvider).saveSnapshot(any(Object.class));
113 doNothing().when(mockDataPersistenceProvider).persist(any(Object.class), any(Procedure.class));
114 doNothing().when(mockDataPersistenceProvider).deleteSnapshots(any(SnapshotSelectionCriteria.class));
115 doNothing().when(mockDataPersistenceProvider).deleteMessages(any(long.class));
117 doNothing().when(mockProcedure).apply(null);
119 snapshotManager.setCreateSnapshotCallable(mockProcedure);
123 public void tearDown(){
128 public void testConstruction(){
129 assertEquals(false, snapshotManager.isCapturing());
133 public void testCaptureToInstall() throws Exception {
135 // Force capturing toInstall = true
136 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1, 0,
137 new MockRaftActorContext.MockPayload()), 0, "follower-1");
139 assertEquals(true, snapshotManager.isCapturing());
141 verify(mockProcedure).apply(null);
143 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
145 // LastIndex and LastTerm are picked up from the lastLogEntry
146 assertEquals(0L, captureSnapshot.getLastIndex());
147 assertEquals(1L, captureSnapshot.getLastTerm());
149 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
150 assertEquals(0L, captureSnapshot.getLastAppliedIndex());
151 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
154 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
155 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
156 actorRef.underlyingActor().clear();
160 public void testCapture() throws Exception {
161 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
162 new MockRaftActorContext.MockPayload()), 9);
166 assertEquals(true, snapshotManager.isCapturing());
168 verify(mockProcedure).apply(null);
170 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
172 // LastIndex and LastTerm are picked up from the lastLogEntry
173 assertEquals(9L, captureSnapshot.getLastIndex());
174 assertEquals(1L, captureSnapshot.getLastTerm());
176 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
177 assertEquals(9L, captureSnapshot.getLastAppliedIndex());
178 assertEquals(1L, captureSnapshot.getLastAppliedTerm());
181 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
182 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
184 actorRef.underlyingActor().clear();
189 public void testCaptureWithNullLastLogEntry() throws Exception {
190 boolean capture = snapshotManager.capture(null, 1);
194 assertEquals(true, snapshotManager.isCapturing());
196 verify(mockProcedure).apply(null);
198 CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
200 System.out.println(captureSnapshot);
202 // LastIndex and LastTerm are picked up from the lastLogEntry
203 assertEquals(-1L, captureSnapshot.getLastIndex());
204 assertEquals(-1L, captureSnapshot.getLastTerm());
206 // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
207 assertEquals(-1L, captureSnapshot.getLastAppliedIndex());
208 assertEquals(-1L, captureSnapshot.getLastAppliedTerm());
211 assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
212 assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
213 actorRef.underlyingActor().clear();
218 public void testCaptureWithCreateProcedureError () throws Exception {
219 doThrow(new Exception("mock")).when(mockProcedure).apply(null);
221 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
222 new MockRaftActorContext.MockPayload()), 9);
224 assertFalse(capture);
226 assertEquals(false, snapshotManager.isCapturing());
228 verify(mockProcedure).apply(null);
232 public void testIllegalCapture() throws Exception {
233 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
234 new MockRaftActorContext.MockPayload()), 9);
238 verify(mockProcedure).apply(null);
240 reset(mockProcedure);
242 // This will not cause snapshot capture to start again
243 capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
244 new MockRaftActorContext.MockPayload()), 9);
246 assertFalse(capture);
248 verify(mockProcedure, never()).apply(null);
252 public void testPersistWhenReplicatedToAllIndexMinusOne(){
253 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
254 doReturn(1L).when(mockReplicatedLog).getSnapshotTerm();
256 doReturn(true).when(mockRaftActorContext).hasFollowers();
258 doReturn(8L).when(mockRaftActorContext).getLastApplied();
260 MockRaftActorContext.MockReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(
261 3L, 9L, new MockRaftActorContext.MockPayload());
263 MockRaftActorContext.MockReplicatedLogEntry lastAppliedEntry = new MockRaftActorContext.MockReplicatedLogEntry(
264 2L, 8L, new MockRaftActorContext.MockPayload());
266 doReturn(lastAppliedEntry).when(mockReplicatedLog).get(8L);
267 doReturn(Arrays.asList(lastLogEntry)).when(mockReplicatedLog).getFrom(9L);
269 // when replicatedToAllIndex = -1
270 snapshotManager.capture(lastLogEntry, -1);
272 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
273 snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
275 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
276 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
278 Snapshot snapshot = snapshotArgumentCaptor.getValue();
280 assertEquals("getLastTerm", 3L, snapshot.getLastTerm());
281 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
282 assertEquals("getLastAppliedTerm", 2L, snapshot.getLastAppliedTerm());
283 assertEquals("getLastAppliedIndex", 8L, snapshot.getLastAppliedIndex());
284 assertArrayEquals("getState", bytes, snapshot.getState());
285 assertEquals("getUnAppliedEntries", Arrays.asList(lastLogEntry), snapshot.getUnAppliedEntries());
286 assertEquals("electionTerm", mockElectionTerm.getCurrentTerm(), snapshot.getElectionTerm());
287 assertEquals("electionVotedFor", mockElectionTerm.getVotedFor(), snapshot.getElectionVotedFor());
289 verify(mockReplicatedLog).snapshotPreCommit(7L, 1L);
293 public void testPersistWhenReplicatedToAllIndexNotMinus(){
294 doReturn(45L).when(mockReplicatedLog).getSnapshotIndex();
295 doReturn(6L).when(mockReplicatedLog).getSnapshotTerm();
296 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
297 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(9);
298 doReturn(6L).when(replicatedLogEntry).getTerm();
299 doReturn(9L).when(replicatedLogEntry).getIndex();
301 // when replicatedToAllIndex != -1
302 snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
303 new MockRaftActorContext.MockPayload()), 9);
305 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
306 snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
308 ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
309 verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
311 Snapshot snapshot = snapshotArgumentCaptor.getValue();
313 assertEquals("getLastTerm", 6L, snapshot.getLastTerm());
314 assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
315 assertEquals("getLastAppliedTerm", 6L, snapshot.getLastAppliedTerm());
316 assertEquals("getLastAppliedIndex", 9L, snapshot.getLastAppliedIndex());
317 assertArrayEquals("getState", bytes, snapshot.getState());
318 assertEquals("getUnAppliedEntries size", 0, snapshot.getUnAppliedEntries().size());
320 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
322 verify(mockRaftActorBehavior).setReplicatedToAllIndex(9);
326 public void testPersistWhenReplicatedLogDataSizeGreaterThanThreshold(){
327 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
329 // when replicatedToAllIndex = -1
330 snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
331 new MockRaftActorContext.MockPayload()), -1);
333 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
335 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
337 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
339 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
343 public void testPersistWhenReplicatedLogSizeExceedsSnapshotBatchCount() {
344 doReturn(10L).when(mockReplicatedLog).size(); // matches snapshotBatchCount
345 doReturn(100).when(mockReplicatedLog).dataSize();
347 doReturn(5L).when(mockReplicatedLog).getSnapshotIndex();
348 doReturn(5L).when(mockReplicatedLog).getSnapshotTerm();
350 long replicatedToAllIndex = 1;
351 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
352 doReturn(replicatedLogEntry).when(mockReplicatedLog).get(replicatedToAllIndex);
353 doReturn(6L).when(replicatedLogEntry).getTerm();
354 doReturn(replicatedToAllIndex).when(replicatedLogEntry).getIndex();
356 snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
357 new MockRaftActorContext.MockPayload()), replicatedToAllIndex);
359 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, 2000000L);
361 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
363 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
365 verify(mockRaftActorBehavior).setReplicatedToAllIndex(replicatedToAllIndex);
369 public void testPersistSendInstallSnapshot(){
370 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
372 // when replicatedToAllIndex = -1
373 boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
374 new MockRaftActorContext.MockPayload()), -1, "follower-1");
378 byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
380 snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
382 assertEquals(true, snapshotManager.isCapturing());
384 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
386 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
388 ArgumentCaptor<SendInstallSnapshot> sendInstallSnapshotArgumentCaptor
389 = ArgumentCaptor.forClass(SendInstallSnapshot.class);
391 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), sendInstallSnapshotArgumentCaptor.capture());
393 SendInstallSnapshot sendInstallSnapshot = sendInstallSnapshotArgumentCaptor.getValue();
395 assertTrue(Arrays.equals(bytes, sendInstallSnapshot.getSnapshot().getState()));
399 public void testCallingPersistWithoutCaptureWillDoNothing(){
400 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
402 verify(mockDataPersistenceProvider, never()).saveSnapshot(any(Snapshot.class));
404 verify(mockReplicatedLog, never()).snapshotPreCommit(9L, 6L);
406 verify(mockRaftActorBehavior, never()).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
409 public void testCallingPersistTwiceWillDoNoHarm(){
410 doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
412 // when replicatedToAllIndex = -1
413 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
414 new MockRaftActorContext.MockPayload()), -1, "follower-1");
416 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
418 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
420 verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
422 verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
424 verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
428 public void testCommit(){
429 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
431 // when replicatedToAllIndex = -1
432 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
433 new MockRaftActorContext.MockPayload()), -1, "follower-1");
435 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
437 assertEquals(true, snapshotManager.isCapturing());
439 snapshotManager.commit(100L, mockRaftActorBehavior);
441 assertEquals(false, snapshotManager.isCapturing());
443 verify(mockReplicatedLog).snapshotCommit();
445 verify(mockDataPersistenceProvider).deleteMessages(50L);
447 ArgumentCaptor<SnapshotSelectionCriteria> criteriaCaptor = ArgumentCaptor.forClass(SnapshotSelectionCriteria.class);
449 verify(mockDataPersistenceProvider).deleteSnapshots(criteriaCaptor.capture());
451 assertEquals(90, criteriaCaptor.getValue().maxSequenceNr()); // sequenceNumber = 100
452 // config snapShotBatchCount = 10
453 // therefore maxSequenceNumber = 90
455 MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
459 public void testCommitBeforePersist(){
460 // when replicatedToAllIndex = -1
461 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
462 new MockRaftActorContext.MockPayload()), -1, "follower-1");
464 snapshotManager.commit(100L, mockRaftActorBehavior);
466 verify(mockReplicatedLog, never()).snapshotCommit();
468 verify(mockDataPersistenceProvider, never()).deleteMessages(100L);
470 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
475 public void testCommitBeforeCapture(){
476 snapshotManager.commit(100L, mockRaftActorBehavior);
478 verify(mockReplicatedLog, never()).snapshotCommit();
480 verify(mockDataPersistenceProvider, never()).deleteMessages(anyLong());
482 verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
487 public void testCallingCommitMultipleTimesCausesNoHarm(){
488 doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
490 // when replicatedToAllIndex = -1
491 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
492 new MockRaftActorContext.MockPayload()), -1, "follower-1");
494 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
496 snapshotManager.commit(100L, mockRaftActorBehavior);
498 snapshotManager.commit(100L, mockRaftActorBehavior);
500 verify(mockReplicatedLog, times(1)).snapshotCommit();
502 verify(mockDataPersistenceProvider, times(1)).deleteMessages(50L);
504 verify(mockDataPersistenceProvider, times(1)).deleteSnapshots(any(SnapshotSelectionCriteria.class));
508 public void testRollback(){
509 // when replicatedToAllIndex = -1
510 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
511 new MockRaftActorContext.MockPayload()), -1, "follower-1");
513 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
515 snapshotManager.rollback();
517 verify(mockReplicatedLog).snapshotRollback();
519 MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
524 public void testRollbackBeforePersist(){
525 // when replicatedToAllIndex = -1
526 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
527 new MockRaftActorContext.MockPayload()), -1, "follower-1");
529 snapshotManager.rollback();
531 verify(mockReplicatedLog, never()).snapshotRollback();
535 public void testRollbackBeforeCapture(){
536 snapshotManager.rollback();
538 verify(mockReplicatedLog, never()).snapshotRollback();
542 public void testCallingRollbackMultipleTimesCausesNoHarm(){
543 // when replicatedToAllIndex = -1
544 snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
545 new MockRaftActorContext.MockPayload()), -1, "follower-1");
547 snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
549 snapshotManager.rollback();
551 snapshotManager.rollback();
553 verify(mockReplicatedLog, times(1)).snapshotRollback();
557 public void testTrimLogWhenTrimIndexLessThanLastApplied() {
558 doReturn(20L).when(mockRaftActorContext).getLastApplied();
560 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
561 doReturn(true).when(mockReplicatedLog).isPresent(10);
562 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
563 doReturn(5L).when(replicatedLogEntry).getTerm();
565 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
566 assertEquals("return index", 10L, retIndex);
568 verify(mockReplicatedLog).snapshotPreCommit(10, 5);
569 verify(mockReplicatedLog).snapshotCommit();
571 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
575 public void testTrimLogWhenLastAppliedNotSet() {
576 doReturn(-1L).when(mockRaftActorContext).getLastApplied();
578 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
579 doReturn(true).when(mockReplicatedLog).isPresent(10);
580 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
581 doReturn(5L).when(replicatedLogEntry).getTerm();
583 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
584 assertEquals("return index", -1L, retIndex);
586 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
587 verify(mockReplicatedLog, never()).snapshotCommit();
589 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
593 public void testTrimLogWhenLastAppliedZero() {
594 doReturn(0L).when(mockRaftActorContext).getLastApplied();
596 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
597 doReturn(true).when(mockReplicatedLog).isPresent(10);
598 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
599 doReturn(5L).when(replicatedLogEntry).getTerm();
601 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
602 assertEquals("return index", -1L, retIndex);
604 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
605 verify(mockReplicatedLog, never()).snapshotCommit();
607 verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
611 public void testTrimLogWhenTrimIndexNotPresent() {
612 doReturn(20L).when(mockRaftActorContext).getLastApplied();
614 doReturn(false).when(mockReplicatedLog).isPresent(10);
616 long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
617 assertEquals("return index", -1L, retIndex);
619 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
620 verify(mockReplicatedLog, never()).snapshotCommit();
622 // Trim index is greater than replicatedToAllIndex so should update it.
623 verify(mockRaftActorBehavior).setReplicatedToAllIndex(10L);
627 public void testTrimLogAfterCapture(){
628 boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
629 new MockRaftActorContext.MockPayload()), 9);
633 assertEquals(true, snapshotManager.isCapturing());
635 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
636 doReturn(20L).when(mockRaftActorContext).getLastApplied();
637 doReturn(true).when(mockReplicatedLog).isPresent(10);
638 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
639 doReturn(5L).when(replicatedLogEntry).getTerm();
641 snapshotManager.trimLog(10, mockRaftActorBehavior);
643 verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
644 verify(mockReplicatedLog, never()).snapshotCommit();
649 public void testTrimLogAfterCaptureToInstall(){
650 boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
651 new MockRaftActorContext.MockPayload()), 9, "follower-1");
655 assertEquals(true, snapshotManager.isCapturing());
657 ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
658 doReturn(20L).when(mockRaftActorContext).getLastApplied();
659 doReturn(true).when(mockReplicatedLog).isPresent(10);
660 doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
661 doReturn(5L).when(replicatedLogEntry).getTerm();
663 snapshotManager.trimLog(10, mockRaftActorBehavior);
665 verify(mockReplicatedLog, never()).snapshotPreCommit(10, 5);
666 verify(mockReplicatedLog, never()).snapshotCommit();
671 public void testLastAppliedTermInformationReader() {
673 LastAppliedTermInformationReader reader = new LastAppliedTermInformationReader();
675 doReturn(4L).when(mockReplicatedLog).getSnapshotTerm();
676 doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
678 ReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(6L, 9L,
679 new MockRaftActorContext.MockPayload());
681 // No followers and valid lastLogEntry
682 reader.init(mockReplicatedLog, 1L, lastLogEntry, false);
684 assertEquals("getTerm", 6L, reader.getTerm());
685 assertEquals("getIndex", 9L, reader.getIndex());
687 // No followers and null lastLogEntry
688 reader.init(mockReplicatedLog, 1L, null, false);
690 assertEquals("getTerm", -1L, reader.getTerm());
691 assertEquals("getIndex", -1L, reader.getIndex());
693 // Followers and valid originalIndex entry
694 doReturn(new MockRaftActorContext.MockReplicatedLogEntry(5L, 8L,
695 new MockRaftActorContext.MockPayload())).when(mockReplicatedLog).get(8L);
696 reader.init(mockReplicatedLog, 8L, lastLogEntry, true);
698 assertEquals("getTerm", 5L, reader.getTerm());
699 assertEquals("getIndex", 8L, reader.getIndex());
701 // Followers and null originalIndex entry and valid snapshot index
702 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
704 assertEquals("getTerm", 4L, reader.getTerm());
705 assertEquals("getIndex", 7L, reader.getIndex());
707 // Followers and null originalIndex entry and invalid snapshot index
708 doReturn(-1L).when(mockReplicatedLog).getSnapshotIndex();
709 reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
711 assertEquals("getTerm", -1L, reader.getTerm());
712 assertEquals("getIndex", -1L, reader.getIndex());