Bump to Silicon
[transportpce.git] / common / src / test / java / org / opendaylight / transportpce / common / device / DeviceTransactionManagerTest.java
1 /*
2  * Copyright © 2017 Orange, Inc. 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
9 package org.opendaylight.transportpce.common.device;
10
11 import static org.mockito.ArgumentMatchers.any;
12
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.Optional;
16 import java.util.concurrent.ExecutionException;
17 import java.util.concurrent.Future;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20 import org.junit.After;
21 import org.junit.Assert;
22 import org.junit.Before;
23 import org.junit.Ignore;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.Mock;
27 import org.mockito.Mockito;
28 import org.mockito.junit.MockitoJUnitRunner;
29 import org.opendaylight.mdsal.binding.api.DataBroker;
30 import org.opendaylight.mdsal.binding.api.MountPoint;
31 import org.opendaylight.mdsal.binding.api.MountPointService;
32 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
33 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.NetworkId;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.Network;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.network.rev180226.networks.NetworkBuilder;
37 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
38 import org.opendaylight.yangtools.yang.binding.DataObject;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40
41
42 @RunWith(MockitoJUnitRunner.class)
43 public class DeviceTransactionManagerTest {
44
45     @Mock
46     private MountPointService mountPointServiceMock;
47     @Mock
48     private MountPoint mountPointMock;
49     @Mock
50     private DataBroker dataBrokerMock;
51     @Mock
52     private ReadWriteTransaction rwTransactionMock;
53
54
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;
60     private long defaultTimeout = 1000;
61     private TimeUnit defaultTimeUnit = TimeUnit.MILLISECONDS;
62
63     @Before
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.when(rwTransactionMock.commit()).thenReturn(FluentFutures.immediateNullFluentFuture());
69         NetworkId networkId =  new NetworkId("NETWORK1");
70         defaultData = new NetworkBuilder().setNetworkId(networkId).build();
71         this.transactionManager = new DeviceTransactionManagerImpl(mountPointServiceMock, 3000);
72     }
73
74     @After
75     public void after() {
76         transactionManager.preDestroy();
77     }
78
79     @Test
80     public void basicPositiveTransactionTest() {
81         try {
82             putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
83         } catch (InterruptedException | ExecutionException e) {
84             Assert.fail("Exception catched! " + e);
85             return;
86         }
87
88         Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
89         Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
90     }
91
92     @Test
93     @Ignore
94     public void advancedPositiveTransactionTest() {
95         try {
96             Future<java.util.Optional<DeviceTransaction>> firstDeviceTxFuture =
97                     transactionManager.getDeviceTransaction(defaultDeviceId);
98             DeviceTransaction firstDeviceTx = firstDeviceTxFuture.get().get();
99
100             Future<java.util.Optional<DeviceTransaction>> secondDeviceTxFuture =
101                     transactionManager.getDeviceTransaction(defaultDeviceId);
102             Assert.assertFalse(secondDeviceTxFuture.isDone());
103
104             Future<java.util.Optional<DeviceTransaction>> thirdDeviceTxFuture =
105                     transactionManager.getDeviceTransaction(defaultDeviceId);
106             Assert.assertFalse(thirdDeviceTxFuture.isDone());
107
108             firstDeviceTx.put(defaultDatastore, defaultIid, defaultData);
109             Assert.assertFalse(secondDeviceTxFuture.isDone());
110             Assert.assertFalse(thirdDeviceTxFuture.isDone());
111             Thread.sleep(200);
112             Assert.assertFalse(secondDeviceTxFuture.isDone());
113             Assert.assertFalse(thirdDeviceTxFuture.isDone());
114
115             Future<java.util.Optional<DeviceTransaction>> anotherDeviceTxFuture =
116                     transactionManager.getDeviceTransaction("another-id");
117             Assert.assertTrue(anotherDeviceTxFuture.isDone());
118             anotherDeviceTxFuture.get().get().commit(defaultTimeout, defaultTimeUnit);
119
120             firstDeviceTx.commit(defaultTimeout, defaultTimeUnit);
121             Thread.sleep(200);
122             Assert.assertTrue(secondDeviceTxFuture.isDone());
123             Assert.assertFalse(thirdDeviceTxFuture.isDone());
124
125             DeviceTransaction secondDeviceTx = secondDeviceTxFuture.get().get();
126             secondDeviceTx.put(defaultDatastore, defaultIid, defaultData);
127             Assert.assertFalse(thirdDeviceTxFuture.isDone());
128
129             secondDeviceTx.commit(defaultTimeout, defaultTimeUnit);
130             Thread.sleep(200);
131             Assert.assertTrue(thirdDeviceTxFuture.isDone());
132
133             DeviceTransaction thirdDeviceTx = thirdDeviceTxFuture.get().get();
134             thirdDeviceTx.put(defaultDatastore, defaultIid, defaultData);
135             thirdDeviceTx.commit(defaultTimeout, defaultTimeUnit);
136
137             Mockito.verify(rwTransactionMock, Mockito.times(3)).put(defaultDatastore, defaultIid, defaultData);
138             Mockito.verify(rwTransactionMock, Mockito.times(4)).commit();
139         } catch (InterruptedException | ExecutionException e) {
140             Assert.fail("Exception catched! " + e);
141         }
142     }
143
144     @Test
145     public void bigAmountOfTransactionsOnSameDeviceTest() {
146         int numberOfTxs = 100;
147         List<Future<java.util.Optional<DeviceTransaction>>> deviceTransactionFutures = new LinkedList<>();
148         List<DeviceTransaction> deviceTransactions = new LinkedList<>();
149
150         for (int i = 0; i < numberOfTxs; i++) {
151             deviceTransactionFutures.add(transactionManager.getDeviceTransaction(defaultDeviceId));
152         }
153
154         try {
155             for (Future<java.util.Optional<DeviceTransaction>> futureTx : deviceTransactionFutures) {
156                 DeviceTransaction deviceTx = futureTx.get().get();
157                 deviceTx.commit(defaultTimeout, defaultTimeUnit);
158                 deviceTransactions.add(deviceTx);
159             }
160         } catch (InterruptedException | ExecutionException e) {
161             Assert.fail("Exception catched! " + e);
162         }
163
164         for (DeviceTransaction deviceTx : deviceTransactions) {
165             Assert.assertTrue(deviceTx.wasSubmittedOrCancelled().get());
166         }
167     }
168
169     @Test
170     public void bigAmountOfTransactionsOnDifferentDevicesTest() {
171         int numberOfTxs = 1000;
172         List<DeviceTransaction> deviceTransactions = new LinkedList<>();
173
174         try {
175             for (int i = 0; i < numberOfTxs; i++) {
176                 deviceTransactions.add(transactionManager.getDeviceTransaction(defaultDeviceId + " " + i).get().get());
177             }
178         } catch (InterruptedException | ExecutionException e) {
179             Assert.fail("Exception catched! " + e);
180         }
181
182         deviceTransactions.parallelStream()
183                 .forEach(deviceTransaction -> deviceTransaction.commit(defaultTimeout, defaultTimeUnit));
184
185         deviceTransactions.parallelStream()
186                 .forEach(deviceTransaction -> Assert.assertTrue(deviceTransaction.wasSubmittedOrCancelled().get()));
187     }
188
189     @Test
190     public void bigAmountOfTransactionsOnDifferentDevicesWithoutSubmitTest() {
191         int numberOfTxs = 1000;
192         List<DeviceTransaction> deviceTransactions = new LinkedList<>();
193
194         try {
195             for (int i = 0; i < numberOfTxs; i++) {
196                 deviceTransactions.add(transactionManager.getDeviceTransaction(defaultDeviceId + " " + i).get().get());
197             }
198         } catch (InterruptedException | ExecutionException e) {
199             Assert.fail("Exception catched! " + e);
200         }
201
202         try {
203             Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
204         } catch (InterruptedException e) {
205             Assert.fail("Exception catched! " + e);
206         }
207         deviceTransactions.parallelStream()
208                 .forEach(deviceTransaction -> Assert.assertTrue(deviceTransaction.wasSubmittedOrCancelled().get()));
209     }
210
211     @Test
212     public void notSubmittedTransactionTest() {
213         Future<java.util.Optional<DeviceTransaction>> deviceTxFuture =
214                 transactionManager.getDeviceTransaction(defaultDeviceId);
215         try {
216             deviceTxFuture.get();
217             Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
218         } catch (InterruptedException | ExecutionException e) {
219             Assert.fail("Exception catched! " + e);
220         }
221         Mockito.verify(rwTransactionMock, Mockito.times(1)).cancel();
222
223         try {
224             putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
225         } catch (InterruptedException | ExecutionException e) {
226             Assert.fail("Exception catched! " + e);
227             return;
228         }
229
230         Mockito.verify(rwTransactionMock, Mockito.times(1)).cancel();
231         Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
232         Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
233     }
234
235     @Test
236     public void dataBrokerTimeoutTransactionTest() {
237         Mockito.when(dataBrokerMock.newReadWriteTransaction()).then(invocation -> {
238             Thread.sleep(transactionManager.getMaxDurationToSubmitTransaction() + 1000);
239             return rwTransactionMock;
240         });
241
242         try {
243             putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
244         } catch (InterruptedException | ExecutionException e) {
245             Assert.fail("Exception catched! " + e);
246         }
247
248         Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
249
250         Mockito.when(dataBrokerMock.newReadWriteTransaction()).thenReturn(rwTransactionMock); // remove sleep
251
252         try {
253             putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
254         } catch (InterruptedException | ExecutionException e) {
255             Assert.fail("Exception catched! " + e);
256             return;
257         }
258
259         Mockito.verify(rwTransactionMock, Mockito.times(2)).put(defaultDatastore, defaultIid, defaultData);
260         Mockito.verify(rwTransactionMock, Mockito.times(2)).commit();
261     }
262
263     @Test
264     public void getFutureTimeoutTransactionTest() {
265         Mockito.when(dataBrokerMock.newReadWriteTransaction()).then(invocation -> {
266             Thread.sleep(3000);
267             return rwTransactionMock;
268         });
269
270         Exception throwedException = null;
271
272         Future<java.util.Optional<DeviceTransaction>> deviceTxFuture =
273                 transactionManager.getDeviceTransaction(defaultDeviceId);
274         try {
275             deviceTxFuture.get(1000, TimeUnit.MILLISECONDS);
276         } catch (InterruptedException | ExecutionException e) {
277             Assert.fail("Exception catched! " + e);
278         } catch (TimeoutException e) {
279             throwedException = e;
280         }
281
282         if (throwedException == null) {
283             Assert.fail("TimeoutException should be thrown!");
284             return;
285         }
286
287         Mockito.when(dataBrokerMock.newReadWriteTransaction()).thenReturn(rwTransactionMock); // remove sleep
288
289         try {
290             putAndSubmit(transactionManager, defaultDeviceId, defaultDatastore, defaultIid, defaultData);
291         } catch (InterruptedException | ExecutionException e) {
292             Assert.fail("Exception catched! " + e);
293             return;
294         }
295
296         Mockito.verify(rwTransactionMock, Mockito.times(1)).put(defaultDatastore, defaultIid, defaultData);
297         Mockito.verify(rwTransactionMock, Mockito.times(1)).commit();
298     }
299
300     private <T extends DataObject> void putAndSubmit(DeviceTransactionManagerImpl deviceTxManager, String deviceId,
301             LogicalDatastoreType store, InstanceIdentifier<T> path, T data)
302             throws ExecutionException, InterruptedException {
303         Future<java.util.Optional<DeviceTransaction>> deviceTxFuture = deviceTxManager.getDeviceTransaction(deviceId);
304         DeviceTransaction deviceTx = deviceTxFuture.get().get();
305         deviceTx.put(store, path, data);
306         deviceTx.commit(defaultTimeout, defaultTimeUnit);
307     }
308 }