c4bc396e006caff69708f4004f2fcce090017a46
[openflowplugin.git] / applications / topology-manager / src / test / java / org / opendaylight / openflowplugin / applications / topology / manager / TerminationPointChangeListenerImplTest.java
1 /*
2  * Copyright (c) 2015, 2017 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.openflowplugin.applications.topology.manager;
9
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;
33
34 import com.google.common.util.concurrent.FluentFuture;
35 import com.google.common.util.concurrent.SettableFuture;
36 import java.util.Arrays;
37 import java.util.Collections;
38 import java.util.List;
39 import java.util.Optional;
40 import java.util.concurrent.CountDownLatch;
41 import org.junit.Test;
42 import org.mockito.ArgumentCaptor;
43 import org.opendaylight.mdsal.binding.api.DataTreeModification;
44 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
45 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.topology.inventory.rev131030.InventoryNodeConnector;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
51 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
52 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
53 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
54 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
55 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
56 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
57 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
58 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
59 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
60
61 public class TerminationPointChangeListenerImplTest extends DataTreeChangeListenerBase {
62     @SuppressWarnings("rawtypes")
63     @Test
64     public void testOnNodeConnectorRemoved() {
65
66         NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
67         TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
68
69         final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
70         Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
71
72         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes
73                 .NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
74
75         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
76                 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
77
78         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
79
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();
85
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")))
91             };
92
93         final SettableFuture<Optional<Topology>> readFuture = SettableFuture.create();
94         readFuture.set(Optional.of(topology));
95         ReadWriteTransaction mockTx1 = mock(ReadWriteTransaction.class);
96         doReturn(FluentFuture.from(readFuture)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topologyIID);
97
98         SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
99         readFutureNode.set(Optional.of(topoNode));
100         doReturn(FluentFuture.from(readFutureNode)).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
101
102         final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
103
104         int expDeleteCalls = expDeletedIIDs.length;
105         CountDownLatch deleteLatch = new CountDownLatch(expDeleteCalls);
106         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
107                 ArgumentCaptor.forClass(InstanceIdentifier.class);
108         setupStubbedDeletes(mockTx1, deletedLinkIDs, deleteLatch);
109
110         doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
111
112         DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
113         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
114
115         waitForSubmit(submitLatch1);
116
117         setReadFutureAsync(topology, readFuture);
118
119         waitForDeletes(expDeleteCalls, deleteLatch);
120
121         assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
122
123         verifyMockTx(mockTx1);
124     }
125
126     @SuppressWarnings("rawtypes")
127     @Test
128     public void testOnNodeConnectorRemovedWithNoTopology() {
129
130         NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
131         TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
132
133         InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
134         Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
135
136         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
137                 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
138
139         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
140                 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
141
142         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
143
144         final InstanceIdentifier[] expDeletedIIDs = {
145                 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
146                         .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
147             };
148
149         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
150         doReturn(FluentFutures.immediateFluentFuture(Optional.empty())).when(mockTx)
151                 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
152         final CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
153
154         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topoNode))).when(mockTx)
155                 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
156
157         CountDownLatch deleteLatch = new CountDownLatch(1);
158         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
159                 ArgumentCaptor.forClass(InstanceIdentifier.class);
160         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
161
162         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
163
164         DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
165         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
166
167         waitForSubmit(submitLatch);
168
169         waitForDeletes(1, deleteLatch);
170
171         assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
172     }
173
174     @Test
175     public void testOnNodeConnectorUpdated() {
176
177         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
178                                                                  nodeKey = newInvNodeKey("node1");
179
180         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
181                 newInvNodeConnKey("tp1");
182
183         InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
184
185         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
186         CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
187         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
188
189         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
190         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
191
192         waitForSubmit(submitLatch);
193
194         ArgumentCaptor<TerminationPoint> mergedNode = ArgumentCaptor.forClass(TerminationPoint.class);
195         NodeId expNodeId = new NodeId("node1");
196         TpId expTpId = new TpId("tp1");
197         InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
198                 Node.class, new NodeKey(expNodeId)).child(TerminationPoint.class,
199                         new TerminationPointKey(expTpId));
200         verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
201                 mergedNode.capture(), eq(true));
202         assertEquals("getTpId", expTpId, mergedNode.getValue().getTpId());
203         InventoryNodeConnector augmentation = mergedNode.getValue().augmentation(
204                 InventoryNodeConnector.class);
205         assertNotNull("Missing augmentation", augmentation);
206         assertEquals("getInventoryNodeConnectorRef", new NodeConnectorRef(invNodeConnID),
207                 augmentation.getInventoryNodeConnectorRef());
208     }
209
210     @SuppressWarnings("rawtypes")
211     @Test
212     public void testOnNodeConnectorUpdatedWithLinkStateDown() {
213
214         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
215                                                                  nodeKey = newInvNodeKey("node1");
216
217         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
218                 newInvNodeConnKey("tp1");
219
220         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
221
222         List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
223         Topology topology = new TopologyBuilder().setLink(linkList).build();
224
225         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
226         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
227                 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
228         setupStubbedSubmit(mockTx);
229
230         CountDownLatch deleteLatch = new CountDownLatch(1);
231         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
232                 ArgumentCaptor.forClass(InstanceIdentifier.class);
233         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
234
235         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
236
237         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
238         when(dataTreeModification.getRootNode().getDataAfter())
239                 .thenReturn(provideFlowCapableNodeConnector(true, false));
240         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
241
242         waitForDeletes(1, deleteLatch);
243
244         InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
245                 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
246                         new TerminationPointKey(new TpId("tp1")));
247
248         verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
249                 any(TerminationPoint.class), eq(true));
250
251         assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
252                 linkList.get(0).key())}, deletedLinkIDs);
253     }
254
255     @SuppressWarnings("rawtypes")
256     @Test
257     public void testOnNodeConnectorUpdatedWithPortDown() {
258
259         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
260                                                                  nodeKey = newInvNodeKey("node1");
261
262         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
263                 newInvNodeConnKey("tp1");
264
265         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
266
267         List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
268         Topology topology = new TopologyBuilder().setLink(linkList).build();
269
270         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
271         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
272                 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
273         setupStubbedSubmit(mockTx);
274
275         CountDownLatch deleteLatch = new CountDownLatch(1);
276         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
277                 ArgumentCaptor.forClass(InstanceIdentifier.class);
278         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
279
280         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
281
282         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
283         when(dataTreeModification.getRootNode().getDataAfter())
284                 .thenReturn(provideFlowCapableNodeConnector(false, true));
285         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
286
287         waitForDeletes(1, deleteLatch);
288
289         InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
290                 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
291                         new TerminationPointKey(new TpId("tp1")));
292
293         verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
294                 any(TerminationPoint.class), eq(true));
295
296         assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
297                 linkList.get(0).key())}, deletedLinkIDs);
298     }
299 }