Add netconf-impl unit tests 13/47713/1
authorAndrej Mak <andrej.mak@pantheon.tech>
Fri, 28 Oct 2016 06:36:29 +0000 (08:36 +0200)
committerAndrej Mak <andrej.mak@pantheon.tech>
Fri, 28 Oct 2016 06:37:26 +0000 (08:37 +0200)
Change-Id: If36e4cee4de8635b6e361e0e6eb9809060f99dbd
Signed-off-by: Andrej Mak <andrej.mak@pantheon.tech>
netconf/netconf-impl/src/main/java/org/opendaylight/netconf/impl/osgi/NetconfOperationRouterImpl.java
netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionListenerTest.java [new file with mode: 0644]
netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionTest.java [new file with mode: 0644]

index 432390bc12a5b4d44f89153754ea81c6c13f3478..1e118129242522058a5deedef766136ae0d216ae 100644 (file)
@@ -148,21 +148,6 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return sortedPriority;
     }
 
-    public static final NetconfOperationChainedExecution EXECUTION_TERMINATION_POINT = new NetconfOperationChainedExecution() {
-        @Override
-        public boolean isExecutionTermination() {
-            return true;
-        }
-
-        @Override
-        public Document execute(final Document requestMessage) throws DocumentedException {
-            throw new DocumentedException("This execution represents the termination point in operation execution and cannot be executed itself",
-                    DocumentedException.ErrorType.APPLICATION,
-                    DocumentedException.ErrorTag.OPERATION_FAILED,
-                    DocumentedException.ErrorSeverity.ERROR);
-        }
-    };
-
     private static class NetconfOperationExecution implements NetconfOperationChainedExecution {
         private final NetconfOperation netconfOperation;
         private final NetconfOperationChainedExecution subsequentExecution;
diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionListenerTest.java b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionListenerTest.java
new file mode 100644 (file)
index 0000000..af514d1
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016 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.netconf.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import io.netty.channel.embedded.EmbeddedChannel;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.hamcrest.CustomMatcher;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.api.NetconfTerminationReason;
+import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
+import org.opendaylight.netconf.api.monitoring.SessionEvent;
+import org.opendaylight.netconf.api.monitoring.SessionListener;
+import org.opendaylight.netconf.impl.osgi.NetconfOperationRouter;
+import org.opendaylight.netconf.notifications.NetconfNotification;
+import org.w3c.dom.Document;
+
+public class NetconfServerSessionListenerTest {
+
+    @Mock
+    private NetconfOperationRouter router;
+    @Mock
+    private NetconfMonitoringService monitoring;
+    @Mock
+    private AutoCloseable closeable;
+    @Mock
+    private SessionListener monitoringListener;
+    private NetconfServerSession session;
+    private EmbeddedChannel channel;
+    private NetconfServerSessionListener listener;
+
+    @BeforeClass
+    public static void classSetUp() throws Exception {
+        XMLUnit.setIgnoreWhitespace(true);
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn(monitoringListener).when(monitoring).getSessionListener();
+        doNothing().when(monitoringListener).onSessionUp(any());
+        doNothing().when(monitoringListener).onSessionDown(any());
+        doNothing().when(monitoringListener).onSessionEvent(any());
+        channel = new EmbeddedChannel();
+        session = new NetconfServerSession(null, channel, 0L, null);
+        listener = new NetconfServerSessionListener(router, monitoring, closeable);
+    }
+
+    @Test
+    public void testOnSessionUp() throws Exception {
+        listener.onSessionUp(session);
+        verify(monitoringListener).onSessionUp(session);
+    }
+
+    @Test
+    public void testOnSessionDown() throws Exception {
+        final Exception cause = new RuntimeException("cause");
+        listener.onSessionDown(session, cause);
+        verify(monitoringListener).onSessionDown(session);
+        verify(closeable).close();
+        verify(router).close();
+    }
+
+    @Test
+    public void testOnSessionTerminated() throws Exception {
+        listener.onSessionTerminated(session, new NetconfTerminationReason("reason"));
+        verify(monitoringListener).onSessionDown(session);
+        verify(closeable).close();
+        verify(router).close();
+    }
+
+    @Test
+    public void testOnMessage() throws Exception {
+        final Document reply = XmlUtil.readXmlToDocument("<rpc-reply message-id=\"101\" " +
+                "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc-reply>");
+        doReturn(reply).when(router).onNetconfMessage(any(), any());
+        final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"101\" " +
+                "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc>"));
+        listener.onMessage(session, msg);
+        verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_SUCCESS)));
+        channel.runPendingTasks();
+        final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
+        final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
+        Assert.assertTrue(diff.toString(), diff.similar());
+    }
+
+    @Test
+    public void testOnMessageRuntimeFail() throws Exception {
+        doThrow(new RuntimeException("runtime fail")).when(router).onNetconfMessage(any(), any());
+        final Document reply =
+                XmlUtil.readXmlToDocument("<rpc message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" +
+                        "<example/></rpc>");
+        final NetconfMessage msg = new NetconfMessage(reply);
+        try {
+            listener.onMessage(session, msg);
+            Assert.fail("Expected exception " + IllegalStateException.class);
+        } catch (final IllegalStateException e) {
+            verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
+        }
+    }
+
+    @Test
+    public void testOnMessageDocumentedFail() throws Exception {
+        final Document reply =
+                XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
+                        "<rpc-error>\n" +
+                        "<error-type>PROTOCOL</error-type>\n" +
+                        "<error-tag>unknown-element</error-tag>\n" +
+                        "<error-severity>ERROR</error-severity>\n" +
+                        "<error-message>Unknown tag bad-rpc in message:\n" +
+                        "&lt;bad-rpc/&gt;\n" +
+                        "</error-message>\n" +
+                        "<error-info>\n" +
+                        "<bad-element>bad-rpc</bad-element>\n" +
+                        "</error-info>\n" +
+                        "</rpc-error>\n" +
+                        "</rpc-reply>");
+        final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<bad-rpc/>"));
+        listener.onMessage(session, msg);
+        verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
+        verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.OUT_RPC_ERROR)));
+        channel.runPendingTasks();
+        final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
+        System.out.println(XmlUtil.toString(sentMsg.getDocument()));
+        System.out.println(XmlUtil.toString(reply));
+        final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
+        Assert.assertTrue(diff.toString(), diff.similar());
+    }
+
+    @Test
+    public void testOnNotification() throws Exception {
+        listener.onNotification(session, new NetconfNotification(XmlUtil.readXmlToDocument("<notification/>")));
+        verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.NOTIFICATION)));
+    }
+
+    private CustomMatcher<SessionEvent> sessionEventIs(final SessionEvent.Type type) {
+        return new CustomMatcher<SessionEvent>(type.name()) {
+            @Override
+            public boolean matches(final Object item) {
+                if (!(item instanceof SessionEvent)) {
+                    return false;
+                }
+                final SessionEvent e = (SessionEvent) item;
+                return e.getType().equals(type) && e.getSession().equals(session);
+            }
+        };
+    }
+
+}
\ No newline at end of file
diff --git a/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionTest.java b/netconf/netconf-impl/src/test/java/org/opendaylight/netconf/impl/NetconfServerSessionTest.java
new file mode 100644 (file)
index 0000000..84603bc
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016 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.netconf.impl;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelOutboundHandlerAdapter;
+import io.netty.channel.embedded.EmbeddedChannel;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.util.xml.XmlUtil;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.netconf.nettyutil.AbstractChannelInitializer;
+import org.opendaylight.netconf.nettyutil.handler.NetconfEXICodec;
+import org.opendaylight.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
+import org.opendaylight.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
+import org.opendaylight.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
+import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
+import org.opendaylight.netconf.notifications.NetconfNotification;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
+import org.openexi.proc.common.EXIOptions;
+import org.w3c.dom.Document;
+
+public class NetconfServerSessionTest {
+
+    private static final String HOST = "127.0.0.1";
+    private static final String PORT = "17830";
+    private static final String SSH_TRANSPORT = "ssh";
+    private static final String TCP_TRANSPORT = "tcp";
+    private static final String SESSION_ID = "1";
+    private static final String USER = "admin";
+    private NetconfServerSession session;
+    private EmbeddedChannel channel;
+    private NetconfMessage msg;
+    @Mock
+    private NetconfServerSessionListener listener;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        final NetconfHelloMessageAdditionalHeader header =
+                new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, SSH_TRANSPORT, SESSION_ID);
+        channel = new EmbeddedChannel();
+        session = new NetconfServerSession(listener, channel, 1L, header);
+        doNothing().when(listener).onSessionUp(any());
+        msg = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc-reply></rpc-reply>"));
+    }
+
+    @Test
+    public void testSessionUp() throws Exception {
+        session.sessionUp();
+        verify(listener).onSessionUp(session);
+    }
+
+    @Test
+    public void testDelayedClose() throws Exception {
+        doNothing().when(listener).onSessionTerminated(eq(session), any());
+        session.delayedClose();
+        session.sendMessage(msg);
+        channel.runPendingTasks();
+        final Object o = channel.readOutbound();
+        Assert.assertEquals(msg, o);
+        verify(listener).onSessionTerminated(eq(session), any());
+    }
+
+    @Test
+    public void testSendMessage() throws Exception {
+        session.sendMessage(msg);
+        channel.runPendingTasks();
+        final Object o = channel.readOutbound();
+        Assert.assertEquals(msg, o);
+    }
+
+    @Test
+    public void testSendNotification() throws Exception {
+        doNothing().when(listener).onNotification(any(), any());
+        final Document msgDoc = XmlUtil.readXmlToDocument("<notification></notification>");
+        final NetconfNotification msg = new NetconfNotification(msgDoc);
+        session.sendMessage(msg);
+        channel.runPendingTasks();
+        final Object o = channel.readOutbound();
+        Assert.assertEquals(msg, o);
+        verify(listener).onNotification(session, msg);
+    }
+
+    @Test
+    public void testOnIncommingRpcSuccess() throws Exception {
+        session.sessionUp();
+        final Session managementSession = this.session.toManagementSession();
+        this.session.onIncommingRpcSuccess();
+        final Session afterRpcSuccess = this.session.toManagementSession();
+        Assert.assertEquals(managementSession.getInRpcs().getValue() + 1,
+                afterRpcSuccess.getInRpcs().getValue().longValue());
+    }
+
+    @Test
+    public void testOnIncommingRpcFail() throws Exception {
+        session.sessionUp();
+        final Session managementSession = this.session.toManagementSession();
+        this.session.onIncommingRpcFail();
+        final Session afterRpcSuccess = this.session.toManagementSession();
+        Assert.assertEquals(managementSession.getInBadRpcs().getValue() + 1,
+                afterRpcSuccess.getInBadRpcs().getValue().longValue());
+    }
+
+    @Test
+    public void testOnOutgoingRpcError() throws Exception {
+        session.sessionUp();
+        final Session managementSession = this.session.toManagementSession();
+        this.session.onOutgoingRpcError();
+        final Session afterRpcSuccess = this.session.toManagementSession();
+        Assert.assertEquals(managementSession.getOutRpcErrors().getValue() + 1,
+                afterRpcSuccess.getOutRpcErrors().getValue().longValue());
+    }
+
+    @Test
+    public void testToManagementSession() throws Exception {
+        final NetconfHelloMessageAdditionalHeader header =
+                new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, TCP_TRANSPORT, SESSION_ID);
+        final EmbeddedChannel channel = new EmbeddedChannel();
+        final NetconfServerSession tcpSession = new NetconfServerSession(listener, channel, 1L, header);
+        tcpSession.sessionUp();
+        final Session managementSession = tcpSession.toManagementSession();
+        Assert.assertEquals(new String(managementSession.getSourceHost().getValue()), HOST);
+        Assert.assertEquals(managementSession.getUsername(), USER);
+        Assert.assertEquals(managementSession.getSessionId().toString(), SESSION_ID);
+        Assert.assertEquals(managementSession.getTransport(), NetconfTcp.class);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testToManagementSessionUnknownTransport() throws Exception {
+        final NetconfHelloMessageAdditionalHeader header =
+                new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, "http", SESSION_ID);
+        final EmbeddedChannel channel = new EmbeddedChannel();
+        final NetconfServerSession tcpSession = new NetconfServerSession(listener, channel, 1L, header);
+        tcpSession.sessionUp();
+        tcpSession.toManagementSession();
+    }
+
+    @Test
+    public void testToManagementSessionIpv6() throws Exception {
+        final NetconfHelloMessageAdditionalHeader header =
+                new NetconfHelloMessageAdditionalHeader(USER, "::1", PORT, SSH_TRANSPORT, SESSION_ID);
+        final EmbeddedChannel channel = new EmbeddedChannel();
+        final NetconfServerSession tcpSession = new NetconfServerSession(listener, channel, 1L, header);
+        tcpSession.sessionUp();
+        final Session managementSession = tcpSession.toManagementSession();
+        Assert.assertEquals(new String(managementSession.getSourceHost().getValue()), "::1");
+        Assert.assertEquals(managementSession.getUsername(), USER);
+        Assert.assertEquals(managementSession.getSessionId().toString(), SESSION_ID);
+        Assert.assertEquals(managementSession.getTransport(), NetconfSsh.class);
+    }
+
+    @Test
+    public void testThisInstance() throws Exception {
+        Assert.assertEquals(session, session.thisInstance());
+    }
+
+    @Test
+    public void testAddExiHandlers() throws Exception {
+        channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER,
+                new NetconfXMLToMessageDecoder());
+        channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER,
+                new NetconfMessageToXMLEncoder());
+        final NetconfEXICodec codec = new NetconfEXICodec(new EXIOptions());
+        session.addExiHandlers(NetconfEXIToMessageDecoder.create(codec), NetconfMessageToEXIEncoder.create(codec));
+    }
+
+    @Test
+    public void testStopExiCommunication() throws Exception {
+        channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER,
+                new ChannelInboundHandlerAdapter());
+        channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER,
+                new ChannelOutboundHandlerAdapter());
+        session.stopExiCommunication();
+        //handler is replaced only after next send message call
+        final ChannelHandler exiEncoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER);
+        Assert.assertTrue(ChannelOutboundHandlerAdapter.class.equals(exiEncoder.getClass()));
+        session.sendMessage(msg);
+        channel.runPendingTasks();
+        final ChannelHandler decoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER);
+        Assert.assertTrue(NetconfXMLToMessageDecoder.class.equals(decoder.getClass()));
+        final ChannelHandler encoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER);
+        Assert.assertTrue(NetconfMessageToXMLEncoder.class.equals(encoder.getClass()));
+    }
+
+}
\ No newline at end of file