2 * Copyright (c) 2014 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.l2switch.loopremover.topology;
10 import static org.mockito.ArgumentMatchers.any;
11 import static org.mockito.ArgumentMatchers.anyList;
12 import static org.mockito.Mockito.times;
13 import static org.mockito.Mockito.verify;
14 import static org.mockito.Mockito.when;
16 import com.google.common.util.concurrent.FluentFuture;
17 import java.util.ArrayList;
18 import java.util.List;
20 import java.util.Optional;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.mockito.Mock;
24 import org.mockito.Mockito;
25 import org.mockito.MockitoAnnotations;
26 import org.opendaylight.mdsal.binding.api.DataBroker;
27 import org.opendaylight.mdsal.binding.api.DataObjectModification;
28 import org.opendaylight.mdsal.binding.api.DataTreeChangeListener;
29 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
30 import org.opendaylight.mdsal.binding.api.DataTreeModification;
31 import org.opendaylight.mdsal.binding.api.ReadTransaction;
32 import org.opendaylight.mdsal.binding.api.ReadWriteTransaction;
33 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatus;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatusAwareNodeConnector;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2switch.loopremover.rev140714.StpStatusAwareNodeConnectorBuilder;
40 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.LinkId;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.DestinationBuilder;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.link.attributes.SourceBuilder;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
48 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
49 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
50 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.LinkBuilder;
51 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
52 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
53 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
55 public class TopologyLinkDataChangeHandlerTest {
57 private DataBroker dataBroker;
59 private NetworkGraphService networkGraphService;
60 private TopologyLinkDataChangeHandler topologyLinkDataChangeHandler;
63 public void initMocks() {
64 MockitoAnnotations.initMocks(this);
65 topologyLinkDataChangeHandler = new TopologyLinkDataChangeHandler(dataBroker, networkGraphService);
66 topologyLinkDataChangeHandler.setTopologyId(null);
67 topologyLinkDataChangeHandler.setGraphRefreshDelay(0);
71 public void testRegisterAsDataChangeListener() throws Exception {
72 topologyLinkDataChangeHandler.registerAsDataChangeListener();
73 verify(dataBroker, times(1)).registerDataTreeChangeListener(any(DataTreeIdentifier.class),
74 any(DataTreeChangeListener.class));
77 @SuppressWarnings("unchecked")
79 public void testOnDataChanged_CreatedDataNoRefresh() throws Exception {
80 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
81 .child(Topology.class)
84 Link hostLink = new LinkBuilder().setLinkId(new LinkId("host:1")).build();
85 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
86 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
87 when(mockModification.getDataAfter()).thenReturn(hostLink);
88 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
89 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
91 when(mockChange.getRootNode()).thenReturn(mockModification);
92 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
94 verify(networkGraphService, times(0)).clear();
97 @SuppressWarnings("unchecked")
99 public void testOnDataChanged_CreatedDataRefresh() throws Exception {
100 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
101 .child(Topology.class)
104 Link hostLink = new LinkBuilder().setLinkId(new LinkId("openflow:1")).build();
105 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
106 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
107 when(mockModification.getDataAfter()).thenReturn(hostLink);
108 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
109 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
111 when(mockChange.getRootNode()).thenReturn(mockModification);
112 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
114 verify(networkGraphService, times(1)).clear();
117 @SuppressWarnings("unchecked")
119 public void testOnDataChanged_RemovedDataNoRefresh() throws Exception {
120 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
121 .child(Topology.class)
124 Link hostLink = new LinkBuilder().setLinkId(new LinkId("host:1")).build();
125 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
126 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
127 when(mockModification.getDataBefore()).thenReturn(hostLink);
128 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
129 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
131 when(mockChange.getRootNode()).thenReturn(mockModification);
132 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
134 verify(networkGraphService, times(0)).clear();
137 @SuppressWarnings("unchecked")
139 public void testOnDataChanged_RemovedDataRefresh() throws Exception {
140 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
141 .child(Topology.class)
144 Link hostLink = new LinkBuilder().setLinkId(new LinkId("openflow:1")).build();
145 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
146 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
147 when(mockModification.getDataBefore()).thenReturn(hostLink);
148 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
149 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
151 when(mockChange.getRootNode()).thenReturn(mockModification);
152 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
154 verify(networkGraphService, times(1)).clear();
157 @SuppressWarnings("unchecked")
159 public void testUpdateNodeConnectorStatus_NoLinks() throws Exception {
160 // Setup code to trigger the TopologyDataChangeEventProcessor
161 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
162 .child(Topology.class)
165 Link nodeLink = new LinkBuilder().setLinkId(new LinkId("openflow:1")).build();
166 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
167 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
168 when(mockModification.getDataAfter()).thenReturn(nodeLink);
169 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
170 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
172 when(mockChange.getRootNode()).thenReturn(mockModification);
174 Topology topology = new TopologyBuilder().setTopologyId(new TopologyId("topo")).setLink(Map.of()).build();
175 Optional<Topology> topologyOptional = Optional.of(topology);
176 FluentFuture<Optional<Topology>> checkedFuture = FluentFutures.immediateFluentFuture(topologyOptional);
177 ReadTransaction readOnlyTransaction = Mockito.mock(ReadTransaction.class);
178 when(readOnlyTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
179 .thenReturn(checkedFuture);
180 when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
182 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
184 verify(dataBroker, times(0)).newReadWriteTransaction();
185 verify(networkGraphService, times(0)).addLinks(any(List.class));
186 verify(networkGraphService, times(0)).getAllLinks();
187 verify(networkGraphService, times(0)).getLinksInMst();
190 @SuppressWarnings("unchecked")
192 public void testUpdateNodeConnectorStatus_WithLinks() throws Exception {
193 // Setup code to trigger the TopologyDataChangeEventProcessor
194 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
195 .child(Topology.class)
198 Link nodeLink = new LinkBuilder().setLinkId(new LinkId("openflow:1")).build();
199 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
200 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
201 when(mockModification.getDataAfter()).thenReturn(nodeLink);
202 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
203 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
205 when(mockChange.getRootNode()).thenReturn(mockModification);
207 // getLinksFromTopology
208 Topology topology = new TopologyBuilder()
209 .setTopologyId(new TopologyId("topo"))
210 .setLink(BindingMap.of(new LinkBuilder().setLinkId(new LinkId("openflow:1")).build()))
212 Optional<Topology> topologyOptional = Optional.of(topology);
213 FluentFuture<Optional<Topology>> checkedFuture = FluentFutures.immediateFluentFuture(topologyOptional);
214 ReadTransaction readOnlyTransaction = Mockito.mock(ReadTransaction.class);
215 when(readOnlyTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
216 .thenReturn(checkedFuture);
217 when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
220 ReadWriteTransaction readWriteTransaction = Mockito.mock(ReadWriteTransaction.class);
221 when(dataBroker.newReadWriteTransaction()).thenReturn(readWriteTransaction);
223 // updateNodeConnectorStatus
224 Link link1 = new LinkBuilder().setLinkId(new LinkId("openflow:1"))
225 .setSource(new SourceBuilder().setSourceNode(new NodeId("openflow:1"))
226 .setSourceTp(new TpId("openflow:1")).build())
227 .setDestination(new DestinationBuilder().setDestNode(new NodeId("openflow:1"))
228 .setDestTp(new TpId("openflow:1")).build())
230 Link link2 = new LinkBuilder().setLinkId(new LinkId("openflow:2"))
231 .setSource(new SourceBuilder().setSourceNode(new NodeId("openflow:2"))
232 .setSourceTp(new TpId("openflow:2")).build())
233 .setDestination(new DestinationBuilder().setDestNode(new NodeId("openflow:2"))
234 .setDestTp(new TpId("openflow:2")).build())
237 List<Link> allLinks = new ArrayList<>();
240 when(networkGraphService.getAllLinks()).thenReturn(allLinks);
241 List<Link> mstLinks = new ArrayList<>();
243 when(networkGraphService.getLinksInMst()).thenReturn(mstLinks);
245 // checkIfExistAndUpdateNodeConnector
246 NodeConnector nodeConnector = new NodeConnectorBuilder().setId(new NodeConnectorId("connId")).build();
247 Optional<NodeConnector> optionalNodeConnector = Optional.of(nodeConnector);
248 FluentFuture<Optional<NodeConnector>> checkedFutureNc =
249 FluentFutures.immediateFluentFuture(optionalNodeConnector);
250 when(readWriteTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
251 .thenReturn(checkedFutureNc);
253 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
255 verify(dataBroker, times(1)).newReadWriteTransaction();
256 verify(networkGraphService, times(1)).addLinks(any(ArrayList.class));
257 verify(networkGraphService, times(1)).getAllLinks();
258 verify(networkGraphService, times(1)).getLinksInMst();
259 verify(readWriteTransaction, times(4)).merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
260 any(StpStatusAwareNodeConnector.class));
261 verify(readWriteTransaction, times(1)).commit();
265 public void testUpdateNodeConnectorStatus_WithStpLinks() throws Exception {
266 // Setup code to trigger the TopologyDataChangeEventProcessor
267 InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
268 .child(Topology.class)
271 Link nodeLink = new LinkBuilder().setLinkId(new LinkId("openflow:1")).build();
272 DataTreeModification<Link> mockChange = Mockito.mock(DataTreeModification.class);
273 DataObjectModification<Link> mockModification = Mockito.mock(DataObjectModification.class);
274 when(mockModification.getDataAfter()).thenReturn(nodeLink);
275 when(mockModification.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
276 when(mockChange.getRootPath()).thenReturn(DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL,
278 when(mockChange.getRootNode()).thenReturn(mockModification);
280 // getLinksFromTopology
281 Topology topology = new TopologyBuilder()
282 .setTopologyId(new TopologyId("topo"))
283 .setLink(BindingMap.of(new LinkBuilder().setLinkId(new LinkId("openflow:1")).build()))
285 Optional<Topology> topologyOptional = Optional.of(topology);
286 FluentFuture<Optional<Topology>> checkedFuture = FluentFutures.immediateFluentFuture(topologyOptional);
287 ReadTransaction readOnlyTransaction = Mockito.mock(ReadTransaction.class);
288 when(readOnlyTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
289 .thenReturn(checkedFuture);
290 when(dataBroker.newReadOnlyTransaction()).thenReturn(readOnlyTransaction);
293 ReadWriteTransaction readWriteTransaction = Mockito.mock(ReadWriteTransaction.class);
294 when(dataBroker.newReadWriteTransaction()).thenReturn(readWriteTransaction);
296 // updateNodeConnectorStatus
297 Link link1 = new LinkBuilder().setLinkId(new LinkId("openflow:1"))
298 .setSource(new SourceBuilder().setSourceNode(new NodeId("openflow:1"))
299 .setSourceTp(new TpId("openflow:1")).build())
300 .setDestination(new DestinationBuilder().setDestNode(new NodeId("openflow:1"))
301 .setDestTp(new TpId("openflow:1")).build())
303 Link link2 = new LinkBuilder().setLinkId(new LinkId("openflow:2"))
304 .setSource(new SourceBuilder().setSourceNode(new NodeId("openflow:2"))
305 .setSourceTp(new TpId("openflow:2")).build())
306 .setDestination(new DestinationBuilder().setDestNode(new NodeId("openflow:2"))
307 .setDestTp(new TpId("openflow:2")).build())
310 List<Link> allLinks = new ArrayList<>();
313 when(networkGraphService.getAllLinks()).thenReturn(allLinks);
314 List<Link> mstLinks = new ArrayList<>();
316 when(networkGraphService.getLinksInMst()).thenReturn(mstLinks);
318 // checkIfExistAndUpdateNodeConnector
319 NodeConnector nodeConnector = new NodeConnectorBuilder()
320 .setId(new NodeConnectorId("connId"))
321 .addAugmentation(new StpStatusAwareNodeConnectorBuilder().setStatus(StpStatus.Forwarding).build())
323 Optional<NodeConnector> optionalNodeConnector = Optional.of(nodeConnector);
324 FluentFuture<Optional<NodeConnector>> checkedFutureNc =
325 FluentFutures.immediateFluentFuture(optionalNodeConnector);
326 when(readWriteTransaction.read(any(LogicalDatastoreType.class), any(InstanceIdentifier.class)))
327 .thenReturn(checkedFutureNc);
329 topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
331 verify(dataBroker, times(1)).newReadWriteTransaction();
332 verify(networkGraphService, times(1)).addLinks(anyList());
333 verify(networkGraphService, times(1)).getAllLinks();
334 verify(networkGraphService, times(1)).getLinksInMst();
335 verify(readWriteTransaction, times(2)).merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class),
336 any(StpStatusAwareNodeConnector.class));
337 verify(readWriteTransaction, times(1)).commit();