Add blueprint XML wiring for the BGPDispatcher
[bgpcep.git] / bgp / rib-impl / src / test / java / org / opendaylight / controller / config / yang / bgp / rib / impl / AbstractRIBImplModuleTest.java
index eee2809f011479b0f20db06d0bbc0765f99ee1fe..3fa59e0f6b2c6ae16e160305e27d5aa79e8c9c05 100755 (executable)
@@ -8,15 +8,24 @@
 package org.opendaylight.controller.config.yang.bgp.rib.impl;
 
 import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.contains;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.io.ByteSource;
 import com.google.common.io.Resources;
 import com.google.common.util.concurrent.CheckedFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.util.concurrent.EventExecutor;
+import io.netty.util.concurrent.ImmediateEventExecutor;
+import io.netty.util.concurrent.SucceededFuture;
 import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
+import java.net.InetSocketAddress;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -33,6 +42,8 @@ import org.mockito.Matchers;
 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.config.api.jmx.CommitStatus;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
@@ -54,27 +65,45 @@ import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomBrokerImplModu
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleFactory;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.DomInmemoryDataBrokerModuleMXBean;
 import org.opendaylight.controller.config.yang.md.sal.dom.impl.SchemaServiceImplSingletonModuleFactory;
+import org.opendaylight.controller.config.yang.netty.eventexecutor.AutoCloseableEventExecutor;
 import org.opendaylight.controller.config.yang.netty.eventexecutor.GlobalEventExecutorModuleFactory;
 import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NioEventLoopGroupCloseable;
 import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.controller.sal.dom.broker.GlobalBundleScanningSchemaServiceImpl;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationPublishService;
+import org.opendaylight.controller.md.sal.dom.api.DOMNotificationService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
+import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.YangTextSourceProvider;
+import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
+import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
+import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionProviderContext;
+import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
+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.RibId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.ClusterIdentifier;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
 import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
-import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
-import org.opendaylight.yangtools.yang.parser.repo.URLSchemaContextResolver;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleListener;
 import org.osgi.framework.Filter;
@@ -113,6 +142,9 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
     @Mock
     private RpcResult<TransactionStatus> mockedResult;
 
+    @Mock
+    protected BGPDispatcher mockedBGPDispatcher;
+
     @SuppressWarnings("unchecked")
     @Before
     public void setUp() throws Exception {
@@ -121,15 +153,20 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
         final List<ModuleFactory> moduleFactories = getModuleFactories();
         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.mockedContext, moduleFactories.toArray(new ModuleFactory[moduleFactories.size()])));
 
-        final Filter mockedFilter = mock(Filter.class);
-        Mockito.doReturn(mockedFilter).when(this.mockedContext).createFilter(Mockito.anyString());
+        doAnswer(new Answer<Filter>() {
+            @Override
+            public Filter answer(final InvocationOnMock invocation) {
+                final String str = invocation.getArgumentAt(0, String.class);
+                final Filter mockFilter = mock(Filter.class);
+                doReturn(str).when(mockFilter).toString();
+                return mockFilter;
+            }
+        }).when(mockedContext).createFilter(anyString());
 
         final ServiceReference<?> emptyServiceReference = mock(ServiceReference.class, "Empty");
         final ServiceReference<?> classLoadingStrategySR = mock(ServiceReference.class, "ClassLoadingStrategy");
         final ServiceReference<?> dataProviderServiceReference = mock(ServiceReference.class, "Data Provider");
 
-        Mockito.doReturn(mockedFilter).when(this.mockedContext).createFilter(Mockito.anyString());
-
         Mockito.doNothing().when(this.mockedContext).addServiceListener(any(ServiceListener.class), Mockito.anyString());
         Mockito.doNothing().when(this.mockedContext).removeServiceListener(any(ServiceListener.class));
 
@@ -147,6 +184,7 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
         Mockito.doReturn(emptyServiceReference).when(this.mockedContext).getServiceReference(any(Class.class));
         Mockito.doReturn(dataProviderServiceReference).when(this.mockedContext).getServiceReference(DataBroker.class);
         Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(GeneratedClassLoadingStrategy.class);
