BUG-7215: Fix App Peer ModifiedNodeDoesNotExistException 43/49543/2
authorClaudio D. Gasparini <cgaspari@cisco.com>
Wed, 30 Nov 2016 10:14:58 +0000 (11:14 +0100)
committerRobert Varga <nite@hq.sk>
Tue, 20 Dec 2016 13:35:59 +0000 (13:35 +0000)
If Rib is reconfigured with different Family than the
previous supported one, application peer will be
reconfigured. In the case there are some routes or,
family table configured on Config DS, when restarting
App peer with new configuration will end on
ModifiedNodeDoesNotExistException.

Fix by:
   -Make Application peer more defensiveness by ingore changes
 on config DS for non supported Families.
   - Register Change Listener once AdjRibIn has been
 succesfully initialized.

Change-Id: I25b08b057fad02df365070c0a6d5177b9e0392a0
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibInWriter.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AdjRibsInWriterTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/SynchronizationAndExceptionTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/AbstractConfig.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeerTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeerTest.java

index 0f778f62f65b82cc0a90e30d4dff0e8adcfa8fe4..e9a92b71a369032aaeaf8a81f8bbad2e6879fa79 100644 (file)
@@ -11,17 +11,21 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.NotThreadSafe;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
+import org.opendaylight.protocol.bgp.rib.impl.ApplicationPeer.RegisterAppPeerListener;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContext;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
@@ -56,7 +60,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContaine
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 /**
  * Writer of Adjacency-RIB-In for a single peer. An instance of this object
  * is attached to each {@link BGPPeer} and {@link ApplicationPeer}.
@@ -78,7 +81,7 @@ final class AdjRibInWriter {
     private static final NodeIdentifier PEER_TABLES = new NodeIdentifier(SupportedTables.QNAME);
     private static final NodeIdentifier TABLES = new NodeIdentifier(Tables.QNAME);
     private static final QName SEND_RECEIVE = QName.create(SupportedTables.QNAME, "send-receive").intern();
-    static final NodeIdentifier SIMPLE_ROUTING_POLICY_NID = new NodeIdentifier(QName.create(Peer.QNAME, "simple-routing-policy").intern());
+    private static final NodeIdentifier SIMPLE_ROUTING_POLICY_NID = new NodeIdentifier(QName.create(Peer.QNAME, "simple-routing-policy").intern());
 
     // FIXME: is there a utility method to construct this?
     private static final ContainerNode EMPTY_ADJRIBIN = Builders.containerBuilder().withNodeIdentifier(ADJRIBIN).addChild(ImmutableNodes.mapNodeBuilder(Tables.QNAME).build()).build();
@@ -109,8 +112,8 @@ final class AdjRibInWriter {
      * @param simpleRoutingPolicy simple Routing Policy {@link SimpleRoutingPolicy}
      *@param chain transaction chain  @return A fresh writer instance
      */
