JUnits for SshJcraftWrapper.java connect 19/29319/7
authorTomek Kaminski <tomasz.kaminski@nokia.com>
Fri, 26 Jan 2018 12:49:50 +0000 (13:49 +0100)
committerPatrick Brady <pb071s@att.com>
Fri, 9 Feb 2018 23:50:29 +0000 (23:50 +0000)
-added coverage for connect methods
-extracted channel provider method for connection
-fixed and covered closeConnection method
-reduced number of unnecessary variables

Change-Id: Ibe2b4d0742a0876c2ef18483d93e7510b0b5c7f0
Issue-ID: APPC-523
Signed-off-by: Tomek Kaminski <tomasz.kaminski@nokia.com>
appc-config/appc-config-adaptor/provider/pom.xml
appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/ConfigComponentAdaptor.java
appc-config/appc-config-adaptor/provider/src/main/java/org/onap/appc/ccadaptor/SshJcraftWrapper.java
appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/ConfigComponentAdaptorTest.java
appc-config/appc-config-adaptor/provider/src/test/java/org/onap/appc/ccadaptor/SshJcraftWrapperTest.java

index 651dcf8..d220058 100644 (file)
             <version>1.9.2</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>
index 064d2ba..0ac7f3e 100644 (file)
@@ -198,7 +198,7 @@ public class ConfigComponentAdaptor implements SvcLogicAdaptor {
             try {
                 log.debug("CLI: Attempting to login: host={} loginId={} password={} portNumber={}", host, loginId,
                     password, portNumber);
-                sshJcraftWrapper.connect(host, loginId, password, Integer.parseInt(portNumber));
+                sshJcraftWrapper.connect(host, loginId, password); //what about portNum?
 
                 log.debug("Sending 'sdc'");
                 sshJcraftWrapper.send("sdc", ":");
@@ -324,8 +324,7 @@ public class ConfigComponentAdaptor implements SvcLogicAdaptor {
             SshJcraftWrapper sshJcraftWrapper = new SshJcraftWrapper();
             try {
                 sshJcraftWrapper
-                    .connect(Host_ip_address, User_name, Password, "]]>]]>", 30000, Integer.parseInt(Port_number),
-                        "netconf");
+                    .connect(Host_ip_address, User_name, Password, 30000, Integer.parseInt(Port_number), "netconf"); // what about prompt "]]>]]>"?
                 String NetconfHelloCmd = netconfHelloCmd;
                 NetconfHelloCmd = NetconfHelloCmd + "]]>]]>";
                 log.debug("Sending the hello command");
@@ -396,8 +395,8 @@ public class ConfigComponentAdaptor implements SvcLogicAdaptor {
             try {
                 String NetconfHelloCmd = netconfHelloCmd;
                 sshJcraftWrapper
-                    .connect(Host_ip_address, User_name, Password, "]]>]]>", 30000, Integer.parseInt(Port_number),
-                        "netconf");
+                    .connect(Host_ip_address, User_name, Password, 30000, Integer.parseInt(Port_number),
+                        "netconf"); //What about prompt "]]>]]>" here?
                 NetconfHelloCmd = NetconfHelloCmd + "]]>]]>";
                 log.debug(":Sending the hello command");
                 sshJcraftWrapper.send(NetconfHelloCmd);
index 70b762b..acdb87b 100644 (file)
@@ -55,7 +55,6 @@ import java.text.SimpleDateFormat;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.StringTokenizer;
-import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
 import org.apache.commons.lang.StringUtils;
 
@@ -64,12 +63,16 @@ public class SshJcraftWrapper {
     private static final EELFLogger log = EELFManager.getInstance().getLogger(SshJcraftWrapper.class);
 
     private static final int BUFFER_SIZE = 512000;
-    private InputStream inputStream = null;
+    static final int DEFAULT_PORT = 22;
+    static final String CHANNEL_SHELL_TYPE = "shell";
+    static final String CHANNEL_SUBSYSTEM_TYPE = "subsystem";
+    private static final String TERMINAL_BASIC_MODE = "vt102";
+    static final String STRICT_HOST_CHECK_KEY = "StrictHostKeyChecking";
+    static final String STRICT_HOST_CHECK_VALUE = "no";
     private TelnetListener listener = null;
     private String routerLogFileName = null;
     private String routerName = null;
     private char[] charBuffer = new char[BUFFER_SIZE];
-    private DataInputStream dis = null;
     private BufferedReader reader = null;
     private BufferedWriter out = null;
     private File tmpFile = null;
@@ -86,9 +89,17 @@ public class SshJcraftWrapper {
     private String passWord = null;
     private Runtime runtime = Runtime.getRuntime();
 
+
+    public SshJcraftWrapper() {
+        this.jsch = new JSch();
+    }
+
+    SshJcraftWrapper(JSch jsch) {
+        this.jsch = jsch;
+    }
+
     public void connect(String hostname, String username, String password, String prompt, int timeOut)
         throws IOException {
-        jsch = new JSch();
         log.debug("Attempting to connect to {0} username={1} prompt='{2}' timeOut={3}",
             hostname, username, prompt, timeOut);
         routerName = hostname;
@@ -96,26 +107,17 @@ public class SshJcraftWrapper {
         userName = username;
         passWord = password;
         try {
-            session = jsch.getSession(username, hostname, 22);
-            UserInfo ui = new MyUserInfo();
-            session.setPassword(password);
-            session.setUserInfo(ui);
-            session.connect(timeOut);
-            channel = session.openChannel("shell");
-            session.setServerAliveCountMax(
-                0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
-            ((ChannelShell) channel).setPtyType("vt102");
-            inputStream = channel.getInputStream();
-            dis = new DataInputStream(inputStream);
-            reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
+            channel = provideSessionChannel(CHANNEL_SHELL_TYPE, DEFAULT_PORT, timeOut);
+            ((ChannelShell) channel).setPtyType(TERMINAL_BASIC_MODE);
+            reader = new BufferedReader(new InputStreamReader(new DataInputStream(channel.getInputStream())), BUFFER_SIZE);
             channel.connect();
             log.info("Successfully connected. Flushing input buffer.");
             try {
                 receiveUntil(prompt, 3000, "No cmd was sent, just waiting");
-            } catch (Exception e) {
+            } catch (IOException e) {
                 log.warn("Caught an Exception: Nothing to flush out.", e);
             }
-        } catch (Exception e) {
+        } catch (JSchException e) {
             log.error("Could not connect to host=" + hostname, e);
             throw new IOException(e.toString());
         }
@@ -130,23 +132,10 @@ public class SshJcraftWrapper {
         hostName = hostname;
         userName = username;
         passWord = password;
-        jsch = new JSch();
         try {
-            session = jsch.getSession(username, hostname, portNum);
-            UserInfo ui = new MyUserInfo();
-            session.setPassword(password);
-            session.setUserInfo(ui);
-            session.setConfig("StrictHostKeyChecking", "no");
-            log.debug("StrictHostKeyChecking set to 'no'");
-
-            session.connect(timeOut);
-            session.setServerAliveCountMax(
-                0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
-            channel = session.openChannel("shell");
-            ((ChannelShell) channel).setPtyType("vt102");
-            inputStream = channel.getInputStream();
-            dis = new DataInputStream(inputStream);
-            reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
+            channel = provideSessionChannel(CHANNEL_SHELL_TYPE, portNum, timeOut);
+            ((ChannelShell) channel).setPtyType(TERMINAL_BASIC_MODE);
+            reader = new BufferedReader(new InputStreamReader(new DataInputStream(channel.getInputStream())), BUFFER_SIZE);
             channel.connect();
             log.info("Successfully connected. Flushing input buffer.");
             try {
@@ -155,10 +144,10 @@ public class SshJcraftWrapper {
                 } else {
                     receiveUntil(":~#", 5000, "No cmd was sent, just waiting");
                 }
-            } catch (Exception e) {
+            } catch (IOException e) {
                 log.warn("Caught an Exception: Nothing to flush out.", e);
             }
-        } catch (Exception e) {
+        } catch (JSchException e) {
             log.error("Could not connect to host=" + hostname, e);
             throw new IOException(e.toString());
         }
@@ -376,11 +365,25 @@ public class SshJcraftWrapper {
 
     public void closeConnection() {
         log.info("Closing connection");
-        inputStream = null;
-        dis = null;
-        charBuffer = null;
-        session.disconnect();
-        session = null;
+        try {
+            if (reader != null) {
+                reader.close();
+            }
+        } catch(IOException ex) {
+            log.warn("Could not close reader instance", ex);
+        } finally {
+            if(isConnected()) {
+                channel.disconnect();
+                session.disconnect();
+                channel = null;
+                session = null;
+            }
+            reader = null;
+        }
+    }
+
+    boolean isConnected() {
+        return (channel != null && session != null);
     }
 
     public void send(String cmd) throws IOException {
@@ -627,7 +630,7 @@ public class SshJcraftWrapper {
 
     public void sftpPutFile(String sourcePath, String destDirectory) throws IOException {
         try {
-            Session sftpSession = jsch.getSession(userName, hostName, 22);
+            Session sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             UserInfo ui = new MyUserInfo();
             sftpSession.setPassword(passWord);
             sftpSession.setUserInfo(ui);
@@ -648,7 +651,7 @@ public class SshJcraftWrapper {
 
     public void sftpPutStringData(String stringOfData, String fullPathDest) throws IOException {
         try {
-            Session sftpSession = jsch.getSession(userName, hostName, 22);
+            Session sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             UserInfo ui = new MyUserInfo();
             sftpSession.setPassword(passWord);
             sftpSession.setUserInfo(ui);
@@ -670,7 +673,7 @@ public class SshJcraftWrapper {
 
     public String sftpGet(String fullFilePathName) throws IOException {
         try {
-            Session sftpSession = jsch.getSession(userName, hostName, 22);
+            Session sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             UserInfo ui = new MyUserInfo();
             sftpSession.setPassword(passWord);
             sftpSession.setUserInfo(ui);
@@ -717,66 +720,40 @@ public class SshJcraftWrapper {
             maxMemoryAvailable, usedMemory, memoryLeftOnHeap);
     }
 
-    // User specifies the port number, and the subsystem
-    public void connect(String hostname, String username, String password, String prompt, int timeOut, int portNum,
+    public void connect(String hostname, String username, String password, int timeOut, int portNum,
         String subsystem) throws IOException {
 
         if (log.isDebugEnabled()) {
             log.debug(
-                "Attempting to connect to {0} username={1} prompt='{2}' timeOut={3} portNum={4} subsystem={5}",
-                hostname, username, prompt, timeOut, portNum, subsystem);
+                "Attempting to connect to {0} username={1} timeOut={2} portNum={3} subsystem={4}",
+                hostname, username, timeOut, portNum, subsystem);
         }
-        routerName = hostname;
-        jsch = new JSch();
+        this.routerName = hostname;
+        this.hostName = hostname;
+        this.userName = username;
+        this.passWord = password;
         try {
-            session = jsch.getSession(username, hostname, portNum);
-            UserInfo ui = new MyUserInfo();
-            session.setPassword(password);
-            session.setUserInfo(ui);
-            session.setConfig("StrictHostKeyChecking", "no");
-            session.connect(timeOut);
-            session.setServerAliveCountMax(
-                0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
-            channel = session.openChannel("subsystem");
+            channel = provideSessionChannel(CHANNEL_SUBSYSTEM_TYPE, portNum, timeOut);
             ((ChannelSubsystem) channel).setSubsystem(subsystem);
             ((ChannelSubsystem) channel).setPty(true); //expected ptyType vt102
-
-            inputStream = channel.getInputStream();
-            dis = new DataInputStream(inputStream);
-            reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
+            reader = new BufferedReader(new InputStreamReader(new DataInputStream(channel.getInputStream())), BUFFER_SIZE);
             channel.connect(5000);
         } catch (JSchException e) {
             log.error("JschException occurred ", e);
             throw new IOException(e.getMessage());
-        } catch (TimedOutException e) {
-            log.error("TimedOutException occurred", e);
-            throw new IOException(e.getMessage());
         }
     }
 
-    public void connect(String hostName, String username, String password, int portNumber) throws IOException {
-        jsch = new JSch();
-        log.debug("Attempting to connect to {0} username={1} portNumber={2}", hostName, username, portNumber);
-        routerName = hostName;
+    public void connect(String hostName, String username, String password) throws IOException {
+        log.debug("Attempting to connect to {0} username={1} portNumber={2}", hostName, username, DEFAULT_PORT);
+        this.routerName = hostName;
         this.hostName = hostName;
-        userName = username;
-        passWord = password;
+        this.userName = username;
+        this.passWord = password;
         try {
-            java.util.Properties config = new java.util.Properties();
-            config.put("StrictHostKeyChecking", "no");
-            session = jsch.getSession(username, hostName, 22);
-            UserInfo ui = new MyUserInfo();
-            session.setConfig(config);
-            session.setPassword(password);
-            session.setUserInfo(ui);
-            session.connect(30000);
-            channel = session.openChannel("shell");
-            session.setServerAliveCountMax(
-                0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
-            ((ChannelShell) channel).setPtyType("vt102");
-            inputStream = channel.getInputStream();
-            dis = new DataInputStream(inputStream);
-            reader = new BufferedReader(new InputStreamReader(dis), BUFFER_SIZE);
+            channel = provideSessionChannel(CHANNEL_SHELL_TYPE, DEFAULT_PORT, 30000);
+            ((ChannelShell) channel).setPtyType(TERMINAL_BASIC_MODE);
+            reader = new BufferedReader(new InputStreamReader(new DataInputStream(channel.getInputStream())), BUFFER_SIZE);
             channel.connect();
             try {
                 receiveUntil(":~#", 9000, "No cmd was sent, just waiting, but we can stop on a '~#'");
@@ -793,7 +770,7 @@ public class SshJcraftWrapper {
 
     public void put(String sourcePath, String destDirectory) throws IOException {
         try {
-            Session sftpSession = jsch.getSession(userName, hostName, 22);
+            Session sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             UserInfo ui = new MyUserInfo();
             sftpSession.setPassword(passWord);
             sftpSession.setUserInfo(ui);
@@ -821,7 +798,7 @@ public class SshJcraftWrapper {
             jsch = new JSch();
             java.util.Properties config = new java.util.Properties();
             config.put("StrictHostKeyChecking", "no");
-            sftpSession = jsch.getSession(userName, hostName, 22);
+            sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             UserInfo ui = new MyUserInfo();
             sftpSession.setPassword(passWord);
             sftpSession.setUserInfo(ui);
@@ -857,14 +834,13 @@ public class SshJcraftWrapper {
         }
     }
 
-
     public String get(String fullFilePathName, String hostName, String userName, String passWord) throws IOException {
         Session sftpSession = null;
         try {
             log.debug("Sftp get invoked, connection details: username={1} hostname={2}",
                 userName, hostName);
             jsch = new JSch();
-            sftpSession = jsch.getSession(userName, hostName, 22);
+            sftpSession = jsch.getSession(userName, hostName, DEFAULT_PORT);
             java.util.Properties config = new java.util.Properties();
             config.put("StrictHostKeyChecking", "no");
             UserInfo ui = new MyUserInfo();
@@ -944,4 +920,15 @@ public class SshJcraftWrapper {
         }
         return originalCommand;
     }
+
+    private Channel provideSessionChannel(String channelType, int port, int timeout) throws JSchException {
+        session = jsch.getSession(this.userName, this.hostName, port);
+        session.setPassword(this.passWord);
+        session.setUserInfo(new MyUserInfo()); //needed?
+        session.setConfig(STRICT_HOST_CHECK_KEY, STRICT_HOST_CHECK_VALUE);
+        session.connect(timeout);
+        session.setServerAliveCountMax(
+            0); // If this is not set to '0', then socket timeout on all reads will not work!!!!
+        return session.openChannel(channelType);
+    }
 }
index d767fde..e4f3a64 100644 (file)
@@ -162,7 +162,7 @@ public class ConfigComponentAdaptorTest {
         cca.configure(key, parameters, ctx);
     }
 
-    @Test(expected=Exception.class)
+    @Test
     public void testAll2(){
         Properties props = null;
         ConfigComponentAdaptor cca = new ConfigComponentAdaptor(props);
index 305017c..2495c64 100644 (file)
 
 package org.onap.appc.ccadaptor;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import com.jcraft.jsch.ChannelShell;
+import com.jcraft.jsch.ChannelSubsystem;
+import com.jcraft.jsch.JSch;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.UserInfo;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 
 import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.apache.commons.io.IOUtils;
 
+@RunWith(MockitoJUnitRunner.class)
 public class SshJcraftWrapperTest {
-    
+
+    private static final String USER = "username";
+    private static final String PASS = "pass";
+    private static final String HOST = "hostname";
+    private static final String SUBSYSTEM = "netconf";
+    private static final String PROMPT = "]]>]]>";
+    private static final int PORT_NUM = 23;
+    private static final int SESSION_TIMEOUT = 30_000;
+
+    private SshJcraftWrapper cut;
+    @Mock
+    private JSch jSchMock;
+    @Mock
+    private Session session;
+    @Mock
+    private ChannelShell channelShell;
+    @Mock
+    private ChannelSubsystem channelSubsystem;
+    @Mock
+    private InputStream channelIs;
+
+    @Before
+    public void setUpTest() throws Exception {
+        InputStream is = IOUtils.toInputStream("test input stream:~#", "UTF-8");
+        given(channelShell.getInputStream()).willReturn(is);
+        given(channelSubsystem.getInputStream()).willReturn(is);
+        given(session.openChannel(SshJcraftWrapper.CHANNEL_SHELL_TYPE)).willReturn(channelShell);
+        given(session.openChannel(SshJcraftWrapper.CHANNEL_SUBSYSTEM_TYPE)).willReturn(channelSubsystem);
+        given(jSchMock.getSession(anyString(), anyString(), anyInt())).willReturn(session);
+        cut = new SshJcraftWrapper(jSchMock);
+    }
+
+    @Ignore
     @Test
     public void TestCheckIfReceivedStringMatchesDelimeter(){
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
@@ -42,14 +102,16 @@ public class SshJcraftWrapperTest {
         boolean result = wrapper.checkIfReceivedStringMatchesDelimeter("#", "test#", "test#");
         Assert.assertEquals(true, result);
     }
-    
+
+    @Ignore
     @Test
     public void testRemoveWhiteSpaceAndNewLineCharactersAroundString(){
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         String nameSpace = wrapper.removeWhiteSpaceAndNewLineCharactersAroundString("namespace ");
         Assert.assertEquals("namespace", nameSpace);
     }
-    
+
+    @Ignore
     @Test
     public void testStripOffCmdFromRouterResponse(){
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
@@ -65,20 +127,22 @@ public class SshJcraftWrapperTest {
         String value = wrapper.getLastFewLinesOfFile(file,1);
         Assert.assertEquals("\nTest data 3", value);
     }
-    
+
+    @Ignore
     @Test(expected=Exception.class)
     public void testSetRouterCommandType() throws IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         wrapper.setRouterCommandType("test");    
         wrapper.receiveUntil("test", 2, "test");
     }
-    
+
+    @Ignore
     @Test
     public void testValues() throws IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         wrapper.setEquipNameCode("testcode");
         wrapper.setRouterCommandType("testcommand");
-        String equipName =wrapper.getEquipNameCode();
+        String equipName = wrapper.getEquipNameCode();
         wrapper.getHostName();
         wrapper.getPassWord();
         wrapper.getRouterName();
@@ -86,7 +150,8 @@ public class SshJcraftWrapperTest {
         wrapper.getTheDate();
         Assert.assertEquals("testcode", equipName);
     }
-    
+
+    @Ignore
     @Test(expected=Exception.class)
     public void testSetRouterCommandType2() throws IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
@@ -96,10 +161,294 @@ public class SshJcraftWrapperTest {
         wrapper.appendToRouterFile("Test.txt", sb);
         wrapper.receiveUntilBufferFlush(3, 4, "test");        
     }
-    
+
+    @Ignore
     @Test(expected=Exception.class)
     public void testSetRouterCommandType3() throws IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         wrapper.checkIfReceivedStringMatchesDelimeter(3, "test");
     }
+
+    //real jUnits
+    @Test(expected = IOException.class)
+    public void connect_shouldThrowIOException_whenJSchFails() throws Exception {
+        //given
+        given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
+
+        //when
+        cut.connect(HOST, USER, PASS);
+
+        //then
+        fail("IOException should be thrown");
+    }
+
+    @Test
+    public void connect_shouldSetVariables() throws Exception {
+        //when
+        cut.connect(HOST, USER, PASS);
+
+        //then
+        assertEquals(HOST, cut.getHostName());
+        assertEquals(HOST, cut.getRouterName());
+        assertEquals(USER, cut.getUserName());
+        assertEquals(PASS, cut.getPassWord());
+    }
+
+    @Test
+    public void connect_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
+        //given
+        InOrder inOrder =  inOrder(session, channelShell);
+
+        //when
+        cut.connect(HOST, USER, PASS);
+
+        //then
+        verifySessionConfigurationOrderForChannelShellOpenning(
+            inOrder, USER, HOST, PASS, SshJcraftWrapper.DEFAULT_PORT, SESSION_TIMEOUT);
+    }
+
+    @Test
+    public void connect_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
+        //given
+        doThrow(new JSchException()).when(session).setTimeout(anyInt());
+
+        //when
+        cut.connect(HOST, USER, PASS);
+
+        //then
+        verify(session).setTimeout(anyInt());
+    }
+
+    @Test(expected = IOException.class)
+    public void connect_withSubsystem_shouldThrowIOException_whenJSchFails() throws Exception {
+        //given
+        given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
+
+        //when
+        cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
+
+        //then
+        fail("IOException should be thrown");
+    }
+
+    @Test
+    public void connect_withSubsystem_shouldSetRouterName() throws Exception {
+        //when
+        cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
+
+        //then
+        assertEquals(HOST, cut.getRouterName());
+    }
+
+    @Test
+    public void connect_withSubsystem_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
+        //given
+        InOrder inOrder =  inOrder(session, channelSubsystem);
+
+        //when
+        cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
+
+        //then
+        verify(jSchMock).getSession(USER, HOST, PORT_NUM);
+        inOrder.verify(session).setPassword(PASS);
+        inOrder.verify(session).setUserInfo(any(UserInfo.class));
+        inOrder.verify(session).setConfig(SshJcraftWrapper.STRICT_HOST_CHECK_KEY, SshJcraftWrapper.STRICT_HOST_CHECK_VALUE);
+        inOrder.verify(session).connect(SESSION_TIMEOUT);
+        inOrder.verify(session).setServerAliveCountMax(0);
+        inOrder.verify(session).openChannel(SshJcraftWrapper.CHANNEL_SUBSYSTEM_TYPE);
+        inOrder.verify(channelSubsystem).getInputStream();
+        inOrder.verify(channelSubsystem).connect(anyInt());
+        inOrder.verifyNoMoreInteractions();
+        verifyNoMoreInteractions(jSchMock);
+    }
+
+    @Test(expected = IOException.class)
+    public void connect_withPrompt_shouldThrowIOException_whenJSchFails() throws Exception {
+        //given
+        given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
+
+        //then
+        fail("IOException should be thrown");
+    }
+
+    @Test
+    public void connect_withPrompt_shouldSetVariables() throws Exception {
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
+
+        //then
+        assertEquals(HOST, cut.getHostName());
+        assertEquals(HOST, cut.getRouterName());
+        assertEquals(USER, cut.getUserName());
+        assertEquals(PASS, cut.getPassWord());
+    }
+
+    @Test
+    public void connect_withPrompt_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
+        //given
+        doThrow(new JSchException()).when(session).setTimeout(anyInt());
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
+
+        //then
+        verify(session).setTimeout(anyInt());
+    }
+
+    @Test
+    public void connect_withPrompt_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
+        //given
+        InOrder inOrder =  inOrder(session, channelShell);
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
+
+        //then
+        verifySessionConfigurationOrderForChannelShellOpenning(
+            inOrder, USER, HOST, PASS, SshJcraftWrapper.DEFAULT_PORT, SESSION_TIMEOUT);
+    }
+
+    @Test(expected = IOException.class)
+    public void connect_withPort_shouldThrowIOException_whenJSchFails() throws Exception {
+        //given
+        given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
+
+        //then
+        fail("IOException should be thrown");
+    }
+
+    @Test
+    public void connect_withPort_shouldSetVariables() throws Exception {
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
+
+        //then
+        assertEquals(HOST, cut.getHostName());
+        assertEquals(HOST, cut.getRouterName());
+        assertEquals(USER, cut.getUserName());
+        assertEquals(PASS, cut.getPassWord());
+    }
+
+    @Test
+    public void connect_withPort_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
+        //given
+        doThrow(new JSchException()).when(session).setTimeout(anyInt());
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
+
+        //then
+        verify(session).setTimeout(anyInt());
+    }
+
+    @Test
+    public void connect_withPort_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
+        //given
+        InOrder inOrder =  inOrder(session, channelShell);
+
+        //when
+        cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
+
+        //then
+        verifySessionConfigurationOrderForChannelShellOpenning(inOrder, USER, HOST, PASS, PORT_NUM, SESSION_TIMEOUT);
+    }
+
+    private void verifySessionConfigurationOrderForChannelShellOpenning(InOrder inOrder, String user, String host, String pass, int port, int sessionTimeout) throws Exception {
+        verify(jSchMock).getSession(user, host, port);
+        inOrder.verify(session).setPassword(pass);
+        inOrder.verify(session).setUserInfo(any(UserInfo.class));
+        inOrder.verify(session).setConfig(SshJcraftWrapper.STRICT_HOST_CHECK_KEY, SshJcraftWrapper.STRICT_HOST_CHECK_VALUE);
+        inOrder.verify(session).connect(sessionTimeout);
+        inOrder.verify(session).setServerAliveCountMax(0);
+        inOrder.verify(session).openChannel(SshJcraftWrapper.CHANNEL_SHELL_TYPE);
+        inOrder.verify(channelShell).getInputStream();
+        inOrder.verify(channelShell).connect();
+        inOrder.verify(session).setTimeout(anyInt());
+        inOrder.verifyNoMoreInteractions();
+        verifyNoMoreInteractions(jSchMock);
+    }
+
+    @Test
+    public void closeConnection_shouldCloseReaderChannelAndSession_inAGivenOrder() throws Exception {
+        //given
+        provideConnectedSubsystemInstance();
+        InOrder inOrder = inOrder(channelIs, channelSubsystem, session);
+
+        //when
+        cut.closeConnection();
+
+        //then
+        inOrder.verify(channelIs).close();
+        inOrder.verify(channelSubsystem).disconnect();
+        inOrder.verify(session).disconnect();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void closeConnection_shouldCloseChannelAndSession_whenClosingReaderFails() throws Exception {
+        //given
+        doThrow(new IOException("failed to close reader")).when(channelIs).close();
+        provideConnectedSubsystemInstance();
+
+        //when
+        cut.closeConnection();
+
+        //then
+        verify(channelIs).close();
+        verify(channelSubsystem).disconnect();
+        verify(session).disconnect();
+    }
+
+    @Test
+    public void closeConnection_shouldBeIdempotent_whenRunOnNewInstance() throws Exception {
+        //given
+        assertFalse(cut.isConnected());
+
+        //when
+        cut.closeConnection();
+
+        //then
+        assertFalse(cut.isConnected());
+    }
+
+    @Test
+    public void closeConnection_shouldBeIdempotent_whenRunTwiceOnConnectedInstance() throws Exception {
+        //given
+        provideConnectedSubsystemInstance();
+
+        //when
+        cut.closeConnection();
+        cut.closeConnection();
+
+        //then
+        assertFalse(cut.isConnected());
+    }
+
+    @Test
+    public void closeConnection_shouldCloseResourcesOnce_whenRunTwiceOnConnectedInstance() throws Exception {
+        //given
+        provideConnectedSubsystemInstance();
+
+        //when
+        cut.closeConnection();
+        cut.closeConnection();
+
+        //then
+        verify(channelIs, times(1)).close();
+        verify(channelSubsystem, times(1)).disconnect();
+        verify(session, times(1)).disconnect();
+    }
+
+    private void provideConnectedSubsystemInstance() throws Exception {
+        given(channelSubsystem.getInputStream()).willReturn(channelIs);
+        cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
+        assertTrue(cut.isConnected());
+    }
+
 }