+        Mockito.doReturn(classLoadingStrategySR).when(this.mockedContext).getServiceReference(ClassLoadingStrategy.class);
 
         Mockito.doReturn(this.mockedDataProvider).when(this.mockedContext).getService(dataProviderServiceReference);
         Mockito.doReturn(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy()).when(this.mockedContext).getService(classLoadingStrategySR);
@@ -163,20 +201,62 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
 
         Mockito.doReturn(null).when(this.mockedFuture).get();
 
-        final GlobalBundleScanningSchemaServiceImpl schemaService = GlobalBundleScanningSchemaServiceImpl.createInstance(this.mockedContext);
-        final YangContextParser parser = new YangParserImpl();
-        final SchemaContext context = parser.parseSources(getFilesAsByteSources(getYangModelsPaths()));
-        final URLSchemaContextResolver mockedContextResolver = Mockito.mock(URLSchemaContextResolver.class);
-        Mockito.doReturn(Optional.of(context)).when(mockedContextResolver).getSchemaContext();
+        final SchemaContext context = parseYangStreams(getFilesAsByteSources(getYangModelsPaths()));
+        final SchemaService mockedSchemaService = mock(SchemaService.class);
+        doReturn(context).when(mockedSchemaService).getGlobalContext();
+        doAnswer(new Answer<ListenerRegistration<SchemaContextListener>>() {
+            @Override
+            public ListenerRegistration<SchemaContextListener> answer(InvocationOnMock invocation) {
+                invocation.getArgumentAt(0, SchemaContextListener.class).onGlobalContextUpdated(context);
+                ListenerRegistration<SchemaContextListener> reg = mock(ListenerRegistration.class);
+                doNothing().when(reg).close();
+                return reg;
+            }
+        }).when(mockedSchemaService).registerSchemaContextListener(any(SchemaContextListener.class));
+
+        setupMockService(SchemaService.class, mockedSchemaService);
+        setupMockService(YangTextSourceProvider.class, mock(YangTextSourceProvider.class));
+
+        BindingToNormalizedNodeCodecFactory.getOrCreateInstance(
+                GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), mockedSchemaService);
+
+        BGPExtensionProviderContext mockContext = mock(BGPExtensionProviderContext.class);
+        doReturn(mock(MessageRegistry.class)).when(mockContext).getMessageRegistry();
+        setupMockService(BGPExtensionProviderContext.class, mockContext);
+
+        setupMockService(EventLoopGroup.class, NioEventLoopGroupCloseable.newInstance(0));
+        setupMockService(EventExecutor.class, AutoCloseableEventExecutor.CloseableEventExecutorMixin.globalEventExecutor());
 
-        final Field contextResolverField = schemaService.getClass().getDeclaredField("contextResolver");
-        contextResolverField.setAccessible(true);
+        setupMockService(DOMNotificationService.class, mock(DOMNotificationService.class));
+        setupMockService(DOMNotificationPublishService.class, mock(DOMNotificationPublishService.class));
+        setupMockService(DOMRpcService.class, mock(DOMRpcService.class));
+        setupMockService(DOMRpcProviderService.class, mock(DOMRpcProviderService.class));
+        setupMockService(DOMMountPointService.class, mock(DOMMountPointService.class));
 
-        final Field modifiersField = Field.class.getDeclaredField("modifiers");
-        modifiersField.setAccessible(true);
-        modifiersField.setInt(contextResolverField, contextResolverField.getModifiers() & ~Modifier.FINAL);
+        setupMockService(BGPDispatcher.class, mockedBGPDispatcher);
+        doReturn(new SucceededFuture<>(ImmediateEventExecutor.INSTANCE, null)).when(mockedBGPDispatcher).createReconnectingClient(
+                any(InetSocketAddress.class), any(BGPPeerRegistry.class), anyInt(), any(Optional.class));
 
