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.FutureCallback;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import org.junit.After;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.junit.runner.RunWith;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
21 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
22 import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
23 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
24 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionCommand;
25 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvokerImpl;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
30 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
31 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
32 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
33 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
34 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
35 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.powermock.modules.junit4.PowerMockRunner;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 import java.util.concurrent.CountDownLatch;
42 import java.util.concurrent.TimeUnit;
44 import static org.junit.Assert.assertEquals;
46 @RunWith(PowerMockRunner.class)
47 public class TransactionInvokerImplTest extends AbstractConcurrentDataBrokerTest {
49 private static final Logger LOG = LoggerFactory.getLogger(DataChangeListenerTestBase.class);
51 private TransactionCommand SLEEPING_PILL = new TransactionCommand() {
53 public void execute(ReadWriteTransaction transaction) {
55 LOG.debug("Running sleeping pill");
56 SLEEPING_PILL_STARTED_LATCH.countDown();
57 SLEEPING_PILL_END_LATCH.await(5, TimeUnit.SECONDS);
58 } catch (InterruptedException e) {
64 private TransactionCommand NULL_POINTER_PILL = new TransactionCommand() {
66 public void execute(ReadWriteTransaction transaction) {
67 LOG.debug("Running npe TransactionCommand");
68 NULL_POINTER_PILL_START.countDown();
69 throw new NullPointerException("Failed to execute command");
73 private InstanceIdentifier<Node> nodeIid1;
74 private InstanceIdentifier<Node> nodeIid2;
75 private InstanceIdentifier<Node> nodeIid3;
77 private DataBroker dataBroker;
78 private TransactionInvokerImpl invoker;
79 private CountDownLatch SLEEPING_PILL_STARTED_LATCH;
80 private CountDownLatch SLEEPING_PILL_END_LATCH;
81 private CountDownLatch NULL_POINTER_PILL_START;
84 public void setupTest() throws Exception {
85 dataBroker = getDataBroker();
86 invoker = new TransactionInvokerImpl(dataBroker);
87 nodeIid1 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
88 nodeIid2 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
89 nodeIid3 = createInstanceIdentifier(java.util.UUID.randomUUID().toString());
90 SLEEPING_PILL_STARTED_LATCH = new CountDownLatch(1);
91 SLEEPING_PILL_END_LATCH = new CountDownLatch(1);
92 NULL_POINTER_PILL_START = new CountDownLatch(1);
96 public void cleanup() throws Exception {
102 private void deleteNode(InstanceIdentifier<Node> iid) {
103 ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
104 tx.delete(LogicalDatastoreType.CONFIGURATION, iid);
109 public void testMiddleCommandNullPointerFailure() throws Exception {
110 SettableFuture ft1 = SettableFuture.create();
111 SettableFuture ft2 = SettableFuture.create();
112 SettableFuture ft3 = SettableFuture.create();
114 //add a command which does a sleep of 500ms
115 invoker.invoke(SLEEPING_PILL);
117 //wait fot the above one to be scheduled
118 SLEEPING_PILL_STARTED_LATCH.await(5, TimeUnit.SECONDS);
120 //Now add the commands which will be picked up in one lot
121 invoker.invoke(new AddNodeCmd(nodeIid1, ft1));
122 invoker.invoke(NULL_POINTER_PILL);
123 invoker.invoke(new AddNodeCmd(nodeIid2, ft2));
125 SLEEPING_PILL_END_LATCH.countDown();
127 ft1.get(5, TimeUnit.SECONDS);
128 ft2.get(5, TimeUnit.SECONDS);
130 NULL_POINTER_PILL_START = new CountDownLatch(1);
131 invoker.invoke(NULL_POINTER_PILL);
132 NULL_POINTER_PILL_START.await(5, TimeUnit.SECONDS);
134 //make sure that any commands which are submitted after the previous failure run smoothly
135 invoker.invoke(new AddNodeCmd(nodeIid3, ft3));
136 ft3.get(5, TimeUnit.SECONDS);
140 private InstanceIdentifier<Node> createInstanceIdentifier(String nodeIdString) {
141 NodeId nodeId = new NodeId(new Uri(nodeIdString));
142 NodeKey nodeKey = new NodeKey(nodeId);
143 TopologyKey topoKey = new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID);
144 return InstanceIdentifier.builder(NetworkTopology.class)
145 .child(Topology.class, topoKey)
146 .child(Node.class, nodeKey)
150 private static class AddNodeCmd extends DefaultTransactionComamndImpl {
151 InstanceIdentifier<Node> iid;
153 AddNodeCmd(InstanceIdentifier<Node> iid, SettableFuture ft) {
159 public void execute(ReadWriteTransaction transaction) {
160 NodeBuilder nodeBuilder = new NodeBuilder();
161 nodeBuilder.setNodeId(iid.firstKeyOf(Node.class).getNodeId());
162 HwvtepGlobalAugmentationBuilder builder = new HwvtepGlobalAugmentationBuilder();
163 nodeBuilder.addAugmentation(HwvtepGlobalAugmentation.class, builder.build());
164 transaction.put(LogicalDatastoreType.CONFIGURATION, iid, nodeBuilder.build(), WriteTransaction.CREATE_MISSING_PARENTS);
169 private static class DeleteNodeCmd extends DefaultTransactionComamndImpl {
170 InstanceIdentifier<Node> iid;
172 DeleteNodeCmd(InstanceIdentifier<Node> iid, SettableFuture ft) {
178 public void execute(ReadWriteTransaction transaction) {
179 transaction.delete(LogicalDatastoreType.CONFIGURATION, iid);
183 private static class DefaultTransactionComamndImpl implements TransactionCommand {
185 DefaultTransactionComamndImpl(SettableFuture ft) {
190 public void execute(ReadWriteTransaction transaction) {
195 public void setTransactionResultFuture(ListenableFuture future) {
196 Futures.addCallback(future, new FutureCallback<Void>() {
198 public void onSuccess(Void aVoid) {
202 public void onFailure(Throwable throwable) {
203 ft.setException(throwable);