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