Merge "BUG-2633 - Netconf northbound mapping."
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / AbstractReplicatedLogImplTest.java
1 /*
2  * Copyright (c) 2014 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 package org.opendaylight.controller.cluster.raft;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import java.util.HashMap;
15 import java.util.List;
16 import java.util.Map;
17 import org.junit.After;
18 import org.junit.Assert;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
22 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
23
24 /**
25 *
26 */
27 public class AbstractReplicatedLogImplTest {
28
29     private MockAbstractReplicatedLogImpl replicatedLogImpl;
30
31     @Before
32     public void setUp() {
33         replicatedLogImpl = new MockAbstractReplicatedLogImpl();
34         // create a set of initial entries in the in-memory log
35         replicatedLogImpl.append(new MockReplicatedLogEntry(1, 0, new MockPayload("A")));
36         replicatedLogImpl.append(new MockReplicatedLogEntry(1, 1, new MockPayload("B")));
37         replicatedLogImpl.append(new MockReplicatedLogEntry(1, 2, new MockPayload("C")));
38         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 3, new MockPayload("D")));
39
40     }
41
42     @After
43     public void tearDown() {
44         replicatedLogImpl.journal.clear();
45         replicatedLogImpl.setSnapshotIndex(-1);
46         replicatedLogImpl.setSnapshotTerm(-1);
47         replicatedLogImpl = null;
48     }
49
50     @Test
51     public void testIndexOperations() {
52
53         // check if the values returned are correct, with snapshotIndex = -1
54         assertEquals("B", replicatedLogImpl.get(1).getData().toString());
55         assertEquals("D", replicatedLogImpl.last().getData().toString());
56         assertEquals(3, replicatedLogImpl.lastIndex());
57         assertEquals(2, replicatedLogImpl.lastTerm());
58         assertEquals(2, replicatedLogImpl.getFrom(2).size());
59         assertEquals(4, replicatedLogImpl.size());
60         assertTrue(replicatedLogImpl.isPresent(2));
61         assertFalse(replicatedLogImpl.isPresent(4));
62         assertFalse(replicatedLogImpl.isInSnapshot(2));
63
64         // now create a snapshot of 3 entries, with 1 unapplied entry left in the log
65         // It removes the entries which have made it to snapshot
66         // and updates the snapshot index and term
67         Map<Long, String> state = takeSnapshot(3);
68
69         // check the values after the snapshot.
70         // each index value passed in the test is the logical index (log entry index)
71         // which gets mapped to the list's physical index
72         assertEquals("D", replicatedLogImpl.get(3).getData().toString());
73         assertEquals("D", replicatedLogImpl.last().getData().toString());
74         assertNull(replicatedLogImpl.get(1));
75         assertEquals(3, replicatedLogImpl.lastIndex());
76         assertEquals(2, replicatedLogImpl.lastTerm());
77         assertEquals(0, replicatedLogImpl.getFrom(2).size());
78         assertEquals(1, replicatedLogImpl.size());
79         assertFalse(replicatedLogImpl.isPresent(2));
80         assertTrue(replicatedLogImpl.isPresent(3));
81         assertFalse(replicatedLogImpl.isPresent(4));
82         assertTrue(replicatedLogImpl.isInSnapshot(2));
83
84         // append few more entries
85         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E")));
86         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F")));
87         replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G")));
88         replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H")));
89
90         // check their values as well
91         assertEquals(5, replicatedLogImpl.size());
92         assertEquals("D", replicatedLogImpl.get(3).getData().toString());
93         assertEquals("E", replicatedLogImpl.get(4).getData().toString());
94         assertEquals("H", replicatedLogImpl.last().getData().toString());
95         assertEquals(3, replicatedLogImpl.lastTerm());
96         assertEquals(7, replicatedLogImpl.lastIndex());
97         assertTrue(replicatedLogImpl.isPresent(7));
98         assertFalse(replicatedLogImpl.isInSnapshot(7));
99         assertEquals(1, replicatedLogImpl.getFrom(7).size());
100         assertEquals(2, replicatedLogImpl.getFrom(6).size());
101
102         // take a second snapshot with 5 entries with 0 unapplied entries left in the log
103         state = takeSnapshot(5);
104
105         assertEquals(0, replicatedLogImpl.size());
106         assertNull(replicatedLogImpl.last());
107         assertNull(replicatedLogImpl.get(7));
108         assertNull(replicatedLogImpl.get(1));
109         assertFalse(replicatedLogImpl.isPresent(7));
110         assertTrue(replicatedLogImpl.isInSnapshot(7));
111         assertEquals(0, replicatedLogImpl.getFrom(7).size());
112         assertEquals(0, replicatedLogImpl.getFrom(6).size());
113
114     }
115
116     @Test
117     public void testGetFromWithMax(){
118         List<ReplicatedLogEntry> from = replicatedLogImpl.getFrom(0, 1);
119         Assert.assertEquals(1, from.size());
120         Assert.assertEquals(1, from.get(0).getTerm());
121
122         from = replicatedLogImpl.getFrom(0, 20);
123         Assert.assertEquals(4, from.size());
124         Assert.assertEquals(2, from.get(3).getTerm());
125
126         from = replicatedLogImpl.getFrom(1, 2);
127         Assert.assertEquals(2, from.size());
128         Assert.assertEquals(1, from.get(1).getTerm());
129
130     }
131
132     @Test
133     public void testSnapshotPreCommit() {
134         //add 4 more entries
135         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("E")));
136         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("F")));
137         replicatedLogImpl.append(new MockReplicatedLogEntry(3, 6, new MockPayload("G")));
138         replicatedLogImpl.append(new MockReplicatedLogEntry(3, 7, new MockPayload("H")));
139
140         //sending negative values should not cause any changes
141         replicatedLogImpl.snapshotPreCommit(-1, -1);
142         assertEquals(8, replicatedLogImpl.size());
143         assertEquals(-1, replicatedLogImpl.getSnapshotIndex());
144
145         replicatedLogImpl.snapshotPreCommit(4, 3);
146         assertEquals(3, replicatedLogImpl.size());
147         assertEquals(4, replicatedLogImpl.getSnapshotIndex());
148
149         replicatedLogImpl.snapshotPreCommit(6, 3);
150         assertEquals(1, replicatedLogImpl.size());
151         assertEquals(6, replicatedLogImpl.getSnapshotIndex());
152
153         replicatedLogImpl.snapshotPreCommit(7, 3);
154         assertEquals(0, replicatedLogImpl.size());
155         assertEquals(7, replicatedLogImpl.getSnapshotIndex());
156
157         //running it again on an empty list should not throw exception
158         replicatedLogImpl.snapshotPreCommit(7, 3);
159         assertEquals(0, replicatedLogImpl.size());
160         assertEquals(7, replicatedLogImpl.getSnapshotIndex());
161
162     }
163
164     @Test
165     public void testIsPresent() {
166         assertTrue(replicatedLogImpl.isPresent(0));
167         assertTrue(replicatedLogImpl.isPresent(1));
168         assertTrue(replicatedLogImpl.isPresent(2));
169         assertTrue(replicatedLogImpl.isPresent(3));
170
171         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 4, new MockPayload("D")));
172         replicatedLogImpl.snapshotPreCommit(3, 2); //snapshot on 3
173         replicatedLogImpl.snapshotCommit();
174
175         assertFalse(replicatedLogImpl.isPresent(0));
176         assertFalse(replicatedLogImpl.isPresent(1));
177         assertFalse(replicatedLogImpl.isPresent(2));
178         assertFalse(replicatedLogImpl.isPresent(3));
179         assertTrue(replicatedLogImpl.isPresent(4));
180
181         replicatedLogImpl.snapshotPreCommit(4, 2); //snapshot on 4
182         replicatedLogImpl.snapshotCommit();
183         assertFalse(replicatedLogImpl.isPresent(4));
184
185         replicatedLogImpl.append(new MockReplicatedLogEntry(2, 5, new MockPayload("D")));
186         assertTrue(replicatedLogImpl.isPresent(5));
187     }
188
189     // create a snapshot for test
190     public Map<Long, String> takeSnapshot(final int numEntries) {
191         Map<Long, String> map = new HashMap<>(numEntries);
192         List<ReplicatedLogEntry> entries = replicatedLogImpl.getEntriesTill(numEntries);
193         for (ReplicatedLogEntry entry : entries) {
194             map.put(entry.getIndex(), entry.getData().toString());
195         }
196
197         int term = (int) replicatedLogImpl.lastTerm();
198         int lastIndex = (int) entries.get(entries.size() - 1).getIndex();
199         entries.clear();
200         replicatedLogImpl.setSnapshotTerm(term);
201         replicatedLogImpl.setSnapshotIndex(lastIndex);
202
203         return map;
204
205     }
206     class MockAbstractReplicatedLogImpl extends AbstractReplicatedLogImpl {
207         @Override
208         public void appendAndPersist(final ReplicatedLogEntry replicatedLogEntry) {
209         }
210
211         @Override
212         public void removeFromAndPersist(final long index) {
213         }
214
215         @Override
216         public int dataSize() {
217             return -1;
218         }
219
220         public List<ReplicatedLogEntry> getEntriesTill(final int index) {
221             return journal.subList(0, index);
222         }
223     }
224 }