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