ac59b6a2f224ad143fe62b47cdc33e54c9f9e839
[controller.git] /
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.ArgumentMatchers.anyLong;
12 import static org.mockito.ArgumentMatchers.eq;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.verify;
15
16 import com.google.common.io.ByteSource;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.io.OutputStream;
19 import java.nio.file.Path;
20 import java.util.Map;
21 import java.util.Optional;
22 import org.apache.pekko.actor.ActorRef;
23 import org.apache.pekko.persistence.SaveSnapshotFailure;
24 import org.apache.pekko.persistence.SaveSnapshotSuccess;
25 import org.apache.pekko.persistence.SnapshotMetadata;
26 import org.junit.jupiter.api.BeforeEach;
27 import org.junit.jupiter.api.Test;
28 import org.junit.jupiter.api.extension.ExtendWith;
29 import org.junit.jupiter.api.io.TempDir;
30 import org.mockito.Mock;
31 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.opendaylight.controller.cluster.DataPersistenceProvider;
33 import org.opendaylight.controller.cluster.raft.SnapshotManager.ApplyLeaderSnapshot;
34 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
35 import org.opendaylight.controller.cluster.raft.behaviors.RaftActorBehavior;
36 import org.opendaylight.controller.cluster.raft.persisted.ByteState;
37 import org.opendaylight.controller.cluster.raft.spi.ImmutableRaftEntryMeta;
38
39 /**
40  * Unit tests for RaftActorSnapshotMessageSupport.
41  *
42  * @author Thomas Pantelis
43  */
44 @ExtendWith(MockitoExtension.class)
45 class RaftActorSnapshotMessageSupportTest {
46     @Mock
47     private DataPersistenceProvider mockPersistence;
48     @Mock
49     private RaftActorBehavior mockBehavior;
50     @Mock
51     private RaftActorSnapshotCohort mockCohort;
52     @Mock
53     private SnapshotManager mockSnapshotManager;
54     @Mock
55     private ActorRef mockRaftActorRef;
56     @Mock
57     private ApplyLeaderSnapshot.Callback mockCallback;
58     @TempDir
59     private Path stateDir;
60
61     private RaftActorSnapshotMessageSupport support;
62
63     private RaftActorContext context;
64     private final DefaultConfigParamsImpl configParams = new DefaultConfigParamsImpl();
65
66     @BeforeEach
67     void beforeEach() throws Exception {
68         context = new RaftActorContextImpl(mockRaftActorRef, null, new LocalAccess("test", stateDir), -1, -1, Map.of(),
69             configParams, (short) 0, mockPersistence, applyState -> { }, MoreExecutors.directExecutor()) {
70                 @Override
71                 public SnapshotManager getSnapshotManager() {
72                     return mockSnapshotManager;
73                 }
74         };
75
76         support = new RaftActorSnapshotMessageSupport(context, mockCohort);
77
78         context.setReplicatedLog(ReplicatedLogImpl.newInstance(context));
79     }
80
81     private void sendMessageToSupport(final Object message) {
82         sendMessageToSupport(message, true);
83     }
84
85     private void sendMessageToSupport(final Object message, final boolean expHandled) {
86         boolean handled = support.handleSnapshotMessage(message, mockRaftActorRef);
87         assertEquals("complete", expHandled, handled);
88     }
89
90     @Test
91     public void testOnApplySnapshot() {
92         final var snapshot = new ApplyLeaderSnapshot("leaderId", 1, ImmutableRaftEntryMeta.of(2, 1),
93             ByteSource.wrap(new byte[] { 1, 2, 3, 4, 5 }), null, mockCallback);
94
95         sendMessageToSupport(snapshot);
96
97         verify(mockSnapshotManager).applyFromLeader(snapshot);
98     }
99
100     @Test
101     public void testOnCaptureSnapshotReply() {
102         ByteState state = ByteState.of(new byte[]{1,2,3,4,5});
103         final var stream = mock(OutputStream.class);
104         sendMessageToSupport(new CaptureSnapshotReply(state, stream));
105
106         verify(mockSnapshotManager).persist(eq(state), eq(Optional.of(stream)), anyLong());
107     }
108
109     @Test
110     public void testOnSaveSnapshotSuccess() {
111
112         long sequenceNumber = 100;
113         long timeStamp = 1234L;
114         sendMessageToSupport(new SaveSnapshotSuccess(new SnapshotMetadata("foo", sequenceNumber, timeStamp)));
115
116         verify(mockSnapshotManager).commit(eq(sequenceNumber), eq(timeStamp));
117     }
118
119     @Test
120     public void testOnSaveSnapshotFailure() {
121
122         sendMessageToSupport(new SaveSnapshotFailure(new SnapshotMetadata("foo", 100, 1234L),
123                 new Throwable("mock")));
124
125         verify(mockSnapshotManager).rollback();
126     }
127
128     @Test
129     public void testOnCommitSnapshot() {
130
131         sendMessageToSupport(RaftActorSnapshotMessageSupport.CommitSnapshot.INSTANCE);
132
133         verify(mockSnapshotManager).commit(eq(-1L), eq(-1L));
134     }
135
136     @Test
137     public void testUnhandledMessage() {
138
139         sendMessageToSupport("unhandled", false);
140     }
141 }