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.controller.md.sal.binding.api.DataObjectModification.ModificationType.DELETE;
19 import static org.opendaylight.controller.md.sal.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.base.Optional;
35 import com.google.common.util.concurrent.Futures;
36 import com.google.common.util.concurrent.SettableFuture;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.List;
40 import java.util.concurrent.CountDownLatch;
41 import org.junit.Test;
42 import org.mockito.ArgumentCaptor;
43 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
44 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
45 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
46 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
58 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
61 public class TerminationPointChangeListenerImplTest extends DataTreeChangeListenerBase {
62 @SuppressWarnings("rawtypes")
64 public void testOnNodeConnectorRemoved() {
66 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
67 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
69 final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
70 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
72 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes
73 .NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
75 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
76 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
78 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
80 List<Link> linkList = Arrays.asList(
81 newLink("link1", newSourceTp("tp1"), newDestTp("dest")),
82 newLink("link2", newSourceTp("source"), newDestTp("tp1")),
83 newLink("link3", newSourceTp("source2"), newDestTp("dest2")));
84 final Topology topology = new TopologyBuilder().setLink(linkList).build();
86 final InstanceIdentifier[] expDeletedIIDs = {
87 topologyIID.child(Link.class, linkList.get(0).key()),
88 topologyIID.child(Link.class, linkList.get(1).key()),
89 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
90 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
93 final SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
94 readFuture.set(Optional.of(topology));
95 ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
96 doReturn(Futures.makeChecked(readFuture, ReadFailedException.MAPPER)).when(mockTx1)
97 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
99 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
100 readFutureNode.set(Optional.of(topoNode));
101 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx1)
102 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
104 final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
106 int expDeleteCalls = expDeletedIIDs.length;
107 CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
108 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
109 ArgumentCaptor.forClass(InstanceIdentifier.class);
110 setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
112 doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
114 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
115 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
117 waitForSubmit(submitLatch1);
119 setReadFutureAsync(topology, readFuture);
121 waitForDeletes(expDeleteCalls, deleteLatch);
123 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
125 verifyMockTx(mockTx1);
128 @SuppressWarnings("rawtypes")
130 public void testOnNodeConnectorRemovedWithNoTopology() {
132 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
133 TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
135 InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
136 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
138 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
139 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
141 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
142 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
144 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
146 final InstanceIdentifier[] expDeletedIIDs = {
147 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
148 .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
151 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
152 doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockTx)
153 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
154 final CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
156 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
157 readFutureNode.set(Optional.of(topoNode));
158 doReturn(Futures.makeChecked(readFutureNode, ReadFailedException.MAPPER)).when(mockTx)
159 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
161 CountDownLatch deleteLatch = new CountDownLatch(1);
162 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
163 ArgumentCaptor.forClass(InstanceIdentifier.class);
164 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
166 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
168 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
169 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
171 waitForSubmit(submitLatch);
173 waitForDeletes(1, deleteLatch);
175 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
179 public void testOnNodeConnectorUpdated() {
181 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
182 nodeKey = newInvNodeKey("node1");
184 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
185 newInvNodeConnKey("tp1");
187 InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
189 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
190 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
191 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
193 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
194 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
196 waitForSubmit(submitLatch);
198 ArgumentCaptor<TerminationPoint> mergedNode = ArgumentCaptor.forClass(TerminationPoint.class);
199 NodeId expNodeId = new NodeId("node1");
200 TpId expTpId = new TpId("tp1");
201 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
202 Node.class, new NodeKey(expNodeId)).child(TerminationPoint.class,
203 new TerminationPointKey(expTpId));
204 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
205 mergedNode.capture(), eq(true));
206 assertEquals("getTpId", expTpId, mergedNode.getValue().getTpId());
207 InventoryNodeConnector augmentation = mergedNode.getValue().augmentation(
208 InventoryNodeConnector.class);
209 assertNotNull("Missing augmentation", augmentation);
210 assertEquals("getInventoryNodeConnectorRef", new NodeConnectorRef(invNodeConnID),
211 augmentation.getInventoryNodeConnectorRef());
214 @SuppressWarnings("rawtypes")
216 public void testOnNodeConnectorUpdatedWithLinkStateDown() {
218 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
219 nodeKey = newInvNodeKey("node1");
221 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
222 newInvNodeConnKey("tp1");
224 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
226 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
227 Topology topology = new TopologyBuilder().setLink(linkList).build();
229 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
230 doReturn(Futures.immediateCheckedFuture(Optional.of(topology))).when(mockTx)
231 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
232 setupStubbedSubmit(mockTx);
234 CountDownLatch deleteLatch = new CountDownLatch(1);
235 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
236 ArgumentCaptor.forClass(InstanceIdentifier.class);
237 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
239 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
241 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
242 when(dataTreeModification.getRootNode().getDataAfter())
243 .thenReturn(provideFlowCapableNodeConnector(true, false));
244 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
246 waitForDeletes(1, deleteLatch);
248 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
249 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
250 new TerminationPointKey(new TpId("tp1")));
252 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
253 any(TerminationPoint.class), eq(true));
255 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
256 linkList.get(0).key())}, deletedLinkIDs);
259 @SuppressWarnings("rawtypes")
261 public void testOnNodeConnectorUpdatedWithPortDown() {
263 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
264 nodeKey = newInvNodeKey("node1");
266 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
267 newInvNodeConnKey("tp1");
269 final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
271 List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
272 Topology topology = new TopologyBuilder().setLink(linkList).build();
274 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
275 doReturn(Futures.immediateCheckedFuture(Optional.of(topology))).when(mockTx)
276 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
277 setupStubbedSubmit(mockTx);
279 CountDownLatch deleteLatch = new CountDownLatch(1);
280 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
281 ArgumentCaptor.forClass(InstanceIdentifier.class);
282 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
284 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
286 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
287 when(dataTreeModification.getRootNode().getDataAfter())
288 .thenReturn(provideFlowCapableNodeConnector(false, true));
289 terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
291 waitForDeletes(1, deleteLatch);
293 InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
294 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
295 new TerminationPointKey(new TpId("tp1")));
297 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
298 any(TerminationPoint.class), eq(true));
300 assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
301 linkList.get(0).key())}, deletedLinkIDs);