Improve segmented journal actor metrics
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / databroker / actors / dds / LocalProxyTransactionTest.java
1 /*
2  * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.databroker.actors.dds;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.Mockito.doAnswer;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.verify;
16 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertFutureEquals;
17
18 import akka.testkit.TestProbe;
19 import com.google.common.base.Ticker;
20 import java.util.Optional;
21 import java.util.function.Consumer;
22 import org.junit.Test;
23 import org.mockito.ArgumentCaptor;
24 import org.mockito.invocation.InvocationOnMock;
25 import org.mockito.stubbing.Answer;
26 import org.opendaylight.controller.cluster.access.client.ClientActorBehavior;
27 import org.opendaylight.controller.cluster.access.client.InternalCommand;
28 import org.opendaylight.controller.cluster.access.commands.AbortLocalTransactionRequest;
29 import org.opendaylight.controller.cluster.access.commands.CommitLocalTransactionRequest;
30 import org.opendaylight.controller.cluster.access.commands.ExistsTransactionRequest;
31 import org.opendaylight.controller.cluster.access.commands.ExistsTransactionSuccess;
32 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest;
33 import org.opendaylight.controller.cluster.access.commands.PersistenceProtocol;
34 import org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest;
35 import org.opendaylight.controller.cluster.access.commands.ReadTransactionSuccess;
36 import org.opendaylight.controller.cluster.access.commands.TransactionPurgeRequest;
37 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
38 import org.opendaylight.controller.cluster.access.concepts.Response;
39 import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification;
40 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModificationCursor;
41
42 public abstract class LocalProxyTransactionTest<T extends LocalProxyTransaction>
43         extends AbstractProxyTransactionTest<T> {
44
45     @Override
46     @Test
47     public void testExists() throws Exception {
48         assertFutureEquals(Boolean.TRUE, transaction.exists(PATH_1));
49         assertFutureEquals(Boolean.FALSE, transaction.exists(PATH_3));
50     }
51
52     @Override
53     @Test
54     public void testRead() throws Exception {
55         assertFutureEquals(Optional.of(DATA_1), transaction.read(PATH_1));
56         assertFutureEquals(Optional.empty(), transaction.read(PATH_3));
57     }
58
59     @Test
60     public void testAbort() {
61         transaction.abort();
62         getTester().expectTransactionRequest(AbortLocalTransactionRequest.class);
63     }
64
65     @SuppressWarnings("unchecked")
66     private void setupExecuteInActor() {
67         doAnswer(inv -> {
68             inv.getArgument(0, InternalCommand.class).execute(mock(ClientActorBehavior.class));
69             return null;
70         }).when(context).executeInActor(any(InternalCommand.class));
71     }
72
73     @Test
74     public void testHandleForwardedRemoteReadRequest() {
75         final TestProbe probe = createProbe();
76         final ReadTransactionRequest request =
77                 new ReadTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), PATH_1, true);
78         final Consumer<Response<?, ?>> callback = createCallbackMock();
79         setupExecuteInActor();
80
81         transaction.handleReplayedRemoteRequest(request, callback, Ticker.systemTicker().read());
82         final ArgumentCaptor<Response<?, ?>> captor = ArgumentCaptor.forClass(Response.class);
83         verify(callback).accept(captor.capture());
84         final Response<?, ?> value = captor.getValue();
85         assertTrue(value instanceof ReadTransactionSuccess);
86         final ReadTransactionSuccess success = (ReadTransactionSuccess) value;
87         assertEquals(Optional.of(DATA_1), success.getData());
88     }
89
90     @Test
91     public void testHandleForwardedRemoteExistsRequest() {
92         final TestProbe probe = createProbe();
93         final ExistsTransactionRequest request =
94                 new ExistsTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), PATH_1, true);
95         final Consumer<Response<?, ?>> callback = createCallbackMock();
96         setupExecuteInActor();
97
98         transaction.handleReplayedRemoteRequest(request, callback, Ticker.systemTicker().read());
99         final ArgumentCaptor<Response<?, ?>> captor = ArgumentCaptor.forClass(Response.class);
100         verify(callback).accept(captor.capture());
101         final Response<?, ?> value = captor.getValue();
102         assertTrue(value instanceof ExistsTransactionSuccess);
103         final ExistsTransactionSuccess success = (ExistsTransactionSuccess) value;
104         assertTrue(success.getExists());
105     }
106
107     @Test
108     public void testHandleForwardedRemotePurgeRequest() {
109         final TestProbe probe = createProbe();
110         final TransactionPurgeRequest request = new TransactionPurgeRequest(TRANSACTION_ID, 0L, probe.ref());
111         testHandleForwardedRemoteRequest(request);
112     }
113
114     @Override
115     @Test
116     public void testForwardToRemoteAbort() {
117         final TestProbe probe = createProbe();
118         final AbortLocalTransactionRequest request = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
119         final ModifyTransactionRequest modifyRequest = testForwardToRemote(request, ModifyTransactionRequest.class);
120         assertEquals(Optional.of(PersistenceProtocol.ABORT), modifyRequest.getPersistenceProtocol());
121     }
122
123     @Override
124     @Test
125     public void testForwardToRemoteCommit() {
126         final TestProbe probe = createProbe();
127         final CursorAwareDataTreeModification modification = mock(CursorAwareDataTreeModification.class);
128         final CommitLocalTransactionRequest request =
129                 new CommitLocalTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), modification, null, true);
130         doAnswer(LocalProxyTransactionTest::applyToCursorAnswer).when(modification).applyToCursor(any());
131         final ModifyTransactionRequest modifyRequest = testForwardToRemote(request, ModifyTransactionRequest.class);
132         verify(modification).applyToCursor(any());
133         assertEquals(Optional.of(PersistenceProtocol.THREE_PHASE), modifyRequest.getPersistenceProtocol());
134         checkModifications(modifyRequest);
135     }
136
137     @Test
138     public void testForwardToLocalAbort() {
139         final TestProbe probe = createProbe();
140         final AbortLocalTransactionRequest request = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
141         testForwardToLocal(request, AbortLocalTransactionRequest.class);
142     }
143
144     @Test
145     public void testForwardToLocalPurge() {
146         final TestProbe probe = createProbe();
147         final TransactionPurgeRequest request = new TransactionPurgeRequest(TRANSACTION_ID, 0L, probe.ref());
148         testForwardToLocal(request, TransactionPurgeRequest.class);
149     }
150
151     protected <R extends TransactionRequest<R>> R testForwardToLocal(final TransactionRequest<?> toForward,
152                                                                      final Class<R> expectedMessageClass) {
153         final Consumer<Response<?, ?>> callback = createCallbackMock();
154         final TransactionTester<LocalReadWriteProxyTransaction> transactionTester = createLocalProxy();
155         final LocalReadWriteProxyTransaction successor = transactionTester.getTransaction();
156         transaction.forwardToLocal(successor, toForward, callback);
157         return transactionTester.expectTransactionRequest(expectedMessageClass);
158     }
159
160     /**
161      * To emulate side effect of void method.
162      * {@link CursorAwareDataTreeModification#applyToCursor(DataTreeModificationCursor)}
163      *
164      * @param invocation invocation
165      * @return void - always null
166      */
167     protected static final <T> Answer<T> applyToCursorAnswer(final InvocationOnMock invocation) {
168         final DataTreeModificationCursor cursor = invocation.getArgument(0);
169         cursor.write(PATH_1.getLastPathArgument(), DATA_1);
170         cursor.merge(PATH_2.getLastPathArgument(), DATA_2);
171         cursor.delete(PATH_3.getLastPathArgument());
172         return null;
173     }
174 }