From 9fee7709aee0234aa264f8d38bd3127957872cc0 Mon Sep 17 00:00:00 2001 From: Dana Kutenicsova Date: Mon, 15 Jun 2015 23:53:38 +0200 Subject: [PATCH] BUG-3362 : improved tests for application peer Change-Id: I7fd771d534b1950ff08b47e7126009d8d3afe768 Signed-off-by: Dana Kutenicsova --- .../bgp/rib/impl/ApplicationPeer.java | 19 ++ .../protocol/bgp/rib/impl/RIBImpl.java | 7 +- .../bgp/rib/impl/AbstractRIBTestSetup.java | 245 +++++++++++++++++ .../protocol/bgp/rib/impl/PeerTest.java | 258 ++++-------------- 4 files changed, 318 insertions(+), 211 deletions(-) create mode 100644 bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java index 0c4228661b..821af49a51 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/ApplicationPeer.java @@ -33,6 +33,19 @@ import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNod import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Application Peer is a special case of BGP peer. It serves as an interface + * for user to advertise user routes to ODL and through ODL to other BGP peers. + * + * This peer has it's own RIB, where it stores all user routes. This RIB is + * located in configurational datastore. Routes are added through RESTCONF. + * + * They are then processed as routes from any other peer, through AdjRib, + * EffectiveRib,LocRib and if they are advertised further, through AdjRibOut. + * + * For purposed of import policies such as Best Path Selection, application + * peer needs to have a BGP-ID that is configurable. + */ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol.bgp.rib.spi.Peer, DOMDataTreeChangeListener, TransactionChainListener { private static final Logger LOG = LoggerFactory.getLogger(ApplicationPeer.class); @@ -59,6 +72,12 @@ public class ApplicationPeer implements AutoCloseable, org.opendaylight.protocol this.writer = this.writer.transform(RouterIds.createPeerId(ipAddress), this.targetRib.getRibSupportContext(), this.targetRib.getLocalTablesKeys(), false); } + /** + * Routes come from application RIB that is identified by (configurable) name. + * Each route is pushed into AdjRibsInWriter with it's whole context. In this + * method, it doesn't matter if the routes are removed or added, this will + * be determined in LocRib. + */ @Override public void onDataTreeChanged(final Collection changes) { final DOMDataWriteTransaction tx = this.chain.newWriteOnlyTransaction(); diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java index a66066539f..0e5295ca81 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java @@ -7,6 +7,7 @@ */ package org.opendaylight.protocol.bgp.rib.impl; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects.ToStringHelper; import com.google.common.base.Optional; @@ -74,8 +75,10 @@ import org.slf4j.LoggerFactory; @ThreadSafe public final class RIBImpl extends DefaultRibReference implements AutoCloseable, RIB, TransactionChainListener, SchemaContextListener { private static final Logger LOG = LoggerFactory.getLogger(RIBImpl.class); - private static final QName RIB_ID_QNAME = QName.cachedReference(QName.create(Rib.QNAME, "id")); - private static final ContainerNode EMPTY_TABLE_ATTRIBUTES = ImmutableNodes.containerNode(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes.QNAME); + @VisibleForTesting + public static final QName RIB_ID_QNAME = QName.cachedReference(QName.create(Rib.QNAME, "id")); + @VisibleForTesting + public static final ContainerNode EMPTY_TABLE_ATTRIBUTES = ImmutableNodes.containerNode(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Attributes.QNAME); private final ReconnectStrategyFactory tcpStrategyFactory; private final ReconnectStrategyFactory sessionStrategyFactory; diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java new file mode 100644 index 0000000000..53da2ad84e --- /dev/null +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/AbstractRIBTestSetup.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.protocol.bgp.rib.impl; + +import com.google.common.base.Optional; +import com.google.common.base.Throwables; +import com.google.common.util.concurrent.CheckedFuture; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import javassist.ClassPool; +import org.junit.After; +import org.junit.Before; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; +import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; +import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener; +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.parser.BgpTableTypeImpl; +import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher; +import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext; +import org.opendaylight.protocol.bgp.rib.spi.RIBSupport; +import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext; +import org.opendaylight.protocol.framework.ReconnectStrategyFactory; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.BgpRib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.RibId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.TablesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.SubsequentAddressFamily; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily; +import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory; +import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator; +import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator; +import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; +import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; +import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy; +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; +import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.util.BindingReflections; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; + +public class AbstractRIBTestSetup { + + private RIBImpl rib; + private final Ipv4Address clusterId = new Ipv4Address("128.0.0.1"); + private final Ipv4Address ribId = new Ipv4Address("127.0.0.1"); + static final Class AFI = Ipv4AddressFamily.class; + static final Class SAFI = UnicastSubsequentAddressFamily.class; + static final TablesKey KEY = new TablesKey(AFI, SAFI); + private BindingCodecTreeFactory codecFactory; + private RIBActivator a1; + RIBSupport ribSupport; + + @Mock + private BGPDispatcher dispatcher; + + @Mock + private ReconnectStrategyFactory tcpStrategyFactory; + + @Mock + private DataBroker dps; + + @Mock + private DOMDataBroker dom; + + @Mock + private BindingTransactionChain chain; + + @Mock + private WriteTransaction transWrite; + + @Mock + private DOMTransactionChain domChain; + + @Mock + private DOMDataWriteTransaction domTransWrite; + + @Mock + private CheckedFuture future; + + @Mock + private Optional o; + + @Mock + private DOMDataTreeChangeService service; + + @Before + public void setUp() throws Exception { + mockRib(); + } + + public void mockRib() throws Exception { + final RIBExtensionProviderContext context = new SimpleRIBExtensionProviderContext(); + final ModuleInfoBackedContext strategy = createClassLoadingStrategy(); + final SchemaContext schemaContext = strategy.tryToCreateSchemaContext().get(); + this.codecFactory = createCodecFactory(strategy,schemaContext); + final List localTables = new ArrayList<>(); + localTables.add(new BgpTableTypeImpl(AFI, SAFI)); + this.a1 = new RIBActivator(); + this.a1.startRIBExtensionProvider(context); + mockedMethods(); + this.rib = new RIBImpl(new RibId("test"), new AsNumber(5L), this.ribId, + this.clusterId, context , this.dispatcher, this.tcpStrategyFactory, this.codecFactory, this.tcpStrategyFactory, this.dps, this.dom, localTables, GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()); + this.rib.onGlobalContextUpdated(schemaContext); + this.ribSupport = getRib().getRibSupportContext().getRIBSupportContext(KEY).getRibSupport(); + } + + private static ModuleInfoBackedContext createClassLoadingStrategy() { + final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create(); + try { + ctx.registerModuleInfo(BindingReflections.getModuleInfo(Ipv4Route.class)); + } catch (final Exception e) { + throw Throwables.propagate(e); + } + return ctx; + } + + private static BindingCodecTreeFactory createCodecFactory(final ClassLoadingStrategy str, final SchemaContext ctx) { + final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())); + final BindingNormalizedNodeCodecRegistry codec = new BindingNormalizedNodeCodecRegistry(generator); + codec.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(str, ctx)); + return codec; + } + + @SuppressWarnings("unchecked") + private void mockedMethods() throws Exception { + MockitoAnnotations.initMocks(this); + final ReadOnlyTransaction readTx = Mockito.mock(ReadOnlyTransaction.class); + Mockito.doReturn(null).when(this.service).registerDataTreeChangeListener(Mockito.any(DOMDataTreeIdentifier.class), Mockito.any(DOMDataTreeChangeListener.class)); + final Map, DOMDataBrokerExtension> map = new HashMap<>(); + map.put(DOMDataTreeChangeService.class, this.service); + Mockito.doNothing().when(readTx).close(); + Mockito.doReturn(readTx).when(this.dps).newReadOnlyTransaction(); + final CheckedFuture, ReadFailedException> readFuture = Mockito.mock(CheckedFuture.class); + Mockito.doNothing().when(this.domTransWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class)); + Mockito.doNothing().when(this.domTransWrite).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class)); + Mockito.doNothing().when(this.domTransWrite).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class)); + Mockito.doReturn(Optional.absent()).when(readFuture).checkedGet(); + Mockito.doReturn(readFuture).when(readTx).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class)); + Mockito.doReturn(this.chain).when(this.dps).createTransactionChain(Mockito.any(RIBImpl.class)); + Mockito.doNothing().when(this.domChain).close(); + Mockito.doReturn(this.domTransWrite).when(this.domChain).newWriteOnlyTransaction(); + Mockito.doNothing().when(getTransaction()).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.eq(YangInstanceIdentifier.of(BgpRib.QNAME)), Mockito.any(NormalizedNode.class)); + Mockito.doReturn(map).when(this.dom).getSupportedExtensions(); + Mockito.doReturn(this.domChain).when(this.dom).createTransactionChain(Mockito.any(BGPPeer.class)); + Mockito.doReturn(this.transWrite).when(this.chain).newWriteOnlyTransaction(); + Mockito.doReturn(false).when(this.o).isPresent(); + Mockito.doReturn(this.o).when(this.future).checkedGet(); + Mockito.doReturn(this.future).when(this.domTransWrite).submit(); + Mockito.doNothing().when(this.future).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class)); + Mockito.doNothing().when(this.transWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class), Mockito.eq(true)); + Mockito.doNothing().when(this.transWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class)); + Mockito.doReturn(this.future).when(this.transWrite).submit(); + } + + public Collection ipv4Input(final YangInstanceIdentifier target, final ModificationType type, final Ipv4Prefix... prefix) { + final Collection col = new HashSet<>(); + final DataTreeCandidate candidate = Mockito.mock(DataTreeCandidate.class); + final DataTreeCandidateNode rootNode = Mockito.mock(DataTreeCandidateNode.class); + Mockito.doReturn(rootNode).when(candidate).getRootNode(); + Mockito.doReturn(type).when(rootNode).getModificationType(); + Mockito.doCallRealMethod().when(rootNode).toString(); + Mockito.doReturn(target).when(candidate).getRootPath(); + Mockito.doCallRealMethod().when(candidate).toString(); + final Collection children = new HashSet<>(); + for (final Ipv4Prefix p : prefix) { + final NodeIdentifierWithPredicates routekey = new NodeIdentifierWithPredicates(Ipv4Route.QNAME, IPv4RIBSupport.PREFIX_QNAME, p); + final DataContainerNodeBuilder b = ImmutableNodes.mapEntryBuilder(); + b.withNodeIdentifier(routekey); + b.addChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(IPv4RIBSupport.PREFIX_QNAME)).withValue(p.getValue()).build()); + + final DataTreeCandidateNode child = Mockito.mock(DataTreeCandidateNode.class); + Mockito.doReturn(createIdentifier(target, p)).when(child).getIdentifier(); + Mockito.doReturn(Optional.of(b.build())).when(child).getDataAfter(); + children.add(child); + } + Mockito.doReturn(children).when(rootNode).getChildNodes(); + col.add(candidate); + return col; + } + + public PathArgument createIdentifier(final YangInstanceIdentifier base, final Ipv4Prefix prefix) { + final NodeIdentifierWithPredicates routekey = new NodeIdentifierWithPredicates(Ipv4Route.QNAME, IPv4RIBSupport.PREFIX_QNAME, prefix); + return YangInstanceIdentifier.of(IPv4RIBSupport.PREFIX_QNAME).node(routekey).getLastPathArgument(); + } + + public RIBImpl getRib() { + return this.rib; + } + + public DOMDataBroker getDOMBroker() { + return this.dom; + } + + public DOMDataWriteTransaction getTransaction() { + return this.domTransWrite; + } + + @After + public void tearDown() { + this.a1.close(); + } +} diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java index 7e3a2b5e94..734d65125f 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java @@ -10,54 +10,26 @@ package org.opendaylight.protocol.bgp.rib.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; -import com.google.common.base.Optional; -import com.google.common.base.Throwables; + import com.google.common.collect.Lists; -import com.google.common.util.concurrent.CheckedFuture; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelPipeline; import io.netty.channel.DefaultChannelPromise; import io.netty.channel.EventLoop; import java.net.InetSocketAddress; -import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import javassist.ClassPool; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; -import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain; -import org.opendaylight.controller.md.sal.binding.api.DataBroker; -import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction; -import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; -import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker; -import org.opendaylight.controller.md.sal.dom.api.DOMDataBrokerExtension; -import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeChangeListener; -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.parser.BgpTableTypeImpl; -import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher; -import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext; -import org.opendaylight.protocol.bgp.rib.spi.RIBSupport; import org.opendaylight.protocol.bgp.rib.spi.RibSupportUtils; -import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext; -import org.opendaylight.protocol.framework.ReconnectStrategyFactory; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev150305.ipv4.routes.ipv4.routes.Ipv4Route; @@ -72,224 +44,78 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.mess import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.WithdrawnRoutesBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2Builder; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.MultiprotocolCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.optional.capabilities.c.parameters.multiprotocol._case.MultiprotocolCapabilityBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder; 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.RibId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.Rib; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.bgp.rib.rib.LocRib; 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily; -import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory; -import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator; -import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator; -import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry; -import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; -import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy; -import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext; -import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; -import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils; -import org.opendaylight.yangtools.yang.binding.DataObject; -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.Notification; -import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; -import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates; -import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate; -import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateNodes; -import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.DefaultDataTreeCandidate; -import org.opendaylight.yangtools.yang.data.impl.schema.Builders; -import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; -import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; -import org.opendaylight.yangtools.yang.model.api.SchemaContext; - -public class PeerTest { - - private final TablesKey tk = new TablesKey(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class); - - private RIBImpl r; - - @Mock - BGPDispatcher dispatcher; - - @Mock - ReconnectStrategyFactory tcpStrategyFactory; - - @Mock - DataBroker dps; - - @Mock - DOMDataBroker dom; - - @Mock - WriteTransaction transWrite; - - @Mock - DOMDataWriteTransaction domTransWrite; +import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType; - @Mock - BindingTransactionChain chain; +public class PeerTest extends AbstractRIBTestSetup { - @Mock - DOMTransactionChain domChain; + private ApplicationPeer peer; - BindingCodecTreeFactory codecFactory; + private BGPSessionImpl session; - ApplicationPeer peer; - - @Mock - CheckedFuture future; - - @Mock - Optional o; - - @Mock - DOMDataTreeChangeService service; - - BGPSessionImpl session; - - List routes; + private Map> routes; private BGPPeer classic; - @Mock - Channel channel; - - @Mock - ChannelPipeline pipeline; - - @Mock - private EventLoop eventLoop; - - private RIBActivator a1; - - @SuppressWarnings("unchecked") + @Override @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - final ModuleInfoBackedContext strategy = createClassLoadingStrategy(); - final SchemaContext schemaContext = strategy.tryToCreateSchemaContext().get(); - this.codecFactory = createCodecFactory(strategy,schemaContext); - final List localTables = new ArrayList<>(); - this.routes = new ArrayList<>(); - localTables.add(new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class)); - final RIBExtensionProviderContext context = new SimpleRIBExtensionProviderContext(); - this.a1 = new RIBActivator(); - this.a1.startRIBExtensionProvider(context); - Mockito.doReturn(this.chain).when(this.dps).createTransactionChain(Mockito.any(RIBImpl.class)); - Mockito.doReturn(this.domChain).when(this.dom).createTransactionChain(Mockito.any(BGPPeer.class)); - final Map, DOMDataBrokerExtension> map = new HashMap<>(); - map.put(DOMDataTreeChangeService.class, this.service); - Mockito.doReturn(null).when(this.service).registerDataTreeChangeListener(Mockito.any(DOMDataTreeIdentifier.class), Mockito.any(DOMDataTreeChangeListener.class)); - Mockito.doReturn(map).when(this.dom).getSupportedExtensions(); - Mockito.doReturn(this.o).when(this.future).checkedGet(); - Mockito.doNothing().when(this.domChain).close(); + super.setUp(); + this.routes = new HashMap<>(); + overrideMockedBehaviour(); + } + + private void overrideMockedBehaviour() { Mockito.doAnswer(new Answer() { @Override public Object answer(final InvocationOnMock invocation) throws Throwable { final Object[] args = invocation.getArguments(); - final NormalizedNode node = (NormalizedNode)args[2]; - if (node.getNodeType().equals(Ipv4Route.QNAME) || node.getNodeType().equals(IPv4RIBSupport.PREFIX_QNAME)) { - PeerTest.this.routes.add((YangInstanceIdentifier) args[1]); + final NormalizedNodenode = (NormalizedNode)args[2]; + if (node.getIdentifier().getNodeType().equals(Ipv4Route.QNAME) || node.getNodeType().equals(IPv4RIBSupport.PREFIX_QNAME)) { + PeerTest.this.routes.put((YangInstanceIdentifier) args[1], node); } return args[1]; } - }).when(this.domTransWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class)); - Mockito.doNothing().when(this.domTransWrite).merge(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class)); - Mockito.doAnswer(new Answer() { + }).when(getTransaction()).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class), Mockito.any(NormalizedNode.class)); + Mockito.doAnswer(new Answer() { @Override public Object answer(final InvocationOnMock invocation) throws Throwable { final Object[] args = invocation.getArguments(); PeerTest.this.routes.remove(args[1]); return args[1]; } - }).when(this.domTransWrite).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class)); - Mockito.doReturn(false).when(this.o).isPresent(); - Mockito.doReturn(this.future).when(this.domTransWrite).submit(); - Mockito.doNothing().when(this.future).addListener(Mockito.any(Runnable.class), Mockito.any(Executor.class)); - Mockito.doReturn(this.transWrite).when(this.chain).newWriteOnlyTransaction(); - Mockito.doNothing().when(this.transWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class), Mockito.eq(true)); - Mockito.doNothing().when(this.transWrite).put(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class), Mockito.any(DataObject.class)); - Mockito.doReturn(this.future).when(this.transWrite).submit(); - Mockito.doReturn(this.domTransWrite).when(this.domChain).newWriteOnlyTransaction(); - Mockito.doReturn(this.eventLoop).when(this.channel).eventLoop(); - Mockito.doReturn("channel").when(this.channel).toString(); - Mockito.doReturn(this.pipeline).when(this.channel).pipeline(); - Mockito.doReturn(this.pipeline).when(this.pipeline).addLast(Mockito.any(ChannelHandler.class)); - this.r = new RIBImpl(new RibId("test"), new AsNumber(5L), new Ipv4Address("127.0.0.1"), - new Ipv4Address("128.0.0.1"), context , this.dispatcher, this.tcpStrategyFactory, this.codecFactory, this.tcpStrategyFactory, this.dps, this.dom, localTables,GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()); - this.peer = new ApplicationPeer(new ApplicationRibId("t"), new Ipv4Address("127.0.0.1"), this.r); - this.r.onGlobalContextUpdated(schemaContext); - final ReadOnlyTransaction readTx = Mockito.mock(ReadOnlyTransaction.class); - Mockito.doNothing().when(readTx).close(); - Mockito.doReturn(readTx).when(this.dps).newReadOnlyTransaction(); - final CheckedFuture, ReadFailedException> readFuture = Mockito.mock(CheckedFuture.class); - Mockito.doReturn(Optional.absent()).when(readFuture).checkedGet(); - Mockito.doReturn(readFuture).when(readTx).read(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(InstanceIdentifier.class)); - } - - private static BindingCodecTreeFactory createCodecFactory(final ClassLoadingStrategy str, final SchemaContext ctx) { - final DataObjectSerializerGenerator generator = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault())); - final BindingNormalizedNodeCodecRegistry codec = new BindingNormalizedNodeCodecRegistry(generator); - codec.onBindingRuntimeContextUpdated(BindingRuntimeContext.create(str, ctx)); - return codec; + }).when(getTransaction()).delete(Mockito.eq(LogicalDatastoreType.OPERATIONAL), Mockito.any(YangInstanceIdentifier.class)); } - private static ModuleInfoBackedContext createClassLoadingStrategy() { - final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create(); - try { - ctx.registerModuleInfo(BindingReflections.getModuleInfo(Ipv4Route.class)); - } catch (final Exception e) { - throw Throwables.propagate(e); - } - return ctx; - } - - @After - public void tearDown() { - this.a1.close(); - } @Test public void testAppPeer() { - final Collection changes = new ArrayList<>(); - final RIBSupport support = this.r.getRibSupportContext().getRIBSupportContext(this.tk).getRibSupport(); - - final YangInstanceIdentifier base = this.r.getYangRibId().node(LocRib.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(this.tk)); - - final NodeIdentifierWithPredicates routekey = new NodeIdentifierWithPredicates(Ipv4Route.QNAME, IPv4RIBSupport.PREFIX_QNAME, new Ipv4Prefix("127.0.0.1/32")); - final DataContainerNodeBuilder b = ImmutableNodes.mapEntryBuilder(); - b.withNodeIdentifier(routekey); - b.addChild(Builders.leafBuilder().withNodeIdentifier(new NodeIdentifier(IPv4RIBSupport.PREFIX_QNAME)).withValue("127.0.0.1/32").build()); - - changes.add(new DefaultDataTreeCandidate(support.routePath(base.node(Routes.QNAME), routekey), DataTreeCandidateNodes.fromNormalizedNode(b.build()))); + final Ipv4Prefix first = new Ipv4Prefix("127.0.0.2/32"); + final Ipv4Prefix second = new Ipv4Prefix("127.0.0.1/32"); + this.peer = new ApplicationPeer(new ApplicationRibId("t"), new Ipv4Address("127.0.0.1"), getRib()); + final YangInstanceIdentifier base = getRib().getYangRibId().node(LocRib.QNAME).node(Tables.QNAME).node(RibSupportUtils.toYangTablesKey(KEY)); + this.peer.onDataTreeChanged(ipv4Input(base, ModificationType.WRITE, first, second)); + assertEquals(2, this.routes.size()); - this.peer.onDataTreeChanged(changes); - assertEquals(1, this.routes.size()); + this.peer.onDataTreeChanged(ipv4Input(base, ModificationType.DELETE, new Ipv4Prefix("127.0.0.3/32"))); + assertEquals(3, this.routes.size()); } @Test - public void testClassicPeer() { - this.classic = new BGPPeer("testPeer", this.r); - Mockito.doReturn(null).when(this.eventLoop).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class)); - Mockito.doReturn(Boolean.TRUE).when(this.channel).isWritable(); - Mockito.doReturn(null).when(this.channel).close(); - Mockito.doReturn(new DefaultChannelPromise(this.channel)).when(this.channel).writeAndFlush(any(Notification.class)); - - Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(this.channel).remoteAddress(); - Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(this.channel).localAddress(); - final List params = Lists.newArrayList(new BgpParametersBuilder().setOptionalCapabilities(Lists.newArrayList(new OptionalCapabilitiesBuilder().setCParameters(new MultiprotocolCaseBuilder() - .setMultiprotocolCapability(new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build())).build()); - this.session = new BGPSessionImpl(this.classic, this.channel, new OpenBuilder().setBgpIdentifier(new Ipv4Address("1.1.1.1")).setHoldTimer(50).setMyAsNumber(72).setBgpParameters(params).build(), 30, null); + public void testClassicPeer() throws Exception { + this.classic = new BGPPeer("testPeer", getRib()); + this.mockSession(); assertEquals("testPeer", this.classic.getName()); this.classic.onSessionUp(this.session); Assert.assertArrayEquals(new byte[] {1, 1, 1, 1}, this.classic.getRawIdentifier()); @@ -302,7 +128,7 @@ public class PeerTest { assertEquals(2, this.routes.size()); //create new peer so that it gets advertized routes from RIB - try (final BGPPeer testingPeer = new BGPPeer("testingPeer", this.r)) { + try (final BGPPeer testingPeer = new BGPPeer("testingPeer", getRib())) { testingPeer.onSessionUp(this.session); assertEquals(2, this.routes.size()); assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().intValue()); @@ -319,12 +145,26 @@ public class PeerTest { new AttributesBuilder().addAugmentation( Attributes2.class, new Attributes2Builder().setMpUnreachNlri( - new MpUnreachNlriBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build()).build()); + new MpUnreachNlriBuilder().setAfi(AFI).setSafi(SAFI).build()).build()).build()).build()); this.classic.releaseConnection(); } - @After - public void cleanUp() { - this.peer.close(); + private void mockSession() { + final EventLoop eventLoop = Mockito.mock(EventLoop.class); + final Channel channel = Mockito.mock(Channel.class); + final ChannelPipeline pipeline = Mockito.mock(ChannelPipeline.class); + Mockito.doReturn(null).when(eventLoop).schedule(any(Runnable.class), any(long.class), any(TimeUnit.class)); + Mockito.doReturn(eventLoop).when(channel).eventLoop(); + Mockito.doReturn(Boolean.TRUE).when(channel).isWritable(); + Mockito.doReturn(null).when(channel).close(); + Mockito.doReturn(pipeline).when(channel).pipeline(); + Mockito.doCallRealMethod().when(channel).toString(); + Mockito.doReturn(pipeline).when(pipeline).addLast(Mockito.any(ChannelHandler.class)); + Mockito.doReturn(new DefaultChannelPromise(channel)).when(channel).writeAndFlush(any(Notification.class)); + Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(channel).remoteAddress(); + Mockito.doReturn(new InetSocketAddress("localhost", 12345)).when(channel).localAddress(); + final List params = Lists.newArrayList(new BgpParametersBuilder().setOptionalCapabilities(Lists.newArrayList(new OptionalCapabilitiesBuilder().setCParameters(new MultiprotocolCaseBuilder() + .setMultiprotocolCapability(new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build())).build()); + this.session = new BGPSessionImpl(this.classic, channel, new OpenBuilder().setBgpIdentifier(new Ipv4Address("1.1.1.1")).setHoldTimer(50).setMyAsNumber(72).setBgpParameters(params).build(), 30, null); } } -- 2.36.6