Bump upstreams to 2022.09
[bgpcep.git] / bgp / topology-provider / src / test / java / org / opendaylight / bgpcep / bgp / topology / provider / LinkstateTopologyBuilderTest.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.bgpcep.bgp.topology.provider;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15 import static org.mockito.ArgumentMatchers.any;
16 import static org.mockito.Mockito.RETURNS_SMART_NULLS;
17 import static org.mockito.Mockito.doThrow;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.never;
20 import static org.mockito.Mockito.spy;
21 import static org.mockito.Mockito.timeout;
22 import static org.mockito.Mockito.times;
23 import static org.mockito.Mockito.verify;
24 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
25 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
26
27 import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Iterables;
29 import io.netty.buffer.Unpooled;
30 import java.nio.charset.StandardCharsets;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.util.Set;
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.IpAddressNoZone;
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.Ipv4AddressNoZone;
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.ietf.params.xml.ns.yang.ietf.routing.types.rev171204.Uint24;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.AdministrativeGroup;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Identifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4RouterIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IsisAreaIdentifier;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIdsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthKey;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.node._case.NodeDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.link.attributes._case.LinkAttributesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.node.attributes._case.NodeAttributesBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.prefix.attributes._case.PrefixAttributesBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilitiesBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefixBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCaseBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpLinkAttributes1;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.isis.topology.rev131021.IgpNodeAttributes1;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Link;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Link1;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.Node1;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.link.attributes.IgpLinkAttributes;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.nt.l3.unicast.igp.topology.rev131021.igp.node.attributes.IgpNodeAttributes;
104 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;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
107 import org.opendaylight.yangtools.yang.common.Uint16;
108 import org.opendaylight.yangtools.yang.common.Uint32;
109 import org.opendaylight.yangtools.yang.common.Uint64;
110 import org.opendaylight.yangtools.yang.common.Uint8;
111
112 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
113
114     private static final String ROUTER_1_ID = "127.0.0.1";
115     private static final String ROUTER_2_ID = "127.0.0.2";
116     private static final String NODE_1_PREFIX = "127.0.1.1/32";
117     private static final AsNumber NODE_1_AS = new AsNumber(Uint32.ONE);
118     private static final AsNumber NODE_2_AS = new AsNumber(Uint32.TWO);
119     private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
120     private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
121     private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
122     private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
123     private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
124     private static final long LISTENER_RESTART_TIME = 20000;
125     private static final int LISTENER_ENFORCE_COUNTER = 2;
126     private static final int SRGB_START = 90000;
127     private static final int SRGB_RANGE = 16;
128     private static final int NODE_SID_INDEX = 4;
129     private static final int ADJ_SID = 24001;
130
131     private LinkstateTopologyBuilder linkstateTopoBuilder;
132     private InstanceIdentifier<Tables> tablePathIID;
133     private String linkstateNodeRouteKey;
134     private String linkstatePrefixRouteKey;
135     private String linkstateLinkRouteKey;
136     private InstanceIdentifier<LinkstateRoute> linkstateNodeRouteIID;
137     private InstanceIdentifier<LinkstateRoute> linkstatePrefixRouteIID;
138     private InstanceIdentifier<LinkstateRoute> linkstateLinkRouteIID;
139
140     @Before
141     @Override
142     public void setUp() {
143         super.setUp();
144         linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
145             LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
146         linkstateTopoBuilder.start();
147         tablePathIID =
148                 LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
149                         .child(Tables.class,
150                                 new TablesKey(LinkstateAddressFamily.VALUE, LinkstateSubsequentAddressFamily.VALUE))
151                         .build();
152         linkstateNodeRouteKey = getLinkstateRouteKey("node-route");
153         linkstatePrefixRouteKey = getLinkstateRouteKey("prefix-route");
154         linkstateLinkRouteKey = getLinkstateRouteKey("link-route");
155         linkstateNodeRouteIID = createLinkstateRouteIID(linkstateNodeRouteKey);
156         linkstatePrefixRouteIID = createLinkstateRouteIID(linkstatePrefixRouteKey);
157         linkstateLinkRouteIID = createLinkstateRouteIID(linkstateLinkRouteKey);
158     }
159
160     @After
161     public void tearDown() throws Exception {
162         linkstateTopoBuilder.close();
163         checkNotPresentOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier());
164     }
165
166     @Test
167     public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
168         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
169             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
170             return topology;
171         });
172     }
173
174     @Test
175     public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
176         // create node
177         updateLinkstateRoute(linkstateNodeRouteIID,
178                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
179         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
180             assertEquals(1, topology.nonnullNode().size());
181             final Node node1 = topology.nonnullNode().values().iterator().next();
182             assertEquals(NODE_1_ISIS_ID, node1.getNodeId().getValue());
183             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
184             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().iterator().next().getIpv4Address().getValue());
185             assertEquals("node1", igpNode1.getName().getValue());
186             final IgpNodeAttributes1 igpNodeAttributes1 = igpNode1.augmentation(IgpNodeAttributes1.class);
187             assertEquals("0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId()
188                     .getValue());
189             assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
190                     .getValue());
191             assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
192                     .getNet().iterator().next().getValue());
193             assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
194                     .topology.rev131021.IgpNodeAttributes1.class));
195             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
196             assertNull(node1.augmentation(
197                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
198             return topology;
199         });
200
201         // create link
202         updateLinkstateRoute(linkstateLinkRouteIID,
203                 createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
204         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
205             assertEquals(1, topology.nonnullLink().size());
206             final Link link1 = topology.nonnullLink().values().iterator().next();
207             assertEquals(2, topology.nonnullNode().size());
208             assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
209             assertEquals(1, Iterables.get(topology.getNode().values(), 1).getTerminationPoint().size());
210             assertEquals("bgpls://IsisLevel2:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as"
211                     + "=2&mt=1", link1.getLinkId().getValue());
212             assertEquals(NODE_1_ISIS_ID, link1.getSource().getSourceNode().getValue());
213             assertEquals(NODE_2_ISIS_ID, link1.getDestination().getDestNode().getValue());
214             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
215             assertEquals("link1", igpLink1.getName());
216             assertEquals((short) 1, igpLink1.augmentation(IgpLinkAttributes1.class).getIsisLinkAttributes()
217                     .getMultiTopologyId().shortValue());
218             assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
219                     .topology.rev131021.IgpLinkAttributes1.class));
220             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
221             assertEquals(2, topology.getNode().size());
222             final Node srcNode;
223             if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
224                 srcNode = topology.getNode().values().iterator().next();
225             } else {
226                 srcNode = Iterables.get(topology.getNode().values(), 1);
227             }
228             assertEquals(1, srcNode.augmentation(
229                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
230                     .getSegments().size());
231             assertEquals(ADJ_SID, link1.augmentation(
232                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
233                     .getSegment().getValue().intValue());
234             return topology;
235         });
236         removeLinkstateRoute(linkstateLinkRouteIID);
237
238         // update node
239         updateLinkstateRoute(linkstateNodeRouteIID,
240                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node", NODE_1_AS, ROUTER_2_ID));
241         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
242             assertEquals(1, topology.getNode().size());
243             final IgpNodeAttributes igpNode2 = topology.getNode().values().iterator().next().augmentation(Node1.class)
244                     .getIgpNodeAttributes();
245             assertEquals(ROUTER_2_ID, igpNode2.getRouterId().iterator().next().getIpv4Address().getValue());
246             assertEquals("updated-node", igpNode2.getName().getValue());
247             return topology;
248         });
249
250         // remove
251         removeLinkstateRoute(linkstateNodeRouteIID);
252         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
253             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
254             assertNull(topology.getNode());
255             assertNull(topology.getLink());
256             return topology;
257         });
258     }
259
260     @Test
261     public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
262         // create node
263         updateLinkstateRoute(linkstateNodeRouteIID,
264                 createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
265         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
266             assertEquals(1, topology.nonnullNode().size());
267             final Node node1 = topology.nonnullNode().values().iterator().next();
268             assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
269             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
270             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().iterator().next().getIpv4Address().getValue());
271             assertEquals("node1", igpNode1.getName().getValue());
272             assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
273             assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
274                     .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
275                     .getTeRouterIdIpv4().getValue());
276             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
277             assertNull(node1.augmentation(
278                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
279             return topology;
280         });
281
282         // update node with prefix
283         updateLinkstateRoute(linkstatePrefixRouteIID,
284                 createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX, 500L, ROUTER_1_ID));
285         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
286             final Node node1 = topology.nonnullNode().values().iterator().next();
287             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
288             assertEquals(1, igpNode1.nonnullPrefix().size());
289             final Prefix prefix = igpNode1.nonnullPrefix().values().iterator().next();
290             assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
291             assertEquals(500L, prefix.getMetric().longValue());
292             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
293             assertEquals(1, node1.augmentation(
294                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
295                     .nonnullSegments().size());
296             assertEquals(SRGB_START + NODE_SID_INDEX, node1.augmentation(
297                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
298                     .nonnullSegments().values().iterator().next().getSegmentId().getValue().intValue());
299             return topology;
300         });
301
302         // create link
303         updateLinkstateRoute(linkstateLinkRouteIID,
304                 createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
305         readDataOperational(getDataBroker(), linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
306             assertEquals(1, topology.nonnullLink().size());
307             final Link link1 = topology.nonnullLink().values().iterator().next();
308             assertEquals(2, topology.getNode().size());
309             assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
310             assertEquals(1, Iterables.get(topology.getNode().values(), 1).getTerminationPoint().size());
311             assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
312                     link1.getLinkId().getValue());
313             assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
314             assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
315             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
316             assertEquals("link1", igpLink1.getName());
317             assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
318             assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
319                     .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
320                     .shortValue());
321             assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
322                     .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
323                     .getSrlgValues().size());
324             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
325             assertEquals(2, topology.getNode().size());
326             final Node srcNode;
327             if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
328                 srcNode = topology.getNode().values().iterator().next();
329             } else {
330                 srcNode = Iterables.get(topology.getNode().values(), 1);
331             }
332             assertEquals(2, srcNode.augmentation(
333                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
334                     .getSegments().size());
335             assertEquals(ADJ_SID, link1.augmentation(
336                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
337                     .getSegment().getValue().intValue());
338             return topology;
339         });
340     }
341
342     /**
343      * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
344      */
345     @Test
346     @SuppressWarnings("checkstyle:IllegalCatch")
347     public void testRouteChangedError() throws Exception {
348         final LinkstateTopologyBuilder spiedLinkstateTopologyBuilder = spy(linkstateTopoBuilder);
349         doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
350         try {
351             spiedLinkstateTopologyBuilder.routeChanged(null, null);
352             fail("Mockito failed to spy routeChanged() method");
353         } catch (final Exception e) {
354             assertTrue(e instanceof RuntimeException);
355         }
356         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
357         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
358         // first we examine if the chain is being reset when no exception is thrown
359         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
360         verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
361         verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
362         verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
363         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
364         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
365         // now pass some invalid data to cause onDataTreeChanged fail
366         final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
367         final List<DataTreeModification<LinkstateRoute>> changes = new ArrayList<>();
368         changes.add(modification);
369         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
370         // one restart transaction chain check in onDataTreeChanged()
371         // we are introducing some timeout here as transaction may be executed in a delay manner
372         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
373         verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
374         assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
375         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
376         final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
377         // call again with empty change to invoke restartTransactionChainOnDemand()
378         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
379         verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
380         // transaction chain should be reset while listener should not
381         verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
382         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
383         // now apply a change with bad modification again
384         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
385         verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
386         // listener scheduled again
387         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
388         // listener timer shouldn't have changed
389         assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
390         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
391         verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
392         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
393         Thread.sleep(LISTENER_RESTART_TIME);
394         // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
395         spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
396         assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
397                 + LISTENER_RESTART_TIME);
398         verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
399         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
400         // enforce counter get increased
401         assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
402         verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
403         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
404         // sleep to let the listener restart timer times out
405         Thread.sleep(LISTENER_RESTART_TIME);
406         // apply a good modification (empty change)
407         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
408         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
409         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
410         verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
411         // listener restarted didn't get rescheduled again
412         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
413         verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
414         verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
415     }
416
417     private static String getLinkstateRouteKey(final String routeKey) {
418         return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
419     }
420
421     private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
422         return tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
423                 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
424     }
425
426     private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
427             final LinkstateRoute data) {
428         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
429         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
430         wTx.commit();
431     }
432
433     private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
434         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
435         wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
436         wTx.commit();
437     }
438
439     private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
440             final AsNumber asNumber, final String ipv4RouterId) {
441         return createBaseBuilder(linkstateNodeRouteKey, protocolId)
442                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
443                         .rev200120.linkstate.object.type.NodeCaseBuilder()
444                         .setNodeDescriptors(new NodeDescriptorsBuilder()
445                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
446                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
447                                         .build())
448                                 .setAsNumber(asNumber).build()).build())
449                 .setAttributes(new AttributesBuilder()
450                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
451                         .addAugmentation(new Attributes1Builder()
452                                 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
453                                         .setNodeAttributes(new NodeAttributesBuilder()
454                                                 .setDynamicHostname(nodeName)
455                                                 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
456                                                 .setIsisAreaId(Set.of(new IsisAreaIdentifier(new byte[]{0x47})))
457                                                 .setSrCapabilities(new SrCapabilitiesBuilder()
458                                                         .setRangeSize(new Uint24(Uint32.valueOf(SRGB_RANGE)))
459                                                         .setSidLabelIndex(new LocalLabelCaseBuilder()
460                                                                 .setLocalLabel(
461                                                                         new MplsLabel(Uint32.valueOf(SRGB_START)))
462                                                                 .build())
463                                                         .build())
464                                                 .build()).build()).build()).build()).build();
465     }
466
467     private LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
468             final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
469         return createBaseBuilder(linkstatePrefixRouteKey, protocolId)
470             .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
471                     .linkstate.object.type.PrefixCaseBuilder()
472                 .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder()
473                         .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
474                                 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
475                                 .build()).setAsNumber(asNumber).build())
476                 .setPrefixDescriptors(new PrefixDescriptorsBuilder()
477                         .setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
478             .setAttributes(new AttributesBuilder()
479                 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
480                 .addAugmentation(new Attributes1Builder()
481                         .setLinkStateAttribute(new PrefixAttributesCaseBuilder()
482                             .setPrefixAttributes(new PrefixAttributesBuilder()
483                                 .setOspfForwardingAddress(new IpAddressNoZone(new Ipv4AddressNoZone(ospfFwdAddress)))
484                                 .setPrefixMetric(new IgpMetric(Uint32.valueOf(igpMetric)))
485                                 .setSrPrefix(new SrPrefixBuilder()
486                                         .setAlgorithm(Algorithm.ShortestPathFirst)
487                                         .setSidLabelIndex(new SidCaseBuilder()
488                                                 .setSid(Uint32.valueOf(NODE_SID_INDEX)).build())
489                                         .build())
490                                 .build())
491                             .build())
492                         .build())
493                 .build())
494             .build();
495     }
496
497     private LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
498             final AsNumber remoteAs, final String linkName) {
499         return createBaseBuilder(linkstateLinkRouteKey, protocolId)
500                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
501                         .rev200120.linkstate.object.type.LinkCaseBuilder()
502                         .setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
503                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
504                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
505                                         .build()).build()).build())
506                         .setRemoteNodeDescriptors(new RemoteNodeDescriptorsBuilder().setAsNumber(remoteAs).build())
507                         .setLinkDescriptors(new LinkDescriptorsBuilder()
508                                 .setMultiTopologyId(new TopologyIdentifier(Uint16.ONE)).build()).build())
509                 .setAttributes(new AttributesBuilder()
510                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
511                         .addAugmentation(new Attributes1Builder()
512                                 .setLinkStateAttribute(new LinkAttributesCaseBuilder()
513                                     .setLinkAttributes(new LinkAttributesBuilder()
514                                         .setSharedRiskLinkGroups(ImmutableSet.of(
515                                             new SrlgId(Uint32.valueOf(5)), new SrlgId(Uint32.valueOf(15))))
516                                         .setAdminGroup(new AdministrativeGroup(Uint32.ZERO))
517                                         .setMaxLinkBandwidth(
518                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0xff}))
519                                         .setMaxReservableBandwidth(
520                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0x1f}))
521                                         .setUnreservedBandwidth(BindingMap.of(new UnreservedBandwidthBuilder()
522                                                 .withKey(new UnreservedBandwidthKey(Uint8.ONE))
523                                                 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
524                                                 .build()))
525                                         .setTeMetric(new TeMetric(Uint32.valueOf(100)))
526                                         .setLinkName(linkName)
527                                         .setSrAdjIds(List.of(new SrAdjIdsBuilder()
528                                                 .setSidLabelIndex(new LocalLabelCaseBuilder()
529                                                         .setLocalLabel(new MplsLabel(Uint32.valueOf(ADJ_SID)))
530                                                         .build())
531                                                 .build()))
532                                         .build())
533                                     .build())
534                                 .build())
535                         .build())
536                 .build();
537     }
538
539     private static LinkstateRouteBuilder createBaseBuilder(final String linkstateRouteKey,
540             final ProtocolId protocolId) {
541         return new LinkstateRouteBuilder()
542             .setIdentifier(IDENTIFIER)
543             .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey))
544             .setRouteKey(linkstateRouteKey)
545             .setProtocolId(protocolId);
546     }
547 }