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.opendaylight.controller.cluster.databroker.actors.dds.TestUtils.assertFutureEquals;
16 import akka.testkit.TestProbe;
17 import com.google.common.base.Ticker;
18 import java.util.function.Consumer;
19 import org.junit.Assert;
20 import org.junit.Test;
21 import org.mockito.ArgumentCaptor;
22 import org.mockito.invocation.InvocationOnMock;
23 import org.mockito.stubbing.Answer;
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.ExistsTransactionRequest;
27 import org.opendaylight.controller.cluster.access.commands.ExistsTransactionSuccess;
28 import org.opendaylight.controller.cluster.access.commands.ModifyTransactionRequest;
29 import org.opendaylight.controller.cluster.access.commands.PersistenceProtocol;
30 import org.opendaylight.controller.cluster.access.commands.ReadTransactionRequest;
31 import org.opendaylight.controller.cluster.access.commands.ReadTransactionSuccess;
32 import org.opendaylight.controller.cluster.access.commands.TransactionPurgeRequest;
33 import org.opendaylight.controller.cluster.access.commands.TransactionRequest;
34 import org.opendaylight.controller.cluster.access.concepts.Response;
35 import org.opendaylight.yangtools.yang.data.api.schema.tree.CursorAwareDataTreeModification;
36 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
38 public abstract class LocalProxyTransactionTest<T extends LocalProxyTransaction>
39 extends AbstractProxyTransactionTest<T> {
43 public void testExists() throws Exception {
44 assertFutureEquals(true, transaction.exists(PATH_1));
45 assertFutureEquals(false, transaction.exists(PATH_3));
50 public void testRead() throws Exception {
51 assertFutureEquals(com.google.common.base.Optional.of(DATA_1), transaction.read(PATH_1));
52 assertFutureEquals(com.google.common.base.Optional.absent(), transaction.read(PATH_3));
56 public void testDoAbort() throws Exception {
57 transaction.doAbort();
58 getTester().expectTransactionRequest(AbortLocalTransactionRequest.class);
62 public void testHandleForwardedRemoteReadRequest() throws Exception {
63 final TestProbe probe = createProbe();
64 final ReadTransactionRequest request =
65 new ReadTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), PATH_1, true);
66 final Consumer<Response<?, ?>> callback = createCallbackMock();
67 transaction.handleReplayedRemoteRequest(request, callback, Ticker.systemTicker().read());
68 final ArgumentCaptor<Response> captor = ArgumentCaptor.forClass(Response.class);
69 verify(callback).accept(captor.capture());
70 final Response<?, ?> value = captor.getValue();
71 Assert.assertTrue(value instanceof ReadTransactionSuccess);
72 final ReadTransactionSuccess success = (ReadTransactionSuccess) value;
73 Assert.assertTrue(success.getData().isPresent());
74 Assert.assertEquals(DATA_1, success.getData().get());
78 public void testHandleForwardedRemoteExistsRequest() throws Exception {
79 final TestProbe probe = createProbe();
80 final ExistsTransactionRequest request =
81 new ExistsTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), PATH_1, true);
82 final Consumer<Response<?, ?>> callback = createCallbackMock();
83 transaction.handleReplayedRemoteRequest(request, callback, Ticker.systemTicker().read());
84 final ArgumentCaptor<Response> captor = ArgumentCaptor.forClass(Response.class);
85 verify(callback).accept(captor.capture());
86 final Response<?, ?> value = captor.getValue();
87 Assert.assertTrue(value instanceof ExistsTransactionSuccess);
88 final ExistsTransactionSuccess success = (ExistsTransactionSuccess) value;
89 Assert.assertTrue(success.getExists());
93 public void testHandleForwardedRemotePurgeRequest() throws Exception {
94 final TestProbe probe = createProbe();
95 final TransactionPurgeRequest request =
96 new TransactionPurgeRequest(TRANSACTION_ID, 0L, probe.ref());
97 testHandleForwardedRemoteRequest(request);
102 public void testForwardToRemoteAbort() throws Exception {
103 final TestProbe probe = createProbe();
104 final AbortLocalTransactionRequest request = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
105 final ModifyTransactionRequest modifyRequest = testForwardToRemote(request, ModifyTransactionRequest.class);
106 Assert.assertTrue(modifyRequest.getPersistenceProtocol().isPresent());
107 Assert.assertEquals(PersistenceProtocol.ABORT, modifyRequest.getPersistenceProtocol().get());
112 public void testForwardToRemoteCommit() throws Exception {
113 final TestProbe probe = createProbe();
114 final CursorAwareDataTreeModification modification = mock(CursorAwareDataTreeModification.class);
115 final CommitLocalTransactionRequest request =
116 new CommitLocalTransactionRequest(TRANSACTION_ID, 0L, probe.ref(), modification, null, true);
117 doAnswer(this::applyToCursorAnswer).when(modification).applyToCursor(any());
118 final ModifyTransactionRequest modifyRequest = testForwardToRemote(request, ModifyTransactionRequest.class);
119 verify(modification).applyToCursor(any());
120 Assert.assertTrue(modifyRequest.getPersistenceProtocol().isPresent());
121 Assert.assertEquals(PersistenceProtocol.THREE_PHASE, modifyRequest.getPersistenceProtocol().get());
122 checkModifications(modifyRequest);
126 public void testForwardToLocalAbort() throws Exception {
127 final TestProbe probe = createProbe();
128 final AbortLocalTransactionRequest request = new AbortLocalTransactionRequest(TRANSACTION_ID, probe.ref());
129 testForwardToLocal(request, AbortLocalTransactionRequest.class);
133 public void testForwardToLocalPurge() throws Exception {
134 final TestProbe probe = createProbe();
135 final TransactionPurgeRequest request = new TransactionPurgeRequest(TRANSACTION_ID, 0L, probe.ref());
136 testForwardToLocal(request, TransactionPurgeRequest.class);
139 protected <T extends TransactionRequest<?>> T testForwardToLocal(final TransactionRequest<?> toForward,
140 final Class<T> expectedMessageClass) {
141 final Consumer<Response<?, ?>> callback = createCallbackMock();
142 final TransactionTester<LocalReadWriteProxyTransaction> transactionTester = createLocalProxy();
143 final LocalReadWriteProxyTransaction successor = transactionTester.getTransaction();
144 transaction.forwardToLocal(successor, toForward, callback);
145 return transactionTester.expectTransactionRequest(expectedMessageClass);
149 * To emulate side effect of void method.
150 * {@link CursorAwareDataTreeModification#applyToCursor(DataTreeModificationCursor)}
152 * @param invocation invocation
153 * @return void - always null
155 protected Answer<?> applyToCursorAnswer(final InvocationOnMock invocation) {
156 final DataTreeModificationCursor cursor =
157 invocation.getArgumentAt(0, DataTreeModificationCursor.class);
158 cursor.write(PATH_1.getLastPathArgument(), DATA_1);
159 cursor.merge(PATH_2.getLastPathArgument(), DATA_2);
160 cursor.delete(PATH_3.getLastPathArgument());