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