Fix warnings in sal-akka-raft test classes
[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
25 import akka.actor.ActorRef;
26 import akka.persistence.SnapshotSelectionCriteria;
27 import akka.testkit.TestActorRef;
28 import java.util.Arrays;
29 import org.junit.After;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.Mock;
34 import org.mockito.MockitoAnnotations;
35 import org.opendaylight.controller.cluster.DataPersistenceProvider;
36 import org.opendaylight.controller.cluster.raft.SnapshotManager.LastAppliedTermInformationReader;
37 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
38 import org.opendaylight.controller.cluster.raft.base.messages.SendInstallSnapshot;
39 import org.opendaylight.controller.cluster.raft.base.messages.SnapshotComplete;
40 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
41 import org.opendaylight.controller.cluster.raft.utils.MessageCollectorActor;
42 import org.slf4j.LoggerFactory;
43
44 public class SnapshotManagerTest extends AbstractActorTest {
45
46     @Mock
47     private RaftActorContext mockRaftActorContext;
48
49     @Mock
50     private ConfigParams mockConfigParams;
51
52     @Mock
53     private ReplicatedLog mockReplicatedLog;
54
55     @Mock
56     private DataPersistenceProvider mockDataPersistenceProvider;
57
58     @Mock
59     private RaftActorBehavior mockRaftActorBehavior;
60
61     @Mock
62     private Runnable mockProcedure;
63
64     @Mock
65     private ElectionTerm mockElectionTerm;
66
67     private SnapshotManager snapshotManager;
68
69     private TestActorFactory factory;
70
71     private TestActorRef<MessageCollectorActor> actorRef;
72
73     @Before
74     public void setUp() {
75         MockitoAnnotations.initMocks(this);
76
77         doReturn(false).when(mockRaftActorContext).hasFollowers();
78         doReturn(mockConfigParams).when(mockRaftActorContext).getConfigParams();
79         doReturn(10L).when(mockConfigParams).getSnapshotBatchCount();
80         doReturn(70).when(mockConfigParams).getSnapshotDataThresholdPercentage();
81         doReturn(mockReplicatedLog).when(mockRaftActorContext).getReplicatedLog();
82         doReturn("123").when(mockRaftActorContext).getId();
83         doReturn(mockDataPersistenceProvider).when(mockRaftActorContext).getPersistenceProvider();
84         doReturn(mockRaftActorBehavior).when(mockRaftActorContext).getCurrentBehavior();
85         doReturn("123").when(mockRaftActorBehavior).getLeaderId();
86
87         doReturn(mockElectionTerm).when(mockRaftActorContext).getTermInformation();
88         doReturn(5L).when(mockElectionTerm).getCurrentTerm();
89         doReturn("member5").when(mockElectionTerm).getVotedFor();
90
91         snapshotManager = new SnapshotManager(mockRaftActorContext, LoggerFactory.getLogger(this.getClass()));
92         factory = new TestActorFactory(getSystem());
93
94         actorRef = factory.createTestActor(MessageCollectorActor.props(), factory.generateActorId("test-"));
95         doReturn(actorRef).when(mockRaftActorContext).getActor();
96
97         snapshotManager.setCreateSnapshotRunnable(mockProcedure);
98     }
99
100     @After
101     public void tearDown() {
102         factory.close();
103     }
104
105     @Test
106     public void testConstruction() {
107         assertEquals(false, snapshotManager.isCapturing());
108     }
109
110     @Test
111     public void testCaptureToInstall() throws Exception {
112
113         // Force capturing toInstall = true
114         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1, 0,
115                 new MockRaftActorContext.MockPayload()), 0, "follower-1");
116
117         assertEquals(true, snapshotManager.isCapturing());
118
119         verify(mockProcedure).run();
120
121         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
122
123         // LastIndex and LastTerm are picked up from the lastLogEntry
124         assertEquals(0L, captureSnapshot.getLastIndex());
125         assertEquals(1L, captureSnapshot.getLastTerm());
126
127         // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
128         assertEquals(0L, captureSnapshot.getLastAppliedIndex());
129         assertEquals(1L, captureSnapshot.getLastAppliedTerm());
130
131         //
132         assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
133         assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
134         actorRef.underlyingActor().clear();
135     }
136
137     @Test
138     public void testCapture() throws Exception {
139         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
140                 new MockRaftActorContext.MockPayload()), 9);
141
142         assertTrue(capture);
143
144         assertEquals(true, snapshotManager.isCapturing());
145
146         verify(mockProcedure).run();
147
148         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
149
150         // LastIndex and LastTerm are picked up from the lastLogEntry
151         assertEquals(9L, captureSnapshot.getLastIndex());
152         assertEquals(1L, captureSnapshot.getLastTerm());
153
154         // Since the actor does not have any followers (no peer addresses) lastApplied will be from lastLogEntry
155         assertEquals(9L, captureSnapshot.getLastAppliedIndex());
156         assertEquals(1L, captureSnapshot.getLastAppliedTerm());
157
158         //
159         assertEquals(-1L, captureSnapshot.getReplicatedToAllIndex());
160         assertEquals(-1L, captureSnapshot.getReplicatedToAllTerm());
161
162         actorRef.underlyingActor().clear();
163
164     }
165
166     @Test
167     public void testCaptureWithNullLastLogEntry() throws Exception {
168         boolean capture = snapshotManager.capture(null, 1);
169
170         assertTrue(capture);
171
172         assertEquals(true, snapshotManager.isCapturing());
173
174         verify(mockProcedure).run();
175
176         CaptureSnapshot captureSnapshot = snapshotManager.getCaptureSnapshot();
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 RuntimeException("mock")).when(mockProcedure).run();
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).run();
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).run();
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()).run();
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, 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, 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[]{}, 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[]{}, 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, 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[]{}, 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
385     @Test
386     public void testCallingPersistTwiceWillDoNoHarm() {
387         doReturn(Integer.MAX_VALUE).when(mockReplicatedLog).dataSize();
388
389         // when replicatedToAllIndex = -1
390         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
391                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
392
393         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
394
395         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
396
397         verify(mockDataPersistenceProvider).saveSnapshot(any(Snapshot.class));
398
399         verify(mockReplicatedLog).snapshotPreCommit(9L, 6L);
400
401         verify(mockRaftActorBehavior).handleMessage(any(ActorRef.class), any(SendInstallSnapshot.class));
402     }
403
404     @Test
405     public void testCommit() {
406         doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
407
408         // when replicatedToAllIndex = -1
409         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
410                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
411
412         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
413
414         assertEquals(true, snapshotManager.isCapturing());
415
416         snapshotManager.commit(100L, 1234L);
417
418         assertEquals(false, snapshotManager.isCapturing());
419
420         verify(mockReplicatedLog).snapshotCommit();
421
422         verify(mockDataPersistenceProvider).deleteMessages(50L);
423
424         ArgumentCaptor<SnapshotSelectionCriteria> criteriaCaptor =
425                 ArgumentCaptor.forClass(SnapshotSelectionCriteria.class);
426
427         verify(mockDataPersistenceProvider).deleteSnapshots(criteriaCaptor.capture());
428
429         assertEquals(100L, criteriaCaptor.getValue().maxSequenceNr());
430         assertEquals(1233L, criteriaCaptor.getValue().maxTimestamp());
431
432         MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
433     }
434
435     @Test
436     public void testCommitBeforePersist() {
437         // when replicatedToAllIndex = -1
438         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
439                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
440
441         snapshotManager.commit(100L, 0);
442
443         verify(mockReplicatedLog, never()).snapshotCommit();
444
445         verify(mockDataPersistenceProvider, never()).deleteMessages(100L);
446
447         verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
448
449     }
450
451     @Test
452     public void testCommitBeforeCapture() {
453         snapshotManager.commit(100L, 0);
454
455         verify(mockReplicatedLog, never()).snapshotCommit();
456
457         verify(mockDataPersistenceProvider, never()).deleteMessages(anyLong());
458
459         verify(mockDataPersistenceProvider, never()).deleteSnapshots(any(SnapshotSelectionCriteria.class));
460
461     }
462
463     @Test
464     public void testCallingCommitMultipleTimesCausesNoHarm() {
465         doReturn(50L).when(mockDataPersistenceProvider).getLastSequenceNumber();
466
467         // when replicatedToAllIndex = -1
468         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
469                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
470
471         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
472
473         snapshotManager.commit(100L, 0);
474
475         snapshotManager.commit(100L, 0);
476
477         verify(mockReplicatedLog, times(1)).snapshotCommit();
478
479         verify(mockDataPersistenceProvider, times(1)).deleteMessages(50L);
480
481         verify(mockDataPersistenceProvider, times(1)).deleteSnapshots(any(SnapshotSelectionCriteria.class));
482     }
483
484     @Test
485     public void testRollback() {
486         // when replicatedToAllIndex = -1
487         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
488                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
489
490         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
491
492         snapshotManager.rollback();
493
494         verify(mockReplicatedLog).snapshotRollback();
495
496         MessageCollectorActor.expectFirstMatching(actorRef, SnapshotComplete.class);
497     }
498
499
500     @Test
501     public void testRollbackBeforePersist() {
502         // when replicatedToAllIndex = -1
503         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
504                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
505
506         snapshotManager.rollback();
507
508         verify(mockReplicatedLog, never()).snapshotRollback();
509     }
510
511     @Test
512     public void testRollbackBeforeCapture() {
513         snapshotManager.rollback();
514
515         verify(mockReplicatedLog, never()).snapshotRollback();
516     }
517
518     @Test
519     public void testCallingRollbackMultipleTimesCausesNoHarm() {
520         // when replicatedToAllIndex = -1
521         snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(6, 9,
522                 new MockRaftActorContext.MockPayload()), -1, "follower-1");
523
524         snapshotManager.persist(new byte[]{}, Runtime.getRuntime().totalMemory());
525
526         snapshotManager.rollback();
527
528         snapshotManager.rollback();
529
530         verify(mockReplicatedLog, times(1)).snapshotRollback();
531     }
532
533     @Test
534     public void testTrimLogWhenTrimIndexLessThanLastApplied() {
535         doReturn(20L).when(mockRaftActorContext).getLastApplied();
536
537         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
538         doReturn(true).when(mockReplicatedLog).isPresent(10);
539         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
540         doReturn(5L).when(replicatedLogEntry).getTerm();
541
542         long retIndex = snapshotManager.trimLog(10);
543         assertEquals("return index", 10L, retIndex);
544
545         verify(mockReplicatedLog).snapshotPreCommit(10, 5);
546         verify(mockReplicatedLog).snapshotCommit();
547
548         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
549     }
550
551     @Test
552     public void testTrimLogWhenLastAppliedNotSet() {
553         doReturn(-1L).when(mockRaftActorContext).getLastApplied();
554
555         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
556         doReturn(true).when(mockReplicatedLog).isPresent(10);
557         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
558         doReturn(5L).when(replicatedLogEntry).getTerm();
559
560         long retIndex = snapshotManager.trimLog(10);
561         assertEquals("return index", -1L, retIndex);
562
563         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
564         verify(mockReplicatedLog, never()).snapshotCommit();
565
566         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
567     }
568
569     @Test
570     public void testTrimLogWhenLastAppliedZero() {
571         doReturn(0L).when(mockRaftActorContext).getLastApplied();
572
573         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
574         doReturn(true).when(mockReplicatedLog).isPresent(10);
575         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
576         doReturn(5L).when(replicatedLogEntry).getTerm();
577
578         long retIndex = snapshotManager.trimLog(10);
579         assertEquals("return index", -1L, retIndex);
580
581         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
582         verify(mockReplicatedLog, never()).snapshotCommit();
583
584         verify(mockRaftActorBehavior, never()).setReplicatedToAllIndex(anyLong());
585     }
586
587     @Test
588     public void testTrimLogWhenTrimIndexNotPresent() {
589         doReturn(20L).when(mockRaftActorContext).getLastApplied();
590
591         doReturn(false).when(mockReplicatedLog).isPresent(10);
592
593         long retIndex = snapshotManager.trimLog(10);
594         assertEquals("return index", -1L, retIndex);
595
596         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
597         verify(mockReplicatedLog, never()).snapshotCommit();
598
599         // Trim index is greater than replicatedToAllIndex so should update it.
600         verify(mockRaftActorBehavior).setReplicatedToAllIndex(10L);
601     }
602
603     @Test
604     public void testTrimLogAfterCapture() {
605         boolean capture = snapshotManager.capture(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
606                 new MockRaftActorContext.MockPayload()), 9);
607
608         assertTrue(capture);
609
610         assertEquals(true, snapshotManager.isCapturing());
611
612         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
613         doReturn(20L).when(mockRaftActorContext).getLastApplied();
614         doReturn(true).when(mockReplicatedLog).isPresent(10);
615         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
616         doReturn(5L).when(replicatedLogEntry).getTerm();
617
618         snapshotManager.trimLog(10);
619
620         verify(mockReplicatedLog, never()).snapshotPreCommit(anyLong(), anyLong());
621         verify(mockReplicatedLog, never()).snapshotCommit();
622
623     }
624
625     @Test
626     public void testTrimLogAfterCaptureToInstall() {
627         boolean capture = snapshotManager.captureToInstall(new MockRaftActorContext.MockReplicatedLogEntry(1,9,
628                 new MockRaftActorContext.MockPayload()), 9, "follower-1");
629
630         assertTrue(capture);
631
632         assertEquals(true, snapshotManager.isCapturing());
633
634         ReplicatedLogEntry replicatedLogEntry = mock(ReplicatedLogEntry.class);
635         doReturn(20L).when(mockRaftActorContext).getLastApplied();
636         doReturn(true).when(mockReplicatedLog).isPresent(10);
637         doReturn(replicatedLogEntry).when(mockReplicatedLog).get(10);
638         doReturn(5L).when(replicatedLogEntry).getTerm();
639
640         snapshotManager.trimLog(10);
641
642         verify(mockReplicatedLog, never()).snapshotPreCommit(10, 5);
643         verify(mockReplicatedLog, never()).snapshotCommit();
644
645     }
646
647     @Test
648     public void testLastAppliedTermInformationReader() {
649
650         LastAppliedTermInformationReader reader = new LastAppliedTermInformationReader();
651
652         doReturn(4L).when(mockReplicatedLog).getSnapshotTerm();
653         doReturn(7L).when(mockReplicatedLog).getSnapshotIndex();
654
655         ReplicatedLogEntry lastLogEntry = new MockRaftActorContext.MockReplicatedLogEntry(6L, 9L,
656                 new MockRaftActorContext.MockPayload());
657
658         // No followers and valid lastLogEntry
659         reader.init(mockReplicatedLog, 1L, lastLogEntry, false);
660
661         assertEquals("getTerm", 6L, reader.getTerm());
662         assertEquals("getIndex", 9L, reader.getIndex());
663
664         // No followers and null lastLogEntry
665         reader.init(mockReplicatedLog, 1L, null, false);
666
667         assertEquals("getTerm", -1L, reader.getTerm());
668         assertEquals("getIndex", -1L, reader.getIndex());
669
670         // Followers and valid originalIndex entry
671         doReturn(new MockRaftActorContext.MockReplicatedLogEntry(5L, 8L,
672                 new MockRaftActorContext.MockPayload())).when(mockReplicatedLog).get(8L);
673         reader.init(mockReplicatedLog, 8L, lastLogEntry, true);
674
675         assertEquals("getTerm", 5L, reader.getTerm());
676         assertEquals("getIndex", 8L, reader.getIndex());
677
678         // Followers and null originalIndex entry and valid snapshot index
679         reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
680
681         assertEquals("getTerm", 4L, reader.getTerm());
682         assertEquals("getIndex", 7L, reader.getIndex());
683
684         // Followers and null originalIndex entry and invalid snapshot index
685         doReturn(-1L).when(mockReplicatedLog).getSnapshotIndex();
686         reader.init(mockReplicatedLog, 7L, lastLogEntry, true);
687
688         assertEquals("getTerm", -1L, reader.getTerm());
689         assertEquals("getIndex", -1L, reader.getIndex());
690     }
691 }