Cleanup Local*ProxyTransactionTest
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / databroker / actors / dds / LocalReadWriteProxyTransactionTest.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.assertFalse;
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.mockito.Mockito.when;
17 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertFutureEquals;
18 import static org.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertOperationThrowsException;
19
20 import akka.testkit.TestProbe;
21 import com.google.common.base.Ticker;
22 import com.google.common.util.concurrent.ListenableFuture;
23 import java.util.Optional;
24 import java.util.function.Consumer;
25 import org.junit.Test;
26 import org.mockito.Mock;
27 import org.opendaylight.controller.cluster.access.commands.AbortLocalTransactionRequest;
28 import org.opendaylight.controller.cluster.access.commands.CommitLocalTransactionRequest;
29 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest;
30 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequestBuilder;
31 import org.opendaylight.controller.cluster.access.commands.TransactionAbortRequest;
32 import org.opendaylight.controller.cluster.access.commands.TransactionCanCommitSuccess;
33 import org.opendaylight.controller.cluster.access.commands.TransactionCommitSuccess;
34 import org.opendaylight.controller.cluster.access.commands.TransactionDelete;
35 import org.opendaylight.controller.cluster.access.commands.TransactionDoCommitRequest;
36 import org.opendaylight.controller.cluster.access.commands.TransactionMerge;
37 import org.opendaylight.controller.cluster.access.commands.TransactionModification;
38 import org.opendaylight.controller.cluster.access.commands.TransactionPreCommitRequest;
39 import org.opendaylight.controller.cluster.access.commands.TransactionPreCommitSuccess;
40 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
41 import org.opendaylight.controller.cluster.access.commands.TransactionWrite;
42 import org.opendaylight.controller.cluster.access.concepts.Response;
43 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
44 import org.opendaylight.yangtools.yang.data.tree.api.CursorAwareDataTreeModification;
45 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
46 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
47
48 public class LocalReadWriteProxyTransactionTest extends LocalProxyTransactionTest<LocalReadWriteProxyTransaction> {
49     @Mock
50     private CursorAwareDataTreeModification modification;
51
52     @Override
53     protected LocalReadWriteProxyTransaction createTransaction(final ProxyHistory parent,
54                                                                final TransactionIdentifier id,
55                                                                final DataTreeSnapshot snapshot) {
56         when(snapshot.newModification()).thenReturn(modification);
57         when(modification.readNode(PATH_1)).thenReturn(Optional.of(DATA_1));
58         when(modification.readNode(PATH_3)).thenReturn(Optional.empty());
59         return new LocalReadWriteProxyTransaction(parent, TestUtils.TRANSACTION_ID, snapshot);
60     }
61
62     @Test
63     public void testIsSnapshotOnly() {
64         assertFalse(transaction.isSnapshotOnly());
65     }
66
67     @Test
68     public void testReadOnlyView() {
69         assertEquals(modification, transaction.readOnlyView());
70     }
71
72     @Test
73     @Override
74     public void testDelete() {
75         transaction.delete(PATH_1);
76         verify(modification).delete(PATH_1);
77     }
78
79     @Test
80     @Override
81     public void testDirectCommit() throws Exception {
82         transaction.seal();
83         final ListenableFuture<Boolean> result = transaction.directCommit();
84         final TransactionTester<LocalReadWriteProxyTransaction> tester = getTester();
85         final CommitLocalTransactionRequest req = tester.expectTransactionRequest(CommitLocalTransactionRequest.class);
86         tester.replySuccess(new TransactionCommitSuccess(TRANSACTION_ID, req.getSequence()));
87         assertFutureEquals(Boolean.TRUE, result);
88     }
89
90     @Test
91     @Override
92     public void testCanCommit() {
93         testRequestResponse(transaction::canCommit, CommitLocalTransactionRequest.class,
94                 TransactionCanCommitSuccess::new);
95     }
96
97     @Test
98     @Override
99     public void testPreCommit() {
100         testRequestResponse(transaction::preCommit, TransactionPreCommitRequest.class,
101                 TransactionPreCommitSuccess::new);
102     }
103
104     @Test
105     @Override
106     public void testDoCommit() {
107         testRequestResponse(transaction::doCommit, TransactionDoCommitRequest.class, TransactionCommitSuccess::new);
108     }
109
110     @Test
111     @Override
112     public void testMerge() {
113         transaction.merge(PATH_1, DATA_1);
114         verify(modification).merge(PATH_1, DATA_1);
115     }
116
117     @Test
118     @Override
119     public void testWrite() {
120         transaction.write(PATH_1, DATA_1);
121         verify(modification).write(PATH_1, DATA_1);
122     }
123
124     @Test
125     public void testCommitRequest() {
126         transaction.doWrite(PATH_1, DATA_1);
127         final boolean coordinated = true;
128         final CommitLocalTransactionRequest request = transaction.commitRequest(coordinated);
129         assertEquals(coordinated, request.isCoordinated());
130         assertEquals(modification, request.getModification());
131     }
132
133     @Test
134     public void testModifyAfterCommitRequest() throws Exception {
135         transaction.doWrite(PATH_1, DATA_1);
136         final boolean coordinated = true;
137         transaction.commitRequest(coordinated);
138         assertOperationThrowsException(() -> transaction.doMerge(PATH_1, DATA_1), IllegalStateException.class);
139     }
140
141     @Test
142     public void testSealOnly() throws Exception {
143         assertOperationThrowsException(() -> transaction.getSnapshot(), IllegalStateException.class);
144         transaction.sealOnly();
145         assertEquals(modification, transaction.getSnapshot());
146     }
147
148     @Test
149     public void testFlushState() {
150         final TransactionTester<RemoteProxyTransaction> transactionTester = createRemoteProxyTransactionTester();
151         final RemoteProxyTransaction successor = transactionTester.getTransaction();
152         doAnswer(LocalProxyTransactionTest::applyToCursorAnswer).when(modification).applyToCursor(any());
153         transaction.sealOnly();
154         final TransactionRequest<?> request = transaction.flushState().get();
155         transaction.forwardToSuccessor(successor, request, null);
156         verify(modification).applyToCursor(any());
157         transactionTester.getTransaction().seal();
158         transactionTester.getTransaction().directCommit();
159         final ModifyTransactionRequest modifyRequest =
160                 transactionTester.expectTransactionRequest(ModifyTransactionRequest.class);
161         checkModifications(modifyRequest);
162     }
163
164     @Test
165     public void testApplyModifyTransactionRequestCoordinated() {
166         applyModifyTransactionRequest(true);
167     }
168
169     @Test
170     public void testApplyModifyTransactionRequestSimple() {
171         applyModifyTransactionRequest(false);
172     }
173
174     @Test
175     public void testApplyModifyTransactionRequestAbort() {
176         final TestProbe probe = createProbe();
177         final ModifyTransactionRequestBuilder builder =
178                 new ModifyTransactionRequestBuilder(TRANSACTION_ID, probe.ref());
179         builder.setSequence(0L);
180         builder.setAbort();
181         final ModifyTransactionRequest request = builder.build();
182         final Consumer<Response<?, ?>> callback = createCallbackMock();
183         transaction.replayModifyTransactionRequest(request, callback, Ticker.systemTicker().read());
184         getTester().expectTransactionRequest(AbortLocalTransactionRequest.class);
185     }
186
187     @Test
188     public void testHandleForwardedRemotePreCommitRequest() {
189         final TestProbe probe = createProbe();
190         final TransactionPreCommitRequest request =
191                 new TransactionPreCommitRequest(TRANSACTION_ID, 0L, probe.ref());
192         testHandleForwardedRemoteRequest(request);
193     }
194
195     @Test
196     public void testHandleForwardedRemoteDoCommitRequest() {
197         final TestProbe probe = createProbe();
198         final TransactionDoCommitRequest request =
199                 new TransactionDoCommitRequest(TRANSACTION_ID, 0L, probe.ref());
200         testHandleForwardedRemoteRequest(request);
201     }
202
203     @Test
204     public void testHandleForwardedRemoteAbortRequest() {
205         final TestProbe probe = createProbe();
206         final TransactionAbortRequest request =
207                 new TransactionAbortRequest(TRANSACTION_ID, 0L, probe.ref());
208         testHandleForwardedRemoteRequest(request);
209     }
210
211     @Test
212     public void testForwardToLocalCommit() {
213         final TestProbe probe = createProbe();
214         final DataTreeModification mod = mock(DataTreeModification.class);
215         final TransactionRequest<?> request =
216                 new CommitLocalTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), mod, null, false);
217         testForwardToLocal(request, CommitLocalTransactionRequest.class);
218     }
219
220     @Test
221     public void testSendAbort() throws Exception {
222         final TestProbe probe = createProbe();
223         final TransactionRequest<?> request = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
224         transaction.sendAbort(request, createCallbackMock());
225         assertOperationThrowsException(() -> transaction.delete(PATH_1), IllegalStateException.class);
226     }
227
228     private void applyModifyTransactionRequest(final boolean coordinated) {
229         final TestProbe probe = createProbe();
230         final ModifyTransactionRequestBuilder builder =
231                 new ModifyTransactionRequestBuilder(TRANSACTION_ID, probe.ref());
232         final TransactionModification write = new TransactionWrite(PATH_1, DATA_1);
233         final TransactionModification merge = new TransactionMerge(PATH_2, DATA_2);
234         final TransactionModification delete = new TransactionDelete(PATH_3);
235         builder.addModification(write);
236         builder.addModification(merge);
237         builder.addModification(delete);
238         builder.setSequence(0L);
239         builder.setCommit(coordinated);
240         final ModifyTransactionRequest request = builder.build();
241         final Consumer<Response<?, ?>> callback = createCallbackMock();
242         transaction.replayModifyTransactionRequest(request, callback, Ticker.systemTicker().read());
243         verify(modification).write(PATH_1, DATA_1);
244         verify(modification).merge(PATH_2, DATA_2);
245         verify(modification).delete(PATH_3);
246         final CommitLocalTransactionRequest commitRequest =
247                 getTester().expectTransactionRequest(CommitLocalTransactionRequest.class);
248         assertEquals(modification, commitRequest.getModification());
249         assertEquals(coordinated, commitRequest.isCoordinated());
250     }
251
252 }