From 70da33f00f68fe04e0baf51e592071096213eebd Mon Sep 17 00:00:00 2001 From: Joss Armstrong Date: Tue, 11 Dec 2018 16:57:24 +0000 Subject: Fix for APPC-1271 Replaced slow running tests which wait for timeout Testing time reduced from 22 seconds to 0.5 seconds Improved tests and line coverage increased from 26% to 96% Issue-ID: APPC-1271 Change-Id: I88713e5c819e5ce1bf695f6de3834db7c3007285 Signed-off-by: Joss Armstrong --- .../adapter/netconf/jsch/NetconfClientJsch.java | 19 ++- .../netconf/jsch/TestNetconfClientJsch.java | 158 +++++++++++++++++---- 2 files changed, 142 insertions(+), 35 deletions(-) (limited to 'appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src') diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/onap/appc/adapter/netconf/jsch/NetconfClientJsch.java b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/onap/appc/adapter/netconf/jsch/NetconfClientJsch.java index 92569d5e0..03c33d813 100644 --- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/onap/appc/adapter/netconf/jsch/NetconfClientJsch.java +++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/main/java/org/onap/appc/adapter/netconf/jsch/NetconfClientJsch.java @@ -5,6 +5,8 @@ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Copyright (C) 2017 Amdocs + * ================================================================================ + * Modifications Copyright (C) 2018 Ericsson * ============================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +31,8 @@ import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.List; import java.util.Properties; @@ -62,7 +66,7 @@ public class NetconfClientJsch implements NetconfClient { String password = connectionDetails.getPassword(); try { JSch.setLogger(new JSchLogger()); - JSch jsch = new JSch(); + JSch jsch = getJSch(); session = jsch.getSession(EncryptionTool.getInstance().decrypt(username), host, port); session.setPassword(EncryptionTool.getInstance().decrypt(password)); session.setConfig("StrictHostKeyChecking", "no"); @@ -131,10 +135,9 @@ public class NetconfClientJsch implements NetconfClient { private void createConnection(NetconfConnectionDetails connectionDetails) throws APPCException { try { -// session.setServerAliveCountMax(0); // If this is not set to '0', then socket timeout on all reads will not work!!!! channel = session.openChannel("subsystem"); ((ChannelSubsystem)channel).setSubsystem("netconf"); - netconfAdapter = new NetconfAdapter(channel.getInputStream(), channel.getOutputStream()); + netconfAdapter = getNetconfAdapter(channel.getInputStream(), channel.getOutputStream()); channel.connect(CHANNEL_CONNECT_TIMEOUT); hello(connectionDetails.getCapabilities()); } catch(Exception e) { @@ -146,7 +149,7 @@ public class NetconfClientJsch implements NetconfClient { private void hello(List capabilities) throws IOException { String helloIn = netconfAdapter.receiveMessage(); if(helloIn == null) { - throw new IOException("Expected hello message, but nothing received error from netconf device"); + throw new IOException("Expected hello message, but nothing received from netconf device"); } if(helloIn.contains("")) { throw new IOException("Expected hello message, but received error from netconf device:\n" + helloIn); @@ -172,4 +175,12 @@ public class NetconfClientJsch implements NetconfClient { throw new IOException("Error response from netconf device: \n" + response); } } + + protected JSch getJSch() { + return new JSch(); + } + + protected NetconfAdapter getNetconfAdapter(InputStream inputStream, OutputStream outputStream) throws IOException { + return new NetconfAdapter(inputStream, outputStream); + } } diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/test/java/org/onap/appc/adapter/netconf/jsch/TestNetconfClientJsch.java b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/test/java/org/onap/appc/adapter/netconf/jsch/TestNetconfClientJsch.java index fb44763df..088c5a022 100644 --- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/test/java/org/onap/appc/adapter/netconf/jsch/TestNetconfClientJsch.java +++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/src/test/java/org/onap/appc/adapter/netconf/jsch/TestNetconfClientJsch.java @@ -4,6 +4,8 @@ * ================================================================================ * Copyright (C) 2018 Samsung * ================================================================================ + * Modifications Copyright (C) 2018 Ericsson + * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -21,78 +23,172 @@ package org.onap.appc.adapter.netconf.jsch; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.isA; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; +import static org.junit.Assert.assertEquals; +import com.jcraft.jsch.ChannelSubsystem; +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; -import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; -import org.onap.appc.adapter.netconf.ConnectionDetails; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; import org.onap.appc.adapter.netconf.NetconfConnectionDetails; import org.onap.appc.adapter.netconf.internal.NetconfAdapter; import org.onap.appc.exceptions.APPCException; - +import org.powermock.reflect.Whitebox; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; import java.util.Properties; public class TestNetconfClientJsch { NetconfClientJsch netconfClientJsch; + private Session mockSession; + private JSch mockJSch; + private ChannelSubsystem mockChannel; + private InputStream mockInputStream; + private OutputStream mockOutputStream; + private NetconfAdapter mockNetconfAdapter; + + @Rule + public ExpectedException expectedEx = ExpectedException.none(); @Before public void SetUp() { - netconfClientJsch = new NetconfClientJsch(); + netconfClientJsch = Mockito.spy(new NetconfClientJsch()); } - @Test (expected = APPCException.class) - public void testConnect() throws APPCException, IOException { + private void setupForConnectTests() throws JSchException, IOException { + mockSession = Mockito.mock(Session.class); + mockJSch = Mockito.mock(JSch.class); + mockChannel = Mockito.mock(ChannelSubsystem.class); + mockInputStream = Mockito.mock(InputStream.class); + mockOutputStream = Mockito.mock(OutputStream.class); + mockNetconfAdapter = Mockito.mock(NetconfAdapter.class); + Mockito.doReturn(mockJSch).when(netconfClientJsch).getJSch(); + Mockito.doReturn(mockSession).when(mockJSch).getSession(Mockito.anyString(), + Mockito.anyString(), Mockito.anyInt()); + Mockito.doReturn(mockChannel).when(mockSession).openChannel("subsystem"); + Mockito.doReturn(mockInputStream).when(mockChannel).getInputStream(); + Mockito.doReturn(mockOutputStream).when(mockChannel).getOutputStream(); + Mockito.doReturn(mockNetconfAdapter).when(netconfClientJsch) + .getNetconfAdapter(Mockito.any(InputStream.class), Mockito.any(OutputStream.class)); + } + + @Test + public void testConnect() throws APPCException, IOException, JSchException { + setupForConnectTests(); + Mockito.doReturn("").when(mockNetconfAdapter).receiveMessage(); NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails(); connectionDetails.setHost("test"); connectionDetails.setPort(8080); connectionDetails.setUsername("test"); connectionDetails.setPassword("test"); + List capabilities = Arrays.asList( + "urn:ietf:params:netconf:base:1.1\r\n"); + connectionDetails.setCapabilities(capabilities); Properties additionalProperties = new Properties(); additionalProperties.setProperty("testKey1", "testParam1"); connectionDetails.setAdditionalProperties(additionalProperties); - netconfClientJsch.connect(connectionDetails); + Mockito.verify(mockNetconfAdapter).sendMessage( + Mockito.contains("urn:ietf:params:netconf:base:1.1")); } - @Test (expected = NullPointerException.class) - public void testExchangeMessage() throws APPCException, IOException { - String message = "test"; - - netconfClientJsch.exchangeMessage(message); + @Test + public void testConnectNullMessage() throws JSchException, IOException, APPCException { + setupForConnectTests(); + NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails(); + expectedEx.expect(APPCException.class); + expectedEx.expectMessage("Cannot establish connection to server"); + netconfClientJsch.connect(connectionDetails); } - @Test (expected = NullPointerException.class) - public void testConfigure() throws APPCException, IOException { - String message = "test"; - - netconfClientJsch.configure(message); + @Test + public void testConnectNullMessageNonNullResponse() + throws JSchException, IOException, APPCException { + setupForConnectTests(); + Mockito.doReturn("NOT NULL RESPONSE").when(mockNetconfAdapter).receiveMessage(); + Mockito.doThrow(new JSchException()).when(mockChannel).connect(10000); + NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails(); + expectedEx.expect(APPCException.class); + expectedEx.expectCause(allOf(isA(RuntimeException.class), + hasProperty("message", is("Error closing netconf device")))); + netconfClientJsch.connect(connectionDetails); } - @Test (expected = NullPointerException.class) - public void testConfigureOk() throws APPCException, IOException { - String message = ""; - - netconfClientJsch.configure(message); + @Test + public void testConnectErrorMessage() throws JSchException, IOException, APPCException { + setupForConnectTests(); + Mockito.doReturn("").when(mockNetconfAdapter).receiveMessage(); + NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails(); + expectedEx.expect(APPCException.class); + expectedEx + .expectCause(allOf(isA(RuntimeException.class), + hasProperty("cause", allOf(isA(IOException.class), + hasProperty("message", + containsString("Error response from netconf device:")), + hasProperty("message", containsString("")) + )))); + netconfClientJsch.connect(connectionDetails); } - @Test (expected = NullPointerException.class) - public void testConfigureNull() throws APPCException, IOException { - String message = null; - - netconfClientJsch.configure(message); + @Test + public void testConnectWithSuccessfulDisconnect() + throws JSchException, IOException, APPCException { + setupForConnectTests(); + Mockito.doThrow(new JSchException()).when(mockChannel).connect(10000); + Mockito.doReturn("").when(mockNetconfAdapter).receiveMessage(); + NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails(); + expectedEx.expect(APPCException.class); + expectedEx.expectCause(allOf(isA(APPCException.class), + hasProperty("message", is(JSchException.class.getName())))); + netconfClientJsch.connect(connectionDetails); } - @Test (expected = NullPointerException.class) - public void testGetConfigure() throws APPCException, IOException { + @Test + public void testGetConfiguration() throws IOException, APPCException { + mockNetconfAdapter = Mockito.mock(NetconfAdapter.class); + Whitebox.setInternalState(netconfClientJsch, "netconfAdapter", mockNetconfAdapter); + Mockito.doReturn("TEST RETURN VALUE").when(mockNetconfAdapter).receiveMessage(); + assertEquals("TEST RETURN VALUE", netconfClientJsch.getConfiguration()); + } + @Test + public void testGetConfigurationExceptionFlow() throws IOException, APPCException { + mockNetconfAdapter = Mockito.mock(NetconfAdapter.class); + Whitebox.setInternalState(netconfClientJsch, "netconfAdapter", mockNetconfAdapter); + Mockito.doThrow(new IOException()).when(mockNetconfAdapter).receiveMessage(); + expectedEx.expect(APPCException.class); + expectedEx.expectMessage(IOException.class.getName()); netconfClientJsch.getConfiguration(); } @Test - public void testDisconnect() throws APPCException, IOException { + public void testConfigure() throws IOException, APPCException { + mockNetconfAdapter = Mockito.mock(NetconfAdapter.class); + Whitebox.setInternalState(netconfClientJsch, "netconfAdapter", mockNetconfAdapter); + Mockito.doReturn("").when(mockNetconfAdapter).receiveMessage(); + netconfClientJsch.configure(null); + Mockito.verify(netconfClientJsch).exchangeMessage(null); + } - netconfClientJsch.disconnect(); + @Test + public void testConfigureExceptionFlow() throws IOException, APPCException { + mockNetconfAdapter = Mockito.mock(NetconfAdapter.class); + Whitebox.setInternalState(netconfClientJsch, "netconfAdapter", mockNetconfAdapter); + Mockito.doThrow(new IOException()).when(mockNetconfAdapter).receiveMessage(); + expectedEx.expect(APPCException.class); + expectedEx.expectMessage(IOException.class.getName()); + netconfClientJsch.configure(null); } } -- cgit 1.2.3-korg