Do not reset datasize after a fake snapshot
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / ReplicatedLogImplTest.java
index 20e362d9b02f79ef3ce00cd7532155c7b8cf646c..35ecd77d390aa41d477aacdad438bb7a62fcee9e 100644 (file)
@@ -8,31 +8,30 @@
 package org.opendaylight.controller.cluster.raft;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.same;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.same;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+
 import akka.japi.Procedure;
-import com.google.common.base.Supplier;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.Collections;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
+import java.util.function.Consumer;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
-import org.mockito.Matchers;
+import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.internal.matchers.Same;
 import org.opendaylight.controller.cluster.DataPersistenceProvider;
 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
-import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
-import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries;
 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
+import org.opendaylight.controller.cluster.raft.persisted.DeleteEntries;
+import org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -50,9 +49,6 @@ public class ReplicatedLogImplTest {
     @Mock
     private RaftActorBehavior mockBehavior;
 
-    @Mock
-    private SnapshotManager mockSnapshotManager;
-
     private RaftActorContext context;
     private final DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
 
@@ -61,23 +57,23 @@ public class ReplicatedLogImplTest {
         MockitoAnnotations.initMocks(this);
 
         context = new RaftActorContextImpl(null, null, "test",
-                new ElectionTermImpl(mockPersistence, "test", LOG),
-                -1, -1, Collections.<String,String>emptyMap(), configParams, LOG)  {
-            @Override
-            public SnapshotManager getSnapshotManager() {
-                return mockSnapshotManager;
-            }
-        };
+                new ElectionTermImpl(mockPersistence, "test", LOG), -1, -1, Collections.emptyMap(),
+                configParams, mockPersistence, applyState -> { }, LOG,  MoreExecutors.directExecutor());
     }
 
