Repository: cloudslang/cs-actions
Issue: SSH: returnCode=-1 but no exception output [1]

sporadically the SSH call returns -1 but no other info (e.g. exception)

```
24/08/15 14:11:03 [DEBUG] Event received: EVENT_ACTION_END Data is: {DESCRIPTION=Action performed, PATH=0.2.2.0.1.0.0, RETURN_VALUES={returnCode=-1, returnResult=, STDERR=, exitStatus=-1, STDOUT=}, STEP_NAME=null, STEP_TYPE=ACTION, TIMESTAMP=Mon Aug 24 14:11:03 UTC 2015, EXECUTION_ID=101600113, TYPE=EVENT_ACTION_END}
```

https://circle-artifacts.com/gh/CloudSlang/cloud-slang-content/1446/artifacts/1/home/ubuntu/cloud-slang-content/builder.log


Changed files:
score-ssh/src/test/java/io/cloudslang/content/ssh/services/impl/SSHServiceImplTest.java
score-ssh/src/main/java/io/cloudslang/content/ssh/services/actions/ScoreSSHShellCommand.java
score-ssh/src/main/java/io/cloudslang/content/ssh/services/SSHService.java
score-ssh/src/main/java/io/cloudslang/content/ssh/services/impl/SSHServiceImpl.java

diff --git a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/SSHService.java b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/SSHService.java
index a422e200e..6a57c5fc3 100644
--- a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/SSHService.java
+++ b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/SSHService.java
@@ -5,7 +5,6 @@ import com.jcraft.jsch.Channel;
 import com.jcraft.jsch.Session;
 import io.cloudslang.content.ssh.entities.CommandResult;
 import io.cloudslang.content.ssh.entities.SSHConnection;
-import io.cloudslang.content.ssh.exceptions.TimeoutException;
 
 import java.util.Map;
 
