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