-    private void verifyPersist(Object message) throws Exception {
-        verifyPersist(message, new Same(message));
+    private void verifyPersist(final Object message) throws Exception {
+        verifyPersist(message, new Same(message), true);
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private void verifyPersist(Object message, Matcher<?> matcher) throws Exception {
+    private void verifyPersist(final Object message, final ArgumentMatcher<?> matcher, final boolean async)
+            throws Exception {
         ArgumentCaptor<Procedure> procedure = ArgumentCaptor.forClass(Procedure.class);
-        verify(mockPersistence).persist(Matchers.argThat(matcher), procedure.capture());
+        if (async) {
+            verify(mockPersistence).persistAsync(argThat(matcher), procedure.capture());
+        } else {
+            verify(mockPersistence).persist(argThat(matcher), procedure.capture());
+        }
 
         procedure.getValue().apply(message);
     }
@@ -85,50 +81,71 @@ public class ReplicatedLogImplTest {
     @SuppressWarnings("unchecked")
     @Test
     public void testAppendAndPersistExpectingNoCapture() throws Exception {
-        ReplicatedLog log = ReplicatedLogImpl.newInstance(context, mockPersistence, mockBehavior);
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
 
-        MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 1, new MockPayload("1"));
+        ReplicatedLogEntry logEntry1 = new SimpleReplicatedLogEntry(1, 1, new MockPayload("1"));
 
-        log.appendAndPersist(logEntry);
+        log.appendAndPersist(logEntry1, null, true);
 
-        verifyPersist(logEntry);
+        verifyPersist(logEntry1);
 
         assertEquals("size", 1, log.size());
 
         reset(mockPersistence);
 
-        Procedure<ReplicatedLogEntry> mockCallback = Mockito.mock(Procedure.class);
-        log.appendAndPersist(logEntry, mockCallback);
+        ReplicatedLogEntry logEntry2 = new SimpleReplicatedLogEntry(2, 1, new MockPayload("2"));
+        Consumer<ReplicatedLogEntry> mockCallback = mock(Consumer.class);
+        log.appendAndPersist(logEntry2, mockCallback, true);
 
-        verifyPersist(logEntry);
+        verifyPersist(logEntry2);
 
-        verify(mockCallback).apply(same(logEntry));
-        verifyNoMoreInteractions(mockSnapshotManager);
+        verify(mockCallback).accept(same(logEntry2));
 
         assertEquals("size", 2, log.size());
     }
 
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testAppendAndPersisWithDuplicateEntry() throws Exception {
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
+
+        Consumer<ReplicatedLogEntry> mockCallback = mock(Consumer.class);
+        ReplicatedLogEntry logEntry = new SimpleReplicatedLogEntry(1, 1, new MockPayload("1"));
+
+        log.appendAndPersist(logEntry, mockCallback, true);
+
+        verifyPersist(logEntry);
+
+        assertEquals("size", 1, log.size());
+
+        reset(mockPersistence, mockCallback);
+
+        log.appendAndPersist(logEntry, mockCallback, true);
+
+        verifyNoMoreInteractions(mockPersistence, mockCallback);
+
+        assertEquals("size", 1, log.size());
+    }
+
     @Test
     public void testAppendAndPersistExpectingCaptureDueToJournalCount() throws Exception {
         configParams.setSnapshotBatchCount(2);
 
         doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
 
-        ReplicatedLog log = ReplicatedLogImpl.newInstance(context, mockPersistence, mockBehavior);
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
 
-        MockReplicatedLogEntry logEntry1 = new MockReplicatedLogEntry(1, 2, new MockPayload("2"));
-        MockReplicatedLogEntry logEntry2 = new MockReplicatedLogEntry(1, 3, new MockPayload("3"));
+        final ReplicatedLogEntry logEntry1 = new SimpleReplicatedLogEntry(2, 1, new MockPayload("2"));
+        final ReplicatedLogEntry logEntry2 = new SimpleReplicatedLogEntry(3, 1, new MockPayload("3"));
 
-        log.appendAndPersist(logEntry1);
+        log.appendAndPersist(logEntry1, null, true);
         verifyPersist(logEntry1);
 
-        verifyNoMoreInteractions(mockSnapshotManager);
         reset(mockPersistence);
 
-        log.appendAndPersist(logEntry2);
+        log.appendAndPersist(logEntry2, null, true);
         verifyPersist(logEntry2);
 
-        verify(mockSnapshotManager).capture(same(logEntry2), eq(1L));
 
         assertEquals("size", 2, log.size());
     }
@@ -137,50 +154,39 @@ public class ReplicatedLogImplTest {
     public void testAppendAndPersistExpectingCaptureDueToDataSize() throws Exception {
         doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
 
-        context.setTotalMemoryRetriever(new Supplier<Long>() {
-            @Override
-            public Long get() {
-                return 100L;
-            }
-        });
+        context.setTotalMemoryRetriever(() -> 100);
 
-        ReplicatedLog log = ReplicatedLogImpl.newInstance(context, mockPersistence, mockBehavior);
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
 
         int dataSize = 600;
-        MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 2, new MockPayload("2", dataSize));
+        ReplicatedLogEntry logEntry = new SimpleReplicatedLogEntry(2, 1, new MockPayload("2", dataSize));
 
-        doReturn(true).when(mockSnapshotManager).capture(same(logEntry), eq(1L));
-
-        log.appendAndPersist(logEntry);
+        log.appendAndPersist(logEntry, null, true);
         verifyPersist(logEntry);
 
-        verify(mockSnapshotManager).capture(same(logEntry), eq(1L));
-
-        reset(mockPersistence, mockSnapshotManager);
+        reset(mockPersistence);
 
-        logEntry = new MockReplicatedLogEntry(1, 3, new MockPayload("3", 5));
+        logEntry = new SimpleReplicatedLogEntry(3, 1, new MockPayload("3", 5));
 
-        log.appendAndPersist(logEntry);
+        log.appendAndPersist(logEntry, null, true);
         verifyPersist(logEntry);
 
-        verifyNoMoreInteractions(mockSnapshotManager);
-
         assertEquals("size", 2, log.size());
     }
 
     @Test
     public void testRemoveFromAndPersist() throws Exception {
 
-        ReplicatedLog log = ReplicatedLogImpl.newInstance(context, mockPersistence, mockBehavior);
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
 
-        log.append(new MockReplicatedLogEntry(1, 0, new MockPayload("0")));
-        log.append(new MockReplicatedLogEntry(1, 1, new MockPayload("1")));
-        log.append(new MockReplicatedLogEntry(1, 2, new MockPayload("2")));
+        log.append(new SimpleReplicatedLogEntry(0, 1, new MockPayload("0")));
+        log.append(new SimpleReplicatedLogEntry(1, 1, new MockPayload("1")));
+        log.append(new SimpleReplicatedLogEntry(2, 1, new MockPayload("2")));
 
         log.removeFromAndPersist(1);
 
         DeleteEntries deleteEntries = new DeleteEntries(1);
-        verifyPersist(deleteEntries, match(deleteEntries));
+        verifyPersist(deleteEntries, match(deleteEntries), false);
 
         assertEquals("size", 1, log.size());
 
@@ -191,18 +197,21 @@ public class ReplicatedLogImplTest {
         verifyNoMoreInteractions(mockPersistence);
     }
 
-    public Matcher<DeleteEntries> match(final DeleteEntries actual){
-        return new BaseMatcher<DeleteEntries>() {
-            @Override
-            public boolean matches(Object o) {
-                DeleteEntries other = (DeleteEntries) o;
-                return actual.getFromIndex() == other.getFromIndex();
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("DeleteEntries: fromIndex: " + actual.getFromIndex());
-            }
-        };
+    @Test
+    public void testCommitFakeSnapshot() {
+        ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
+
+        log.append(new SimpleReplicatedLogEntry(0, 1, new MockPayload("0")));
+        final int dataSizeAfterFirstPayload = log.dataSize();
+
+        log.snapshotPreCommit(0,1);
+        log.snapshotCommit(false);
+
+        assertEquals(0, log.size());
+        assertEquals(dataSizeAfterFirstPayload, log.dataSize());
+    }
+
+    private static ArgumentMatcher<DeleteEntries> match(final DeleteEntries actual) {
+        return other -> actual.getFromIndex() == other.getFromIndex();
     }
 }