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 <joss.armstrong@ericsson.com>
diff --git a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml
index 03143c5..b26a826 100644
--- a/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml
+++ b/appc-adapters/appc-netconf-adapter/appc-netconf-adapter-bundle/pom.xml
@@ -191,7 +191,12 @@
             <artifactId>jsch</artifactId>
             <version>0.1.54</version>
         </dependency>
-
+        <dependency>
+          <groupId>org.hamcrest</groupId>
+          <artifactId>hamcrest-all</artifactId>
+          <version>1.3</version>
+          <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
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 92569d5..03c33d8 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.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 @@
         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 @@
 
     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 @@
     private void hello(List<String> 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("<rpc-error>")) {
             throw new IOException("Expected hello message, but received error from netconf device:\n" + helloIn);
@@ -172,4 +175,12 @@
             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 fb44763..088c5a0 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("<hello>").when(mockNetconfAdapter).receiveMessage();
         NetconfConnectionDetails connectionDetails = new NetconfConnectionDetails();
         connectionDetails.setHost("test");
         connectionDetails.setPort(8080);
         connectionDetails.setUsername("test");
         connectionDetails.setPassword("test");
+        List<String> capabilities = Arrays.asList(
+            "<capability>urn:ietf:params:netconf:base:1.1</capability>\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("<capability>urn:ietf:params:netconf:base:1.1</capability>"));
+    }
 
+    @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 testExchangeMessage() throws APPCException, IOException {
-        String message = "test";
-
-        netconfClientJsch.exchangeMessage(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 testConfigure() throws APPCException, IOException {
-        String message = "test";
-
-        netconfClientJsch.configure(message);
+    @Test
+    public void testConnectErrorMessage() throws JSchException, IOException, APPCException {
+        setupForConnectTests();
+        Mockito.doReturn("<rpc-error>").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("<rpc-error>"))
+                        ))));
+        netconfClientJsch.connect(connectionDetails);
     }
 
-    @Test (expected = NullPointerException.class)
-    public void testConfigureOk() throws APPCException, IOException {
-        String message = "<ok/>";
-
-        netconfClientJsch.configure(message);
+    @Test
+    public void testConnectWithSuccessfulDisconnect()
+            throws JSchException, IOException, APPCException {
+        setupForConnectTests();
+        Mockito.doThrow(new JSchException()).when(mockChannel).connect(10000);
+        Mockito.doReturn("<ok/>").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 testConfigureNull() throws APPCException, IOException {
-        String message = null;
-
-        netconfClientJsch.configure(message);
+    @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 (expected = NullPointerException.class)
-    public void testGetConfigure() throws APPCException, IOException {
-
+    @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("<ok/>").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);
     }
 }