Refactor integration tests for netconf in netconf-it
[controller.git] / opendaylight / netconf / netconf-it / src / test / java / org / opendaylight / controller / netconf / it / AbstractNetconfConfigTest.java
index d4073e5c178f1748ef71ee8466e70982646dab94..bd931c33d0212858b615aed61d843e1e6f1744d9 100644 (file)
  */
 package org.opendaylight.controller.netconf.it;
 
-import java.net.InetSocketAddress;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anySetOf;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.local.LocalAddress;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.concurrent.GlobalEventExecutor;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.DepTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.MultipleDependenciesModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
+import org.opendaylight.controller.config.yang.test.impl.TestImplModuleFactory;
+import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreException;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreServiceImpl;
+import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreSnapshot;
 import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer;
 import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher;
 import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory;
 import org.opendaylight.controller.netconf.impl.SessionIdProvider;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfMonitoringServiceImpl;
 import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl;
+import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceSnapshotImpl;
 import org.opendaylight.controller.netconf.impl.osgi.SessionMonitoringService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationProvider;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService;
+import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory;
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.protocol.framework.NeverReconnectStrategy;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.w3c.dom.Element;
 
-import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
-import io.netty.util.HashedWheelTimer;
-import io.netty.util.concurrent.GlobalEventExecutor;
+public abstract class AbstractNetconfConfigTest extends AbstractConfigTest {
 
-public class AbstractNetconfConfigTest extends AbstractConfigTest {
+    public static final String LOOPBACK_ADDRESS = "127.0.0.1";
+    public static final int SERVER_CONNECTION_TIMEOUT_MILLIS = 5000;
+
+    static ModuleFactory[] FACTORIES = { new TestImplModuleFactory(),
+            new DepTestImplModuleFactory(), new NetconfTestImplModuleFactory(),
+            new IdentityTestModuleFactory(), new MultipleDependenciesModuleFactory() };
 
     private EventLoopGroup nettyThreadgroup;
     private HashedWheelTimer hashedWheelTimer;
 
+    private NetconfClientDispatcherImpl clientDispatcher;
+    private Channel serverTcpChannel;
+
+    private NetconfMessage getConfig;
+    private NetconfMessage get;
+
+    /**
+     * @Before in subclasses is called after this method.
+     */
     @Before
-    public void setUpAbstractNetconfConfigTest() {
+    public void setUpAbstractNetconfConfigTest() throws Exception {
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, FACTORIES));
+
         nettyThreadgroup = new NioEventLoopGroup();
         hashedWheelTimer = new HashedWheelTimer();
+
+        loadMessages();
+
+        setUpTestInitial();
+
+        final NetconfOperationServiceFactoryListenerImpl factoriesListener = new NetconfOperationServiceFactoryListenerImpl();
+        factoriesListener.onAddNetconfOperationServiceFactory(new NetconfOperationServiceFactoryImpl(getYangStore()));
+
+        for (final NetconfOperationServiceFactory netconfOperationServiceFactory : getAdditionalServiceFactories()) {
+            factoriesListener.onAddNetconfOperationServiceFactory(netconfOperationServiceFactory);
+        }
+
+        serverTcpChannel = startNetconfTcpServer(factoriesListener);
+        clientDispatcher = new NetconfClientDispatcherImpl(getNettyThreadgroup(), getNettyThreadgroup(), getHashedWheelTimer());
+    }
+
+    /**
+     * Called before setUp method is executed, so test classes can set up resources before setUpAbstractNetconfConfigTest method is called.
+     */
+    protected void setUpTestInitial() throws Exception {}
+
+    private void loadMessages() throws Exception {
+        this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml");
+        this.get = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/get.xml");
+    }
+
+    public NetconfMessage getGetConfig() {
+        return getConfig;
+    }
+
+    public NetconfMessage getGet() {
+        return get;
+    }
+
+    private Channel startNetconfTcpServer(final NetconfOperationServiceFactoryListenerImpl factoriesListener) throws Exception {
+        final NetconfServerDispatcher dispatch = createDispatcher(factoriesListener, getNetconfMonitoringService(), getNotificationProducer());
+
+        final ChannelFuture s;
+        if(getTcpServerAddress() instanceof LocalAddress) {
+            s = dispatch.createLocalServer(((LocalAddress) getTcpServerAddress()));
+        } else {
+            s = dispatch.createServer(((InetSocketAddress) getTcpServerAddress()));
+        }
+        s.await();
+        return s.channel();
+    }
+
+    protected DefaultCommitNotificationProducer getNotificationProducer() {
+        final DefaultCommitNotificationProducer notificationProducer = mock(DefaultCommitNotificationProducer.class);
+        doNothing().when(notificationProducer).close();
+        doNothing().when(notificationProducer).sendCommitNotification(anyString(), any(Element.class), anySetOf(String.class));
+        return notificationProducer;
+    }
+
+    protected Iterable<NetconfOperationServiceFactory> getAdditionalServiceFactories() {
+        return Collections.emptySet();
+    }
+
+    protected SessionMonitoringService getNetconfMonitoringService() throws Exception {
+        final NetconfOperationProvider netconfOperationProvider = mock(NetconfOperationProvider.class);
+        final NetconfOperationServiceSnapshotImpl snap = mock(NetconfOperationServiceSnapshotImpl.class);
+        doReturn(Collections.<NetconfOperationService>emptySet()).when(snap).getServices();
+        doReturn(snap).when(netconfOperationProvider).openSnapshot(anyString());
+        return new NetconfMonitoringServiceImpl(netconfOperationProvider);
+    }
+
+    protected abstract SocketAddress getTcpServerAddress();
+
+    public NetconfClientDispatcherImpl getClientDispatcher() {
+        return clientDispatcher;
+    }
+
+    private HardcodedYangStoreService getYangStore() throws YangStoreException, IOException {
+        final Collection<InputStream> yangDependencies = getBasicYangs();
+        return new HardcodedYangStoreService(yangDependencies);
+    }
+
+    static Collection<InputStream> getBasicYangs() throws IOException {
+
+        final List<String> paths = Arrays.asList(
+                "/META-INF/yang/config.yang",
+                "/META-INF/yang/rpc-context.yang",
+                "/META-INF/yang/config-test.yang",
+                "/META-INF/yang/config-test-impl.yang",
+                "/META-INF/yang/test-types.yang",
+                "/META-INF/yang/ietf-inet-types.yang");
+
+        final Collection<InputStream> yangDependencies = new ArrayList<>();
+        final List<String> failedToFind = new ArrayList<>();
+        for (final String path : paths) {
+            final InputStream resourceAsStream = NetconfITTest.class.getResourceAsStream(path);
+            if (resourceAsStream == null) {
+                failedToFind.add(path);
+            } else {
+                yangDependencies.add(resourceAsStream);
+            }
+        }
+        assertEquals("Some yang files were not found", Collections.<String>emptyList(), failedToFind);
+        return yangDependencies;
     }
 
     protected NetconfServerDispatcher createDispatcher(
-            NetconfOperationServiceFactoryListenerImpl factoriesListener, SessionMonitoringService sessionMonitoringService,
-            DefaultCommitNotificationProducer commitNotifier) {
-        SessionIdProvider idProvider = new SessionIdProvider();
+            final NetconfOperationServiceFactoryListenerImpl factoriesListener, final SessionMonitoringService sessionMonitoringService,
+            final DefaultCommitNotificationProducer commitNotifier) {
+        final SessionIdProvider idProvider = new SessionIdProvider();
 
-        NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
-                hashedWheelTimer, factoriesListener, idProvider, 5000, commitNotifier, sessionMonitoringService);
+        final NetconfServerSessionNegotiatorFactory serverNegotiatorFactory = new NetconfServerSessionNegotiatorFactory(
+                hashedWheelTimer, factoriesListener, idProvider, SERVER_CONNECTION_TIMEOUT_MILLIS, commitNotifier, sessionMonitoringService);
 
-        NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
+        final NetconfServerDispatcher.ServerChannelInitializer serverChannelInitializer = new NetconfServerDispatcher.ServerChannelInitializer(
                 serverNegotiatorFactory);
         return new NetconfServerDispatcher(serverChannelInitializer, nettyThreadgroup, nettyThreadgroup);
     }
