651c26e2e0184af6ca68595a0056728df67409d5
[bgpcep.git] / bgp / openconfig-state / src / test / java / org / opendaylight / protocol / bgp / state / StateProviderImplTest.java
1 /*
2  * Copyright (c) 2016 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.protocol.bgp.state;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.mockito.ArgumentMatchers.any;
15 import static org.mockito.ArgumentMatchers.anyBoolean;
16 import static org.mockito.ArgumentMatchers.anyLong;
17 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.doAnswer;
19 import static org.mockito.Mockito.doNothing;
20 import static org.mockito.Mockito.doReturn;
21 import static org.mockito.Mockito.mock;
22 import static org.mockito.Mockito.spy;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.opendaylight.protocol.util.CheckUtil.checkNotPresentOperational;
26 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
27
28 import com.google.common.util.concurrent.Futures;
29 import com.google.common.util.concurrent.ListeningExecutorService;
30 import com.google.common.util.concurrent.MoreExecutors;
31 import com.google.common.util.concurrent.Uninterruptibles;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.Executors;
37 import java.util.concurrent.ScheduledExecutorService;
38 import java.util.concurrent.ScheduledFuture;
39 import java.util.concurrent.TimeUnit;
40 import java.util.concurrent.atomic.LongAdder;
41 import org.junit.Before;
42 import org.junit.Test;
43 import org.junit.runner.RunWith;
44 import org.mockito.ArgumentCaptor;
45 import org.mockito.Mock;
46 import org.mockito.junit.MockitoJUnitRunner;
47 import org.opendaylight.infrautils.testutils.LogCapture;
48 import org.opendaylight.infrautils.testutils.internal.RememberingLogger;
49 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTest;
50 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractDataBrokerTestCustomizer;
51 import org.opendaylight.mdsal.binding.dom.adapter.test.ConcurrentDataBrokerTestCustomizer;
52 import org.opendaylight.mdsal.dom.spi.store.DOMStore;
53 import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction;
54 import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
55 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionChain;
56 import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
57 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStore;
58 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
59 import org.opendaylight.protocol.bgp.rib.spi.State;
60 import org.opendaylight.protocol.bgp.rib.spi.state.BGPAfiSafiState;
61 import org.opendaylight.protocol.bgp.rib.spi.state.BGPErrorHandlingState;
62 import org.opendaylight.protocol.bgp.rib.spi.state.BGPGracelfulRestartState;
63 import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerMessagesState;
64 import org.opendaylight.protocol.bgp.rib.spi.state.BGPPeerState;
65 import org.opendaylight.protocol.bgp.rib.spi.state.BGPRibState;
66 import org.opendaylight.protocol.bgp.rib.spi.state.BGPSessionState;
67 import org.opendaylight.protocol.bgp.rib.spi.state.BGPStateProvider;
68 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTimersState;
69 import org.opendaylight.protocol.bgp.rib.spi.state.BGPTransportState;
70 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafi;
71 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.AfiSafiBuilder;
72 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.afi.safi.GracefulRestartBuilder;
73 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp.common.afi.safi.list.afi.safi.graceful.restart.StateBuilder;
74 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.operational.rev151009.BgpAfiSafiGracefulRestartState;
75 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.operational.rev151009.BgpNeighborState;
76 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.operational.rev151009.bgp.neighbor.prefix.counters_state.PrefixesBuilder;
77 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.GracefulRestart;
78 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.AfiSafis;
79 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.AfiSafisBuilder;
80 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ErrorHandling;
81 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.ErrorHandlingBuilder;
82 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Timers;
83 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.TimersBuilder;
84 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Transport;
85 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.TransportBuilder;
86 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
87 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroup;
88 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.peer.group.PeerGroupBuilder;
89 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
90 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
91 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.GlobalBuilder;
92 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
93 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.ADDPATHS;
94 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.ASN32;
95 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.BgpCapability;
96 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.CommunityType;
97 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.GRACEFULRESTART;
98 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.IPV4UNICAST;
99 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.MPBGP;
100 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.ROUTEREFRESH;
101 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.OpenconfigNetworkInstanceData;
102 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.NetworkInstances;
103 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.NetworkInstance;
104 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.NetworkInstanceKey;
105 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.Protocols;
106 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
107 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.ProtocolKey;
108 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.BGP;
109 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
110 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
111 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
112 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
113 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
114 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
115 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Timeticks;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NetworkInstanceProtocol;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.BgpNeighborStateAugmentation;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.BgpNeighborStateAugmentationBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.GlobalAfiSafiStateAugmentationBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborAfiSafiGracefulRestartStateAugmentationBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborAfiSafiStateAugmentationBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborErrorHandlingStateAugmentationBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborGracefulRestartStateAugmentationBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborStateAugmentation;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborTimersStateAugmentationBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.NeighborTransportStateAugmentationBuilder;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.PeerGroupStateAugmentationBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.bgp.neighbor_state.augmentation.MessagesBuilder;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.bgp.neighbor_state.augmentation.messages.ReceivedBuilder;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.network.instance.protocol.bgp.neighbor_state.augmentation.messages.SentBuilder;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.BgpRib;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.RibId;
133 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.Rib;
134 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.bgp.rib.RibKey;
135 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.TablesKey;
136 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.BgpId;
137 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.Ipv4AddressFamily;
138 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.UnicastSubsequentAddressFamily;
139 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
140 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
141 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
142 import org.opendaylight.yangtools.yang.common.Decimal64;
143 import org.opendaylight.yangtools.yang.common.Uint16;
144 import org.opendaylight.yangtools.yang.common.Uint32;
145 import org.opendaylight.yangtools.yang.common.Uint64;
146 import org.slf4j.LoggerFactory;
147
148 @RunWith(MockitoJUnitRunner.StrictStubs.class)
149 public class StateProviderImplTest extends AbstractDataBrokerTest {
150     private final LongAdder totalPathsCounter = new LongAdder();
151     private final LongAdder totalPrefixesCounter = new LongAdder();
152     private final PortNumber localPort = new PortNumber(Uint16.valueOf(1790));
153     private final PortNumber remotePort = new PortNumber(Uint16.valueOf(179));
154     private final Uint16 restartTime = Uint16.valueOf(15);
155     private final String ribId = "identifier-test";
156     private final InstanceIdentifier<Bgp> bgpInstanceIdentifier =
157         InstanceIdentifier.builderOfInherited(OpenconfigNetworkInstanceData.class, NetworkInstances.class).build()
158             .child(NetworkInstance.class, new NetworkInstanceKey("global-bgp"))
159             .child(Protocols.class)
160             .child(Protocol.class, new ProtocolKey(BGP.VALUE, ribId))
161             .augmentation(NetworkInstanceProtocol.class)
162             .child(Bgp.class);
163     static final TablesKey TABLES_KEY = new TablesKey(Ipv4AddressFamily.VALUE, UnicastSubsequentAddressFamily.VALUE);
164     private final AsNumber as = new AsNumber(Uint32.valueOf(72));
165     private final BgpId bgpId = new BgpId("127.0.0.1");
166     private final IpAddressNoZone neighborAddress = new IpAddressNoZone(new Ipv4AddressNoZone("127.0.0.2"));
167     private final List<BgpCapability> supportedCap = List.of(ASN32.VALUE, ROUTEREFRESH.VALUE, MPBGP.VALUE,
168             ADDPATHS.VALUE, GRACEFULRESTART.VALUE);
169     @Mock
170     private BGPStateProvider stateProvider;
171     @Mock
172     private BGPTableTypeRegistryConsumer tableTypeRegistry;
173     @Mock
174     private BGPRibState bgpRibState;
175     @Mock
176     private BGPPeerState bgpPeerState;
177     @Mock
178     private BGPSessionState bgpSessionState;
179     @Mock
180     private BGPPeerMessagesState bgpPeerMessagesState;
181     @Mock
182     private BGPTimersState timersState;
183     @Mock
184     private BGPTransportState bgpTransportState;
185     @Mock
186     private BGPErrorHandlingState bgpErrorHandlingState;
187     @Mock
188     private BGPGracelfulRestartState bgpGracelfulRestartState;
189     @Mock
190     private BGPAfiSafiState bgpAfiSafiState;
191
192     private final List<BGPPeerState> bgpPeerStates = new ArrayList<>();
193     private final List<BGPRibState> bgpRibStates = new ArrayList<>();
194
195     private InMemoryDOMDataStore realOperStore;
196     private InMemoryDOMDataStore spiedOperStore;
197
198     @Before
199     public void setUp() {
200         doReturn(IPV4UNICAST.VALUE).when(tableTypeRegistry).getAfiSafiType(eq(TABLES_KEY));
201
202         doReturn(bgpRibStates).when(stateProvider).getRibStats();
203         doReturn(bgpPeerStates).when(stateProvider).getPeerStats();
204
205         final KeyedInstanceIdentifier<Rib, RibKey> iid = InstanceIdentifier.create(BgpRib.class)
206             .child(Rib.class, new RibKey(new RibId(ribId)));
207         doReturn(iid).when(bgpRibState).getInstanceIdentifier();
208         doReturn(as).when(bgpRibState).getAs();
209         doReturn(bgpId).when(bgpRibState).getRouteId();
210
211         doAnswer(invocation -> totalPathsCounter.longValue())
212                 .when(bgpRibState).getTotalPathsCount();
213         doAnswer(invocation -> totalPrefixesCounter.longValue())
214                 .when(bgpRibState).getTotalPrefixesCount();
215         doAnswer(invocation -> totalPathsCounter.longValue())
216                 .when(bgpRibState).getPathCount(eq(TABLES_KEY));
217         doAnswer(invocation -> totalPrefixesCounter.longValue())
218                 .when(bgpRibState).getPrefixesCount(eq(TABLES_KEY));
219         doAnswer(invocation -> Map.of(TABLES_KEY,
220             totalPathsCounter.longValue())).when(bgpRibState).getPathsCount();
221
222         // Mock Peer
223         doReturn("test-group").when(bgpPeerState).getGroupId();
224         doReturn(iid).when(bgpPeerState).getInstanceIdentifier();
225         doAnswer(invocation -> totalPrefixesCounter.longValue()).when(bgpPeerState).getTotalPrefixes();
226         doAnswer(invocation -> totalPathsCounter.longValue()).when(bgpPeerState).getTotalPathsCount();
227         doReturn(neighborAddress).when(bgpPeerState).getNeighborAddress();
228         doReturn(bgpSessionState).when(bgpPeerState).getBGPSessionState();
229         doReturn(bgpPeerMessagesState).when(bgpPeerState).getBGPPeerMessagesState();
230
231         doReturn(1L).when(bgpPeerMessagesState).getNotificationMessagesReceivedCount();
232         doReturn(1L).when(bgpPeerMessagesState).getNotificationMessagesSentCount();
233         doReturn(1L).when(bgpPeerMessagesState).getUpdateMessagesReceivedCount();
234         doReturn(1L).when(bgpPeerMessagesState).getUpdateMessagesSentCount();
235         doReturn(State.UP).when(bgpSessionState).getSessionState();
236         doReturn(true).when(bgpSessionState).isAddPathCapabilitySupported();
237         doReturn(true).when(bgpSessionState).isAsn32CapabilitySupported();
238         doReturn(true).when(bgpSessionState).isGracefulRestartCapabilitySupported();
239         doReturn(true).when(bgpSessionState).isMultiProtocolCapabilitySupported();
240         doReturn(true).when(bgpSessionState).isRouterRefreshCapabilitySupported();
241
242         doReturn(timersState).when(bgpPeerState).getBGPTimersState();
243         doReturn(10L).when(timersState).getNegotiatedHoldTime();
244         doReturn(10L).when(timersState).getUpTime();
245
246         doReturn(bgpTransportState).when(bgpPeerState).getBGPTransportState();
247         doReturn(localPort).when(bgpTransportState).getLocalPort();
248         doReturn(neighborAddress).when(bgpTransportState).getRemoteAddress();
249         doReturn(remotePort).when(bgpTransportState).getRemotePort();
250
251         doReturn(bgpErrorHandlingState).when(bgpPeerState).getBGPErrorHandlingState();
252         doReturn(1L).when(bgpErrorHandlingState).getErroneousUpdateReceivedCount();
253
254         doReturn(bgpGracelfulRestartState).when(bgpPeerState).getBGPGracelfulRestart();
255         doReturn(true).when(bgpGracelfulRestartState).isLocalRestarting();
256         doReturn(true).when(bgpGracelfulRestartState).isPeerRestarting();
257         doReturn(restartTime.toJava()).when(bgpGracelfulRestartState).getPeerRestartTime();
258         doReturn(BgpAfiSafiGracefulRestartState.Mode.BILATERAL).when(bgpGracelfulRestartState).getMode();
259
260         doReturn(bgpAfiSafiState).when(bgpPeerState).getBGPAfiSafiState();
261         doReturn(Set.of(TABLES_KEY)).when(bgpAfiSafiState).getAfiSafisAdvertized();
262         doReturn(Set.of(TABLES_KEY)).when(bgpAfiSafiState).getAfiSafisReceived();
263         doReturn(1L).when(bgpAfiSafiState).getPrefixesInstalledCount(any());
264         doReturn(2L).when(bgpAfiSafiState).getPrefixesReceivedCount(any());
265         doReturn(1L).when(bgpAfiSafiState).getPrefixesSentCount(any());
266         doReturn(true).when(bgpAfiSafiState).isAfiSafiSupported(any());
267         doReturn(true).when(bgpAfiSafiState).isGracefulRestartAdvertized(any());
268         doReturn(true).when(bgpAfiSafiState).isGracefulRestartReceived(any());
269         doReturn(true).when(bgpAfiSafiState).isLlGracefulRestartAdvertised(any());
270         doReturn(true).when(bgpAfiSafiState).isLlGracefulRestartReceived(any());
271         doReturn(60).when(bgpAfiSafiState).getLlGracefulRestartTimer(any());
272     }
273
274     @Override
275     protected AbstractDataBrokerTestCustomizer createDataBrokerTestCustomizer() {
276         return new ConcurrentDataBrokerTestCustomizer(true) {
277             @Override
278             public DOMStore createOperationalDatastore() {
279                 realOperStore = new InMemoryDOMDataStore("OPER", getDataTreeChangeListenerExecutor());
280                 spiedOperStore = spy(realOperStore);
281                 getSchemaService().registerSchemaContextListener(spiedOperStore);
282                 return spiedOperStore;
283             }
284
285             @Override
286             public ListeningExecutorService getCommitCoordinatorExecutor() {
287                 return MoreExecutors.newDirectExecutorService();
288             }
289         };
290     }
291
292     @Test
293     public void testActiveStateProvider() throws Exception {
294         doReturn(true).when(bgpRibState).isActive();
295         doReturn(true).when(bgpPeerState).isActive();
296
297         try (StateProviderImpl stateProvider =
298                 // FIXME: use a properly-controlled executor service
299                 new StateProviderImpl(getDataBroker(), 1, tableTypeRegistry, this.stateProvider, "global-bgp")) {
300
301             final Global globalExpected = buildGlobalExpected(0);
302             bgpRibStates.add(bgpRibState);
303             readDataOperational(getDataBroker(), bgpInstanceIdentifier, bgpRib -> {
304                 final Global global = bgpRib.getGlobal();
305                 assertEquals(globalExpected, global);
306                 return bgpRib;
307             });
308
309             totalPathsCounter.increment();
310             totalPrefixesCounter.increment();
311
312             final Global globalExpected2 = buildGlobalExpected(1);
313             readDataOperational(getDataBroker(), bgpInstanceIdentifier, bgpRib -> {
314                 final Global global = bgpRib.getGlobal();
315                 assertEquals(globalExpected2, global);
316                 return bgpRib;
317             });
318
319             totalPathsCounter.decrement();
320             totalPrefixesCounter.decrement();
321
322             final Global globalExpected3 = buildGlobalExpected(0);
323             readDataOperational(getDataBroker(), bgpInstanceIdentifier, bgpRib -> {
324                 final Global global = bgpRib.getGlobal();
325                 assertEquals(globalExpected3, global);
326                 assertNull(bgpRib.getNeighbors());
327                 assertNull(bgpRib.getPeerGroups());
328                 return bgpRib;
329             });
330
331             bgpPeerStates.add(bgpPeerState);
332             final PeerGroup peerGroupExpected = buildGroupExpected();
333
334             totalPathsCounter.increment();
335             totalPrefixesCounter.increment();
336
337             final AfiSafis expectedAfiSafis = buildAfiSafis();
338             final ErrorHandling expectedErrorHandling = buildErrorHandling();
339             final GracefulRestart expectedGracefulRestart = buildGracefulRestart();
340             final Transport expectedTransport = buildTransport();
341             final Timers expectedTimers = buildTimers();
342             final BgpNeighborStateAugmentation expectedBgpNeighborState = buildBgpNeighborStateAugmentation();
343
344             readDataOperational(getDataBroker(), bgpInstanceIdentifier, bgpRib -> {
345                 final Neighbors neighbors = bgpRib.getNeighbors();
346                 assertNotNull(neighbors);
347                 assertEquals(peerGroupExpected, bgpRib.getPeerGroups().nonnullPeerGroup().values().iterator().next());
348                 final Neighbor neighborResult = neighbors.nonnullNeighbor().values().iterator().next();
349                 assertEquals(new IpAddress(neighborAddress.getIpv4AddressNoZone()),
350                     neighborResult.getNeighborAddress());
351                 assertEquals(expectedAfiSafis, neighborResult.getAfiSafis());
352                 assertEquals(expectedErrorHandling, neighborResult.getErrorHandling());
353                 assertEquals(expectedGracefulRestart, neighborResult.getGracefulRestart());
354                 assertEquals(expectedTransport, neighborResult.getTransport());
355                 assertEquals(expectedTimers, neighborResult.getTimers());
356                 final org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
357                     .State stateResult = neighborResult.getState();
358                 assertEquals(expectedBgpNeighborState, stateResult.augmentation(BgpNeighborStateAugmentation.class));
359                 assertEquals(BgpNeighborState.SessionState.ESTABLISHED, stateResult
360                     .augmentation(NeighborStateAugmentation.class).getSessionState());
361                 final Set<BgpCapability> supportedCapabilitiesResult = stateResult
362                     .augmentation(NeighborStateAugmentation.class).getSupportedCapabilities();
363                 assertTrue(supportedCapabilitiesResult.containsAll(supportedCap));
364                 return bgpRib;
365             });
366
367             bgpRibStates.clear();
368             checkNotPresentOperational(getDataBroker(), bgpInstanceIdentifier);
369         }
370     }
371
372     @Test
373     public void testInactiveStateProvider() throws Exception {
374         doReturn(false).when(bgpRibState).isActive();
375
376         try (StateProviderImpl stateProvider =
377                 new StateProviderImpl(getDataBroker(), 100, TimeUnit.MILLISECONDS, tableTypeRegistry,
378                         this.stateProvider,
379                     // FIXME: use a properly-controlled executor service ...
380                     "global-bgp", Executors.newScheduledThreadPool(1))) {
381
382             bgpRibStates.add(bgpRibState);
383             /// ... and trigger here
384             Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
385             checkNotPresentOperational(getDataBroker(), bgpInstanceIdentifier);
386
387             bgpPeerStates.add(bgpPeerState);
388             /// ... and trigger here
389             Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
390             checkNotPresentOperational(getDataBroker(), bgpInstanceIdentifier);
391
392             bgpRibStates.clear();
393             /// ... and trigger here
394             Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
395             checkNotPresentOperational(getDataBroker(), bgpInstanceIdentifier);
396         }
397     }
398
399     @Test
400     public void testTransactionChainFailure() throws Exception {
401         if (!(LoggerFactory.getLogger(StateProviderImpl.class) instanceof RememberingLogger)) {
402             throw new IllegalStateException("infrautils-testutils must be on the classpath BEFORE other logger impls"
403                 + LoggerFactory.getLogger(StateProviderImpl.class).getClass());
404         }
405
406         doReturn(true).when(bgpRibState).isActive();
407
408         bgpRibStates.add(bgpRibState);
409
410         ScheduledFuture<?> mockScheduledFuture = mock(ScheduledFuture.class);
411         doReturn(true).when(mockScheduledFuture).cancel(anyBoolean());
412
413         ScheduledExecutorService mockScheduler = mock(ScheduledExecutorService.class);
414         doReturn(mockScheduledFuture).when(mockScheduler).scheduleAtFixedRate(any(Runnable.class), anyLong(),
415                 anyLong(), any(TimeUnit.class));
416         doNothing().when(mockScheduler).shutdown();
417
418         DOMStoreTransactionChain mockTxChain = mock(DOMStoreTransactionChain.class);
419
420         Throwable mockCommitEx = new Exception("mock commit failure");
421         doAnswer(invocation -> {
422             DOMStoreThreePhaseCommitCohort mockCohort = mock(DOMStoreThreePhaseCommitCohort.class);
423             doReturn(Futures.immediateFailedFuture(mockCommitEx)).when(mockCohort).canCommit();
424             doReturn(Futures.immediateFuture(null)).when(mockCohort).abort();
425
426             doAnswer(notused -> {
427                 DOMStoreWriteTransaction mockWriteTx = mock(DOMStoreReadWriteTransaction .class);
428                 doNothing().when(mockWriteTx).write(any(), any());
429                 doNothing().when(mockWriteTx).merge(any(), any());
430                 doReturn(mockCohort).when(mockWriteTx).ready();
431                 return mockWriteTx;
432             }).when(mockTxChain).newReadWriteTransaction();
433
434             return mockTxChain;
435         }).doAnswer(invocation -> realOperStore.createTransactionChain()).when(spiedOperStore).createTransactionChain();
436
437         final int period = 100;
438         final TimeUnit unit = TimeUnit.MILLISECONDS;
439         try (StateProviderImpl stateProvider = new StateProviderImpl(getDataBroker(), period, unit, tableTypeRegistry,
440                 this.stateProvider, "global-bgp", mockScheduler)) {
441
442             ArgumentCaptor<Runnable> timerTask = ArgumentCaptor.forClass(Runnable.class);
443             verify(mockScheduler).scheduleAtFixedRate(timerTask.capture(), eq(0L), eq((long)period), eq(unit));
444
445             timerTask.getValue().run();
446
447             String lastError = RememberingLogger.getLastErrorThrowable().orElseThrow(
448                 () -> new AssertionError("Expected logged ERROR")).toString();
449             assertTrue("Last logged ERROR didn't contain expected string: " + lastError,
450                     lastError.contains(mockCommitEx.getMessage()));
451
452             RememberingLogger.resetLastError();
453
454             timerTask.getValue().run();
455
456             List<LogCapture> loggedErrors = RememberingLogger.getErrorLogCaptures();
457             assertTrue("Expected no logged ERRORs: " + loggedErrors, loggedErrors.isEmpty());
458
459             verify(spiedOperStore, times(2)).createTransactionChain();
460         }
461     }
462
463     private static BgpNeighborStateAugmentation buildBgpNeighborStateAugmentation() {
464         final BgpNeighborStateAugmentation augmentation = new BgpNeighborStateAugmentationBuilder()
465                 .setMessages(new MessagesBuilder().setReceived(new ReceivedBuilder()
466                         .setNOTIFICATION(Uint64.ONE).setUPDATE(Uint64.ONE).build())
467                         .setSent(new SentBuilder().setNOTIFICATION(Uint64.ONE).setUPDATE(Uint64.ONE).build())
468                         .build()).build();
469         return augmentation;
470     }
471
472     private static AfiSafis buildAfiSafis() {
473         final NeighborAfiSafiStateAugmentationBuilder neighborAfiSafiStateAugmentation =
474                 new NeighborAfiSafiStateAugmentationBuilder()
475                 .setActive(true)
476                 .setPrefixes(new PrefixesBuilder()
477                     .setSent(Uint32.ONE)
478                     .setReceived(Uint32.TWO)
479                     .setInstalled(Uint32.ONE)
480                     .build());
481         final AfiSafi afiSafi = new AfiSafiBuilder()
482                 .setAfiSafiName(IPV4UNICAST.VALUE)
483                 .setGracefulRestart(new GracefulRestartBuilder()
484                     .setState(new StateBuilder().setEnabled(false)
485                         .addAugmentation(new NeighborAfiSafiGracefulRestartStateAugmentationBuilder()
486                             .setAdvertised(true)
487                             .setReceived(true)
488                             .setLlStaleTimer(Uint32.valueOf(60))
489                             .setLlAdvertised(true)
490                             .setLlReceived(true)
491                             .build())
492                         .build())
493                     .build())
494                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol.rev151009.bgp
495                         .common.afi.safi.list.afi.safi.StateBuilder()
496                             .setEnabled(false)
497                             .addAugmentation(neighborAfiSafiStateAugmentation.build())
498                         .build())
499                 .build();
500
501         return new AfiSafisBuilder().setAfiSafi(Map.of(afiSafi.key(), afiSafi)).build();
502     }
503
504     private static ErrorHandling buildErrorHandling() {
505         final ErrorHandling errorHandling = new ErrorHandlingBuilder().setState(
506                 new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.error
507                         .handling.StateBuilder().setTreatAsWithdraw(false)
508                         .addAugmentation(new NeighborErrorHandlingStateAugmentationBuilder()
509                                         .setErroneousUpdateMessages(Uint32.ONE).build()).build()).build();
510         return errorHandling;
511     }
512
513     private static Timers buildTimers() {
514         return new TimersBuilder()
515                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
516                     .timers.StateBuilder()
517                         .setConnectRetry(Decimal64.valueOf(2, 30))
518                         .setHoldTime(Decimal64.valueOf(2, 90))
519                         .setKeepaliveInterval(Decimal64.valueOf(2, 30))
520                         .setMinimumAdvertisementInterval(Decimal64.valueOf(2, 30))
521                         .addAugmentation(new NeighborTimersStateAugmentationBuilder()
522                             .setNegotiatedHoldTime(Decimal64.valueOf(2, 10))
523                             .setUptime(new Timeticks(Uint32.ONE)).build())
524                         .build())
525                 .build();
526     }
527
528     private Transport buildTransport() {
529         return new TransportBuilder()
530                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig
531                 .net.yang.bgp.rev151009.bgp.neighbor.group.transport.StateBuilder()
532                     .setMtuDiscovery(false)
533                 .setPassiveMode(false)
534                 .addAugmentation(new NeighborTransportStateAugmentationBuilder()
535                     .setLocalPort(localPort)
536                                 .setRemotePort(remotePort)
537                                 .setRemoteAddress(new IpAddress(neighborAddress.getIpv4AddressNoZone())).build())
538                 .build()).build();
539     }
540
541     private GracefulRestart buildGracefulRestart() {
542         final NeighborGracefulRestartStateAugmentationBuilder gracefulAugmentation
543                 = new NeighborGracefulRestartStateAugmentationBuilder()
544                 .setPeerRestarting(false)
545                 .setLocalRestarting(false)
546                 .setPeerRestartTime(Uint16.ZERO)
547                 .setLocalRestarting(true)
548                 .setPeerRestarting(true)
549                 .setPeerRestartTime(restartTime)
550                 .setMode(BgpAfiSafiGracefulRestartState.Mode.BILATERAL);
551         final GracefulRestart gracefulRestart = new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp
552                 .rev151009.bgp.graceful.restart.GracefulRestartBuilder().setState(new org.opendaylight.yang.gen.v1.http
553                 .openconfig.net.yang.bgp.rev151009.bgp.graceful.restart.graceful.restart.StateBuilder()
554                 .addAugmentation(gracefulAugmentation.build()).build()).build();
555         return gracefulRestart;
556     }
557
558     private Global buildGlobalExpected(final long prefixesAndPaths) {
559         return new GlobalBuilder()
560                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base
561                         .StateBuilder()
562                             .setRouterId(new Ipv4Address(bgpId.getValue()))
563                             .setTotalPrefixes(Uint32.valueOf(prefixesAndPaths))
564                             .setTotalPaths(Uint32.valueOf(prefixesAndPaths))
565                             .setAs(as)
566                             .build())
567                 .setAfiSafis(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.global.base
568                         .AfiSafisBuilder()
569                             .setAfiSafi(BindingMap.of(new AfiSafiBuilder()
570                                 .setAfiSafiName(IPV4UNICAST.VALUE)
571                                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.multiprotocol
572                                     .rev151009.bgp.common.afi.safi.list.afi.safi.StateBuilder()
573                                         .setEnabled(false)
574                                         .addAugmentation(new GlobalAfiSafiStateAugmentationBuilder()
575                                             .setTotalPaths(Uint32.valueOf(prefixesAndPaths))
576                                             .setTotalPrefixes(Uint32.valueOf(prefixesAndPaths))
577                                             .build())
578                                         .build())
579                                 .build()))
580                         .build())
581                 .build();
582     }
583
584     private static PeerGroup buildGroupExpected() {
585         return new PeerGroupBuilder()
586                 .setPeerGroupName("test-group")
587                 .setState(new org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group
588                     .StateBuilder()
589                     .setSendCommunity(CommunityType.NONE)
590                     .setRouteFlapDamping(false)
591                     .addAugmentation(new PeerGroupStateAugmentationBuilder()
592                         .setTotalPaths(Uint32.ONE)
593                         .setTotalPrefixes(Uint32.ONE)
594                         .build())
595                     .build())
596                 .build();
597     }
598 }