Remove MockReplicatedLogEntry
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / AbstractReplicatedLogImplTest.java
index 913665861d6f694dbb01c51d96978c05d6e9c5ea..a37a1314708100f962e8554c5c4ba075bbfbd896 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
@@ -7,23 +8,23 @@
  */
 package org.opendaylight.controller.cluster.raft;
 
-import junit.framework.Assert;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 
+import akka.japi.Procedure;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
+import org.opendaylight.controller.cluster.raft.persisted.SimpleReplicatedLogEntry;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
-import static org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
 /**
-*
+* Unit tests for AbstractReplicatedLogImplTest.
 */
 public class AbstractReplicatedLogImplTest {
 
@@ -33,19 +34,40 @@ public class AbstractReplicatedLogImplTest {
     public void setUp() {
         replicatedLogImpl = new MockAbstractReplicatedLogImpl();
         // create a set of initial entries in the in-memory log
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(0, 1, new MockPayload("A")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(1, 1, new MockPayload("B")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(2, 1, new MockPayload("C")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(3, 2, new MockPayload("D")));
 
     }
 
-    @After
-    public void tearDown() {
-        replicatedLogImpl.journal.clear();
-        replicatedLogImpl.setSnapshotIndex(-1);
-        replicatedLogImpl.setSnapshotTerm(-1);
-        replicatedLogImpl = null;
+    @Test
+    public void testEmptyLog() {
+        replicatedLogImpl = new MockAbstractReplicatedLogImpl();
+
+        assertEquals("size", 0, replicatedLogImpl.size());
+        assertEquals("dataSize", 0, replicatedLogImpl.dataSize());
+        assertEquals("getSnapshotIndex", -1, replicatedLogImpl.getSnapshotIndex());
+        assertEquals("getSnapshotTerm", -1, replicatedLogImpl.getSnapshotTerm());
+        assertEquals("lastIndex", -1, replicatedLogImpl.lastIndex());
+        assertEquals("lastTerm", -1, replicatedLogImpl.lastTerm());
+        assertEquals("isPresent", false, replicatedLogImpl.isPresent(0));
+        assertEquals("isInSnapshot", false, replicatedLogImpl.isInSnapshot(0));
+        Assert.assertNull("get(0)", replicatedLogImpl.get(0));
+        Assert.assertNull("last", replicatedLogImpl.last());
+
+        List<ReplicatedLogEntry> list = replicatedLogImpl.getFrom(0, 1, ReplicatedLog.NO_MAX_SIZE);
+        assertEquals("getFrom size", 0, list.size());
+
+        assertEquals("removeFrom", -1, replicatedLogImpl.removeFrom(1));
+
+        replicatedLogImpl.setSnapshotIndex(2);
+        replicatedLogImpl.setSnapshotTerm(1);
+
+        assertEquals("getSnapshotIndex", 2, replicatedLogImpl.getSnapshotIndex());
+        assertEquals("getSnapshotTerm", 1, replicatedLogImpl.getSnapshotTerm());
+        assertEquals("lastIndex", 2, replicatedLogImpl.lastIndex());
+        assertEquals("lastTerm", 1, replicatedLogImpl.lastTerm());
     }
 
     @Test
@@ -65,7 +87,7 @@ public class AbstractReplicatedLogImplTest {
         // now create a snapshot of 3 entries, with 1 unapplied entry left in the log
         // It removes the entries which have made it to snapshot
         // and updates the snapshot index and term
-        Map state = takeSnapshot(3);
+        takeSnapshot(3);
 
         // check the values after the snapshot.
         // each index value passed in the test is the logical index (log entry index)
@@ -83,10 +105,10 @@ public class AbstractReplicatedLogImplTest {
         assertTrue(replicatedLogImpl.isInSnapshot(2));
 
         // append few more entries
-        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G")));
-        replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(4, 2, new MockPayload("E")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(5, 2, new MockPayload("F")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(6, 3, new MockPayload("G")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(7, 3, new MockPayload("H")));
 
         // check their values as well
         assertEquals(5, replicatedLogImpl.size());
@@ -101,7 +123,7 @@ public class AbstractReplicatedLogImplTest {
         assertEquals(2, replicatedLogImpl.getFrom(6).size());
 
         // take a second snapshot with 5 entries with 0 unapplied entries left in the log
-        state = takeSnapshot(5);
+        takeSnapshot(5);
 
         assertEquals(0, replicatedLogImpl.size());
         assertNull(replicatedLogImpl.last());
@@ -115,57 +137,201 @@ public class AbstractReplicatedLogImplTest {
     }
 
     @Test
-    public void testGetFromWithMax(){
-        List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1);
+    public void testGetFromWithMax() {
+        List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1, ReplicatedLog.NO_MAX_SIZE);
         Assert.assertEquals(1, from.size());
-        Assert.assertEquals(1, from.get(0).getTerm());
+        Assert.assertEquals("A", from.get(0).getData().toString());
 
-        from = replicatedLogImpl.getFrom(0, 20);
+        from = replicatedLogImpl.getFrom(0, 20, ReplicatedLog.NO_MAX_SIZE);
         Assert.assertEquals(4, from.size());
-        Assert.assertEquals(2, from.get(3).getTerm());
+        Assert.assertEquals("A", from.get(0).getData().toString());
+        Assert.assertEquals("D", from.get(3).getData().toString());
 
-        from = replicatedLogImpl.getFrom(1, 2);
+        from = replicatedLogImpl.getFrom(1, 2, ReplicatedLog.NO_MAX_SIZE);
         Assert.assertEquals(2, from.size());
-        Assert.assertEquals(1, from.get(1).getTerm());
+        Assert.assertEquals("B", from.get(0).getData().toString());
+        Assert.assertEquals("C", from.get(1).getData().toString());
 
+        from = replicatedLogImpl.getFrom(1, 3, 2);
+        Assert.assertEquals(2, from.size());
+        Assert.assertEquals("B", from.get(0).getData().toString());
+        Assert.assertEquals("C", from.get(1).getData().toString());
+
+        from = replicatedLogImpl.getFrom(1, 3, 3);
+        Assert.assertEquals(3, from.size());
+        Assert.assertEquals("B", from.get(0).getData().toString());
+        Assert.assertEquals("C", from.get(1).getData().toString());
+        Assert.assertEquals("D", from.get(2).getData().toString());
+
+        from = replicatedLogImpl.getFrom(1, 2, 3);
+        Assert.assertEquals(2, from.size());
+        Assert.assertEquals("B", from.get(0).getData().toString());
+        Assert.assertEquals("C", from.get(1).getData().toString());
+
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(4, 2, new MockPayload("12345")));
+        from = replicatedLogImpl.getFrom(4, 2, 2);
+        Assert.assertEquals(1, from.size());
+        Assert.assertEquals("12345", from.get(0).getData().toString());
+    }
+
+    @Test
+    public void testSnapshotPreCommit() {
+        //add 4 more entries
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(4, 2, new MockPayload("E")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(5, 2, new MockPayload("F")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(6, 3, new MockPayload("G")));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(7, 3, new MockPayload("H")));
+
+        //sending negative values should not cause any changes
+        replicatedLogImpl.snapshotPreCommit(-1, -1);
+        assertEquals(8, replicatedLogImpl.size());
+        assertEquals(-1, replicatedLogImpl.getSnapshotIndex());
+        assertEquals(-1, replicatedLogImpl.getSnapshotTerm());
+
+        replicatedLogImpl.snapshotPreCommit(4, 2);
+        assertEquals(3, replicatedLogImpl.size());
+        assertEquals(4, replicatedLogImpl.getSnapshotIndex());
+        assertEquals(2, replicatedLogImpl.getSnapshotTerm());
+
+        replicatedLogImpl.snapshotPreCommit(6, 3);
+        assertEquals(1, replicatedLogImpl.size());
+        assertEquals(6, replicatedLogImpl.getSnapshotIndex());
+        assertEquals(3, replicatedLogImpl.getSnapshotTerm());
+
+        replicatedLogImpl.snapshotPreCommit(7, 3);
+        assertEquals(0, replicatedLogImpl.size());
+        assertEquals(7, replicatedLogImpl.getSnapshotIndex());
+        assertEquals(3, replicatedLogImpl.getSnapshotTerm());
+
+        //running it again on an empty list should not throw exception
+        replicatedLogImpl.snapshotPreCommit(7, 3);
+        assertEquals(0, replicatedLogImpl.size());
+        assertEquals(7, replicatedLogImpl.getSnapshotIndex());
+        assertEquals(3, replicatedLogImpl.getSnapshotTerm());
+    }
+
+    @Test
+    public void testSnapshotCommit() {
+
+        replicatedLogImpl.snapshotPreCommit(1, 1);
+
+        replicatedLogImpl.snapshotCommit();
+
+        assertEquals("size", 2, replicatedLogImpl.size());
+        assertEquals("dataSize", 2, replicatedLogImpl.dataSize());
+        assertEquals("getSnapshotIndex", 1, replicatedLogImpl.getSnapshotIndex());
+        assertEquals("getSnapshotTerm", 1, replicatedLogImpl.getSnapshotTerm());
+        assertEquals("lastIndex", 3, replicatedLogImpl.lastIndex());
+        assertEquals("lastTerm", 2, replicatedLogImpl.lastTerm());
+
+        Assert.assertNull("get(0)", replicatedLogImpl.get(0));
+        Assert.assertNull("get(1)", replicatedLogImpl.get(1));
+        Assert.assertNotNull("get(2)", replicatedLogImpl.get(2));
+        Assert.assertNotNull("get(3)", replicatedLogImpl.get(3));
+    }
+
+    @Test
+    public void testSnapshotRollback() {
+
+        replicatedLogImpl.snapshotPreCommit(1, 1);
+
+        assertEquals("size", 2, replicatedLogImpl.size());
+        assertEquals("getSnapshotIndex", 1, replicatedLogImpl.getSnapshotIndex());
+        assertEquals("getSnapshotTerm", 1, replicatedLogImpl.getSnapshotTerm());
+
+        replicatedLogImpl.snapshotRollback();
+
+        assertEquals("size", 4, replicatedLogImpl.size());
+        assertEquals("dataSize", 4, replicatedLogImpl.dataSize());
+        assertEquals("getSnapshotIndex", -1, replicatedLogImpl.getSnapshotIndex());
+        assertEquals("getSnapshotTerm", -1, replicatedLogImpl.getSnapshotTerm());
+        Assert.assertNotNull("get(0)", replicatedLogImpl.get(0));
+        Assert.assertNotNull("get(3)", replicatedLogImpl.get(3));
+    }
+
+    @Test
+    public void testIsPresent() {
+        assertTrue(replicatedLogImpl.isPresent(0));
+        assertTrue(replicatedLogImpl.isPresent(1));
+        assertTrue(replicatedLogImpl.isPresent(2));
+        assertTrue(replicatedLogImpl.isPresent(3));
+
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(4, 2, new MockPayload("D")));
+        replicatedLogImpl.snapshotPreCommit(3, 2); //snapshot on 3
+        replicatedLogImpl.snapshotCommit();
+
+        assertFalse(replicatedLogImpl.isPresent(0));
+        assertFalse(replicatedLogImpl.isPresent(1));
+        assertFalse(replicatedLogImpl.isPresent(2));
+        assertFalse(replicatedLogImpl.isPresent(3));
+        assertTrue(replicatedLogImpl.isPresent(4));
+
+        replicatedLogImpl.snapshotPreCommit(4, 2); //snapshot on 4
+        replicatedLogImpl.snapshotCommit();
+        assertFalse(replicatedLogImpl.isPresent(4));
+
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(5, 2, new MockPayload("D")));
+        assertTrue(replicatedLogImpl.isPresent(5));
+    }
+
+    @Test
+    public void testRemoveFrom() {
+
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(4, 2, new MockPayload("E", 2)));
+        replicatedLogImpl.append(new SimpleReplicatedLogEntry(5, 2, new MockPayload("F", 3)));
+
+        assertEquals("dataSize", 9, replicatedLogImpl.dataSize());
+
+        long adjusted = replicatedLogImpl.removeFrom(4);
+        assertEquals("removeFrom - adjusted", 4, adjusted);
+        assertEquals("size", 4, replicatedLogImpl.size());
+        assertEquals("dataSize", 4, replicatedLogImpl.dataSize());
+
+        takeSnapshot(1);
+
+        adjusted = replicatedLogImpl.removeFrom(2);
+        assertEquals("removeFrom - adjusted", 1, adjusted);
+        assertEquals("size", 1, replicatedLogImpl.size());
+        assertEquals("dataSize", 1, replicatedLogImpl.dataSize());
+
+        assertEquals("removeFrom - adjusted", -1, replicatedLogImpl.removeFrom(0));
+        assertEquals("removeFrom - adjusted", -1, replicatedLogImpl.removeFrom(100));
     }
 
     // create a snapshot for test
-    public Map takeSnapshot(int numEntries) {
-        Map map = new HashMap(numEntries);
-        List<ReplicatedLogEntry> entries = replicatedLogImpl.getEntriesTill(numEntries);
-        for (ReplicatedLogEntry entry : entries) {
+    public Map<Long, String> takeSnapshot(final int numEntries) {
+        Map<Long, String> map = new HashMap<>(numEntries);
+
+        long lastIndex = 0;
+        long lastTerm = 0;
+        for (int i = 0; i < numEntries; i++) {
+            ReplicatedLogEntry entry = replicatedLogImpl.getAtPhysicalIndex(i);
             map.put(entry.getIndex(), entry.getData().toString());
+            lastIndex = entry.getIndex();
+            lastTerm = entry.getTerm();
         }
 
-        int term = (int) replicatedLogImpl.lastTerm();
-        int lastIndex = (int) entries.get(entries.size() - 1).getIndex();
-        entries.clear();
-        replicatedLogImpl.setSnapshotTerm(term);
-        replicatedLogImpl.setSnapshotIndex(lastIndex);
+        replicatedLogImpl.snapshotPreCommit(lastIndex, lastTerm);
+        replicatedLogImpl.snapshotCommit();
 
         return map;
 
     }
+
     class MockAbstractReplicatedLogImpl extends AbstractReplicatedLogImpl {
         @Override
-        public void appendAndPersist(ReplicatedLogEntry replicatedLogEntry) {
+        public boolean removeFromAndPersist(final long index) {
+            return true;
         }
 
         @Override
-        public void removeFromAndPersist(long index) {
+        public boolean appendAndPersist(ReplicatedLogEntry replicatedLogEntry, Procedure<ReplicatedLogEntry> callback,
+                boolean doAsync) {
+            return true;
         }
 
-        public void setSnapshotIndex(long snapshotIndex) {
-            this.snapshotIndex = snapshotIndex;
-        }
-
-        public void setSnapshotTerm(long snapshotTerm) {
-            this.snapshotTerm = snapshotTerm;
-        }
-
-        public List<ReplicatedLogEntry> getEntriesTill(int index) {
-            return journal.subList(0, index);
+        @Override
+        public void captureSnapshotIfReady(ReplicatedLogEntry replicatedLogEntry) {
         }
     }
 }