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