2 * Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
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
8 package org.opendaylight.controller.cluster.databroker.actors.dds;
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;
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;
46 public class LocalReadWriteProxyTransactionTest extends LocalProxyTransactionTest<LocalReadWriteProxyTransaction> {
48 private CursorAwareDataTreeModification modification;
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);
61 public void testIsSnapshotOnly() throws Exception {
62 Assert.assertFalse(transaction.isSnapshotOnly());
66 public void testReadOnlyView() throws Exception {
67 Assert.assertEquals(modification, transaction.readOnlyView());
72 public void testDelete() throws Exception {
73 transaction.delete(PATH_1);
74 verify(modification).delete(PATH_1);
79 public void testDirectCommit() throws Exception {
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);
90 public void testCanCommit() throws Exception {
91 testRequestResponse(transaction::canCommit, CommitLocalTransactionRequest.class,
92 TransactionCanCommitSuccess::new);
97 public void testPreCommit() throws Exception {
98 testRequestResponse(transaction::preCommit, TransactionPreCommitRequest.class,
99 TransactionPreCommitSuccess::new);
104 public void testDoCommit() throws Exception {
105 testRequestResponse(transaction::doCommit, TransactionDoCommitRequest.class, TransactionCommitSuccess::new);
110 public void testMerge() throws Exception {
111 transaction.merge(PATH_1, DATA_1);
112 verify(modification).merge(PATH_1, DATA_1);
117 public void testWrite() throws Exception {
118 transaction.write(PATH_1, DATA_1);
119 verify(modification).write(PATH_1, DATA_1);
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());
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);
140 public void testSealOnly() throws Exception {
141 assertOperationThrowsException(() -> transaction.getSnapshot(), IllegalStateException.class);
142 transaction.sealOnly();
143 Assert.assertEquals(modification, transaction.getSnapshot());
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);
163 public void testApplyModifyTransactionRequestCoordinated() throws Exception {
164 applyModifyTransactionRequest(true);
168 public void testApplyModifyTransactionRequestSimple() throws Exception {
169 applyModifyTransactionRequest(false);
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);
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);
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);
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);
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);
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);
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);
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());