2 * Copyright (c) 2015 Brocade Communications Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.raft;
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;
38 * Unit tests for ReplicatedLogImpl.
40 * @author Thomas Pantelis
42 public class ReplicatedLogImplTest {
43 private static final Logger LOG = LoggerFactory.getLogger(RaftActorRecoverySupportTest.class);
46 private DataPersistenceProvider mockPersistence;
49 private RaftActorBehavior mockBehavior;
51 private RaftActorContext context;
52 private final DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
56 MockitoAnnotations.initMocks(this);
58 context = new RaftActorContextImpl(null, null, "test",
59 new ElectionTermImpl(mockPersistence, "test", LOG),
60 -1, -1, Collections.<String,String>emptyMap(), configParams, mockPersistence, LOG);
63 private void verifyPersist(Object message) throws Exception {
64 verifyPersist(message, new Same(message));
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());
72 procedure.getValue().apply(message);
75 @SuppressWarnings("unchecked")
77 public void testAppendAndPersistExpectingNoCapture() throws Exception {
78 ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
80 MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 1, new MockPayload("1"));
82 log.appendAndPersist(logEntry);
84 verifyPersist(logEntry);
86 assertEquals("size", 1, log.size());
88 reset(mockPersistence);
90 Procedure<ReplicatedLogEntry> mockCallback = Mockito.mock(Procedure.class);
91 log.appendAndPersist(logEntry, mockCallback);
93 verifyPersist(logEntry);
95 verify(mockCallback).apply(same(logEntry));
97 assertEquals("size", 2, log.size());
101 public void testAppendAndPersistExpectingCaptureDueToJournalCount() throws Exception {
102 configParams.setSnapshotBatchCount(2);
104 doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
106 ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
108 MockReplicatedLogEntry logEntry1 = new MockReplicatedLogEntry(1, 2, new MockPayload("2"));
109 MockReplicatedLogEntry logEntry2 = new MockReplicatedLogEntry(1, 3, new MockPayload("3"));
111 log.appendAndPersist(logEntry1);
112 verifyPersist(logEntry1);
114 reset(mockPersistence);
116 log.appendAndPersist(logEntry2);
117 verifyPersist(logEntry2);
120 assertEquals("size", 2, log.size());
124 public void testAppendAndPersistExpectingCaptureDueToDataSize() throws Exception {
125 doReturn(1L).when(mockBehavior).getReplicatedToAllIndex();
127 context.setTotalMemoryRetriever(() -> 100);
129 ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
132 MockReplicatedLogEntry logEntry = new MockReplicatedLogEntry(1, 2, new MockPayload("2", dataSize));
134 log.appendAndPersist(logEntry);
135 verifyPersist(logEntry);
137 reset(mockPersistence);
139 logEntry = new MockReplicatedLogEntry(1, 3, new MockPayload("3", 5));
141 log.appendAndPersist(logEntry);
142 verifyPersist(logEntry);
144 assertEquals("size", 2, log.size());
148 public void testRemoveFromAndPersist() throws Exception {
150 ReplicatedLog log = ReplicatedLogImpl.newInstance(context);
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")));
156 log.removeFromAndPersist(1);
158 DeleteEntries deleteEntries = new DeleteEntries(1);
159 verifyPersist(deleteEntries, match(deleteEntries));
161 assertEquals("size", 1, log.size());
163 reset(mockPersistence);
165 log.removeFromAndPersist(1);
167 verifyNoMoreInteractions(mockPersistence);
170 public Matcher<DeleteEntries> match(final DeleteEntries actual){
171 return new BaseMatcher<DeleteEntries>() {
173 public boolean matches(Object o) {
174 DeleteEntries other = (DeleteEntries) o;
175 return actual.getFromIndex() == other.getFromIndex();
179 public void describeTo(Description description) {
180 description.appendText("DeleteEntries: fromIndex: " + actual.getFromIndex());