Merge "Split out sal-akka-raft example"
[controller.git] / opendaylight / md-sal / sal-akka-raft / src / test / java / org / opendaylight / controller / cluster / raft / RaftActorSnapshotMessageSupportTest.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.anyLong;
12 import static org.mockito.Matchers.same;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.verify;
15 import akka.actor.ActorRef;
16 import akka.japi.Procedure;
17 import akka.persistence.SaveSnapshotFailure;
18 import akka.persistence.SaveSnapshotSuccess;
19 import akka.persistence.SnapshotMetadata;
20 import java.util.Arrays;
21 import java.util.Collections;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.mockito.ArgumentCaptor;
25 import org.mockito.Mock;
26 import org.mockito.MockitoAnnotations;
27 import org.opendaylight.controller.cluster.DataPersistenceProvider;
28 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockPayload;
29 import org.opendaylight.controller.cluster.raft.MockRaftActorContext.MockReplicatedLogEntry;
30 import org.opendaylight.controller.cluster.raft.base.messages.ApplySnapshot;
31 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshot;
32 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
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 RaftActorSnapshotMessageSupport.
39  *
40  * @author Thomas Pantelis
41  */
42 public class RaftActorSnapshotMessageSupportTest {
43
44     private static final Logger LOG = LoggerFactory.getLogger(RaftActorRecoverySupportTest.class);
45
46     @Mock
47     private DataPersistenceProvider mockPersistence;
48
49     @Mock
50     private RaftActorBehavior mockBehavior;
51
52     @Mock
53     private RaftActorSnapshotCohort mockCohort;
54
55     @Mock
56     private SnapshotManager mockSnapshotManager;
57
58     @Mock
59     ActorRef mockRaftActorRef;
60
61     private RaftActorSnapshotMessageSupport support;
62
63     private RaftActorContext context;
64     private final DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
65
66     @Before
67     public void setup() {
68         MockitoAnnotations.initMocks(this);
69
70         context = new RaftActorContextImpl(mockRaftActorRef, null, "test",
71                 new ElectionTermImpl(mockPersistence, "test", LOG),
72                 -1, -1, Collections.<String,String>emptyMap(), configParams, mockPersistence, LOG) {
73             @Override
74             public SnapshotManager getSnapshotManager() {
75                 return mockSnapshotManager;
76             }
77         };
78
79         support = new RaftActorSnapshotMessageSupport(mockPersistence, context, mockBehavior, mockCohort);
80
81         doReturn(true).when(mockPersistence).isRecoveryApplicable();
82
83         context.setReplicatedLog(ReplicatedLogImpl.newInstance(context, mockPersistence, mockBehavior));
84     }
85
86     private void sendMessageToSupport(Object message) {
87         sendMessageToSupport(message, true);
88     }
89
90     private void sendMessageToSupport(Object message, boolean expHandled) {
91         boolean handled = support.handleSnapshotMessage(message);
92         assertEquals("complete", expHandled, handled);
93     }
94
95     @Test
96     public void testOnApplySnapshot() {
97
98         ReplicatedLog replicatedLog = context.getReplicatedLog();
99         replicatedLog.append(new MockReplicatedLogEntry(1, 1, new MockPayload("1")));
100
101         byte[] snapshotBytes = {1,2,3,4,5};
102
103         ReplicatedLogEntry unAppliedEntry = new MockReplicatedLogEntry(1, 2, new MockPayload("2"));
104
105         long lastAppliedDuringSnapshotCapture = 1;
106         long lastIndexDuringSnapshotCapture = 2;
107
108         Snapshot snapshot = Snapshot.create(snapshotBytes, Arrays.asList(unAppliedEntry),
109                 lastIndexDuringSnapshotCapture, 1, lastAppliedDuringSnapshotCapture, 1);
110
111         sendMessageToSupport(new ApplySnapshot(snapshot));
112
113         assertEquals("Journal log size", 1, context.getReplicatedLog().size());
114         assertEquals("Last index", lastIndexDuringSnapshotCapture, context.getReplicatedLog().lastIndex());
115         assertEquals("Last applied", lastAppliedDuringSnapshotCapture, context.getLastApplied());
116         assertEquals("Commit index", -1, context.getCommitIndex());
117         assertEquals("Snapshot term", 1, context.getReplicatedLog().getSnapshotTerm());
118         assertEquals("Snapshot index", lastAppliedDuringSnapshotCapture, context.getReplicatedLog().getSnapshotIndex());
119
120         verify(mockCohort).applySnapshot(snapshotBytes);
121     }
122
123     @SuppressWarnings({ "rawtypes", "unchecked" })
124     @Test
125     public void testOnCaptureSnapshot() throws Exception {
126
127         sendMessageToSupport(new CaptureSnapshot(3, 1, 2, 1, 2, 1, null));
128
129         ArgumentCaptor<Procedure> procedure = ArgumentCaptor.forClass(Procedure.class);
130         verify(mockSnapshotManager).create(procedure.capture());
131
132         procedure.getValue().apply(null);
133
134         verify(mockCohort).createSnapshot(same(mockRaftActorRef));
135     }
136
137     @Test
138     public void testOnCaptureSnapshotReply() {
139
140         byte[] snapshot = {1,2,3,4,5};
141         sendMessageToSupport(new CaptureSnapshotReply(snapshot));
142
143         verify(mockSnapshotManager).persist(same(mockPersistence), same(snapshot), same(mockBehavior), anyLong());
144     }
145
146     @Test
147     public void testOnSaveSnapshotSuccess() {
148
149         long sequenceNumber = 100;
150         sendMessageToSupport(new SaveSnapshotSuccess(new SnapshotMetadata("foo", sequenceNumber, 1234L)));
151
152         verify(mockSnapshotManager).commit(mockPersistence, sequenceNumber);
153     }
154
155     @Test
156     public void testOnSaveSnapshotFailure() {
157
158         sendMessageToSupport(new SaveSnapshotFailure(new SnapshotMetadata("foo", 100, 1234L),
159                 new Throwable("mock")));
160
161         verify(mockSnapshotManager).rollback();
162     }
163
164     @Test
165     public void testOnCommitSnapshot() {
166
167         sendMessageToSupport(RaftActorSnapshotMessageSupport.COMMIT_SNAPSHOT);
168
169         verify(mockSnapshotManager).commit(mockPersistence, -1);
170     }
171
172     @Test
173     public void testUnhandledMessage() {
174
175         sendMessageToSupport("unhandled", false);
176     }
177 }