Reduce Mockito workaround
[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.assertThrows;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.Mockito.CALLS_REAL_METHODS;
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.timeout;
21 import static org.mockito.Mockito.times;
22 import static org.mockito.Mockito.verify;
23 import static org.mockito.Mockito.withSettings;
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.List;
32 import java.util.Set;
33 import java.util.concurrent.ExecutionException;
34 import org.junit.After;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.mockito.MockMakers;
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     public void testRouteChangedError() throws Exception {
347         // FIXME: this is a very weird setup and does not work with inline mockmaker
348         //        perhaps that is because of https://github.com/mockito/mockito/issues/2488, but we should be able to
349         //        rework this test in some other way (i.e. pure mocking with real classes)?
350         final var spiedLinkstateTopologyBuilder = mock(LinkstateTopologyBuilder.class,
351             // this part is the same as spy(), but ...
352             withSettings().spiedInstance(linkstateTopoBuilder).defaultAnswer(CALLS_REAL_METHODS)
353             // ... here we use a different MockMaker
354                 .mockMaker(MockMakers.SUBCLASS));
355         doThrow(RuntimeException.class).when(spiedLinkstateTopologyBuilder).routeChanged(any(), any());
356         // Verify throws spying
357         assertThrows(RuntimeException.class, () -> spiedLinkstateTopologyBuilder.routeChanged(null, null));
358
359         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
360         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
361         // first we examine if the chain is being reset when no exception is thrown
362         spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
363         verify(spiedLinkstateTopologyBuilder, times(1)).restartTransactionChainOnDemand();
364         verify(spiedLinkstateTopologyBuilder, never()).scheduleListenerRestart();
365         verify(spiedLinkstateTopologyBuilder, never()).resetTransactionChain();
366         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
367         assertEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
368         // now pass some invalid data to cause onDataTreeChanged fail
369         final DataTreeModification<LinkstateRoute> modification = mock(DataTreeModification.class, RETURNS_SMART_NULLS);
370         final List<DataTreeModification<LinkstateRoute>> changes = List.of(modification);
371         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
372         // one restart transaction chain check in onDataTreeChanged()
373         // we are introducing some timeout here as transaction may be executed in a delay manner
374         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(1)).scheduleListenerRestart();
375         verify(spiedLinkstateTopologyBuilder, times(2)).restartTransactionChainOnDemand();
376         assertNotEquals(0L, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
377         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
378         final long listenerScheduledRestartTime = spiedLinkstateTopologyBuilder.listenerScheduledRestartTime;
379         // call again with empty change to invoke restartTransactionChainOnDemand()
380         spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
381         verify(spiedLinkstateTopologyBuilder, times(3)).restartTransactionChainOnDemand();
382         // transaction chain should be reset while listener should not
383         verify(spiedLinkstateTopologyBuilder, times(1)).resetTransactionChain();
384         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
385         // now apply a change with bad modification again
386         spiedLinkstateTopologyBuilder.onDataTreeChanged(changes);
387         verify(spiedLinkstateTopologyBuilder, times(4)).restartTransactionChainOnDemand();
388         // listener scheduled again
389         verify(spiedLinkstateTopologyBuilder, timeout(5000).times(2)).scheduleListenerRestart();
390         // listener timer shouldn't have changed
391         assertEquals(listenerScheduledRestartTime, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
392         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
393         verify(spiedLinkstateTopologyBuilder, times(2)).resetTransactionChain();
394         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
395         Thread.sleep(LISTENER_RESTART_TIME);
396         // manually invoke onTransactionChainFailed() to have the listener restart scheduled again
397         spiedLinkstateTopologyBuilder.onTransactionChainFailed(null, null, null);
398         assertEquals(spiedLinkstateTopologyBuilder.listenerScheduledRestartTime, listenerScheduledRestartTime
399                 + LISTENER_RESTART_TIME);
400         verify(spiedLinkstateTopologyBuilder, times(5)).restartTransactionChainOnDemand();
401         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
402         // enforce counter get increased
403         assertEquals(1, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
404         verify(spiedLinkstateTopologyBuilder, times(3)).resetTransactionChain();
405         verify(spiedLinkstateTopologyBuilder, never()).resetListener();
406         // sleep to let the listener restart timer times out
407         Thread.sleep(LISTENER_RESTART_TIME);
408         // apply a good modification (empty change)
409         spiedLinkstateTopologyBuilder.onDataTreeChanged(List.of());
410         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartTime);
411         assertEquals(0, spiedLinkstateTopologyBuilder.listenerScheduledRestartEnforceCounter);
412         verify(spiedLinkstateTopologyBuilder, times(6)).restartTransactionChainOnDemand();
413         // listener restarted didn't get rescheduled again
414         verify(spiedLinkstateTopologyBuilder, times(3)).scheduleListenerRestart();
415         verify(spiedLinkstateTopologyBuilder, times(4)).resetTransactionChain();
416         verify(spiedLinkstateTopologyBuilder, times(1)).resetListener();
417     }
418
419     private static String getLinkstateRouteKey(final String routeKey) {
420         return Unpooled.wrappedBuffer(StandardCharsets.UTF_8.encode(routeKey)).array().toString();
421     }
422
423     private InstanceIdentifier<LinkstateRoute> createLinkstateRouteIID(final String linkstateRouteKey) {
424         return tablePathIID.builder().child(LinkstateRoutesCase.class, LinkstateRoutes.class)
425                 .child(LinkstateRoute.class, new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey)).build();
426     }
427
428     private void updateLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID,
429             final LinkstateRoute data) {
430         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
431         wTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID, data);
432         wTx.commit();
433     }
434
435     private void removeLinkstateRoute(final InstanceIdentifier<LinkstateRoute> linkstateRouteIID) {
436         final WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
437         wTx.delete(LogicalDatastoreType.OPERATIONAL, linkstateRouteIID);
438         wTx.commit();
439     }
440
441     private LinkstateRoute createLinkstateNodeRoute(final ProtocolId protocolId, final String nodeName,
442             final AsNumber asNumber, final String ipv4RouterId) {
443         return createBaseBuilder(linkstateNodeRouteKey, protocolId)
444                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
445                         .rev200120.linkstate.object.type.NodeCaseBuilder()
446                         .setNodeDescriptors(new NodeDescriptorsBuilder()
447                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
448                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
449                                         .build())
450                                 .setAsNumber(asNumber).build()).build())
451                 .setAttributes(new AttributesBuilder()
452                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
453                         .addAugmentation(new Attributes1Builder()
454                                 .setLinkStateAttribute(new NodeAttributesCaseBuilder()
455                                         .setNodeAttributes(new NodeAttributesBuilder()
456                                                 .setDynamicHostname(nodeName)
457                                                 .setIpv4RouterId(new Ipv4RouterIdentifier(ipv4RouterId))
458                                                 .setIsisAreaId(Set.of(new IsisAreaIdentifier(new byte[]{0x47})))
459                                                 .setSrCapabilities(new SrCapabilitiesBuilder()
460                                                         .setRangeSize(new Uint24(Uint32.valueOf(SRGB_RANGE)))
461                                                         .setSidLabelIndex(new LocalLabelCaseBuilder()
462                                                                 .setLocalLabel(
463                                                                         new MplsLabel(Uint32.valueOf(SRGB_START)))
464                                                                 .build())
465                                                         .build())
466                                                 .build()).build()).build()).build()).build();
467     }
468
469     private LinkstateRoute createLinkstatePrefixRoute(final ProtocolId protocolId, final AsNumber asNumber,
470             final String ipv4Prefix, final long igpMetric, final String ospfFwdAddress) {
471         return createBaseBuilder(linkstatePrefixRouteKey, protocolId)
472             .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
473                     .linkstate.object.type.PrefixCaseBuilder()
474                 .setAdvertisingNodeDescriptors(new AdvertisingNodeDescriptorsBuilder()
475                         .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
476                                 .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4})).build())
477                                 .build()).setAsNumber(asNumber).build())
478                 .setPrefixDescriptors(new PrefixDescriptorsBuilder()
479                         .setIpReachabilityInformation(new IpPrefix(new Ipv4Prefix(ipv4Prefix))).build()).build())
480             .setAttributes(new AttributesBuilder()
481                 .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
482                 .addAugmentation(new Attributes1Builder()
483                         .setLinkStateAttribute(new PrefixAttributesCaseBuilder()
484                             .setPrefixAttributes(new PrefixAttributesBuilder()
485                                 .setOspfForwardingAddress(new IpAddressNoZone(new Ipv4AddressNoZone(ospfFwdAddress)))
486                                 .setPrefixMetric(new IgpMetric(Uint32.valueOf(igpMetric)))
487                                 .setSrPrefix(new SrPrefixBuilder()
488                                         .setAlgorithm(Algorithm.ShortestPathFirst)
489                                         .setSidLabelIndex(new SidCaseBuilder()
490                                                 .setSid(Uint32.valueOf(NODE_SID_INDEX)).build())
491                                         .build())
492                                 .build())
493                             .build())
494                         .build())
495                 .build())
496             .build();
497     }
498
499     private LinkstateRoute createLinkstateLinkRoute(final ProtocolId protocolId, final AsNumber localAs,
500             final AsNumber remoteAs, final String linkName) {
501         return createBaseBuilder(linkstateLinkRouteKey, protocolId)
502                 .setObjectType(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
503                         .rev200120.linkstate.object.type.LinkCaseBuilder()
504                         .setLocalNodeDescriptors(new LocalNodeDescriptorsBuilder().setAsNumber(localAs)
505                                 .setCRouterIdentifier(new IsisNodeCaseBuilder().setIsisNode(new IsisNodeBuilder()
506                                         .setIsoSystemId(new IsoSystemIdentifier(new byte[]{0, 0, 1, 2, 3, 4}))
507                                         .build()).build()).build())
508                         .setRemoteNodeDescriptors(new RemoteNodeDescriptorsBuilder().setAsNumber(remoteAs).build())
509                         .setLinkDescriptors(new LinkDescriptorsBuilder()
510                                 .setMultiTopologyId(new TopologyIdentifier(Uint16.ONE)).build()).build())
511                 .setAttributes(new AttributesBuilder()
512                         .setOrigin(new OriginBuilder().setValue(BgpOrigin.Igp).build())
513                         .addAugmentation(new Attributes1Builder()
514                                 .setLinkStateAttribute(new LinkAttributesCaseBuilder()
515                                     .setLinkAttributes(new LinkAttributesBuilder()
516                                         .setSharedRiskLinkGroups(ImmutableSet.of(
517                                             new SrlgId(Uint32.valueOf(5)), new SrlgId(Uint32.valueOf(15))))
518                                         .setAdminGroup(new AdministrativeGroup(Uint32.ZERO))
519                                         .setMaxLinkBandwidth(
520                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0xff}))
521                                         .setMaxReservableBandwidth(
522                                                 new Bandwidth(new byte[]{0x00, 0x00, (byte) 0xff, (byte) 0x1f}))
523                                         .setUnreservedBandwidth(BindingMap.of(new UnreservedBandwidthBuilder()
524                                                 .withKey(new UnreservedBandwidthKey(Uint8.ONE))
525                                                 .setBandwidth(new Bandwidth(new byte[]{0x00, 0x00, 0x00, (byte) 0xff}))
526                                                 .build()))
527                                         .setTeMetric(new TeMetric(Uint32.valueOf(100)))
528                                         .setLinkName(linkName)
529                                         .setSrAdjIds(List.of(new SrAdjIdsBuilder()
530                                                 .setSidLabelIndex(new LocalLabelCaseBuilder()
531                                                         .setLocalLabel(new MplsLabel(Uint32.valueOf(ADJ_SID)))
532                                                         .build())
533                                                 .build()))
534                                         .build())
535                                     .build())
536                                 .build())
537                         .build())
538                 .build();
539     }
540
541     private static LinkstateRouteBuilder createBaseBuilder(final String linkstateRouteKey,
542             final ProtocolId protocolId) {
543         return new LinkstateRouteBuilder()
544             .setIdentifier(IDENTIFIER)
545             .withKey(new LinkstateRouteKey(new PathId(Uint32.ZERO), linkstateRouteKey))
546             .setRouteKey(linkstateRouteKey)
547             .setProtocolId(protocolId);
548     }
549 }