Switch to MD-SAL APIs
[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.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;
59
60 public class TerminationPointChangeListenerImplTest extends DataTreeChangeListenerBase {
61     @SuppressWarnings("rawtypes")
62     @Test
63     public void testOnNodeConnectorRemoved() {
64
65         NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
66         TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
67
68         final InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
69         Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
70
71         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes
72                 .NodeKey nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
73
74         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
75                 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
76
77         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
78
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();
84
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")))
90             };
91
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);
96
97         SettableFuture<Optional<Node>> readFutureNode = SettableFuture.create();
98         readFutureNode.set(Optional.of(topoNode));
99         doReturn(readFutureNode).when(mockTx1).read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
100
101         final CountDownLatch submitLatch1 = setupStubbedSubmit(mockTx1);
102
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);
108
109         doReturn(mockTx1).when(mockTxChain).newReadWriteTransaction();
110
111         DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
112         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
113
114         waitForSubmit(submitLatch1);
115
116         setReadFutureAsync(topology, readFuture);
117
118         waitForDeletes(expDeleteCalls, deleteLatch);
119
120         assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
121
122         verifyMockTx(mockTx1);
123     }
124
125     @SuppressWarnings("rawtypes")
126     @Test
127     public void testOnNodeConnectorRemovedWithNoTopology() {
128
129         NodeKey topoNodeKey = new NodeKey(new NodeId("node1"));
130         TerminationPointKey terminationPointKey = new TerminationPointKey(new TpId("tp1"));
131
132         InstanceIdentifier<Node> topoNodeII = topologyIID.child(Node.class, topoNodeKey);
133         Node topoNode = new NodeBuilder().withKey(topoNodeKey).build();
134
135         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
136                 nodeKey = newInvNodeKey(topoNodeKey.getNodeId().getValue());
137
138         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
139                 newInvNodeConnKey(terminationPointKey.getTpId().getValue());
140
141         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
142
143         final InstanceIdentifier[] expDeletedIIDs = {
144                 topologyIID.child(Node.class, new NodeKey(new NodeId("node1")))
145                         .child(TerminationPoint.class, new TerminationPointKey(new TpId("tp1")))
146             };
147
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);
152
153         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topoNode))).when(mockTx)
154                 .read(LogicalDatastoreType.OPERATIONAL, topoNodeII);
155
156         CountDownLatch deleteLatch = new CountDownLatch(1);
157         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
158                 ArgumentCaptor.forClass(InstanceIdentifier.class);
159         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
160
161         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
162
163         DataTreeModification dataTreeModification = setupDataTreeChange(DELETE, invNodeConnID);
164         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
165
166         waitForSubmit(submitLatch);
167
168         waitForDeletes(1, deleteLatch);
169
170         assertDeletedIDs(expDeletedIIDs, deletedLinkIDs);
171     }
172
173     @Test
174     public void testOnNodeConnectorUpdated() {
175
176         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
177                                                                  nodeKey = newInvNodeKey("node1");
178
179         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
180                 newInvNodeConnKey("tp1");
181
182         InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
183
184         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
185         CountDownLatch submitLatch = setupStubbedSubmit(mockTx);
186         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
187
188         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
189         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
190
191         waitForSubmit(submitLatch);
192
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());
207     }
208
209     @SuppressWarnings("rawtypes")
210     @Test
211     public void testOnNodeConnectorUpdatedWithLinkStateDown() {
212
213         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
214                                                                  nodeKey = newInvNodeKey("node1");
215
216         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
217                 newInvNodeConnKey("tp1");
218
219         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
220
221         List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
222         Topology topology = new TopologyBuilder().setLink(linkList).build();
223
224         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
225         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
226                 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
227         setupStubbedSubmit(mockTx);
228
229         CountDownLatch deleteLatch = new CountDownLatch(1);
230         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
231                 ArgumentCaptor.forClass(InstanceIdentifier.class);
232         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
233
234         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
235
236         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
237         when(dataTreeModification.getRootNode().getDataAfter())
238                 .thenReturn(provideFlowCapableNodeConnector(true, false));
239         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
240
241         waitForDeletes(1, deleteLatch);
242
243         InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
244                 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
245                         new TerminationPointKey(new TpId("tp1")));
246
247         verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
248                 any(TerminationPoint.class), eq(true));
249
250         assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
251                 linkList.get(0).key())}, deletedLinkIDs);
252     }
253
254     @SuppressWarnings("rawtypes")
255     @Test
256     public void testOnNodeConnectorUpdatedWithPortDown() {
257
258         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
259                                                                  nodeKey = newInvNodeKey("node1");
260
261         org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey ncKey =
262                 newInvNodeConnKey("tp1");
263
264         final InstanceIdentifier<?> invNodeConnID = newNodeConnID(nodeKey, ncKey);
265
266         List<Link> linkList = Arrays.asList(newLink("link1", newSourceTp("tp1"), newDestTp("dest")));
267         Topology topology = new TopologyBuilder().setLink(linkList).build();
268
269         ReadWriteTransaction mockTx = mock(ReadWriteTransaction.class);
270         doReturn(FluentFutures.immediateFluentFuture(Optional.of(topology))).when(mockTx)
271                 .read(LogicalDatastoreType.OPERATIONAL, topologyIID);
272         setupStubbedSubmit(mockTx);
273
274         CountDownLatch deleteLatch = new CountDownLatch(1);
275         ArgumentCaptor<InstanceIdentifier> deletedLinkIDs =
276                 ArgumentCaptor.forClass(InstanceIdentifier.class);
277         setupStubbedDeletes(mockTx, deletedLinkIDs, deleteLatch);
278
279         doReturn(mockTx).when(mockTxChain).newReadWriteTransaction();
280
281         DataTreeModification dataTreeModification = setupDataTreeChange(WRITE, invNodeConnID);
282         when(dataTreeModification.getRootNode().getDataAfter())
283                 .thenReturn(provideFlowCapableNodeConnector(false, true));
284         terminationPointListener.onDataTreeChanged(Collections.singleton(dataTreeModification));
285
286         waitForDeletes(1, deleteLatch);
287
288         InstanceIdentifier<TerminationPoint> expTpPath = topologyIID.child(
289                 Node.class, new NodeKey(new NodeId("node1"))).child(TerminationPoint.class,
290                         new TerminationPointKey(new TpId("tp1")));
291
292         verify(mockTx).merge(eq(LogicalDatastoreType.OPERATIONAL), eq(expTpPath),
293                 any(TerminationPoint.class), eq(true));
294
295         assertDeletedIDs(new InstanceIdentifier[]{topologyIID.child(Link.class,
296                 linkList.get(0).key())}, deletedLinkIDs);
297     }
298 }