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