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