@@ -60,19 +222,58 @@ public class AbstractNetconfConfigTest extends AbstractConfigTest {
         return nettyThreadgroup;
     }
 
+    /**
+     * @After in subclasses is be called before this.
+     */
     @After
-    public void cleanUpTimer() {
+    public void cleanUpNetconf() throws Exception {
+        serverTcpChannel.close().await();
         hashedWheelTimer.stop();
-        nettyThreadgroup.shutdownGracefully();
+        nettyThreadgroup.shutdownGracefully().await();
     }
 
     public NetconfClientConfiguration getClientConfiguration(final InetSocketAddress tcpAddress, final int timeout) {
         final NetconfClientConfigurationBuilder b = NetconfClientConfigurationBuilder.create();
         b.withAddress(tcpAddress);
         b.withSessionListener(new SimpleNetconfClientSessionListener());
-        b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE,
-                timeout));
+        b.withReconnectStrategy(new NeverReconnectStrategy(GlobalEventExecutor.INSTANCE, timeout));
         b.withConnectionTimeoutMillis(timeout);
         return b.build();
     }
+
+    public static final class HardcodedYangStoreService implements YangStoreService {
+
+        private final List<InputStream> byteArrayInputStreams;
+
+        public HardcodedYangStoreService(final Collection<? extends InputStream> inputStreams) throws YangStoreException, IOException {
+            byteArrayInputStreams = new ArrayList<>();
+            for (final InputStream inputStream : inputStreams) {
+                assertNotNull(inputStream);
+                final byte[] content = IOUtils.toByteArray(inputStream);
+                final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(content);
+                byteArrayInputStreams.add(byteArrayInputStream);
+            }
+        }
+
+        @Override
+        public YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException {
+            for (final InputStream inputStream : byteArrayInputStreams) {
+                try {
+                    inputStream.reset();
+                } catch (final IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+
+            final YangParserImpl yangParser = new YangParserImpl();
+            final SchemaContext schemaContext = yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values()));
+            final YangStoreServiceImpl yangStoreService = new YangStoreServiceImpl(new SchemaContextProvider() {
+                @Override
+                public SchemaContext getSchemaContext() {
+                    return schemaContext ;
+                }
+            });
+            return yangStoreService.getYangStoreSnapshot();
+        }
+    }
 }