-        contextResolverField.set(schemaService, mockedContextResolver);
+        setupMockService(RIBExtensionProviderContext.class, new SimpleRIBExtensionProviderContext());
+    }
+
+    protected void setupMockService(final Class<?> serviceInterface, final Object instance) throws Exception {
+        final ServiceReference<?> mockServiceRef = mock(ServiceReference.class);
+        doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext).
+                getServiceReferences(anyString(), contains(serviceInterface.getName()));
+        doReturn(new ServiceReference[]{mockServiceRef}).when(mockedContext).
+                getServiceReferences(serviceInterface.getName(), null);
+        doReturn(instance).when(mockedContext).getService(mockServiceRef);
+    }
+
+    private static SchemaContext parseYangStreams(final Collection<ByteSource> streams) {
+        final CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR
+                .newBuild();
+        try {
+            return reactor.buildEffective(streams);
+        } catch (final ReactorException | IOException e) {
+            throw new RuntimeException("Unable to build schema context from " + streams, e);
+        }
     }
 
     protected List<ModuleFactory> getModuleFactories() {
@@ -197,13 +277,7 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
                 @Override
                 public void handleServiceRegistration(final Class<?> clazz, final Object serviceInstance, final Dictionary<String, ?> props) {
                     final SchemaContextListener listener = (SchemaContextListener) serviceInstance;
-                    final YangContextParser parser = new YangParserImpl();
-                    final SchemaContext context;
-                    try {
-                        context = parser.parseSources(getFilesAsByteSources(getYangModelsPaths()));
-                    } catch (IOException | YangSyntaxErrorException e) {
-                        throw new IllegalStateException("Failed to parse models", e);
-                    }
+                    final SchemaContext context = parseYangStreams(getFilesAsByteSources(getYangModelsPaths()));
                     listener.onGlobalContextUpdated(context);
                 }
             };
@@ -215,7 +289,6 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
     @After
     public void closeAllModules() throws Exception {
         super.destroyAllConfigBeans();
-        GlobalBundleScanningSchemaServiceImpl.destroyInstance();
 
     }
 
@@ -238,12 +311,18 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
         mxBean.setDataProvider(dataBroker);
         mxBean.setDomDataProvider(lookupDomAsyncDataBroker(transaction));
         mxBean.setCodecTreeFactory(lookupMappingServiceInstance(transaction));
-        mxBean.setBgpDispatcher(BGPDispatcherImplModuleTest.createInstance(transaction));
+        mxBean.setBgpDispatcher(createBGPDispatcherImplInstance(transaction));
         mxBean.setExtensions(createRibExtensionsInstance(transaction));
         mxBean.setRibId(ribId);
         mxBean.setLocalAs(localAs);
-        mxBean.setBgpRibId(bgpId);
-        mxBean.setClusterId(clusterId);
+        mxBean.setBgpRibId(bgpId != null ? new BgpId(bgpId) : null);
+        mxBean.setClusterId(clusterId != null ? new ClusterIdentifier(clusterId) : null);
+        return nameCreated;
+    }
+
+    public static ObjectName createBGPDispatcherImplInstance(final ConfigTransactionJMXClient transaction) throws InstanceAlreadyExistsException {
+        final ObjectName nameCreated = transaction.createModule(BGPDispatcherImplModuleFactory.NAME, "bgp-message-fct");
+        final BGPDispatcherImplModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, BGPDispatcherImplModuleMXBean.class);
         return nameCreated;
     }
 
@@ -312,7 +391,7 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
     }
 
     public List<String> getYangModelsPaths() {
-        final List<String> paths = Lists.newArrayList("/META-INF/yang/bgp-rib.yang", "/META-INF/yang/ietf-inet-types.yang",
+        final List<String> paths = Lists.newArrayList("/META-INF/yang/bgp-rib.yang", "/META-INF/yang/ietf-inet-types@2013-07-15.yang",
                 "/META-INF/yang/bgp-message.yang", "/META-INF/yang/bgp-multiprotocol.yang", "/META-INF/yang/bgp-types.yang",
                 "/META-INF/yang/network-concepts.yang", "/META-INF/yang/ieee754.yang", "/META-INF/yang/yang-ext.yang");
         return paths;