2 * Copyright (c) 2015, 2017 Cisco 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
8 package org.opendaylight.openflowplugin.applications.topology.manager;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.eq;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.when;
18 import static org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType.DELETE;
19 import static org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType.WRITE;
20 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.assertDeletedIDs;
21 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newDestTp;
22 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newInvNodeConnKey;
23 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newInvNodeKey;
24 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newLink;
25 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newNodeConnID;
26 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newSourceTp;
27 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setReadFutureAsync;
28 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setupStubbedDeletes;
29 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setupStubbedSubmit;
30 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.verifyMockTx;
31 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.waitForDeletes;
32 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.waitForSubmit;
34 import com.google.common.util.concurrent.SettableFuture;
35 import java.util.Arrays;
36 import java.util.Collections;
37 import java.util.List;
38 import java.util.Optional;
39 import java.util.concurrent.CountDownLatch;
40 import org.junit.Test;
41 import org.mockito.ArgumentCaptor;
42 import org.opendaylight.mdsal.binding.api.DataTreeModification;
43 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
57 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60 public class TerminationPointChangeListenerImplTest extends DataTreeChangeListenerBase {
61 @SuppressWarnings("rawtypes")
63 public void testOnNodeConnectorRemoved() {
65 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
66 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
68 final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
69 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
71 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes
72 .NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
74 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
75 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
77 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
79 List<Link> linkList = Arrays.asList(
80 newLink("link1", newSourceTp("tp1"), newDestTp("dest")),
81 newLink("link2", newSourceTp("source"), newDestTp("tp1")),
82 newLink("link3", newSourceTp("source2"), newDestTp("dest2")));
83 final Topology topology = new TopologyBuilder().setLink(linkList).build();
85 final InstanceIdentifier[] expDeletedIIDs = {
86 topologyIID.child(Link.class, linkList.get(0).key()),
87 topologyIID.child(Link.class, linkList.get(1).key()),
88 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
89 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
92 final SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
93 readFuture.set(Optional.of(topology));
94 ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
95 doReturn(readFuture).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topologyIID);
97 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
98 readFutureNode.set(Optional.of(topoNode));
99 doReturn(readFutureNode).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
101 final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
103 int expDeleteCalls = expDeletedIIDs.length;
104 CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
105 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
106 ArgumentCaptor.forClass(InstanceIdentifier.class);
107 setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
109 doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
111 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
112 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
114 waitForSubmit(submitLatch1);
116 setReadFutureAsync(topology, readFuture);
118 waitForDeletes(expDeleteCalls, deleteLatch);
120 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
122 verifyMockTx(mockTx1);
125 @SuppressWarnings("rawtypes")
127 public void testOnNodeConnectorRemovedWithNoTopology() {
129 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
130 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
132 InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
133 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
135 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
136 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
138 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
139 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
141 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
143 final InstanceIdentifier[] expDeletedIIDs = {
144 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
145 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
148 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
149 doReturn(FluentFutures.immediateFluentFuture(Optional.empty())).when(mockTx)
150 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
151 final CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
153 doReturn(FluentFutures.immediateFluentFuture(Optional.of(topoNode))).when(mockTx)
154 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
156 CountDownLatch deleteLatch = new CountDownLatch(1);
157 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
158 ArgumentCaptor.forClass(InstanceIdentifier.class);
159 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
161 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
163 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
164 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
166 waitForSubmit(submitLatch);
168 waitForDeletes(1, deleteLatch);
170 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
174 public void testOnNodeConnectorUpdated() {
176 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
177 nodeKey = newInvNodeKey("node1");
179 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
180 newInvNodeConnKey("tp1");
182 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
184 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
185 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
186 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
188 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
189 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
191 waitForSubmit(submitLatch);
193 ArgumentCaptor<TerminationPoint> mergedNode = ArgumentCaptor.forClass(TerminationPoint.class);
194 NodeId expNodeId = new NodeId("node1");
195 TpId expTpId = new TpId("tp1");
196 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
197 Node.class, new NodeKey(expNodeId)).child(TerminationPoint.class,
198 new TerminationPointKey(expTpId));
199 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
200 mergedNode.capture(), eq(true));
201 assertEquals("getTpId", expTpId, mergedNode.getValue().getTpId());
202 InventoryNodeConnector augmentation = mergedNode.getValue().augmentation(
203 InventoryNodeConnector.class);
204 assertNotNull("Missing augmentation", augmentation);
205 assertEquals("getInventoryNodeConnectorRef", new NodeConnectorRef(invNodeConnID),
206 augmentation.getInventoryNodeConnectorRef());
209 @SuppressWarnings("rawtypes")
211 public void testOnNodeConnectorUpdatedWithLinkStateDown() {
213 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
214 nodeKey = newInvNodeKey("node1");
216 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
217 newInvNodeConnKey("tp1");
219 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
221 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
222 Topology topology = new TopologyBuilder().setLink(linkList).build();
224 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
225 doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
226 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
227 setupStubbedSubmit(mockTx);
229 CountDownLatch deleteLatch = new CountDownLatch(1);
230 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
231 ArgumentCaptor.forClass(InstanceIdentifier.class);
232 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
234 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
236 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
237 when(dataTreeModification.getRootNode().getDataAfter())
238 .thenReturn(provideFlowCapableNodeConnector(true, false));
239 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
241 waitForDeletes(1, deleteLatch);
243 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
244 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
245 new TerminationPointKey(new TpId("tp1")));
247 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
248 any(TerminationPoint.class), eq(true));
250 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
251 linkList.get(0).key())}, deletedLinkIDs);
254 @SuppressWarnings("rawtypes")
256 public void testOnNodeConnectorUpdatedWithPortDown() {
258 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
259 nodeKey = newInvNodeKey("node1");
261 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
262 newInvNodeConnKey("tp1");
264 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
266 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
267 Topology topology = new TopologyBuilder().setLink(linkList).build();
269 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
270 doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
271 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
272 setupStubbedSubmit(mockTx);
274 CountDownLatch deleteLatch = new CountDownLatch(1);
275 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
276 ArgumentCaptor.forClass(InstanceIdentifier.class);
277 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
279 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
281 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
282 when(dataTreeModification.getRootNode().getDataAfter())
283 .thenReturn(provideFlowCapableNodeConnector(false, true));
284 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
286 waitForDeletes(1, deleteLatch);
288 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
289 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
290 new TerminationPointKey(new TpId("tp1")));
292 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
293 any(TerminationPoint.class), eq(true));
295 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
296 linkList.get(0).key())}, deletedLinkIDs);