-    static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role, final Optional<SimpleRoutingPolicy> simpleRoutingPolicy,
-        @Nonnull final DOMTransactionChain chain) {
+    static AdjRibInWriter create(@Nonnull final YangInstanceIdentifier ribId, @Nonnull final PeerRole role,
+        final Optional<SimpleRoutingPolicy> simpleRoutingPolicy, @Nonnull final DOMTransactionChain chain) {
         return new AdjRibInWriter(ribId, chain, role, simpleRoutingPolicy, null, Collections.emptyMap());
     }
 
@@ -125,15 +128,34 @@ final class AdjRibInWriter {
      * @param addPathTablesType
      * @return New writer
      */
+    AdjRibInWriter transform(final PeerId newPeerId, final RIBSupportContextRegistry registry,
+        final Set<TablesKey> tableTypes, final Map<TablesKey, SendReceive> addPathTablesType) {
+        return transform(newPeerId, registry, tableTypes, addPathTablesType, null);
+    }
+
     AdjRibInWriter transform(final PeerId newPeerId, final RIBSupportContextRegistry registry, final Set<TablesKey> tableTypes,
-        final Map<TablesKey, SendReceive> addPathTablesType) {
+        final Map<TablesKey, SendReceive> addPathTablesType, @Nullable final RegisterAppPeerListener registerAppPeerListener) {
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
 
         final YangInstanceIdentifier newPeerPath;
         newPeerPath = createEmptyPeerStructure(newPeerId, tx);
-        final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, registry, tableTypes, addPathTablesType, tx);
-        tx.submit();
+        final ImmutableMap<TablesKey, TableContext> tb = createNewTableInstances(newPeerPath, registry, tableTypes,
+            addPathTablesType, tx);
 
+        Futures.addCallback(tx.submit(), new FutureCallback<Void>() {
+            @Override
+            public void onSuccess(final Void result) {
+                if(registerAppPeerListener != null) {
+                    LOG.trace("Application Peer Listener registered");
+                    registerAppPeerListener.register();
+                }
+            }
+
+            @Override
+            public void onFailure(final Throwable throwable) {
+                LOG.error("Failed to register Application Peer Listener", throwable);
+            }
+        });
         return new AdjRibInWriter(this.ribPath, this.chain, this.role, this.simpleRoutingPolicy, newPeerPath, tb);
     }
 
index a028b437b98c4ac4127c7ca976861c4b1a92888a..c1fb365ef798055309e1d830a568f8c80c5d2ce0 100644 (file)
@@ -13,6 +13,7 @@ import com.google.common.net.InetAddresses;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
@@ -20,6 +21,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
 import org.opendaylight.controller.md.sal.dom.api.ClusteredDOMDataTreeChangeListener;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeService;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMTransactionChain;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPConfigModuleTracker;
@@ -29,6 +32,7 @@ import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPPeerStats;
 import org.opendaylight.protocol.bgp.rib.impl.stats.peer.BGPPeerStatsImpl;
 import org.opendaylight.protocol.bgp.rib.spi.ExportPolicyPeerTracker;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
+import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
 import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
@@ -39,6 +43,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.peer.AdjRibIn;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
@@ -77,6 +82,17 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
     private EffectiveRibInWriter effectiveRibInWriter;
     private AdjRibInWriter adjRibInWriter;
     private BGPPeerStats peerStats;
+    private ListenerRegistration<ApplicationPeer> registration;
+    private final Set<NodeIdentifierWithPredicates> supportedTables = new HashSet<>();
+
+
+    @FunctionalInterface
+    interface RegisterAppPeerListener {
+        /**
+         * Register Application Peer Change Listener once AdjRibIn has been successfully initialized.
+         */
+        void register();
+    }
 
     public ApplicationPeer(final ApplicationRibId applicationRibId, final Ipv4Address ipAddress, final RIB rib,
         final BGPConfigModuleTracker moduleTracker) {
@@ -95,7 +111,8 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
         this(applicationRibId, bgpPeerId, targetRibDependency, null);
     }
 
-    public void instantiateServiceInstance() {
+    public synchronized void instantiateServiceInstance(final DOMDataTreeChangeService dataTreeChangeService,
+        final DOMDataTreeIdentifier appPeerDOMId) {
         this.chain = this.rib.createPeerChain(this);
         this.writerChain = this.rib.createPeerChain(this);
 
@@ -107,11 +124,20 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
             if (exportTracker != null) {
                 exportTracker.registerPeer(peerId, null, this.peerIId, PeerRole.Internal, simpleRoutingPolicy);
             }
+            this.supportedTables.add(RibSupportUtils.toYangTablesKey(tablesKey));
         });
 
         this.adjRibInWriter = AdjRibInWriter.create(this.rib.getYangRibId(), PeerRole.Internal, simpleRoutingPolicy, this.writerChain);
         final RIBSupportContextRegistry context = this.rib.getRibSupportContext();
-        this.adjRibInWriter = this.adjRibInWriter.transform(peerId, context, localTables, Collections.emptyMap());
+        final RegisterAppPeerListener registerAppPeerListener = () -> {
+            synchronized (this) {
+                if(this.chain != null) {
+                    this.registration = dataTreeChangeService.registerDataTreeChangeListener(appPeerDOMId, this);
+                }
+            }
+        };
+        this.adjRibInWriter = this.adjRibInWriter.transform(peerId, context, localTables, Collections.emptyMap(),
+            registerAppPeerListener);
         this.peerStats = new BGPPeerStatsImpl(this.name, localTables);
         this.effectiveRibInWriter = EffectiveRibInWriter.create(this.rib.getService(), this.rib.createPeerChain(this), this.peerIId,
             this.rib.getImportPolicyPeerTracker(), context, PeerRole.Internal, this.peerStats.getEffectiveRibInRouteCounters(),
@@ -128,7 +154,11 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
      * be determined in LocRib.
      */
     @Override
-    public void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
+    public synchronized void onDataTreeChanged(final Collection<DataTreeCandidate> changes) {
+        if(this.chain == null) {
+            LOG.trace("Skipping data changed called to Application Peer. Change : {}", changes);
+            return;
+        }
         final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction();
         LOG.debug("Received data change to ApplicationRib {}", changes);
         for (final DataTreeCandidate tc : changes) {
@@ -137,6 +167,10 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
             final PathArgument lastArg = path.getLastPathArgument();
             Verify.verify(lastArg instanceof NodeIdentifierWithPredicates, "Unexpected type %s in path %s", lastArg.getClass(), path);
             final NodeIdentifierWithPredicates tableKey = (NodeIdentifierWithPredicates) lastArg;
+            if (!this.supportedTables.contains(tableKey)) {
+                LOG.trace("Skipping received data change for non supported family {}.", tableKey);
+                continue;
+            }
             for (final DataTreeCandidateNode child : tc.getRootNode().getChildNodes()) {
                 final PathArgument childIdentifier = child.getIdentifier();
                 final YangInstanceIdentifier tableId = this.adjRibsInId.node(tableKey).node(childIdentifier);
@@ -176,7 +210,7 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
      * @param tx
      * @param routeTableIdentifier
      */
-    private void processRoutesTable(final DataTreeCandidateNode node, final YangInstanceIdentifier identifier,
+    private synchronized void processRoutesTable(final DataTreeCandidateNode node, final YangInstanceIdentifier identifier,
             final DOMDataWriteTransaction tx, final YangInstanceIdentifier routeTableIdentifier) {
         for (final DataTreeCandidateNode child : node.getChildNodes()) {
             final YangInstanceIdentifier childIdentifier = identifier.node(child.getIdentifier());
@@ -215,18 +249,24 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
     }
 
     @Override
-    public void close() {
-        if(this.effectiveRibInWriter != null) {
+    public synchronized void close() {
+        if (this.registration != null) {
+            this.registration.close();
+            this.registration = null;
+        }
+        if (this.effectiveRibInWriter != null) {
             this.effectiveRibInWriter.close();
         }
-        if(this.adjRibInWriter != null) {
+        if (this.adjRibInWriter != null) {
             this.adjRibInWriter.removePeer();
         }
-        if(this.chain != null) {
+        if (this.chain != null) {
             this.chain.close();
+            this.chain = null;
         }
-        if(this.writerChain != null) {
+        if (this.writerChain != null) {
             this.writerChain.close();
+            this.writerChain = null;
         }
         if (this.moduleTracker != null) {
             this.moduleTracker.onInstanceClose();
@@ -239,13 +279,13 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol
     }
 
     @Override
-    public void onTransactionChainFailed(final TransactionChain<?, ?> chain, final AsyncTransaction<?, ?> transaction,
-            final Throwable cause) {
-        LOG.error("Transaction chain failed.", cause);
+    public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
+        final AsyncTransaction<?, ?> transaction, final Throwable cause) {
+        LOG.error("Transaction chain {} failed.", transaction != null ? transaction.getIdentifier() : null, cause);
     }
 
     @Override
     public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
-        LOG.debug("Transaction chain {} successfull.", chain);
+        LOG.debug("Transaction chain {} successful.", chain);
     }
 }
index 61e5ce2252d1433c5ea3fe56a5bc7546c60bc5df..580900bff81560f772faa0d2ea7eeaaad440e9dc 100644 (file)
@@ -29,7 +29,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRib;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.ApplicationRibId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.Tables;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.slf4j.Logger;
@@ -43,11 +42,13 @@ public final class AppPeer implements PeerBean {
     private BGPOpenConfigMappingService mappingService;
 
     @Override
-    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService, final WriteConfiguration configurationWriter) {
+    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService,
+        final WriteConfiguration configurationWriter) {
+        Preconditions.checkState(this.bgpAppPeerSingletonService == null, "Previous peer instance was not closed.");
         this.currentConfiguration = neighbor;
         this.mappingService = mappingService;
-        this.bgpAppPeerSingletonService = new BgpAppPeerSingletonService(rib, createAppRibId(neighbor), neighbor.getNeighborAddress().getIpv4Address(),
-                configurationWriter);
+        this.bgpAppPeerSingletonService = new BgpAppPeerSingletonService(rib, createAppRibId(neighbor),
+            neighbor.getNeighborAddress().getIpv4Address(), configurationWriter);
     }
 
     @Override
@@ -60,6 +61,7 @@ public final class AppPeer implements PeerBean {
     public void close() {
         try {
             this.bgpAppPeerSingletonService.close();
+            this.bgpAppPeerSingletonService = null;
         } catch (final Exception e) {
             LOG.warn("Failed to close application peer instance", e);
         }
@@ -84,11 +86,11 @@ public final class AppPeer implements PeerBean {
         private final DOMDataTreeChangeService dataTreeChangeService;
         private final ApplicationRibId appRibId;
         private ClusterSingletonServiceRegistration singletonServiceRegistration;
-        private ListenerRegistration<ApplicationPeer> registration;
         private final ServiceGroupIdentifier serviceGroupIdentifier;
         private final WriteConfiguration configurationWriter;
 
-        BgpAppPeerSingletonService(final RIB rib, final ApplicationRibId appRibId, final Ipv4Address neighborAddress, final WriteConfiguration configurationWriter) {
+        BgpAppPeerSingletonService(final RIB rib, final ApplicationRibId appRibId, final Ipv4Address neighborAddress,
+            final WriteConfiguration configurationWriter) {
             this.applicationPeer = new ApplicationPeer(appRibId, neighborAddress, rib);
             this.appRibId = appRibId;
             this.dataTreeChangeService = rib.getService();
@@ -115,17 +117,13 @@ public final class AppPeer implements PeerBean {
             LOG.info("Application Peer Singleton Service {} instantiated", getIdentifier());
             final YangInstanceIdentifier yangIId = YangInstanceIdentifier.builder().node(ApplicationRib.QNAME)
                 .nodeWithKey(ApplicationRib.QNAME, APP_ID_QNAME, this.appRibId.getValue()).node(Tables.QNAME).node(Tables.QNAME).build();
-            this.applicationPeer.instantiateServiceInstance();
-            this.registration = this.dataTreeChangeService
-                .registerDataTreeChangeListener(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, yangIId), this.applicationPeer);
+            this.applicationPeer.instantiateServiceInstance(this.dataTreeChangeService,
+                new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, yangIId));
         }
 
         @Override
         public ListenableFuture<Void> closeServiceInstance() {
             LOG.info("Application Peer Singleton Service {} instance closed", getIdentifier());
-            if(this.registration != null) {
-                this.registration.close();
-            }
             this.applicationPeer.close();
             return Futures.immediateFuture(null);
         }
index beda7c7d1ba09b9d6f5f10aa8d2332cbabd8ffa1..3af961fe6d8777a9710ff78c839f6f944093bcb4 100644 (file)
@@ -80,7 +80,7 @@ public final class BgpPeer implements PeerBean, BGPPeerRuntimeMXBean {
     @Override
     public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService,
         final WriteConfiguration configurationWriter) {
-        Preconditions.checkState(this.bgpPeerSingletonService == null, "Previous peer instance {} was not closed.");
+        Preconditions.checkState(this.bgpPeerSingletonService == null, "Previous peer instance was not closed.");
         this.bgpPeerSingletonService = new BgpPeerSingletonService(rib, neighbor, mappingService, configurationWriter);
         this.currentConfiguration = neighbor;
     }
index bb7cf2287e26335cf2903d1cde41487f5b41e61d..aea8c6341cf69dcf9c388ef89144380837b30398 100644 (file)
@@ -8,12 +8,12 @@
 package org.opendaylight.protocol.bgp.rib.impl;
 
 import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.never;
 
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.CheckedFuture;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -30,8 +30,6 @@ import org.opendaylight.protocol.bgp.rib.impl.spi.RIBSupportContextRegistry;
 import org.opendaylight.protocol.bgp.rib.spi.IdentifierUtils;
 import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.SendReceive;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamilies;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.mp.capabilities.add.path.capability.AddressFamiliesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.Rib;
@@ -65,10 +63,6 @@ public class AdjRibsInWriterTest {
 
     private static final TablesKey K4 = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
     private final Set<TablesKey> tableTypes = Sets.newHashSet(K4);
-
-    private static final AddressFamilies ADDRESS_FAMILIES = new AddressFamiliesBuilder().setAfi(Ipv4AddressFamily.class)
-        .setSafi(UnicastSubsequentAddressFamily.class).setSendReceive(SendReceive.Both).build();
-    private final List<AddressFamilies> addPathTablesType = Collections.singletonList(ADDRESS_FAMILIES);
     private static final Map<TablesKey, SendReceive> ADD_PATH_TABLE_MAPS = Collections.singletonMap(K4, SendReceive.Both);
 
     private final String peerIp = "12.34.56.78";
@@ -78,7 +72,9 @@ public class AdjRibsInWriterTest {
         MockitoAnnotations.initMocks(this);
         Mockito.doReturn("MockedTrans").when(this.tx).toString();
         Mockito.doReturn(this.tx).when(this.chain).newWriteOnlyTransaction();
-        Mockito.doReturn(Mockito.mock(CheckedFuture.class)).when(this.tx).submit();
+        final CheckedFuture checkedFuture =  Mockito.mock(CheckedFuture.class);
+        Mockito.doNothing().when(checkedFuture).addListener(any(), any());
+        Mockito.doReturn(checkedFuture).when(this.tx).submit();
         Mockito.doNothing().when(this.tx).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
         Mockito.doNothing().when(this.tx).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class));
         Mockito.doReturn(this.context).when(this.registry).getRIBSupportContext(Mockito.any(TablesKey.class));
index 3eba3ddad7a90f72edffe3ce524ed940ae79fa02..4365e26f70c72ca836c961f3237e872752bdb202 100644 (file)
@@ -127,7 +127,7 @@ public class PeerTest extends AbstractRIBTestSetup {
         final Ipv4Prefix second = new Ipv4Prefix("127.0.0.1/32");
         final Ipv4Prefix third = new Ipv4Prefix("127.0.0.3/32");
         this.peer = new ApplicationPeer(new ApplicationRibId("t"), new Ipv4Address("127.0.0.1"), getRib());
-        this.peer.instantiateServiceInstance();
+        this.peer.instantiateServiceInstance(null, null);
         final YangInstanceIdentifier base = getRib().getYangRibId().node(LocRib.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(KEY));
         this.peer.onDataTreeChanged(ipv4Input(base, ModificationType.WRITE, first, second, third));
         assertEquals(3, this.routes.size());
index beb9ab70736079f47897326193eaa9647037d14f..619a210563029cfde0ae8fb238374a90871af52a 100644 (file)
@@ -33,6 +33,7 @@ import java.net.InetSocketAddress;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import org.junit.Before;
 import org.junit.Test;
@@ -184,6 +185,14 @@ public class SynchronizationAndExceptionTest extends AbstractAddPathTest {
             any(YangInstanceIdentifier.class), any(NormalizedNode.class));
         Mockito.doNothing().when(this.tx).delete(Mockito.any(LogicalDatastoreType.class), Mockito.any(YangInstanceIdentifier.class));
         final CheckedFuture future = mock(CheckedFuture.class);
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                final Runnable callback = (Runnable) invocation.getArguments()[0];
+                callback.run();
+                return null;
+            }
+        }).when(future).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class));
         Mockito.doReturn(future).when(this.tx).submit();
         Mockito.doReturn(mock(Optional.class)).when(future).checkedGet();
     }
index 4afe25257594c8677612395524ab60ba0ab5fd21..569ca3d7ee5a63ff2d2e857743ba2764f8a57b65 100644 (file)
@@ -18,6 +18,7 @@ import com.google.common.util.concurrent.CheckedFuture;
 import io.netty.util.concurrent.Future;
 import java.net.InetSocketAddress;
 import java.util.Collections;
+import java.util.concurrent.Executor;
 import org.junit.Before;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -62,7 +63,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.osgi.framework.ServiceRegistration;
 
 class AbstractConfig {
-    protected static final AsNumber AS = new AsNumber(123456L);
+    protected static final AsNumber AS = new AsNumber(72L);
     @Mock
     protected RIB rib;
     @Mock
@@ -96,14 +97,10 @@ class AbstractConfig {
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        Mockito.doAnswer(new Answer<ClusterSingletonServiceRegistration>() {
-            @Override
-            public ClusterSingletonServiceRegistration answer(final InvocationOnMock invocationOnMock) throws Throwable {
-                singletonService = (ClusterSingletonService) invocationOnMock.getArguments()[0];
-                return singletonServiceRegistration;
-            }
+        Mockito.doAnswer(invocationOnMock->{
+            this.singletonService = (ClusterSingletonService) invocationOnMock.getArguments()[0];
+            return this.singletonServiceRegistration;
         }).when(this.rib).registerClusterSingletonService(any(ClusterSingletonService.class));
-
         Mockito.doReturn(new UnsignedInt32Counter("counter")).when(this.render).getConfiguredPeerCounter();
         Mockito.doReturn(this.render).when(this.rib).getRenderStats();
         Mockito.doReturn(this.domTx).when(this.rib).createPeerChain(any(TransactionChainListener.class));
@@ -119,8 +116,18 @@ class AbstractConfig {
         Mockito.doNothing().when(this.domDW).delete(eq(LogicalDatastoreType.OPERATIONAL), any(YangInstanceIdentifier.class));
         Mockito.doNothing().when(this.domDW).merge(eq(LogicalDatastoreType.OPERATIONAL), any(YangInstanceIdentifier.class), any(NormalizedNode.class));
         final CheckedFuture checkedFuture = mock(CheckedFuture.class);
+        Mockito.doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(final InvocationOnMock invocation) throws Throwable {
+                final Runnable callback = (Runnable) invocation.getArguments()[0];
+                callback.run();
+                return null;
+            }
+        }).when(checkedFuture).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class));
         Mockito.doReturn(checkedFuture).when(this.domDW).submit();
         Mockito.doReturn(null).when(checkedFuture).checkedGet();
+        Mockito.doReturn(null).when(checkedFuture).get();
+        Mockito.doReturn("checkedFuture").when(checkedFuture).toString();
 
         Mockito.doNothing().when(this.singletonServiceRegistration).close();
         Mockito.doReturn(YangInstanceIdentifier.of(Rib.QNAME)).when(this.rib).getYangRibId();
@@ -128,8 +135,8 @@ class AbstractConfig {
         Mockito.doReturn(this.listener).when(this.dataTreeChangeService).registerDataTreeChangeListener(any(), any());
         Mockito.doReturn(mock(ServiceGroupIdentifier.class)).when(this.rib).getRibIServiceGroupIdentifier();
         Mockito.doReturn(new BgpId("127.0.0.1")).when(this.rib).getBgpIdentifier();
-        Mockito.doReturn(true).when(future).cancel(true);
-        Mockito.doReturn(future).when(this.dispatcher)
+        Mockito.doReturn(true).when(this.future).cancel(true);
+        Mockito.doReturn(this.future).when(this.dispatcher)
             .createReconnectingClient(any(InetSocketAddress.class), any(BGPPeerRegistry.class), anyInt(), any(Optional.class));
         Mockito.doReturn(this.dispatcher).when(this.rib).getDispatcher();
 
index 666481a53567ad1d6c113d0f17aabd13a8c5df24..7c278fc3bc95df9ba283c7b2565b54eb5334722b 100644 (file)
@@ -24,8 +24,10 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 
 public class AppPeerTest extends AbstractConfig {
     private static final AppPeer APP_PEER = new AppPeer();
+    private final Neighbor neighbor = new NeighborBuilder()
+        .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).build();
 
-
+    @Override
     @Before
     public void setUp() throws Exception {
         super.setUp();
@@ -34,19 +36,22 @@ public class AppPeerTest extends AbstractConfig {
 
     @Test
     public void testAppPeer() throws Exception {
-        final Neighbor neighbor = new NeighborBuilder().setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).build();
-        APP_PEER.start(this.rib, neighbor, this.mappingService, this.configurationWriter);
+        APP_PEER.start(this.rib, this.neighbor, this.mappingService, this.configurationWriter);
         Mockito.verify(this.rib).getYangRibId();
         Mockito.verify(this.rib).getService();
         Mockito.verify(this.rib).getRibIServiceGroupIdentifier();
         Mockito.verify(this.rib).registerClusterSingletonService(any(ClusterSingletonService.class));
 
         this.singletonService.instantiateServiceInstance();
+        Mockito.verify(this.rib, times(2)).getYangRibId();
         Mockito.verify(this.configurationWriter).apply();
         Mockito.verify(this.rib).getRibSupportContext();
         Mockito.verify(this.rib).getLocalTablesKeys();
         Mockito.verify(this.domTx).newWriteOnlyTransaction();
 
+        APP_PEER.close();
+        Mockito.verify(this.singletonServiceRegistration).close();
+
         APP_PEER.restart(this.rib, this.mappingService);
         this.singletonService.instantiateServiceInstance();
         Mockito.verify(this.rib, times(4)).getYangRibId();
@@ -57,9 +62,10 @@ public class AppPeerTest extends AbstractConfig {
         this.singletonService.closeServiceInstance();
         Mockito.verify(this.listener, times(2)).close();
 
-        assertTrue(APP_PEER.containsEqualConfiguration(new NeighborBuilder().setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.1"))).build()));
-        assertFalse(APP_PEER.containsEqualConfiguration(new NeighborBuilder().setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.2"))).build()));
+        assertTrue(APP_PEER.containsEqualConfiguration(this.neighbor));
+        assertFalse(APP_PEER.containsEqualConfiguration(new NeighborBuilder()
+            .setNeighborAddress(new IpAddress(new Ipv4Address("127.0.0.2"))).build()));
         APP_PEER.close();
-        Mockito.verify(this.singletonServiceRegistration).close();
+        Mockito.verify(this.singletonServiceRegistration, times(2)).close();
     }
 }
\ No newline at end of file
index 3cde1b5a25c4d29f1296da63a498024b38d34198..1d78d86497b8654fa96fb69acaad28ea0321ad47 100644 (file)
@@ -102,7 +102,7 @@ public class BgpPeerTest extends AbstractConfig {
             this.bgpPeer.start(this.rib, neighbor, this.mappingService, this.configurationWriter);
             fail("Expected Exception");
         } catch (final IllegalStateException expected) {
-            assertEquals("Previous peer instance {} was not closed.", expected.getMessage());
+            assertEquals("Previous peer instance was not closed.", expected.getMessage());
         }
         this.bgpPeer.setServiceRegistration(this.serviceRegistration);
         this.bgpPeer.close();