2 * Copyright (c) 2014 Brocade Communications Systems, Inc. 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.md.controller.topology.manager;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.SettableFuture;
15 import com.google.common.util.concurrent.Uninterruptibles;
16 import org.junit.After;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.mockito.ArgumentCaptor;
20 import org.mockito.InOrder;
21 import org.mockito.Mock;
22 import org.mockito.MockitoAnnotations;
23 import org.mockito.invocation.InvocationOnMock;
24 import org.mockito.stubbing.Answer;
25 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
29 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
30 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
31 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdatedBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdatedBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkDiscoveredBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.topology.discovery.rev130819.LinkRemovedBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.StateBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemovedBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdatedBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemovedBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdatedBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNode;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Destination;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.Source;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
75 import java.util.Arrays;
76 import java.util.HashSet;
77 import java.util.List;
79 import java.util.concurrent.CountDownLatch;
80 import java.util.concurrent.ExecutorService;
81 import java.util.concurrent.Executors;
82 import java.util.concurrent.TimeUnit;
84 import static org.junit.Assert.assertEquals;
85 import static org.junit.Assert.assertNotNull;
86 import static org.junit.Assert.assertTrue;
87 import static org.junit.Assert.fail;
88 import static org.mockito.Mockito.any;
89 import static org.mockito.Mockito.atLeast;
90 import static org.mockito.Mockito.doAnswer;
91 import static org.mockito.Mockito.doReturn;
92 import static org.mockito.Mockito.eq;
93 import static org.mockito.Mockito.inOrder;
94 import static org.mockito.Mockito.mock;
95 import static org.mockito.Mockito.never;
96 import static org.mockito.Mockito.verify;
98 public class FlowCapableTopologyExporterTest {
101 private DataBroker mockDataBroker;
104 private BindingTransactionChain mockTxChain;
106 private OperationProcessor processor;
108 private FlowCapableTopologyExporter exporter;
110 private InstanceIdentifier<Topology> topologyIID;
112 private final ExecutorService executor = Executors.newFixedThreadPool(1);
115 public void setUp() {
116 MockitoAnnotations.initMocks(this);
118 doReturn(mockTxChain).when(mockDataBroker)
119 .createTransactionChain(any(TransactionChainListener.class));
121 processor = new OperationProcessor(mockDataBroker);
123 topologyIID = InstanceIdentifier.create(NetworkTopology.class)
124 .child(Topology.class, new TopologyKey(new TopologyId("test")));
125 exporter = new FlowCapableTopologyExporter(processor, topologyIID);
127 executor.execute(processor);
131 public void tearDown() {
132 executor.shutdownNow();
135 @SuppressWarnings({ "rawtypes" })
137 public void testOnNodeRemoved() {
139 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
140 InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
141 Node topoNode = new NodeBuilder().setKey(topoNodeKey).build();
143 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
144 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
145 InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
146 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
149 List<Link> linkList = Arrays.asList(
150 newLink("link1", newSourceNode("node1"), newDestNode("dest")),
151 newLink("link2", newSourceNode("source"), newDestNode("node1")),
152 newLink("link2", newSourceNode("source2"), newDestNode("dest2")));
153 final Topology topology = new TopologyBuilder().setLink(linkList).build();
155 InstanceIdentifier[] expDeletedIIDs = {
156 topologyIID.child(Link.class, linkList.get(0).getKey()),
157 topologyIID.child(Link.class, linkList.get(1).getKey()),
158 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
161 SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
162 readFuture.set(Optional.of(topology));
163 ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
164 doReturn(Futures.makeChecked(readFuture, ReadFailedException.MAPPER)).when(mockTx1)
165 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
167 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
168 readFutureNode.set(Optional.of(topoNode));
169 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx1)
170 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
172 CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
174 int expDeleteCalls = expDeletedIIDs.length;
175 CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
176 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
177 ArgumentCaptor.forClass(InstanceIdentifier.class);
178 setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
180 doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
182 exporter.onNodeRemoved(new NodeRemovedBuilder().setNodeRef(new NodeRef(invNodeID)).build());
184 waitForSubmit(submitLatch1);
186 setReadFutureAsync(topology, readFuture);
188 waitForDeletes(expDeleteCalls, deleteLatch);
190 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
192 verifyMockTx(mockTx1);
195 @SuppressWarnings({ "rawtypes" })
197 public void testOnNodeRemovedWithNoTopology() {
199 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
200 InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
201 Node topoNode = new NodeBuilder().setKey(topoNodeKey).build();
203 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
204 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
205 InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
206 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
209 InstanceIdentifier[] expDeletedIIDs = {
210 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
213 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
214 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockTx)
215 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
216 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
218 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
219 readFutureNode.set(Optional.of(topoNode));
220 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx)
221 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
223 CountDownLatch deleteLatch = new CountDownLatch(1);
224 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
225 ArgumentCaptor.forClass(InstanceIdentifier.class);
226 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
228 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
230 exporter.onNodeRemoved(new NodeRemovedBuilder().setNodeRef(new NodeRef(invNodeID)).build());
232 waitForSubmit(submitLatch);
234 waitForDeletes(1, deleteLatch);
236 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
239 @SuppressWarnings("rawtypes")
241 public void testOnNodeConnectorRemoved() {
243 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
244 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
246 InstanceIdentifier<TerminationPoint> topoTermPointII = topologyIID.child(Node.class, topoNodeKey)
247 .child(TerminationPoint.class, terminationPointKey);
248 TerminationPoint topoTermPoint = new TerminationPointBuilder().setKey(terminationPointKey).build();
250 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
251 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
253 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
254 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
256 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
258 List<Link> linkList = Arrays.asList(
259 newLink("link1", newSourceTp("tp1"), newDestTp("dest")),
260 newLink("link2", newSourceTp("source"), newDestTp("tp1")),
261 newLink("link3", newSourceTp("source2"), newDestTp("dest2")));
262 final Topology topology = new TopologyBuilder().setLink(linkList).build();
264 InstanceIdentifier[] expDeletedIIDs = {
265 topologyIID.child(Link.class, linkList.get(0).getKey()),
266 topologyIID.child(Link.class, linkList.get(1).getKey()),
267 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
268 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
271 final SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
272 readFuture.set(Optional.of(topology));
273 ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
274 doReturn(Futures.makeChecked(readFuture, ReadFailedException.MAPPER)).when(mockTx1)
275 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
277 SettableFuture<Optional<TerminationPoint>> readFutureNode = SettableFuture.create();
278 readFutureNode.set(Optional.of(topoTermPoint));
279 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx1)
280 .read(LogicalDatastoreType.OPERATIONAL, topoTermPointII);
282 CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
284 int expDeleteCalls = expDeletedIIDs.length;
285 CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
286 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
287 ArgumentCaptor.forClass(InstanceIdentifier.class);
288 setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
291 doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
293 exporter.onNodeConnectorRemoved(new NodeConnectorRemovedBuilder().setNodeConnectorRef(
294 new NodeConnectorRef(invNodeConnID)).build());
296 waitForSubmit(submitLatch1);
298 setReadFutureAsync(topology, readFuture);
300 waitForDeletes(expDeleteCalls, deleteLatch);
302 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
304 verifyMockTx(mockTx1);
307 @SuppressWarnings("rawtypes")
309 public void testOnNodeConnectorRemovedWithNoTopology() {
311 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
312 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
314 InstanceIdentifier<TerminationPoint> topoTermPointII = topologyIID.child(Node.class, topoNodeKey)
315 .child(TerminationPoint.class, terminationPointKey);
316 TerminationPoint topoTermPoint = new TerminationPointBuilder().setKey(terminationPointKey).build();
318 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
319 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
321 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
322 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
324 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
326 InstanceIdentifier[] expDeletedIIDs = {
327 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
328 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
331 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
332 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockTx)
333 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
334 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
336 SettableFuture<Optional<TerminationPoint>> readFutureNode = SettableFuture.create();
337 readFutureNode.set(Optional.of(topoTermPoint));
338 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx)
339 .read(LogicalDatastoreType.OPERATIONAL, topoTermPointII);
341 CountDownLatch deleteLatch = new CountDownLatch(1);
342 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
343 ArgumentCaptor.forClass(InstanceIdentifier.class);
344 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
346 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
348 exporter.onNodeConnectorRemoved(new NodeConnectorRemovedBuilder().setNodeConnectorRef(
349 new NodeConnectorRef(invNodeConnID)).build());
351 waitForSubmit(submitLatch);
353 waitForDeletes(1, deleteLatch);
355 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
359 public void testOnNodeUpdated() {
361 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
362 nodeKey = newInvNodeKey("node1");
363 InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
364 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
367 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
368 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
369 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
371 exporter.onNodeUpdated(new NodeUpdatedBuilder().setNodeRef(new NodeRef(invNodeID))
372 .setId(nodeKey.getId()).addAugmentation(FlowCapableNodeUpdated.class,
373 new FlowCapableNodeUpdatedBuilder().build()).build());
375 waitForSubmit(submitLatch);
377 ArgumentCaptor<Node> mergedNode = ArgumentCaptor.forClass(Node.class);
378 NodeId expNodeId = new NodeId("node1");
379 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(topologyIID.child(Node.class,
380 new NodeKey(expNodeId))), mergedNode.capture(), eq(true));
381 assertEquals("getNodeId", expNodeId, mergedNode.getValue().getNodeId());
382 InventoryNode augmentation = mergedNode.getValue().getAugmentation(InventoryNode.class);
383 assertNotNull("Missing augmentation", augmentation);
384 assertEquals("getInventoryNodeRef", new NodeRef(invNodeID), augmentation.getInventoryNodeRef());
387 @SuppressWarnings("rawtypes")
389 public void testOnNodeConnectorUpdated() {
391 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
392 nodeKey = newInvNodeKey("node1");
394 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
395 newInvNodeConnKey("tp1");
397 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
399 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
400 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
401 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
403 exporter.onNodeConnectorUpdated(new NodeConnectorUpdatedBuilder().setNodeConnectorRef(
404 new NodeConnectorRef(invNodeConnID)).setId(ncKey.getId()).addAugmentation(
405 FlowCapableNodeConnectorUpdated.class,
406 new FlowCapableNodeConnectorUpdatedBuilder().build()).build());
408 waitForSubmit(submitLatch);
410 ArgumentCaptor<TerminationPoint> mergedNode = ArgumentCaptor.forClass(TerminationPoint.class);
411 NodeId expNodeId = new NodeId("node1");
412 TpId expTpId = new TpId("tp1");
413 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
414 Node.class, new NodeKey(expNodeId)).child(TerminationPoint.class,
415 new TerminationPointKey(expTpId));
416 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
417 mergedNode.capture(), eq(true));
418 assertEquals("getTpId", expTpId, mergedNode.getValue().getTpId());
419 InventoryNodeConnector augmentation = mergedNode.getValue().getAugmentation(
420 InventoryNodeConnector.class);
421 assertNotNull("Missing augmentation", augmentation);
422 assertEquals("getInventoryNodeConnectorRef", new NodeConnectorRef(invNodeConnID),
423 augmentation.getInventoryNodeConnectorRef());
426 @SuppressWarnings("rawtypes")
428 public void testOnNodeConnectorUpdatedWithLinkStateDown() {
430 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
431 nodeKey = newInvNodeKey("node1");
433 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
434 newInvNodeConnKey("tp1");
436 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
438 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
439 Topology topology = new TopologyBuilder().setLink(linkList).build();
441 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
442 doReturn(Futures.immediateCheckedFuture(Optional.of(topology))).when(mockTx)
443 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
444 setupStubbedSubmit(mockTx);
446 CountDownLatch deleteLatch = new CountDownLatch(1);
447 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
448 ArgumentCaptor.forClass(InstanceIdentifier.class);
449 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
451 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
453 exporter.onNodeConnectorUpdated(new NodeConnectorUpdatedBuilder().setNodeConnectorRef(
454 new NodeConnectorRef(invNodeConnID)).setId(ncKey.getId()).addAugmentation(
455 FlowCapableNodeConnectorUpdated.class,
456 new FlowCapableNodeConnectorUpdatedBuilder().setState(
457 new StateBuilder().setLinkDown(true).build()).build()).build());
459 waitForDeletes(1, deleteLatch);
461 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
462 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
463 new TerminationPointKey(new TpId("tp1")));
465 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
466 any(TerminationPoint.class), eq(true));
468 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
469 linkList.get(0).getKey())}, deletedLinkIDs);
473 @SuppressWarnings("rawtypes")
475 public void testOnNodeConnectorUpdatedWithPortDown() {
477 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
478 nodeKey = newInvNodeKey("node1");
480 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
481 newInvNodeConnKey("tp1");
483 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
485 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
486 Topology topology = new TopologyBuilder().setLink(linkList).build();
488 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
489 doReturn(Futures.immediateCheckedFuture(Optional.of(topology))).when(mockTx)
490 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
491 setupStubbedSubmit(mockTx);
493 CountDownLatch deleteLatch = new CountDownLatch(1);
494 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
495 ArgumentCaptor.forClass(InstanceIdentifier.class);
496 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
498 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
500 exporter.onNodeConnectorUpdated(new NodeConnectorUpdatedBuilder().setNodeConnectorRef(
501 new NodeConnectorRef(invNodeConnID)).setId(ncKey.getId()).addAugmentation(
502 FlowCapableNodeConnectorUpdated.class,
503 new FlowCapableNodeConnectorUpdatedBuilder().setConfiguration(
504 new PortConfig(true, true, true, true)).build()).build());
506 waitForDeletes(1, deleteLatch);
508 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
509 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
510 new TerminationPointKey(new TpId("tp1")));
512 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
513 any(TerminationPoint.class), eq(true));
515 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
516 linkList.get(0).getKey())}, deletedLinkIDs);
520 public void testOnLinkDiscovered() {
522 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
523 sourceNodeKey = newInvNodeKey("sourceNode");
524 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
525 sourceNodeConnKey = newInvNodeConnKey("sourceTP");
526 InstanceIdentifier<?> sourceConnID = newNodeConnID(sourceNodeKey, sourceNodeConnKey);
528 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
529 destNodeKey = newInvNodeKey("destNode");
530 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
531 destNodeConnKey = newInvNodeConnKey("destTP");
532 InstanceIdentifier<?> destConnID = newNodeConnID(destNodeKey, destNodeConnKey);
534 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
535 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
536 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
538 exporter.onLinkDiscovered(new LinkDiscoveredBuilder().setSource(
539 new NodeConnectorRef(sourceConnID)).setDestination(
540 new NodeConnectorRef(destConnID)).build());
542 waitForSubmit(submitLatch);
544 ArgumentCaptor<Link> mergedNode = ArgumentCaptor.forClass(Link.class);
545 verify(mockTx).put(eq(LogicalDatastoreType.OPERATIONAL), eq(topologyIID.child(
546 Link.class, new LinkKey(new LinkId(sourceNodeConnKey.getId())))),
547 mergedNode.capture(), eq(true));
548 assertEquals("Source node ID", "sourceNode",
549 mergedNode.getValue().getSource().getSourceNode().getValue());
550 assertEquals("Dest TP ID", "sourceTP",
551 mergedNode.getValue().getSource().getSourceTp().getValue());
552 assertEquals("Dest node ID", "destNode",
553 mergedNode.getValue().getDestination().getDestNode().getValue());
554 assertEquals("Dest TP ID", "destTP",
555 mergedNode.getValue().getDestination().getDestTp().getValue());
559 public void testOnLinkRemovedLinkExists() {
561 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
562 sourceNodeKey = newInvNodeKey("sourceNode");
563 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
564 sourceNodeConnKey = newInvNodeConnKey("sourceTP");
565 InstanceIdentifier<?> sourceConnID = newNodeConnID(sourceNodeKey, sourceNodeConnKey);
567 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
568 destNodeKey = newInvNodeKey("destNode");
569 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
570 destNodeConnKey = newInvNodeConnKey("destTP");
571 InstanceIdentifier<?> destConnID = newNodeConnID(destNodeKey, destNodeConnKey);
573 Link link = newLink(sourceNodeConnKey.getId().getValue(), newSourceTp(sourceNodeConnKey.getId().getValue()),
574 newDestTp(destNodeConnKey.getId().getValue()));
576 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
577 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
578 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
579 doReturn(Futures.immediateCheckedFuture(Optional.of(link))).when(mockTx).read(LogicalDatastoreType.OPERATIONAL, topologyIID.child(
580 Link.class, new LinkKey(new LinkId(sourceNodeConnKey.getId()))));
582 exporter.onLinkRemoved(new LinkRemovedBuilder().setSource(
583 new NodeConnectorRef(sourceConnID)).setDestination(
584 new NodeConnectorRef(destConnID)).build());
586 waitForSubmit(submitLatch);
588 verify(mockTx).delete(LogicalDatastoreType.OPERATIONAL, topologyIID.child(
589 Link.class, new LinkKey(new LinkId(sourceNodeConnKey.getId()))));
593 public void testOnLinkRemovedLinkDoesNotExist() {
595 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
596 sourceNodeKey = newInvNodeKey("sourceNode");
597 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
598 sourceNodeConnKey = newInvNodeConnKey("sourceTP");
599 InstanceIdentifier<?> sourceConnID = newNodeConnID(sourceNodeKey, sourceNodeConnKey);
601 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
602 destNodeKey = newInvNodeKey("destNode");
603 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
604 destNodeConnKey = newInvNodeConnKey("destTP");
605 InstanceIdentifier<?> destConnID = newNodeConnID(destNodeKey, destNodeConnKey);
607 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
608 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
609 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
610 doReturn(Futures.immediateCheckedFuture(Optional.<Link>absent())).when(mockTx).read(LogicalDatastoreType.OPERATIONAL, topologyIID.child(
611 Link.class, new LinkKey(new LinkId(sourceNodeConnKey.getId()))));
613 exporter.onLinkRemoved(new LinkRemovedBuilder().setSource(
614 new NodeConnectorRef(sourceConnID)).setDestination(
615 new NodeConnectorRef(destConnID)).build());
617 waitForSubmit(submitLatch);
619 verify(mockTx, never()).delete(LogicalDatastoreType.OPERATIONAL, topologyIID.child(
620 Link.class, new LinkKey(new LinkId(sourceNodeConnKey.getId()))));
623 private void verifyMockTx(ReadWriteTransaction mockTx) {
624 InOrder inOrder = inOrder(mockTx);
625 inOrder.verify(mockTx, atLeast(0)).submit();
626 inOrder.verify(mockTx, never()).delete(eq(LogicalDatastoreType.OPERATIONAL),
627 any(InstanceIdentifier.class));
630 @SuppressWarnings("rawtypes")
631 private void assertDeletedIDs(InstanceIdentifier[] expDeletedIIDs,
632 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs) {
633 Set<InstanceIdentifier> actualIIDs = new HashSet<>(deletedLinkIDs.getAllValues());
634 for(InstanceIdentifier id: expDeletedIIDs) {
635 assertTrue("Missing expected deleted IID " + id, actualIIDs.contains(id));
639 private void setReadFutureAsync(final Topology topology,
640 final SettableFuture<Optional<Topology>> readFuture) {
644 Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
645 readFuture.set(Optional.of(topology));
651 private void waitForSubmit(CountDownLatch latch) {
652 assertEquals("Transaction submitted", true,
653 Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS));
656 private void waitForDeletes(int expDeleteCalls, final CountDownLatch latch) {
657 boolean done = Uninterruptibles.awaitUninterruptibly(latch, 5, TimeUnit.SECONDS);
659 fail("Expected " + expDeleteCalls + " delete calls. Actual: " +
660 (expDeleteCalls - latch.getCount()));
664 private CountDownLatch setupStubbedSubmit(ReadWriteTransaction mockTx) {
665 final CountDownLatch latch = new CountDownLatch(1);
666 doAnswer(new Answer<CheckedFuture<Void, TransactionCommitFailedException>>() {
668 public CheckedFuture<Void, TransactionCommitFailedException> answer(
669 InvocationOnMock invocation) {
671 return Futures.immediateCheckedFuture(null);
673 }).when(mockTx).submit();
678 @SuppressWarnings("rawtypes")
679 private void setupStubbedDeletes(ReadWriteTransaction mockTx,
680 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs, final CountDownLatch latch) {
681 doAnswer(new Answer<Void>() {
683 public Void answer(InvocationOnMock invocation) {
687 }).when(mockTx).delete(eq(LogicalDatastoreType.OPERATIONAL), deletedLinkIDs.capture());
690 private org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
691 newInvNodeKey(String id) {
692 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey nodeKey =
693 new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey(
694 new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.
695 rev130819.NodeId(id));
699 private NodeConnectorKey newInvNodeConnKey(String id) {
700 return new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey(
701 new org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.
702 NodeConnectorId(id));
705 private KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> newNodeConnID(
706 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey nodeKey,
707 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey) {
708 return InstanceIdentifier.create(Nodes.class).child(
709 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
710 nodeKey).child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.
711 rev130819.node.NodeConnector.class, ncKey);
714 private Link newLink(String id, Source source, Destination dest) {
715 return new LinkBuilder().setLinkId(new LinkId(id))
716 .setSource(source).setDestination(dest).build();
719 private Destination newDestTp(String id) {
720 return new DestinationBuilder().setDestTp(new TpId(id)).build();
723 private Source newSourceTp(String id) {
724 return new SourceBuilder().setSourceTp(new TpId(id)).build();
727 private Destination newDestNode(String id) {
728 return new DestinationBuilder().setDestNode(new NodeId(id)).build();
731 private Source newSourceNode(String id) {
732 return new SourceBuilder().setSourceNode(new NodeId(id)).build();