@@ -26,7 +25,7 @@ public interface SSHService extends AutoCloseable {
      * @param agentForwarding   Weathers the agent forwarding is enabled or not.
      * @return the command result.
      */
-    CommandResult runShellCommand(String command, String characterSet, boolean usePseudoTerminal, int connectTimeout, int commandTimeout, boolean agentForwarding) throws TimeoutException;
+    CommandResult runShellCommand(String command, String characterSet, boolean usePseudoTerminal, int connectTimeout, int commandTimeout, boolean agentForwarding);
 
     /**
      * Checks the SSH session.
diff --git a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/actions/ScoreSSHShellCommand.java b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/actions/ScoreSSHShellCommand.java
index 52039d9a2..5cfdd7bb0 100644
--- a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/actions/ScoreSSHShellCommand.java
+++ b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/actions/ScoreSSHShellCommand.java
@@ -1,7 +1,6 @@
 package io.cloudslang.content.ssh.services.actions;
 
 import io.cloudslang.content.ssh.entities.*;
-import io.cloudslang.content.ssh.exceptions.TimeoutException;
 import io.cloudslang.content.ssh.services.SSHService;
 import io.cloudslang.content.ssh.services.impl.SSHServiceImpl;
 import io.cloudslang.content.ssh.utils.Constants;
@@ -72,8 +71,7 @@ public class ScoreSSHShellCommand extends SSHShellAbstract {
             SSHShellInputs sshShellInputs,
             Map<String, String> returnResult,
             SSHService service, String sessionId,
-            boolean saveSSHSession
-    ) throws TimeoutException {
+            boolean saveSSHSession) {
 
         int timeoutNumber = StringUtils.toInt(sshShellInputs.getTimeout(), Constants.DEFAULT_TIMEOUT);
         boolean usePseudoTerminal = StringUtils.toBoolean(sshShellInputs.getPty(), Constants.DEFAULT_USE_PSEUDO_TERMINAL);
diff --git a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/impl/SSHServiceImpl.java b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/impl/SSHServiceImpl.java
index 510c0b2bd..c4a57fdb4 100644
--- a/score-ssh/src/main/java/io/cloudslang/content/ssh/services/impl/SSHServiceImpl.java
+++ b/score-ssh/src/main/java/io/cloudslang/content/ssh/services/impl/SSHServiceImpl.java
@@ -119,8 +119,7 @@ public class SSHServiceImpl implements SSHService {
             boolean usePseudoTerminal,
             int connectTimeout,
             int commandTimeout,
-            boolean agentForwarding
-    ) throws TimeoutException {
+            boolean agentForwarding) {
         try {
             if (!isConnected()) {
                 session.connect(connectTimeout);
@@ -142,14 +141,14 @@ public class SSHServiceImpl implements SSHService {
             // wait for response
             long currentTime = System.currentTimeMillis();
             long timeLimit = currentTime + commandTimeout;
-            while (!channel.isEOF() && currentTime < timeLimit) {
+            while (!channel.isClosed() && currentTime < timeLimit) {
                 try {
                     Thread.sleep(POLLING_INTERVAL);
                 } catch (InterruptedException ignore) {
                 }
                 currentTime = System.currentTimeMillis();
             }
-            boolean timedOut = !channel.isEOF();
+            boolean timedOut = !channel.isClosed();
 
             // save the response
             CommandResult result = new CommandResult();
@@ -165,7 +164,7 @@ public class SSHServiceImpl implements SSHService {
             }
 
             return result;
-        } catch (JSchException | UnsupportedEncodingException e) {
+        } catch (JSchException | UnsupportedEncodingException | TimeoutException e) {
             throw new RuntimeException(e);
         }
     }
diff --git a/score-ssh/src/test/java/io/cloudslang/content/ssh/services/impl/SSHServiceImplTest.java b/score-ssh/src/test/java/io/cloudslang/content/ssh/services/impl/SSHServiceImplTest.java
index 71b5199c2..9b4d2de97 100644
--- a/score-ssh/src/test/java/io/cloudslang/content/ssh/services/impl/SSHServiceImplTest.java
+++ b/score-ssh/src/test/java/io/cloudslang/content/ssh/services/impl/SSHServiceImplTest.java
@@ -9,10 +9,11 @@ import io.cloudslang.content.ssh.entities.CommandResult;
 import io.cloudslang.content.ssh.entities.ConnectionDetails;
 import io.cloudslang.content.ssh.entities.KeyFile;
 import io.cloudslang.content.ssh.entities.KnownHostsFile;
-import io.cloudslang.content.ssh.exceptions.TimeoutException;
 import io.cloudslang.content.ssh.services.SSHService;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -52,15 +53,19 @@ public class SSHServiceImplTest {
 
     @Mock
     private Session sessionMock;
+
     @Mock
     private ChannelShell channelShellMock;
+
     @Mock
     private CommandResult commandResultMock;
 
-
     @Mock
     private JSch jSchMock;
 
+    @Rule
+    public ExpectedException exception = ExpectedException.none();
+
     @Before
     public void setUp() throws Exception {
         PowerMockito.whenNew(JSch.class).withNoArguments().thenReturn(jSchMock);
@@ -68,7 +73,7 @@ public class SSHServiceImplTest {
         Mockito.doNothing().when(jSchMock).addIdentity(SHELL_PATH);
         PowerMockito.when(sessionMock.openChannel("shell")).thenReturn(channelShellMock);
         Mockito.doNothing().when(channelShellMock).connect(CONNECT_TIMEOUT);
-        PowerMockito.when(channelShellMock.isEOF()).thenReturn(true);
+        PowerMockito.when(channelShellMock.isClosed()).thenReturn(true);
     }
 
     @Test
@@ -117,9 +122,12 @@ public class SSHServiceImplTest {
         assertEquals(commandResult.getStandardOutput(), "");
     }
 
-    @Test(expected = RuntimeException.class)
+    @Test
     public void testRunShellCommandInvalidEncoding() throws Exception {
         SSHService sshService = new SSHServiceImpl(sessionMock, channelShellMock);
+
+        exception.expect(RuntimeException.class);
+
         sshService.runShellCommand("", "test", true, CONNECT_TIMEOUT, COMMAND_TIMEOUT, AGENT_FORWARDING_TRUE);
     }
 
@@ -163,10 +171,14 @@ public class SSHServiceImplTest {
         sshService.removeFromCache(Mockito.any(GlobalSessionObject.class), "sessionId");
     }
 
-    @Test(expected = TimeoutException.class)
+    @Test
     public void testTimeoutExceptionIsThrown() throws Exception {
-        PowerMockito.when(channelShellMock.isEOF()).thenReturn(false);
+        PowerMockito.when(channelShellMock.isClosed()).thenReturn(false);
         SSHService sshService = new SSHServiceImpl(sessionMock, channelShellMock);
+
+        exception.expect(RuntimeException.class);
+        exception.expectMessage("Timeout");
+
         sshService.runShellCommand("ls", "UTF-8", true, CONNECT_TIMEOUT, 0, AGENT_FORWARDING_FALSE);
     }