2 * Copyright © 2017 Orange, Inc. 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
9 package org.opendaylight.transportpce.common.device;
11 import static org.mockito.Matchers.any;
13 import com.google.common.base.Optional;
14 import com.google.common.util.concurrent.FluentFuture;
15 import com.google.common.util.concurrent.Futures;
16 import com.google.common.util.concurrent.ListeningExecutorService;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.util.LinkedList;
19 import java.util.List;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.Future;
23 import java.util.concurrent.TimeUnit;
24 import java.util.concurrent.TimeoutException;
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.junit.After;
27 import org.junit.Assert;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.mockito.Mockito;
33 import org.mockito.runners.MockitoJUnitRunner;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
36 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
37 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
39 import org.opendaylight.mdsal.common.api.CommitInfo;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkBuilder;
42 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
43 import org.opendaylight.yangtools.yang.binding.DataObject;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47 @RunWith(MockitoJUnitRunner.class)
48 public class DeviceTransactionManagerTest {
50 @Mock private MountPointService mountPointServiceMock;
51 @Mock private MountPoint mountPointMock;
52 @Mock private DataBroker dataBrokerMock;
53 @Mock private ReadWriteTransaction rwTransactionMock;
55 private DeviceTransactionManagerImpl transactionManager;
56 private String defaultDeviceId = "device-id";
57 private LogicalDatastoreType defaultDatastore = LogicalDatastoreType.OPERATIONAL;
58 private InstanceIdentifier<Network> defaultIid = InstanceIdentifier.create(Network.class);
59 private Network defaultData = new NetworkBuilder().build();
60 private long defaultTimeout = 1000;
61 private TimeUnit defaultTimeUnit = TimeUnit.MILLISECONDS;
64 public void before() {
65 Mockito.when(mountPointServiceMock.getMountPoint(any())).thenReturn(Optional.of(mountPointMock));
66 Mockito.when(mountPointMock.getService(any())).thenReturn(Optional.of(dataBrokerMock));
67 Mockito.when(dataBrokerMock.newReadWriteTransaction()).thenReturn(rwTransactionMock);
68 Mockito.doReturn(FluentFutures.immediateNullFluentFuture()).when(rwTransactionMock.commit());
70 this.transactionManager = new DeviceTransactionManagerImpl(mountPointServiceMock, 3000);
75 transactionManager.preDestroy();
79 public void basicPositiveTransactionTest() {
81 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
82 } catch (InterruptedException | ExecutionException e) {
83 Assert.fail("Exception catched! " + e);
87 Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
88 Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
92 public void advancedPositiveTransactionTest() {
94 Future<java.util.Optional<DeviceTransaction>> firstDeviceTxFuture =
95 transactionManager.getDeviceTransaction(defaultDeviceId);
96 DeviceTransaction firstDeviceTx = firstDeviceTxFuture.get().get();
98 Future<java.util.Optional<DeviceTransaction>> secondDeviceTxFuture =
99 transactionManager.getDeviceTransaction(defaultDeviceId);
100 Assert.assertFalse(secondDeviceTxFuture.isDone());
102 Future<java.util.Optional<DeviceTransaction>> thirdDeviceTxFuture =
103 transactionManager.getDeviceTransaction(defaultDeviceId);
104 Assert.assertFalse(thirdDeviceTxFuture.isDone());
106 firstDeviceTx.put(defaultDatastore, defaultIid, defaultData);
107 Assert.assertFalse(secondDeviceTxFuture.isDone());
108 Assert.assertFalse(thirdDeviceTxFuture.isDone());
110 Assert.assertFalse(secondDeviceTxFuture.isDone());
111 Assert.assertFalse(thirdDeviceTxFuture.isDone());
113 Future<java.util.Optional<DeviceTransaction>> anotherDeviceTxFuture =
114 transactionManager.getDeviceTransaction("another-id");
115 Assert.assertTrue(anotherDeviceTxFuture.isDone());
116 anotherDeviceTxFuture.get().get().commit(defaultTimeout, defaultTimeUnit);
118 firstDeviceTx.commit(defaultTimeout, defaultTimeUnit);
120 Assert.assertTrue(secondDeviceTxFuture.isDone());
121 Assert.assertFalse(thirdDeviceTxFuture.isDone());
123 DeviceTransaction secondDeviceTx = secondDeviceTxFuture.get().get();
124 secondDeviceTx.put(defaultDatastore, defaultIid, defaultData);
125 Assert.assertFalse(thirdDeviceTxFuture.isDone());
127 secondDeviceTx.commit(defaultTimeout, defaultTimeUnit);
129 Assert.assertTrue(thirdDeviceTxFuture.isDone());
131 DeviceTransaction thirdDeviceTx = thirdDeviceTxFuture.get().get();
132 thirdDeviceTx.put(defaultDatastore, defaultIid, defaultData);
133 thirdDeviceTx.commit(defaultTimeout, defaultTimeUnit);
135 Mockito.verify(rwTransactionMock, Mockito.times(3)).put(defaultDatastore, defaultIid, defaultData);
136 Mockito.verify(rwTransactionMock, Mockito.times(4)).commit();
137 } catch (InterruptedException | ExecutionException e) {
138 Assert.fail("Exception catched! " + e);
143 public void bigAmountOfTransactionsOnSameDeviceTest() {
144 int numberOfTxs = 100;
145 List<Future<java.util.Optional<DeviceTransaction>>> deviceTransactionFutures = new LinkedList<>();
146 List<DeviceTransaction> deviceTransactions = new LinkedList<>();
148 for (int i = 0; i < numberOfTxs; i++) {
149 deviceTransactionFutures.add(transactionManager.getDeviceTransaction(defaultDeviceId));
153 for (Future<java.util.Optional<DeviceTransaction>> futureTx : deviceTransactionFutures) {
154 DeviceTransaction deviceTx = futureTx.get().get();
155 deviceTx.commit(defaultTimeout, defaultTimeUnit);
156 deviceTransactions.add(deviceTx);
158 } catch (InterruptedException | ExecutionException e) {
159 Assert.fail("Exception catched! " + e);
162 for (DeviceTransaction deviceTx : deviceTransactions) {
163 Assert.assertTrue(deviceTx.wasSubmittedOrCancelled().get());
168 public void bigAmountOfTransactionsOnDifferentDevicesTest() {
169 int numberOfTxs = 1000;
170 List<DeviceTransaction> deviceTransactions = new LinkedList<>();
173 for (int i = 0; i < numberOfTxs; i++) {
174 deviceTransactions.add(transactionManager.getDeviceTransaction(defaultDeviceId + " " + i).get().get());
176 } catch (InterruptedException | ExecutionException e) {
177 Assert.fail("Exception catched! " + e);
180 deviceTransactions.parallelStream()
181 .forEach(deviceTransaction -> deviceTransaction.commit(defaultTimeout, defaultTimeUnit));
183 deviceTransactions.parallelStream()
184 .forEach(deviceTransaction -> Assert.assertTrue(deviceTransaction.wasSubmittedOrCancelled().get()));
188 public void bigAmountOfTransactionsOnDifferentDevicesWithoutSubmitTest() {
189 int numberOfTxs = 1000;
190 List<DeviceTransaction> deviceTransactions = new LinkedList<>();
193 for (int i = 0; i < numberOfTxs; i++) {
194 deviceTransactions.add(transactionManager.getDeviceTransaction(defaultDeviceId + " " + i).get().get());
196 } catch (InterruptedException | ExecutionException e) {
197 Assert.fail("Exception catched! " + e);
201 Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
202 } catch (InterruptedException e) {
203 Assert.fail("Exception catched! " + e);
205 deviceTransactions.parallelStream()
206 .forEach(deviceTransaction -> Assert.assertTrue(deviceTransaction.wasSubmittedOrCancelled().get()));
210 public void notSubmittedTransactionTest() {
211 Future<java.util.Optional<DeviceTransaction>> deviceTxFuture =
212 transactionManager.getDeviceTransaction(defaultDeviceId);
214 deviceTxFuture.get();
215 Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
216 } catch (InterruptedException | ExecutionException e) {
217 Assert.fail("Exception catched! " + e);
219 Mockito.verify(rwTransactionMock, Mockito.times(1)).cancel();
222 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
223 } catch (InterruptedException | ExecutionException e) {
224 Assert.fail("Exception catched! " + e);
228 Mockito.verify(rwTransactionMock, Mockito.times(1)).cancel();
229 Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
230 Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
234 public void dataBrokerTimeoutTransactionTest() {
235 Mockito.when(dataBrokerMock.newReadWriteTransaction()).then(invocation -> {
236 Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
237 return rwTransactionMock;
241 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
242 } catch (InterruptedException | ExecutionException e) {
243 Assert.fail("Exception catched! " + e);
246 Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
248 Mockito.when(dataBrokerMock.newReadWriteTransaction()).thenReturn(rwTransactionMock); // remove sleep
251 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
252 } catch (InterruptedException | ExecutionException e) {
253 Assert.fail("Exception catched! " + e);
257 Mockito.verify(rwTransactionMock, Mockito.times(2)).put(defaultDatastore, defaultIid, defaultData);
258 Mockito.verify(rwTransactionMock, Mockito.times(2)).commit();
262 public void getFutureTimeoutTransactionTest() {
263 Mockito.when(dataBrokerMock.newReadWriteTransaction()).then(invocation -> {
265 return rwTransactionMock;
268 Exception throwedException = null;
270 Future<java.util.Optional<DeviceTransaction>> deviceTxFuture =
271 transactionManager.getDeviceTransaction(defaultDeviceId);
273 deviceTxFuture.get(1000, TimeUnit.MILLISECONDS);
274 } catch (InterruptedException | ExecutionException e) {
275 Assert.fail("Exception catched! " + e);
276 } catch (TimeoutException e) {
277 throwedException = e;
280 if (throwedException == null) {
281 Assert.fail("TimeoutException should be thrown!");
285 Mockito.when(dataBrokerMock.newReadWriteTransaction()).thenReturn(rwTransactionMock); // remove sleep
288 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
289 } catch (InterruptedException | ExecutionException e) {
290 Assert.fail("Exception catched! " + e);
294 Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
295 Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
299 public void submitTxTimeoutTransactionTest() {
300 ListeningExecutorService executor = MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
301 Mockito.when(rwTransactionMock.commit()).then(invocation -> Futures.makeChecked(executor.submit(() -> {
304 } catch (InterruptedException e) {
305 Assert.fail("Exception catched in future! " + e);
308 }), input -> input));
310 Future<java.util.Optional<DeviceTransaction>> deviceTxFuture =
311 transactionManager.getDeviceTransaction(defaultDeviceId);
312 DeviceTransaction deviceTx;
314 deviceTx = deviceTxFuture.get().get();
315 } catch (InterruptedException | ExecutionException e) {
316 Assert.fail("Exception catched! " + e);
320 deviceTx.put(defaultDatastore, defaultIid, defaultData);
322 Exception throwedException = null;
324 FluentFuture<? extends @NonNull CommitInfo> submitFuture = deviceTx.commit(200, defaultTimeUnit);
327 } catch (InterruptedException e) {
328 Assert.fail("Exception catched! " + e);
329 } catch (ExecutionException e) {
330 throwedException = e;
333 if (throwedException == null
334 || !throwedException.getMessage().contains(TimeoutException.class.getName())) {
335 Assert.fail("TimeoutException inside of should be thrown!");
340 Mockito.doReturn(FluentFutures.immediateNullFluentFuture()).when(rwTransactionMock.commit());
343 putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
344 } catch (InterruptedException | ExecutionException e) {
345 Assert.fail("Exception catched! " + e);
349 Mockito.verify(rwTransactionMock, Mockito.times(2)).put(defaultDatastore, defaultIid, defaultData);
350 Mockito.verify(rwTransactionMock, Mockito.times(2)).commit();
355 private <T extends DataObject> void putAndSubmit(DeviceTransactionManagerImpl deviceTxManager, String deviceId,
356 LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
357 throws ExecutionException, InterruptedException {
358 Future<java.util.Optional<DeviceTransaction>> deviceTxFuture = deviceTxManager.getDeviceTransaction(deviceId);
359 DeviceTransaction deviceTx = deviceTxFuture.get().get();
360 deviceTx.put(store, path, data);
361 deviceTx.commit(defaultTimeout, defaultTimeUnit);