da196006d9c706b686138a07749d295f010e28da
[l2switch.git] / loopremover / implementation / src / test / java / org / opendaylight / l2switch / loopremover / topology / TopologyLinkDataChangeHandlerTest.java
1 /*
2  * Copyright (c) 2014 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.l2switch.loopremover.topology;
9
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;
15
16 import com.google.common.util.concurrent.FluentFuture;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.Map;
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;
54
55 public class TopologyLinkDataChangeHandlerTest {
56     @Mock
57     private DataBroker dataBroker;
58     @Mock
59     private NetworkGraphService networkGraphService;
60     private TopologyLinkDataChangeHandler topologyLinkDataChangeHandler;
61
62     @Before
63     public void initMocks() {
64         MockitoAnnotations.initMocks(this);
65         topologyLinkDataChangeHandler = new TopologyLinkDataChangeHandler(dataBroker, networkGraphService);
66         topologyLinkDataChangeHandler.setTopologyId(null);
67         topologyLinkDataChangeHandler.setGraphRefreshDelay(0);
68     }
69
70     @Test
71     public void testRegisterAsDataChangeListener() throws Exception {
72         topologyLinkDataChangeHandler.registerAsDataChangeListener();
73         verify(dataBroker, times(1)).registerDataTreeChangeListener(any(DataTreeIdentifier.class),
74                 any(DataTreeChangeListener.class));
75     }
76
77     @SuppressWarnings("unchecked")
78     @Test
79     public void testOnDataChanged_CreatedDataNoRefresh() throws Exception {
80         InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
81             .child(Topology.class)
82             .child(Link.class)
83             .build();
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,
90                 instanceId));
91         when(mockChange.getRootNode()).thenReturn(mockModification);
92         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
93         Thread.sleep(500);
94         verify(networkGraphService, times(0)).clear();
95     }
96
97     @SuppressWarnings("unchecked")
98     @Test
99     public void testOnDataChanged_CreatedDataRefresh() throws Exception {
100         InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
101             .child(Topology.class)
102             .child(Link.class)
103             .build();
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,
110                 instanceId));
111         when(mockChange.getRootNode()).thenReturn(mockModification);
112         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
113         Thread.sleep(500);
114         verify(networkGraphService, times(1)).clear();
115     }
116
117     @SuppressWarnings("unchecked")
118     @Test
119     public void testOnDataChanged_RemovedDataNoRefresh() throws Exception {
120         InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
121             .child(Topology.class)
122             .child(Link.class)
123             .build();
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,
130                 instanceId));
131         when(mockChange.getRootNode()).thenReturn(mockModification);
132         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
133         Thread.sleep(500);
134         verify(networkGraphService, times(0)).clear();
135     }
136
137     @SuppressWarnings("unchecked")
138     @Test
139     public void testOnDataChanged_RemovedDataRefresh() throws Exception {
140         InstanceIdentifier<Link> instanceId = InstanceIdentifier.builder(NetworkTopology.class)
141             .child(Topology.class)
142             .child(Link.class)
143             .build();
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,
150                 instanceId));
151         when(mockChange.getRootNode()).thenReturn(mockModification);
152         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
153         Thread.sleep(500);
154         verify(networkGraphService, times(1)).clear();
155     }
156
157     @SuppressWarnings("unchecked")
158     @Test
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)
163             .child(Link.class)
164             .build();
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,
171                 instanceId));
172         when(mockChange.getRootNode()).thenReturn(mockModification);
173         // End setup code
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);
181
182         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
183         Thread.sleep(500);
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();
188     }
189
190     @SuppressWarnings("unchecked")
191     @Test
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)
196             .child(Link.class)
197             .build();
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,
204                 instanceId));
205         when(mockChange.getRootNode()).thenReturn(mockModification);
206
207         // getLinksFromTopology
208         Topology topology = new TopologyBuilder()
209             .setTopologyId(new TopologyId("topo"))
210             .setLink(BindingMap.of(new LinkBuilder().setLinkId(new LinkId("openflow:1")).build()))
211             .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);
218
219         // run
220         ReadWriteTransaction readWriteTransaction = Mockito.mock(ReadWriteTransaction.class);
221         when(dataBroker.newReadWriteTransaction()).thenReturn(readWriteTransaction);
222
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())
229                 .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())
235                 .build();
236
237         List<Link> allLinks = new ArrayList<>();
238         allLinks.add(link1);
239         allLinks.add(link2);
240         when(networkGraphService.getAllLinks()).thenReturn(allLinks);
241         List<Link> mstLinks = new ArrayList<>();
242         mstLinks.add(link1);
243         when(networkGraphService.getLinksInMst()).thenReturn(mstLinks);
244
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);
252
253         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
254         Thread.sleep(500);
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();
262     }
263
264     @Test
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)
269             .child(Link.class)
270             .build();
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,
277                 instanceId));
278         when(mockChange.getRootNode()).thenReturn(mockModification);
279
280         // getLinksFromTopology
281         Topology topology = new TopologyBuilder()
282             .setTopologyId(new TopologyId("topo"))
283             .setLink(BindingMap.of(new LinkBuilder().setLinkId(new LinkId("openflow:1")).build()))
284             .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);
291
292         // run
293         ReadWriteTransaction readWriteTransaction = Mockito.mock(ReadWriteTransaction.class);
294         when(dataBroker.newReadWriteTransaction()).thenReturn(readWriteTransaction);
295
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())
302                 .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())
308                 .build();
309
310         List<Link> allLinks = new ArrayList<>();
311         allLinks.add(link1);
312         allLinks.add(link2);
313         when(networkGraphService.getAllLinks()).thenReturn(allLinks);
314         List<Link> mstLinks = new ArrayList<>();
315         mstLinks.add(link1);
316         when(networkGraphService.getLinksInMst()).thenReturn(mstLinks);
317
318         // checkIfExistAndUpdateNodeConnector
319         NodeConnector nodeConnector = new NodeConnectorBuilder()
320                 .setId(new NodeConnectorId("connId"))
321                 .addAugmentation(new StpStatusAwareNodeConnectorBuilder().setStatus(StpStatus.Forwarding).build())
322                 .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);
328
329         topologyLinkDataChangeHandler.onDataTreeChanged(List.of(mockChange));
330         Thread.sleep(500);
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();
338     }
339 }