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