c6ee950d142afe1b0ff963aa9fef7b0fec6a2e0c
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / ReplicatedLogImplTest.java
1 /*
2  * Copyright (c) 2015 Brocade Communications 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.mockito.Matchers.same;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.reset;
14 import static org.mockito.Mockito.verify;
15 import static org.mockito.Mockito.verifyNoMoreInteractions;
16 import akka.japi.Procedure;
17 import java.util.Collections;
18 import org.hamcrest.BaseMatcher;
19 import org.hamcrest.Description;
20 import org.hamcrest.Matcher;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.mockito.ArgumentCaptor;
24 import org.mockito.Matchers;
25 import org.mockito.Mock;
26 import org.mockito.Mockito;
27 import org.mockito.MockitoAnnotations;
28 import org.mockito.internal.matchers.Same;
29 import org.opendaylight.controller.cluster.DataPersistenceProvider;
30 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
31 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
32 import org.opendaylight.controller.cluster.raft.base.messages.DeleteEntries;
33 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36
37 /**
38  * Unit tests for ReplicatedLogImpl.
39  *
40  * @author Thomas Pantelis
41  */
42 public class ReplicatedLogImplTest {
43     private static final Logger LOG = LoggerFactory.getLogger(RaftActorRecoverySupportTest.class);
44
45     @Mock
46     private DataPersistenceProvider mockPersistence;
47
48     @Mock
49     private RaftActorBehavior mockBehavior;
50
51     private RaftActorContext context;
52     private final DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
53
54     @Before
55     public void setup() {
56         MockitoAnnotations.initMocks(this);
57
58         context = new RaftActorContextImpl(null, null, "test",
59                 new ElectionTermImpl(mockPersistence, "test", LOG),
60                 -1, -1, Collections.<String,String>emptyMap(), configParams, mockPersistence, LOG);
61     }
62
63     private void verifyPersist(Object message) throws Exception {
64         verifyPersist(message, new Same(message));
65     }
66
67     @SuppressWarnings({ "unchecked", "rawtypes" })
68     private void verifyPersist(Object message, Matcher<?> matcher) throws Exception {
69         ArgumentCaptor<Procedure> procedure = ArgumentCaptor.forClass(Procedure.class);
70         verify(mockPersistence).persist(Matchers.argThat(matcher), procedure.capture());
71
72         procedure.getValue().apply(message);
73     }
74
75     @SuppressWarnings("unchecked")
76     @Test
77     public void testAppendAndPersistExpectingNoCapture() throws Exception {
78         ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
79
80         MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 1, new MockPayload("1"));
81
82         log.appendAndPersist(logEntry);
83
84         verifyPersist(logEntry);
85
86         assertEquals("size", 1, log.size());
87
88         reset(mockPersistence);
89
90         Procedure<ReplicatedLogEntry> mockCallback = Mockito.mock(Procedure.class);
91         log.appendAndPersist(logEntry, mockCallback);
92
93         verifyPersist(logEntry);
94
95         verify(mockCallback).apply(same(logEntry));
96
97         assertEquals("size", 2, log.size());
98     }
99
100     @Test
101     public void testAppendAndPersistExpectingCaptureDueToJournalCount() throws Exception {
102         configParams.setSnapshotBatchCount(2);
103
104         doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
105
106         ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
107
108         MockReplicatedLogEntry logEntry1 = new MockReplicatedLogEntry(1, 2, new MockPayload("2"));
109         MockReplicatedLogEntry logEntry2 = new MockReplicatedLogEntry(1, 3, new MockPayload("3"));
110
111         log.appendAndPersist(logEntry1);
112         verifyPersist(logEntry1);
113
114         reset(mockPersistence);
115
116         log.appendAndPersist(logEntry2);
117         verifyPersist(logEntry2);
118
119
120         assertEquals("size", 2, log.size());
121     }
122
123     @Test
124     public void testAppendAndPersistExpectingCaptureDueToDataSize() throws Exception {
125         doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
126
127         context.setTotalMemoryRetriever(() -> 100);
128
129         ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
130
131         int dataSize = 600;
132         MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 2, new MockPayload("2", dataSize));
133
134         log.appendAndPersist(logEntry);
135         verifyPersist(logEntry);
136
137         reset(mockPersistence);
138
139         logEntry = new MockReplicatedLogEntry(1, 3, new MockPayload("3", 5));
140
141         log.appendAndPersist(logEntry);
142         verifyPersist(logEntry);
143
144         assertEquals("size", 2, log.size());
145     }
146
147     @Test
148     public void testRemoveFromAndPersist() throws Exception {
149
150         ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
151
152         log.append(new MockReplicatedLogEntry(1, 0, new MockPayload("0")));
153         log.append(new MockReplicatedLogEntry(1, 1, new MockPayload("1")));
154         log.append(new MockReplicatedLogEntry(1, 2, new MockPayload("2")));
155
156         log.removeFromAndPersist(1);
157
158         DeleteEntries deleteEntries = new DeleteEntries(1);
159         verifyPersist(deleteEntries, match(deleteEntries));
160
161         assertEquals("size", 1, log.size());
162
163         reset(mockPersistence);
164
165         log.removeFromAndPersist(1);
166
167         verifyNoMoreInteractions(mockPersistence);
168     }
169
170     public Matcher<DeleteEntries> match(final DeleteEntries actual){
171         return new BaseMatcher<DeleteEntries>() {
172             @Override
173             public boolean matches(Object o) {
174                 DeleteEntries other = (DeleteEntries) o;
175                 return actual.getFromIndex() == other.getFromIndex();
176             }
177
178             @Override
179             public void describeTo(Description description) {
180                 description.appendText("DeleteEntries: fromIndex: " + actual.getFromIndex());
181             }
182         };
183     }
184 }