Update MRI projects for Aluminium
[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.Iterables;
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.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.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.AdministrativeGroup;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Identifier;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Ipv4RouterIdentifier;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.IsisAreaIdentifier;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateAddressFamily;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.LinkstateSubsequentAddressFamily;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.TopologyIdentifier;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.bgp.rib.rib.loc.rib.tables.routes.LinkstateRoutesCase;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.SrAdjIdsBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.attribute.UnreservedBandwidthKey;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptorsBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LocalNodeDescriptorsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.RemoteNodeDescriptorsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.node._case.NodeDescriptorsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.AdvertisingNodeDescriptorsBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.PrefixDescriptorsBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCaseBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCaseBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCaseBuilder;
67 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;
68 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;
69 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;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.LinkstateRoutes;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRoute;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.LinkstateRouteKey;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.routes.linkstate.routes.linkstate.route.Attributes1Builder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.IsisNodeCaseBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.identifier.c.router.identifier.isis.node._case.IsisNodeBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.node.state.SrCapabilitiesBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.prefix.state.SrPrefixBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.PathId;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.OriginBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.rib.LocRib;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.Tables;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.Algorithm;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.LocalLabelCaseBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.segment.routing.ext.rev200120.sid.label.index.sid.label.index.SidCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpOrigin;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IgpMetric;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.IsoSystemIdentifier;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.TeMetric;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.SrlgId;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.uint24.rev200104.Uint24;
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.common.Uint16;
107 import org.opendaylight.yangtools.yang.common.Uint32;
108 import org.opendaylight.yangtools.yang.common.Uint64;
109 import org.opendaylight.yangtools.yang.common.Uint8;
110
111 public class LinkstateTopologyBuilderTest extends AbstractTopologyBuilderTest {
112
113     private static final String ROUTER_1_ID = "127.0.0.1";
114     private static final String ROUTER_2_ID = "127.0.0.2";
115     private static final String NODE_1_PREFIX = "127.0.1.1/32";
116     private static final AsNumber NODE_1_AS = new AsNumber(Uint32.ONE);
117     private static final AsNumber NODE_2_AS = new AsNumber(Uint32.TWO);
118     private static final String NODE_1_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=1&router=0000.0102.0304";
119     private static final String NODE_2_ISIS_ID = "bgpls://IsisLevel2:1/type=node&as=2";
120     private static final String NODE_1_OSPF_ID = "bgpls://Ospf:1/type=node&as=1&router=0000.0102.0304";
121     private static final String NODE_2_OSPF_ID = "bgpls://Ospf:1/type=node&as=2";
122     private static final Identifier IDENTIFIER = new Identifier(Uint64.ONE);
123     private static final long LISTENER_RESTART_TIME = 20000;
124     private static final int LISTENER_ENFORCE_COUNTER = 2;
125     private static final int SRGB_START = 90000;
126     private static final int SRGB_RANGE = 16;
127     private static final int NODE_SID_INDEX = 4;
128     private static final int ADJ_SID = 24001;
129
130     private LinkstateTopologyBuilder linkstateTopoBuilder;
131     private InstanceIdentifier<Tables> tablePathIID;
132     private String linkstateNodeRouteKey;
133     private String linkstatePrefixRouteKey;
134     private String linkstateLinkRouteKey;
135     private InstanceIdentifier<LinkstateRoute> linkstateNodeRouteIID;
136     private InstanceIdentifier<LinkstateRoute> linkstatePrefixRouteIID;
137     private InstanceIdentifier<LinkstateRoute> linkstateLinkRouteIID;
138
139     @Before
140     @Override
141     public void setUp() {
142         super.setUp();
143         this.linkstateTopoBuilder = new LinkstateTopologyBuilder(getDataBroker(), LOC_RIB_REF, TEST_TOPOLOGY_ID,
144             LISTENER_RESTART_TIME, LISTENER_ENFORCE_COUNTER);
145         this.linkstateTopoBuilder.start();
146         this.tablePathIID =
147                 LOC_RIB_REF.getInstanceIdentifier().builder().child(LocRib.class)
148                         .child(Tables.class,
149                                 new TablesKey(LinkstateAddressFamily.class, LinkstateSubsequentAddressFamily.class))
150                         .build();
151         this.linkstateNodeRouteKey = getLinkstateRouteKey("node-route");
152         this.linkstatePrefixRouteKey = getLinkstateRouteKey("prefix-route");
153         this.linkstateLinkRouteKey = getLinkstateRouteKey("link-route");
154         this.linkstateNodeRouteIID = createLinkstateRouteIID(this.linkstateNodeRouteKey);
155         this.linkstatePrefixRouteIID = createLinkstateRouteIID(this.linkstatePrefixRouteKey);
156         this.linkstateLinkRouteIID = createLinkstateRouteIID(this.linkstateLinkRouteKey);
157     }
158
159     @After
160     public void tearDown() throws Exception {
161         this.linkstateTopoBuilder.close();
162         checkNotPresentOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier());
163     }
164
165     @Test
166     public void testLinkstateTopologyBuilderTopologyTypes() throws InterruptedException, ExecutionException {
167         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
168             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
169             return topology;
170         });
171     }
172
173     @Test
174     public void testIsisLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
175         // create node
176         updateLinkstateRoute(this.linkstateNodeRouteIID,
177                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "node1", NODE_1_AS, ROUTER_1_ID));
178         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
179             assertEquals(1, topology.nonnullNode().size());
180             final Node node1 = topology.nonnullNode().values().iterator().next();
181             assertEquals(NODE_1_ISIS_ID, node1.getNodeId().getValue());
182             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
183             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
184             assertEquals("node1", igpNode1.getName().getValue());
185             final IgpNodeAttributes1 igpNodeAttributes1 = igpNode1.augmentation(IgpNodeAttributes1.class);
186             assertEquals("0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId()
187                     .getValue());
188             assertEquals(ROUTER_1_ID, igpNodeAttributes1.getIsisNodeAttributes().getTed().getTeRouterIdIpv4()
189                     .getValue());
190             assertEquals("47.0000.0000.0000.0000.0102.0304", igpNodeAttributes1.getIsisNodeAttributes()
191                     .getNet().get(0).getValue());
192             assertNull(igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
193                     .topology.rev131021.IgpNodeAttributes1.class));
194             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
195             assertNull(node1.augmentation(
196                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
197             return topology;
198         });
199
200         // create link
201         updateLinkstateRoute(this.linkstateLinkRouteIID,
202                 createLinkstateLinkRoute(ProtocolId.IsisLevel2, NODE_1_AS, NODE_2_AS, "link1"));
203         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
204             assertEquals(1, topology.nonnullLink().size());
205             final Link link1 = topology.nonnullLink().values().iterator().next();
206             assertEquals(2, topology.nonnullNode().size());
207             assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
208             assertEquals(1, Iterables.get(topology.getNode().values(), 1).getTerminationPoint().size());
209             assertEquals("bgpls://IsisLevel2:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as"
210                     + "=2&mt=1", link1.getLinkId().getValue());
211             assertEquals(NODE_1_ISIS_ID, link1.getSource().getSourceNode().getValue());
212             assertEquals(NODE_2_ISIS_ID, link1.getDestination().getDestNode().getValue());
213             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
214             assertEquals("link1", igpLink1.getName());
215             assertEquals((short) 1, igpLink1.augmentation(IgpLinkAttributes1.class).getIsisLinkAttributes()
216                     .getMultiTopologyId().shortValue());
217             assertNull(igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.ospf
218                     .topology.rev131021.IgpLinkAttributes1.class));
219             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
220             assertEquals(2, topology.getNode().size());
221             final Node srcNode;
222             if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
223                 srcNode = topology.getNode().values().iterator().next();
224             } else {
225                 srcNode = Iterables.get(topology.getNode().values(), 1);
226             }
227             assertEquals(1, srcNode.augmentation(
228                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
229                     .getSegments().size());
230             assertEquals(ADJ_SID, link1.augmentation(
231                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
232                     .getSegment().getValue().intValue());
233             return topology;
234         });
235         removeLinkstateRoute(this.linkstateLinkRouteIID);
236
237         // update node
238         updateLinkstateRoute(this.linkstateNodeRouteIID,
239                 createLinkstateNodeRoute(ProtocolId.IsisLevel2, "updated-node", NODE_1_AS, ROUTER_2_ID));
240         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
241             assertEquals(1, topology.getNode().size());
242             final IgpNodeAttributes igpNode2 = topology.getNode().values().iterator().next().augmentation(Node1.class)
243                     .getIgpNodeAttributes();
244             assertEquals(ROUTER_2_ID, igpNode2.getRouterId().get(0).getIpv4Address().getValue());
245             assertEquals("updated-node", igpNode2.getName().getValue());
246             return topology;
247         });
248
249         // remove
250         removeLinkstateRoute(this.linkstateNodeRouteIID);
251         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
252             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
253             assertNull(topology.getNode());
254             assertNull(topology.getLink());
255             return topology;
256         });
257     }
258
259     @Test
260     public void testOspfLinkstateTopologyBuilder() throws InterruptedException, ExecutionException {
261         // create node
262         updateLinkstateRoute(this.linkstateNodeRouteIID,
263                 createLinkstateNodeRoute(ProtocolId.Ospf, "node1", NODE_1_AS, ROUTER_1_ID));
264         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
265             assertEquals(1, topology.nonnullNode().size());
266             final Node node1 = topology.nonnullNode().values().iterator().next();
267             assertEquals(NODE_1_OSPF_ID, node1.getNodeId().getValue());
268             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
269             assertEquals(ROUTER_1_ID, igpNode1.getRouterId().get(0).getIpv4Address().getValue());
270             assertEquals("node1", igpNode1.getName().getValue());
271             assertNull(igpNode1.augmentation(IgpNodeAttributes1.class));
272             assertEquals(ROUTER_1_ID, igpNode1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
273                     .yang.ospf.topology.rev131021.IgpNodeAttributes1.class).getOspfNodeAttributes().getTed()
274                     .getTeRouterIdIpv4().getValue());
275             assertEquals(LinkstateTopologyBuilder.LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
276             assertNull(node1.augmentation(
277                 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class));
278             return topology;
279         });
280
281         // update node with prefix
282         updateLinkstateRoute(this.linkstatePrefixRouteIID,
283                 createLinkstatePrefixRoute(ProtocolId.Ospf, NODE_1_AS, NODE_1_PREFIX, 500L, ROUTER_1_ID));
284         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
285             final Node node1 = topology.nonnullNode().values().iterator().next();
286             final IgpNodeAttributes igpNode1 = node1.augmentation(Node1.class).getIgpNodeAttributes();
287             assertEquals(1, igpNode1.nonnullPrefix().size());
288             final Prefix prefix = igpNode1.nonnullPrefix().values().iterator().next();
289             assertEquals(NODE_1_PREFIX, prefix.getPrefix().getIpv4Prefix().getValue());
290             assertEquals(500L, prefix.getMetric().longValue());
291             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
292             assertEquals(1, node1.augmentation(
293                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
294                     .nonnullSegments().size());
295             assertEquals(SRGB_START + NODE_SID_INDEX, node1.augmentation(
296                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
297                     .nonnullSegments().values().iterator().next().getSegmentId().getValue().intValue());
298             return topology;
299         });
300
301         // create link
302         updateLinkstateRoute(this.linkstateLinkRouteIID,
303                 createLinkstateLinkRoute(ProtocolId.Ospf, NODE_1_AS, NODE_2_AS, "link1"));
304         readDataOperational(getDataBroker(), this.linkstateTopoBuilder.getInstanceIdentifier(), topology -> {
305             assertEquals(1, topology.nonnullLink().size());
306             final Link link1 = topology.nonnullLink().values().iterator().next();
307             assertEquals(2, topology.getNode().size());
308             assertEquals(1, Iterables.get(topology.getNode().values(), 0).getTerminationPoint().size());
309             assertEquals(1, Iterables.get(topology.getNode().values(), 1).getTerminationPoint().size());
310             assertEquals("bgpls://Ospf:1/type=link&local-as=1&local-router=0000.0102.0304&remote-as=2&mt=1",
311                     link1.getLinkId().getValue());
312             assertEquals(NODE_1_OSPF_ID, link1.getSource().getSourceNode().getValue());
313             assertEquals(NODE_2_OSPF_ID, link1.getDestination().getDestNode().getValue());
314             final IgpLinkAttributes igpLink1 = link1.augmentation(Link1.class).getIgpLinkAttributes();
315             assertEquals("link1", igpLink1.getName());
316             assertNull(igpLink1.augmentation(IgpLinkAttributes1.class));
317             assertEquals((short) 1, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang
318                     .ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getMultiTopologyId()
319                     .shortValue());
320             assertEquals(2, igpLink1.augmentation(org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns
321                     .yang.ospf.topology.rev131021.IgpLinkAttributes1.class).getOspfLinkAttributes().getTed().getSrlg()
322                     .getSrlgValues().size());
323             assertEquals(LinkstateTopologyBuilder.SR_AWARE_LINKSTATE_TOPOLOGY_TYPE, topology.getTopologyTypes());
324             assertEquals(2, topology.getNode().size());
325             final Node srcNode;
326             if (topology.getNode().values().iterator().next().getNodeId().getValue().contains("0000.0102.0304")) {
327                 srcNode = topology.getNode().values().iterator().next();
328             } else {
329                 srcNode = Iterables.get(topology.getNode().values(), 1);
330             }
331             assertEquals(2, srcNode.augmentation(
332                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Node1.class)
333                     .getSegments().size());
334             assertEquals(ADJ_SID, link1.augmentation(
335                     org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.sr.rev130819.Link1.class)
336                     .getSegment().getValue().intValue());
337             return topology;
338         });
339     }
340
341     /**
342      * This test is to verify if the AbstractTopologyBuilder/LinkstateTopologyBuilder is handling exception correctly.
343      */
344     @Test
345     @SuppressWarnings("checkstyle:IllegalCatch")
346     public void testRouteChangedError() throws Exception {
347         final LinkstateTopologyBuilder spiedLinkstateTopologyBuilder = spy(this.linkstateTopoBuilder);
348         doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
349         try {
350             spiedLinkstateTopologyBuilder.routeChanged(null, null);
351             fail("Mockito failed to spy routeChanged() method");
352         } catch (final Exception e) {
353             assertTrue(e instanceof RuntimeException);
354         }
355         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
356         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
357         // first we examine if the chain is being reset when no exception is thrown
358         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
359         verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
360         verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
361         verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
362         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
363         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
364         // now pass some invalid data to cause onDataTreeChanged fail
365         final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
366         final List<DataTreeModification<LinkstateRoute>> changes = new ArrayList<>();
367         changes.add(modification);
368         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
369         // one restart transaction chain check in onDataTreeChanged()
370         // we are introducing some timeout here as transaction may be executed in a delay manner
371         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
372         verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
373         assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
374         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
375         final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
376         // call again with empty change to invoke restartTransactionChainOnDemand()
377         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
378         verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
379         // transaction chain should be reset while listener should not
380         verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
381         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
382         // now apply a change with bad modification again
383         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
384         verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
385         // listener scheduled again
386         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
387         // listener timer shouldn't have changed
388         assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
389         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
390         verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
391         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
392         Thread.sleep(LISTENER_RESTART_TIME);
393         // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
394         spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
395         assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
396                 + LISTENER_RESTART_TIME);
397         verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
398         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
399         // enforce counter get increased
400         assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
401         verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
402         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
403         // sleep to let the listener restart timer times out
404         Thread.sleep(LISTENER_RESTART_TIME);
405         // apply a good modification (empty change)
406         spiedLinkstateTopologyBuilder.onDataTreeChanged(new ArrayList<>());
407         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
408         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
409         verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
410         // listener restarted didn't get rescheduled again
411         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
412         verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
413         verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
414     }
415
416     private static String getLinkstateRouteKey(final String routeKey) {
417         return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
418     }
419
420     private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
421         return this.tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
422                 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
423     }
424
425     private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
426             final LinkstateRoute data) {
427         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
428         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
429         wTx.commit();
430     }
431
432     private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
433         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
434         wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
435         wTx.commit();
436     }
437
438     private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
439             final AsNumber asNumber, final String ipv4RouterId) {
440         return createBaseBuilder(this.linkstateNodeRouteKey, protocolId)
441                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
442                         .rev200120.linkstate.object.type.NodeCaseBuilder()
443                         .setNodeDescriptors(new NodeDescriptorsBuilder()
444                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
445                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
446                                         .build())
447                                 .setAsNumber(asNumber).build()).build())
448                 .setAttributes(new AttributesBuilder()
449                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
450                         .addAugmentation(new Attributes1Builder()
451                                 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
452                                         .setNodeAttributes(new NodeAttributesBuilder()
453                                                 .setDynamicHostname(nodeName)
454                                                 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
455                                                 .setIsisAreaId(Collections.singletonList(
456                                                         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(this.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(this.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(Lists.newArrayList(
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(Lists.newArrayList(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(Collections.singletonList(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 }