Fix deprecation warnings around addAugmentation()
[ovsdb.git] / hwvtepsouthbound / hwvtepsouthbound-impl / src / test / java / org / opendaylight / ovsdb / hwvtepsouthbound / TransactionInvokerImplTest.java
1 /*
2  * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. 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.ovsdb.hwvtepsouthbound;
10
11 import com.google.common.util.concurrent.FluentFuture;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.MoreExecutors;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.concurrent.CountDownLatch;
16 import java.util.concurrent.TimeUnit;
17 import org.junit.After;
18 import org.junit.Before;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.mockito.junit.MockitoJUnitRunner;
22 import org.opendaylight.mdsal.binding.api.DataBroker;
23 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionCommand;
27 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 @RunWith(MockitoJUnitRunner.class)
42 public class TransactionInvokerImplTest extends AbstractConcurrentDataBrokerTest {
43
44     private static final Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class);
45
46     private final CountDownLatch sleepingPillStartedLatch = new CountDownLatch(1);
47     private final CountDownLatch sleepingPillEndLatch = new CountDownLatch(1);
48     private CountDownLatch nullPointerPillStart = new CountDownLatch(1);
49
50     private final TransactionCommand sleepingPill = transaction -> {
51         try {
52             LOG.debug("Running sleeping pill");
53             sleepingPillStartedLatch.countDown();
54             sleepingPillEndLatch.await(5, TimeUnit.SECONDS);
55         } catch (InterruptedException e) {
56             //ignore the error
57         }
58     };
59
60     private final TransactionCommand nullPointerPill = transaction -> {
61         LOG.debug("Running npe TransactionCommand");
62         nullPointerPillStart.countDown();
63         throw new NullPointerException("Failed to execute command");
64     };
65
66     private InstanceIdentifier<Node> nodeIid1;
67     private InstanceIdentifier<Node> nodeIid2;
68     private InstanceIdentifier<Node> nodeIid3;
69
70     private DataBroker dataBroker;
71     private TransactionInvokerImpl invoker;
72
73     @Before
74     public void setupTest() throws Exception {
75         dataBroker = getDataBroker();
76         invoker = new TransactionInvokerImpl(dataBroker);
77         nodeIid1 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
78         nodeIid2 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
79         nodeIid3 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
80     }
81
82     @After
83     public void cleanup() throws Exception {
84         deleteNode(nodeIid1);
85         deleteNode(nodeIid2);
86         deleteNode(nodeIid3);
87     }
88
89     private void deleteNode(final InstanceIdentifier<Node> iid) {
90         ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
91         tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
92         tx.commit();
93     }
94
95     @Test
96     public void testMiddleCommandNullPointerFailure() throws Exception {
97         final SettableFuture ft1 = SettableFuture.create();
98         final SettableFuture ft2 = SettableFuture.create();
99         final SettableFuture ft3 = SettableFuture.create();
100
101         //add a command which does a sleep of 500ms
102         invoker.invoke(sleepingPill);
103
104         //wait fot the above one to be scheduled
105         sleepingPillStartedLatch.await(5, TimeUnit.SECONDS);
106
107         //Now add the commands which will be picked up in one lot
108         invoker.invoke(new AddNodeCmd(nodeIid1, ft1));
109         invoker.invoke(nullPointerPill);
110         invoker.invoke(new AddNodeCmd(nodeIid2, ft2));
111
112         sleepingPillEndLatch.countDown();
113
114         ft1.get(5, TimeUnit.SECONDS);
115         ft2.get(5, TimeUnit.SECONDS);
116
117         nullPointerPillStart = new CountDownLatch(1);
118         invoker.invoke(nullPointerPill);
119         nullPointerPillStart.await(5, TimeUnit.SECONDS);
120
121         //make sure that any commands which are submitted after the previous failure run smoothly
122         invoker.invoke(new AddNodeCmd(nodeIid3, ft3));
123         ft3.get(5, TimeUnit.SECONDS);
124     }
125
126
127     private InstanceIdentifier<Node> createInstanceIdentifier(final String nodeIdString) {
128         NodeId nodeId = new NodeId(new Uri(nodeIdString));
129         NodeKey nodeKey = new NodeKey(nodeId);
130         TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
131         return InstanceIdentifier.builder(NetworkTopology.class)
132                 .child(Topology.class, topoKey)
133                 .child(Node.class, nodeKey)
134                 .build();
135     }
136
137     private static class AddNodeCmd extends DefaultTransactionComamndImpl {
138         InstanceIdentifier<Node> iid;
139
140         AddNodeCmd(final InstanceIdentifier<Node> iid, final SettableFuture ft) {
141             super(ft);
142             this.iid = iid;
143         }
144
145         @Override
146         public void execute(final ReadWriteTransaction transaction) {
147             NodeBuilder nodeBuilder = new NodeBuilder();
148             nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId());
149             nodeBuilder.addAugmentation(new HwvtepGlobalAugmentationBuilder().build());
150             transaction.mergeParentStructurePut(LogicalDatastoreType.CONFIGURATION, iid, nodeBuilder.build());
151         }
152     }
153
154     private static class DeleteNodeCmd extends DefaultTransactionComamndImpl {
155         InstanceIdentifier<Node> iid;
156
157         DeleteNodeCmd(final InstanceIdentifier<Node> iid, final SettableFuture ft) {
158             super(ft);
159             this.iid = iid;
160         }
161
162         @Override
163         public void execute(final ReadWriteTransaction transaction) {
164             transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
165         }
166     }
167
168     private static class DefaultTransactionComamndImpl implements TransactionCommand {
169         SettableFuture ft;
170
171         DefaultTransactionComamndImpl(final SettableFuture ft) {
172             this.ft = ft;
173         }
174
175         @Override
176         public void execute(final ReadWriteTransaction transaction) {
177
178         }
179
180         @Override
181         public void setTransactionResultFuture(final FluentFuture future) {
182             future.addCallback(new FutureCallback<>() {
183                 @Override
184                 public void onSuccess(final Object notUsed) {
185                     ft.set(null);
186                 }
187
188                 @Override
189                 public void onFailure(final Throwable throwable) {
190                     ft.setException(throwable);
191                 }
192             }, MoreExecutors.directExecutor());
193         }
194     }
195 }