2 * Copyright (c) 2017 Ericsson India Global Services Pvt Ltd. 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.ovsdb.hwvtepsouthbound;
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.api.WriteTransaction;
25 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionCommand;
28 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
36 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
37 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
38 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
39 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
43 @RunWith(MockitoJUnitRunner.class)
44 public class TransactionInvokerImplTest extends AbstractConcurrentDataBrokerTest {
46 private static final Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class);
48 private final CountDownLatch sleepingPillStartedLatch = new CountDownLatch(1);
49 private final CountDownLatch sleepingPillEndLatch = new CountDownLatch(1);
50 private CountDownLatch nullPointerPillStart = new CountDownLatch(1);
52 private final TransactionCommand sleepingPill = transaction -> {
54 LOG.debug("Running sleeping pill");
55 sleepingPillStartedLatch.countDown();
56 sleepingPillEndLatch.await(5, TimeUnit.SECONDS);
57 } catch (InterruptedException e) {
62 private final TransactionCommand nullPointerPill = transaction -> {
63 LOG.debug("Running npe TransactionCommand");
64 nullPointerPillStart.countDown();
65 throw new NullPointerException("Failed to execute command");
68 private InstanceIdentifier<Node> nodeIid1;
69 private InstanceIdentifier<Node> nodeIid2;
70 private InstanceIdentifier<Node> nodeIid3;
72 private DataBroker dataBroker;
73 private TransactionInvokerImpl invoker;
76 public void setupTest() throws Exception {
77 dataBroker = getDataBroker();
78 invoker = new TransactionInvokerImpl(dataBroker);
79 nodeIid1 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
80 nodeIid2 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
81 nodeIid3 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
85 public void cleanup() throws Exception {
91 private void deleteNode(InstanceIdentifier<Node> iid) {
92 ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
93 tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
98 public void testMiddleCommandNullPointerFailure() throws Exception {
99 final SettableFuture ft1 = SettableFuture.create();
100 final SettableFuture ft2 = SettableFuture.create();
101 final SettableFuture ft3 = SettableFuture.create();
103 //add a command which does a sleep of 500ms
104 invoker.invoke(sleepingPill);
106 //wait fot the above one to be scheduled
107 sleepingPillStartedLatch.await(5, TimeUnit.SECONDS);
109 //Now add the commands which will be picked up in one lot
110 invoker.invoke(new AddNodeCmd(nodeIid1, ft1));
111 invoker.invoke(nullPointerPill);
112 invoker.invoke(new AddNodeCmd(nodeIid2, ft2));
114 sleepingPillEndLatch.countDown();
116 ft1.get(5, TimeUnit.SECONDS);
117 ft2.get(5, TimeUnit.SECONDS);
119 nullPointerPillStart = new CountDownLatch(1);
120 invoker.invoke(nullPointerPill);
121 nullPointerPillStart.await(5, TimeUnit.SECONDS);
123 //make sure that any commands which are submitted after the previous failure run smoothly
124 invoker.invoke(new AddNodeCmd(nodeIid3, ft3));
125 ft3.get(5, TimeUnit.SECONDS);
129 private InstanceIdentifier<Node> createInstanceIdentifier(String nodeIdString) {
130 NodeId nodeId = new NodeId(new Uri(nodeIdString));
131 NodeKey nodeKey = new NodeKey(nodeId);
132 TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
133 return InstanceIdentifier.builder(NetworkTopology.class)
134 .child(Topology.class, topoKey)
135 .child(Node.class, nodeKey)
139 private static class AddNodeCmd extends DefaultTransactionComamndImpl {
140 InstanceIdentifier<Node> iid;
142 AddNodeCmd(InstanceIdentifier<Node> iid, SettableFuture ft) {
148 public void execute(ReadWriteTransaction transaction) {
149 NodeBuilder nodeBuilder = new NodeBuilder();
150 nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId());
151 HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
152 nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
153 transaction.put(LogicalDatastoreType.CONFIGURATION, iid, nodeBuilder.build(),
154 WriteTransaction.CREATE_MISSING_PARENTS);
159 private static class DeleteNodeCmd extends DefaultTransactionComamndImpl {
160 InstanceIdentifier<Node> iid;
162 DeleteNodeCmd(InstanceIdentifier<Node> iid, SettableFuture ft) {
168 public void execute(ReadWriteTransaction transaction) {
169 transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
173 private static class DefaultTransactionComamndImpl implements TransactionCommand {
176 DefaultTransactionComamndImpl(SettableFuture ft) {
181 public void execute(ReadWriteTransaction transaction) {
186 public void setTransactionResultFuture(FluentFuture future) {
187 future.addCallback(new FutureCallback<Object>() {
189 public void onSuccess(Object notUsed) {
194 public void onFailure(Throwable throwable) {
195 ft.setException(throwable);
197 }, MoreExecutors.directExecutor());