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