Add getPeerIds to RaftActorContext
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / SnapshotManagerTest.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.cluster.raft;
10
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;
24 import akka.actor.ActorRef;
25 import akka.japi.Procedure;
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.behaviors.RaftActorBehavior;
40 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
41 import org.slf4j.LoggerFactory;
42
43 public class SnapshotManagerTest extends AbstractActorTest {
44
45     @Mock
46     private RaftActorContext mockRaftActorContext;
47
48     @Mock
49     private ConfigParams mockConfigParams;
50
51     @Mock
52     private ReplicatedLog mockReplicatedLog;
53
54     @Mock
55     private DataPersistenceProvider mockDataPersistenceProvider;
56
57     @Mock
58     private RaftActorBehavior mockRaftActorBehavior;
59
60     @Mock
61     private Procedure<Void> mockProcedure;
62
63     @Mock
64     private ElectionTerm mockElectionTerm;
65
66     private SnapshotManager snapshotManager;
67
68     private TestActorFactory factory;
69
70     private TestActorRef<MessageCollectorActor> actorRef;
71
72     @Before
73     public void setUp(){
74         MockitoAnnotations.initMocks(this);
75
76         doReturn(false).when(mockRaftActorContext).hasFollowers();
77         doReturn(mockConfigParams).when(mockRaftActorContext).getConfigParams();
78         doReturn(10L).when(mockConfigParams).getSnapshotBatchCount();
79         doReturn(70).when(mockConfigParams).getSnapshotDataThresholdPercentage();
80         doReturn(mockReplicatedLog).when(mockRaftActorContext).getReplicatedLog();
81         doReturn("123").when(mockRaftActorContext).getId();
82         doReturn(mockDataPersistenceProvider).when(mockRaftActorContext).getPersistenceProvider();
83         doReturn("123").when(mockRaftActorBehavior).getLeaderId();
84
85         doReturn(mockElectionTerm).when(mockRaftActorContext).getTermInformation();
86         doReturn(5L).when(mockElectionTerm).getCurrentTerm();
87         doReturn("member5").when(mockElectionTerm).getVotedFor();
88
89         snapshotManager = new SnapshotManager(mockRaftActorContext, LoggerFactory.getLogger(this.getClass()));
90         factory = new TestActorFactory(getSystem());
91
92         actorRef = factory.createTestActor(MessageCollectorActor.props(), factory.generateActorId("test-"));
93         doReturn(actorRef).when(mockRaftActorContext).getActor();
94
95         snapshotManager.setCreateSnapshotCallable(mockProcedure);
96     }
97
98     @After
99     public void tearDown(){
100         factory.close();
101     }
102
103     @Test
104     public void testConstruction(){
105         assertEquals(false, snapshotManager.isCapturing());
106     }
107
108     @Test
109     public void testCaptureToInstall() throws Exception {
110
111         // Force capturing toInstall = true
112         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1, 0,
113                 new MockRaftActorContext.MockPayload()), 0, "follower-1");
114
115         assertEquals(true, snapshotManager.isCapturing());
116
117         verify(mockProcedure).apply(null);
118
119         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
120
121         // LastIndex and LastTerm are picked up from the lastLogEntry
122         assertEquals(0L, captureSnapshot.getLastIndex());
123         assertEquals(1L, captureSnapshot.getLastTerm());
124
125         // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
126         assertEquals(0L, captureSnapshot.getLastAppliedIndex());
127         assertEquals(1L, captureSnapshot.getLastAppliedTerm());
128
129         //
130         assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
131         assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
132         actorRef.underlyingActor().clear();
133     }
134
135     @Test
136     public void testCapture() throws Exception {
137         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
138                 new MockRaftActorContext.MockPayload()), 9);
139
140         assertTrue(capture);
141
142         assertEquals(true, snapshotManager.isCapturing());
143
144         verify(mockProcedure).apply(null);
145
146         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
147
148         // LastIndex and LastTerm are picked up from the lastLogEntry
149         assertEquals(9L, captureSnapshot.getLastIndex());
150         assertEquals(1L, captureSnapshot.getLastTerm());
151
152         // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
153         assertEquals(9L, captureSnapshot.getLastAppliedIndex());
154         assertEquals(1L, captureSnapshot.getLastAppliedTerm());
155
156         //
157         assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
158         assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
159
160         actorRef.underlyingActor().clear();
161
162     }
163
164     @Test
165     public void testCaptureWithNullLastLogEntry() throws Exception {
166         boolean capture = snapshotManager.capture(null, 1);
167
168         assertTrue(capture);
169
170         assertEquals(true, snapshotManager.isCapturing());
171
172         verify(mockProcedure).apply(null);
173
174         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
175
176         System.out.println(captureSnapshot);
177
178         // LastIndex and LastTerm are picked up from the lastLogEntry
179         assertEquals(-1L, captureSnapshot.getLastIndex());
180         assertEquals(-1L, captureSnapshot.getLastTerm());
181
182         // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
183         assertEquals(-1L, captureSnapshot.getLastAppliedIndex());
184         assertEquals(-1L, captureSnapshot.getLastAppliedTerm());
185
186         //
187         assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
188         assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
189         actorRef.underlyingActor().clear();
190
191     }
192
193     @Test
194     public void testCaptureWithCreateProcedureError () throws Exception {
195         doThrow(new Exception("mock")).when(mockProcedure).apply(null);
196
197         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
198                 new MockRaftActorContext.MockPayload()), 9);
199
200         assertFalse(capture);
201
202         assertEquals(false, snapshotManager.isCapturing());
203
204         verify(mockProcedure).apply(null);
205     }
206
207     @Test
208     public void testIllegalCapture() throws Exception {
209         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
210                 new MockRaftActorContext.MockPayload()), 9);
211
212         assertTrue(capture);
213
214         verify(mockProcedure).apply(null);
215
216         reset(mockProcedure);
217
218         // This will not cause snapshot capture to start again
219         capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
220                 new MockRaftActorContext.MockPayload()), 9);
221
222         assertFalse(capture);
223
224         verify(mockProcedure, never()).apply(null);
225     }
226
227     @Test
228     public void testPersistWhenReplicatedToAllIndexMinusOne(){
229         doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
230         doReturn(1L).when(mockReplicatedLog).getSnapshotTerm();
231
232         doReturn(true).when(mockRaftActorContext).hasFollowers();
233
234         doReturn(8L).when(mockRaftActorContext).getLastApplied();
235
236         MockRaftActorContext.MockReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(
237                 3L, 9L, new MockRaftActorContext.MockPayload());
238
239         MockRaftActorContext.MockReplicatedLogEntry lastAppliedEntry = new MockRaftActorContext.MockReplicatedLogEntry(
240                 2L, 8L, new MockRaftActorContext.MockPayload());
241
242         doReturn(lastAppliedEntry).when(mockReplicatedLog).get(8L);
243         doReturn(Arrays.asList(lastLogEntry)).when(mockReplicatedLog).getFrom(9L);
244
245         // when replicatedToAllIndex = -1
246         snapshotManager.capture(lastLogEntry, -1);
247
248         byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
249         snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
250
251         ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
252         verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
253
254         Snapshot snapshot = snapshotArgumentCaptor.getValue();
255
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());
264
265         verify(mockReplicatedLog).snapshotPreCommit(7L, 1L);
266     }
267
268     @Test
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();
276
277         // when replicatedToAllIndex != -1
278         snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
279                 new MockRaftActorContext.MockPayload()), 9);
280
281         byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
282         snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
283
284         ArgumentCaptor<Snapshot> snapshotArgumentCaptor = ArgumentCaptor.forClass(Snapshot.class);
285         verify(mockDataPersistenceProvider).saveSnapshot(snapshotArgumentCaptor.capture());
286
287         Snapshot snapshot = snapshotArgumentCaptor.getValue();
288
289         assertEquals("getLastTerm", 6L, snapshot.getLastTerm());
290         assertEquals("getLastIndex", 9L, snapshot.getLastIndex());
291         assertEquals("getLastAppliedTerm", 6L, snapshot.getLastAppliedTerm());
292         assertEquals("getLastAppliedIndex", 9L, snapshot.getLastAppliedIndex());
293         assertArrayEquals("getState", bytes, snapshot.getState());
294         assertEquals("getUnAppliedEntries size", 0, snapshot.getUnAppliedEntries().size());
295
296         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
297
298         verify(mockRaftActorBehavior).setReplicatedToAllIndex(9);
299     }
300
301     @Test
302     public void testPersistWhenReplicatedLogDataSizeGreaterThanThreshold(){
303         doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
304
305         // when replicatedToAllIndex = -1
306         snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6,9,
307                 new MockRaftActorContext.MockPayload()), -1);
308
309         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
310
311         verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
312
313         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
314
315         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
316     }
317
318     @Test
319     public void testPersistWhenReplicatedLogSizeExceedsSnapshotBatchCount() {
320         doReturn(10L).when(mockReplicatedLog).size(); // matches snapshotBatchCount
321         doReturn(100).when(mockReplicatedLog).dataSize();
322
323         doReturn(5L).when(mockReplicatedLog).getSnapshotIndex();
324         doReturn(5L).when(mockReplicatedLog).getSnapshotTerm();
325
326         long replicatedToAllIndex = 1;
327         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
328         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(replicatedToAllIndex);
329         doReturn(6L).when(replicatedLogEntry).getTerm();
330         doReturn(replicatedToAllIndex).when(replicatedLogEntry).getIndex();
331
332         snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
333                 new MockRaftActorContext.MockPayload()), replicatedToAllIndex);
334
335         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, 2000000L);
336
337         verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
338
339         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
340
341         verify(mockRaftActorBehavior).setReplicatedToAllIndex(replicatedToAllIndex);
342     }
343
344     @Test
345     public void testPersistSendInstallSnapshot(){
346         doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
347
348         // when replicatedToAllIndex = -1
349         boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
350                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
351
352         assertTrue(capture);
353
354         byte[] bytes = new byte[] {1,2,3,4,5,6,7,8,9,10};
355
356         snapshotManager.persist(bytes, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
357
358         assertEquals(true, snapshotManager.isCapturing());
359
360         verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
361
362         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
363
364         ArgumentCaptor<SendInstallSnapshot> sendInstallSnapshotArgumentCaptor
365                 = ArgumentCaptor.forClass(SendInstallSnapshot.class);
366
367         verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), sendInstallSnapshotArgumentCaptor.capture());
368
369         SendInstallSnapshot sendInstallSnapshot = sendInstallSnapshotArgumentCaptor.getValue();
370
371         assertTrue(Arrays.equals(bytes, sendInstallSnapshot.getSnapshot().getState()));
372     }
373
374     @Test
375     public void testCallingPersistWithoutCaptureWillDoNothing(){
376         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
377
378         verify(mockDataPersistenceProvider, never()).saveSnapshot(any(Snapshot.class));
379
380         verify(mockReplicatedLog, never()).snapshotPreCommit(9L, 6L);
381
382         verify(mockRaftActorBehavior, never()).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
383     }
384     @Test
385     public void testCallingPersistTwiceWillDoNoHarm(){
386         doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
387
388         // when replicatedToAllIndex = -1
389         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
390                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
391
392         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
393
394         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
395
396         verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
397
398         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
399
400         verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
401     }
402
403     @Test
404     public void testCommit(){
405         doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
406
407         // when replicatedToAllIndex = -1
408         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
409                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
410
411         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
412
413         assertEquals(true, snapshotManager.isCapturing());
414
415         snapshotManager.commit(100L, mockRaftActorBehavior);
416
417         assertEquals(false, snapshotManager.isCapturing());
418
419         verify(mockReplicatedLog).snapshotCommit();
420
421         verify(mockDataPersistenceProvider).deleteMessages(50L);
422
423         ArgumentCaptor<SnapshotSelectionCriteria> criteriaCaptor = ArgumentCaptor.forClass(SnapshotSelectionCriteria.class);
424
425         verify(mockDataPersistenceProvider).deleteSnapshots(criteriaCaptor.capture());
426
427         assertEquals(90, criteriaCaptor.getValue().maxSequenceNr()); // sequenceNumber = 100
428                                                                      // config snapShotBatchCount = 10
429                                                                      // therefore maxSequenceNumber = 90
430     }
431
432     @Test
433     public void testCommitBeforePersist(){
434         // when replicatedToAllIndex = -1
435         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
436                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
437
438         snapshotManager.commit(100L, mockRaftActorBehavior);
439
440         verify(mockReplicatedLog, never()).snapshotCommit();
441
442         verify(mockDataPersistenceProvider, never()).deleteMessages(100L);
443
444         verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
445
446     }
447
448     @Test
449     public void testCommitBeforeCapture(){
450         snapshotManager.commit(100L, mockRaftActorBehavior);
451
452         verify(mockReplicatedLog, never()).snapshotCommit();
453
454         verify(mockDataPersistenceProvider, never()).deleteMessages(anyLong());
455
456         verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
457
458     }
459
460     @Test
461     public void testCallingCommitMultipleTimesCausesNoHarm(){
462         doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
463
464         // when replicatedToAllIndex = -1
465         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
466                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
467
468         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
469
470         snapshotManager.commit(100L, mockRaftActorBehavior);
471
472         snapshotManager.commit(100L, mockRaftActorBehavior);
473
474         verify(mockReplicatedLog, times(1)).snapshotCommit();
475
476         verify(mockDataPersistenceProvider, times(1)).deleteMessages(50L);
477
478         verify(mockDataPersistenceProvider, times(1)).deleteSnapshots(any(SnapshotSelectionCriteria.class));
479     }
480
481     @Test
482     public void testRollback(){
483         // when replicatedToAllIndex = -1
484         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
485                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
486
487         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
488
489         snapshotManager.rollback();
490
491         verify(mockReplicatedLog).snapshotRollback();
492     }
493
494
495     @Test
496     public void testRollbackBeforePersist(){
497         // when replicatedToAllIndex = -1
498         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
499                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
500
501         snapshotManager.rollback();
502
503         verify(mockReplicatedLog, never()).snapshotRollback();
504     }
505
506     @Test
507     public void testRollbackBeforeCapture(){
508         snapshotManager.rollback();
509
510         verify(mockReplicatedLog, never()).snapshotRollback();
511     }
512
513     @Test
514     public void testCallingRollbackMultipleTimesCausesNoHarm(){
515         // when replicatedToAllIndex = -1
516         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
517                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
518
519         snapshotManager.persist(new byte[]{}, mockRaftActorBehavior, Runtime.getRuntime().totalMemory());
520
521         snapshotManager.rollback();
522
523         snapshotManager.rollback();
524
525         verify(mockReplicatedLog, times(1)).snapshotRollback();
526     }
527
528     @Test
529     public void testTrimLogWhenTrimIndexLessThanLastApplied() {
530         doReturn(20L).when(mockRaftActorContext).getLastApplied();
531
532         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
533         doReturn(true).when(mockReplicatedLog).isPresent(10);
534         doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
535         doReturn(5L).when(replicatedLogEntry).getTerm();
536
537         long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
538         assertEquals("return index", 10L, retIndex);
539
540         verify(mockReplicatedLog).snapshotPreCommit(10, 5);
541         verify(mockReplicatedLog).snapshotCommit();
542
543         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
544     }
545
546     @Test
547     public void testTrimLogWhenLastAppliedNotSet() {
548         doReturn(-1L).when(mockRaftActorContext).getLastApplied();
549
550         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
551         doReturn(true).when(mockReplicatedLog).isPresent(10);
552         doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
553         doReturn(5L).when(replicatedLogEntry).getTerm();
554
555         long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
556         assertEquals("return index", -1L, retIndex);
557
558         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
559         verify(mockReplicatedLog, never()).snapshotCommit();
560
561         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
562     }
563
564     @Test
565     public void testTrimLogWhenLastAppliedZero() {
566         doReturn(0L).when(mockRaftActorContext).getLastApplied();
567
568         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
569         doReturn(true).when(mockReplicatedLog).isPresent(10);
570         doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
571         doReturn(5L).when(replicatedLogEntry).getTerm();
572
573         long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
574         assertEquals("return index", -1L, retIndex);
575
576         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
577         verify(mockReplicatedLog, never()).snapshotCommit();
578
579         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
580     }
581
582     @Test
583     public void testTrimLogWhenTrimIndexNotPresent() {
584         doReturn(20L).when(mockRaftActorContext).getLastApplied();
585
586         doReturn(false).when(mockReplicatedLog).isPresent(10);
587
588         long retIndex = snapshotManager.trimLog(10, mockRaftActorBehavior);
589         assertEquals("return index", -1L, retIndex);
590
591         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
592         verify(mockReplicatedLog, never()).snapshotCommit();
593
594         // Trim index is greater than replicatedToAllIndex so should update it.
595         verify(mockRaftActorBehavior).setReplicatedToAllIndex(10L);
596     }
597
598     @Test
599     public void testTrimLogAfterCapture(){
600         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
601                 new MockRaftActorContext.MockPayload()), 9);
602
603         assertTrue(capture);
604
605         assertEquals(true, snapshotManager.isCapturing());
606
607         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
608         doReturn(20L).when(mockRaftActorContext).getLastApplied();
609         doReturn(true).when(mockReplicatedLog).isPresent(10);
610         doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
611         doReturn(5L).when(replicatedLogEntry).getTerm();
612
613         snapshotManager.trimLog(10, mockRaftActorBehavior);
614
615         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
616         verify(mockReplicatedLog, never()).snapshotCommit();
617
618     }
619
620     @Test
621     public void testTrimLogAfterCaptureToInstall(){
622         boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
623                 new MockRaftActorContext.MockPayload()), 9, "follower-1");
624
625         assertTrue(capture);
626
627         assertEquals(true, snapshotManager.isCapturing());
628
629         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
630         doReturn(20L).when(mockRaftActorContext).getLastApplied();
631         doReturn(true).when(mockReplicatedLog).isPresent(10);
632         doReturn(replicatedLogEntry).when((mockReplicatedLog)).get(10);
633         doReturn(5L).when(replicatedLogEntry).getTerm();
634
635         snapshotManager.trimLog(10, mockRaftActorBehavior);
636
637         verify(mockReplicatedLog, never()).snapshotPreCommit(10, 5);
638         verify(mockReplicatedLog, never()).snapshotCommit();
639
640     }
641
642     @Test
643     public void testLastAppliedTermInformationReader() {
644
645         LastAppliedTermInformationReader reader = new LastAppliedTermInformationReader();
646
647         doReturn(4L).when(mockReplicatedLog).getSnapshotTerm();
648         doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
649
650         ReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(6L, 9L,
651                 new MockRaftActorContext.MockPayload());
652
653         // No followers and valid lastLogEntry
654         reader.init(mockReplicatedLog, 1L, lastLogEntry, false);
655
656         assertEquals("getTerm", 6L, reader.getTerm());
657         assertEquals("getIndex", 9L, reader.getIndex());
658
659         // No followers and null lastLogEntry
660         reader.init(mockReplicatedLog, 1L, null, false);
661
662         assertEquals("getTerm", -1L, reader.getTerm());
663         assertEquals("getIndex", -1L, reader.getIndex());
664
665         // Followers and valid originalIndex entry
666         doReturn(new MockRaftActorContext.MockReplicatedLogEntry(5L, 8L,
667                 new MockRaftActorContext.MockPayload())).when(mockReplicatedLog).get(8L);
668         reader.init(mockReplicatedLog, 8L, lastLogEntry, true);
669
670         assertEquals("getTerm", 5L, reader.getTerm());
671         assertEquals("getIndex", 8L, reader.getIndex());
672
673         // Followers and null originalIndex entry and valid snapshot index
674         reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
675
676         assertEquals("getTerm", 4L, reader.getTerm());
677         assertEquals("getIndex", 7L, reader.getIndex());
678
679         // Followers and null originalIndex entry and invalid snapshot index
680         doReturn(-1L).when(mockReplicatedLog).getSnapshotIndex();
681         reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
682
683         assertEquals("getTerm", -1L, reader.getTerm());
684         assertEquals("getIndex", -1L, reader.getIndex());
685     }
686 }