2 * Copyright (c) 2015 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.eq;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.verify;
16 import static org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType.DELETE;
17 import static org.opendaylight.mdsal.binding.api.DataObjectModification.ModificationType.WRITE;
18 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.assertDeletedIDs;
19 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newDestNode;
20 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newInvNodeKey;
21 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newLink;
22 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.newSourceNode;
23 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setReadFutureAsync;
24 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setupStubbedDeletes;
25 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.setupStubbedSubmit;
26 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.verifyMockTx;
27 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.waitForDeletes;
28 import static org.opendaylight.openflowplugin.applications.topology.manager.TestUtils.waitForSubmit;
30 import com.google.common.util.concurrent.FluentFuture;
31 import com.google.common.util.concurrent.SettableFuture;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Optional;
36 import java.util.concurrent.CountDownLatch;
37 import org.junit.Test;
38 import org.mockito.ArgumentCaptor;
39 import org.opendaylight.mdsal.binding.api.DataTreeModification;
40 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNode;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
52 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
55 public class NodeChangeListenerImplTest extends DataTreeChangeListenerBase {
56 @SuppressWarnings({ "rawtypes" })
58 public void testOnNodeRemoved() {
59 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
60 final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
61 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
63 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819
64 .nodes.NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
65 final InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
66 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
69 List<Link> linkList = Arrays.asList(
70 newLink("link1", newSourceNode("node1"), newDestNode("dest")),
71 newLink("link2", newSourceNode("source"), newDestNode("node1")),
72 newLink("link2", newSourceNode("source2"), newDestNode("dest2")));
73 final Topology topology = new TopologyBuilder().setLink(linkList).build();
75 final InstanceIdentifier[] expDeletedIIDs = {
76 topologyIID.child(Link.class, linkList.get(0).key()),
77 topologyIID.child(Link.class, linkList.get(1).key()),
78 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
81 SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
82 readFuture.set(Optional.of(topology));
83 ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
84 doReturn(FluentFuture.from(readFuture)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topologyIID);
86 SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
87 readFutureNode.set(Optional.of(topoNode));
88 doReturn(FluentFuture.from(readFutureNode)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
90 final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
92 int expDeleteCalls = expDeletedIIDs.length;
93 CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
94 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
95 ArgumentCaptor.forClass(InstanceIdentifier.class);
96 setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
98 doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
100 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeID);
101 nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
103 waitForSubmit(submitLatch1);
105 setReadFutureAsync(topology, readFuture);
107 waitForDeletes(expDeleteCalls, deleteLatch);
109 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
111 verifyMockTx(mockTx1);
114 @SuppressWarnings({ "rawtypes" })
116 public void testOnNodeRemovedWithNoTopology() {
118 NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
119 InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
120 Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
122 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
123 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
124 final InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
125 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
128 final InstanceIdentifier[] expDeletedIIDs = {
129 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
132 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
133 doReturn(FluentFutures.immediateFluentFuture(Optional.empty())).when(mockTx)
134 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
135 final CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
137 doReturn(FluentFutures.immediateFluentFuture(Optional.of(topoNode))).when(mockTx)
138 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
140 CountDownLatch deleteLatch = new CountDownLatch(1);
141 ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
142 ArgumentCaptor.forClass(InstanceIdentifier.class);
143 setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
145 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
147 DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeID);
148 nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
150 waitForSubmit(submitLatch);
152 waitForDeletes(1, deleteLatch);
154 assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
158 public void testOnNodeAdded() {
160 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
161 nodeKey = newInvNodeKey("node1");
162 InstanceIdentifier<?> invNodeID = InstanceIdentifier.create(Nodes.class).child(
163 org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class,
166 ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
167 CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
168 doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
170 DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeID);
171 nodeChangeListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
173 waitForSubmit(submitLatch);
175 ArgumentCaptor<Node> mergedNode = ArgumentCaptor.forClass(Node.class);
176 NodeId expNodeId = new NodeId("node1");
177 verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(topologyIID.child(Node.class,
178 new NodeKey(expNodeId))), mergedNode.capture(), eq(true));
179 assertEquals("getNodeId", expNodeId, mergedNode.getValue().getNodeId());
180 InventoryNode augmentation = mergedNode.getValue().augmentation(InventoryNode.class);
181 assertNotNull("Missing augmentation", augmentation);
182 assertEquals("getInventoryNodeRef", new NodeRef(invNodeID), augmentation.getInventoryNodeRef());