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.bgpcep.bgp.topology.provider;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.RETURNS_SMART_NULLS;
18 import static org.mockito.Mockito.doThrow;
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.never;
21 import static org.mockito.Mockito.spy;
22 import static org.mockito.Mockito.timeout;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
26 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
28 import com.google.common.collect.Lists;
29 import io.netty.buffer.Unpooled;
30 import java.nio.charset.StandardCharsets;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.List;
34 import java.util.concurrent.ExecutionException;
35 import org.junit.After;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.opendaylight.mdsal.binding.api.DataTreeModification;
39 import org.opendaylight.mdsal.binding.api.WriteTransaction;
40 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
45 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.AdministrativeGroup;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.Identifier;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.Ipv4RouterIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.IsisAreaIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateAddressFamily;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.LinkstateSubsequentAddressFamily;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.ProtocolId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.TopologyIdentifier;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.attribute.UnreservedBandwidthBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.attribute.UnreservedBandwidthKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LinkDescriptorsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.node._case.NodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributesBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.LinkstateRoutes;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRoute;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.LinkstateRouteKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.linkstate.route.Attributes1;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.OriginBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.BgpOrigin;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpLinkAttributes1;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpNodeAttributes1;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
92 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Link1;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.link.attributes.IgpLinkAttributes;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.IgpNodeAttributes;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.igp.node.attributes.Prefix;
98 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
99 import org.opendaylight.yangtools.yang.common.Uint16;
100 import org.opendaylight.yangtools.yang.common.Uint32;
101 import org.opendaylight.yangtools.yang.common.Uint64;
102 import org.opendaylight.yangtools.yang.common.Uint8;
104 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
106 private static final String LINKSTATE_ROUTE_KEY = Unpooled.wrappedBuffer(
107 StandardCharsets.UTF_8.encode("linkstate-route")).array().toString();
108 private static final String ROUTER_1_ID = "127.0.0.1";
109 private static final String ROUTER_2_ID = "127.0.0.2";
110 private static final String NODE_1_PREFIX = "127.0.1.1/32";
111 private static final AsNumber NODE_1_AS = new AsNumber(Uint32.ONE);
112 private static final AsNumber NODE_2_AS = new AsNumber(Uint32.TWO);
113 private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
114 private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
115 private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
116 private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
117 private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
118 private static final long LISTENER_RESTART_TIME = 20000;
119 private static final int LISTENER_ENFORCE_COUNTER = 2;
121 private LinkstateTopologyBuilder linkstateTopoBuilder;
122 private InstanceIdentifier<LinkstateRoute> linkstateRouteIID;
126 public void setUp() {
128 this.linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
129 LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
130 this.linkstateTopoBuilder.start();
131 final InstanceIdentifier<Tables> path = LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
132 .child(Tables.class, new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
134 this.linkstateRouteIID = path.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
135 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), LINKSTATE_ROUTE_KEY))
141 public void tearDown() throws Exception {
142 this.linkstateTopoBuilder.close();
143 checkNotPresentOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier());
147 public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
148 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
149 assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
150 .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class));
151 assertNotNull(topology.getTopologyTypes().augmentation(org.opendaylight.yang.gen.v1.urn.opendaylight
152 .params.xml.ns.yang.odl.bgp.topology.types.rev160524.TopologyTypes1.class)
153 .getBgpLinkstateTopology());
159 public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
161 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
162 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
163 assertEquals(1, topology.getNode().size());
164 final Node node1 = topology.getNode().get(0);
165 assertEquals(NODE_1_ISIS_ID, node1.getNodeId().getValue());
166 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
167 assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
168 assertEquals("node1", igpNode1.getName().getValue());
169 final IgpNodeAttributes1 igpNodeAttributes1 = igpNode1.augmentation(IgpNodeAttributes1.class);
170 assertEquals("0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId()
172 assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
174 assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
175 .getNet().get(0).getValue());
176 assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
177 .topology.rev131021.IgpNodeAttributes1.class));
183 updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
184 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
185 assertEquals(1, topology.getLink().size());
186 final Link link1 = topology.getLink().get(0);
187 assertEquals(2, topology.getNode().size());
188 assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
189 assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
190 assertEquals("bgpls://IsisLevel2:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as"
191 + "=2&mt=1", link1.getLinkId().getValue());
192 assertEquals(NODE_1_ISIS_ID, link1.getSource().getSourceNode().getValue());
193 assertEquals(NODE_2_ISIS_ID, link1.getDestination().getDestNode().getValue());
194 final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
195 assertEquals("link1", igpLink1.getName());
196 assertEquals((short) 1, igpLink1.augmentation(IgpLinkAttributes1.class).getIsisLinkAttributes()
197 .getMultiTopologyId().shortValue());
198 assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
199 .topology.rev131021.IgpLinkAttributes1.class));
205 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node",
206 NODE_1_AS, ROUTER_2_ID));
207 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
208 assertEquals(1, topology.getNode().size());
209 final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
210 .getIgpNodeAttributes();
211 assertEquals(ROUTER_2_ID, igpNode2.getRouterId().get(0).getIpv4Address().getValue());
212 assertEquals("updated-node", igpNode2.getName().getValue());
217 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
218 wTx.delete(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID);
220 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
221 assertNull(topology.getNode());
222 assertNull(topology.getLink());
228 public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
230 updateLinkstateRoute(createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
231 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
232 assertEquals(1, topology.getNode().size());
233 final Node node1 = topology.getNode().get(0);
234 assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
235 final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
236 assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
237 assertEquals("node1", igpNode1.getName().getValue());
238 assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
239 assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
240 .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
241 .getTeRouterIdIpv4().getValue());
245 // update node with prefix
246 updateLinkstateRoute(createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX,
248 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
249 final IgpNodeAttributes igpNode2 = topology.getNode().get(0).augmentation(Node1.class)
250 .getIgpNodeAttributes();
251 assertEquals(1, igpNode2.getPrefix().size());
252 final Prefix prefix = igpNode2.getPrefix().get(0);
253 assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
254 assertEquals(500L, prefix.getMetric().longValue());
260 updateLinkstateRoute(createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
261 readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
262 assertEquals(1, topology.getLink().size());
263 final Link link1 = topology.getLink().get(0);
264 assertEquals(2, topology.getNode().size());
265 assertEquals(1, topology.getNode().get(0).getTerminationPoint().size());
266 assertEquals(1, topology.getNode().get(1).getTerminationPoint().size());
267 assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
268 link1.getLinkId().getValue());
269 assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
270 assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
271 final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
272 assertEquals("link1", igpLink1.getName());
273 assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
274 assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
275 .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
277 assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
278 .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
279 .getSrlgValues().size());
287 * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
290 @SuppressWarnings("checkstyle:IllegalCatch")
291 public void testRouteChangedError() throws Exception {
292 final LinkstateTopologyBuilder spiedLinkstateTopologyBuilder = spy(this.linkstateTopoBuilder);
293 doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
295 spiedLinkstateTopologyBuilder.routeChanged(null, null);
296 fail("Mockito failed to spy routeChanged() method");
297 } catch (final Exception e) {
298 assertTrue(e instanceof RuntimeException);
300 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
301 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
302 // first we examine if the chain is being reset when no exception is thrown
303 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
304 verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
305 verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
306 verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
307 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
308 assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
309 // now pass some invalid data to cause onDataTreeChanged fail
310 final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
311 final List<DataTreeModification<LinkstateRoute>> changes = new ArrayList<>();
312 changes.add(modification);
313 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
314 // one restart transaction chain check in onDataTreeChanged()
315 // we are introducing some timeout here as transaction may be executed in a delay manner
316 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
317 verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
318 assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
319 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
320 final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
321 // call again with empty change to invoke restartTransactionChainOnDemand()
322 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
323 verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
324 // transaction chain should be reset while listener should not
325 verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
326 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
327 // now apply a change with bad modification again
328 spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
329 verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
330 // listener scheduled again
331 verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
332 // listener timer shouldn't have changed
333 assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
334 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
335 verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
336 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
337 Thread.sleep(LISTENER_RESTART_TIME);
338 // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
339 spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
340 assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
341 + LISTENER_RESTART_TIME);
342 verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
343 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
344 // enforce counter get increased
345 assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
346 verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
347 verify(spiedLinkstateTopologyBuilder, never()).resetListener();
348 // sleep to let the listener restart timer times out
349 Thread.sleep(LISTENER_RESTART_TIME);
350 // apply a good modification (empty change)
351 spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
352 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
353 assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
354 verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
355 // listener restarted didn't get rescheduled again
356 verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
357 verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
358 verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
361 private void updateLinkstateRoute(final LinkstateRoute data) {
362 final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
363 wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, this.linkstateRouteIID, data);
367 private static LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
368 final AsNumber asNumber, final String ipv4RouterId) {
369 return createBaseBuilder(protocolId)
370 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
371 .rev180329.linkstate.object.type.NodeCaseBuilder()
372 .setNodeDescriptors(new NodeDescriptorsBuilder()
373 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
374 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
376 .setAsNumber(asNumber).build()).build())
377 .setAttributes(new AttributesBuilder()
378 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
379 .addAugmentation(Attributes1.class, new Attributes1Builder()
380 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
381 .setNodeAttributes(new NodeAttributesBuilder()
382 .setDynamicHostname(nodeName)
383 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
384 .setIsisAreaId(Collections.singletonList(
385 new IsisAreaIdentifier(new byte[]{0x47})))
386 .build()).build()).build()).build()).build();
389 private static LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
390 final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
391 return createBaseBuilder(protocolId)
392 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329
393 .linkstate.object.type.PrefixCaseBuilder()
394 .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder().setAsNumber(asNumber).build())
395 .setPrefixDescriptors(new PrefixDescriptorsBuilder()
396 .setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
397 .setAttributes(new AttributesBuilder()
398 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
399 .addAugmentation(Attributes1.class, new Attributes1Builder()
400 .setLinkStateAttribute(new PrefixAttributesCaseBuilder()
401 .setPrefixAttributes(new PrefixAttributesBuilder()
402 .setOspfForwardingAddress(new IpAddress(new Ipv4Address(ospfFwdAddress)))
403 .setPrefixMetric(new IgpMetric(Uint32.valueOf(igpMetric)))
411 private static LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
412 final AsNumber remoteAs, final String linkName) {
413 return createBaseBuilder(protocolId)
414 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
415 .rev180329.linkstate.object.type.LinkCaseBuilder()
416 .setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
417 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
418 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
419 .build()).build()).build())
420 .setRemoteNodeDescriptors(new RemoteNodeDescriptorsBuilder().setAsNumber(remoteAs).build())
421 .setLinkDescriptors(new LinkDescriptorsBuilder()
422 .setMultiTopologyId(new TopologyIdentifier(Uint16.ONE)).build()).build())
423 .setAttributes(new AttributesBuilder()
424 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
425 .addAugmentation(Attributes1.class, new Attributes1Builder()
426 .setLinkStateAttribute(new LinkAttributesCaseBuilder()
427 .setLinkAttributes(new LinkAttributesBuilder()
428 .setSharedRiskLinkGroups(Lists.newArrayList(
429 new SrlgId(Uint32.valueOf(5)), new SrlgId(Uint32.valueOf(15))))
430 .setAdminGroup(new AdministrativeGroup(Uint32.ZERO))
431 .setMaxLinkBandwidth(
432 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0xff}))
433 .setMaxReservableBandwidth(
434 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0x1f}))
435 .setUnreservedBandwidth(Lists.newArrayList(new UnreservedBandwidthBuilder()
436 .withKey(new UnreservedBandwidthKey(Uint8.ONE))
437 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
439 .setTeMetric(new TeMetric(Uint32.valueOf(100)))
440 .setLinkName(linkName)
448 private static LinkstateRouteBuilder createBaseBuilder(final ProtocolId protocolId) {
449 return new LinkstateRouteBuilder()
450 .setIdentifier(IDENTIFIER)
451 .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), LINKSTATE_ROUTE_KEY))
452 .setRouteKey(LINKSTATE_ROUTE_KEY)
453 .setProtocolId(protocolId);