Unit tests for send methods 09/32909/4
authorTomek Kaminski <tomasz.kaminski@nokia.com>
Mon, 26 Feb 2018 14:45:24 +0000 (15:45 +0100)
committerPatrick Brady <pb071s@att.com>
Fri, 2 Mar 2018 16:54:16 +0000 (16:54 +0000)
Covered functionality of 4 send methods with JUnits

Change-Id: I21de5eab799e52899959cf61199a4d185a47268c
Issue-ID: APPC-591
Signed-off-by: Tomek Kaminski <tomasz.kaminski@nokia.com>
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/SshJcraftWrapperTest.java

index 4d81b6c..2059245 100644 (file)
@@ -91,6 +91,8 @@ public class SshJcraftWrapper {
     private String passWord = null;
     private int readIntervalMs = 500;
     private int readBufferSizeBytes = 512_000;
+    private int charsChunkSize = 300_000;
+    private int sessionTimeoutMs = 9_000;
     private char[] charBuffer;
     private Runtime runtime = Runtime.getRuntime();
 
@@ -405,12 +407,19 @@ public class SshJcraftWrapper {
     }
 
     boolean isConnected() {
-        return (channel != null && session != null);
+        return channel != null && session != null;
     }
 
     public void send(String cmd) throws IOException {
         try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
-            sendSshCommand(cmd, dos);
+            String command = enhanceCommandWithEOL(cmd);
+            int length = command.length();
+            log.debug("Sending ssh command: length={0}, payload: {1}", command.length(), command);
+            if(isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
+                sendSshCommandInChunks(command, dos);
+            } else {
+                sendSshCommand(command, dos);
+            }
         } catch (IOException e) {
             log.error(Msg.SSH_DATA_EXCEPTION, e.getMessage());
             throw e;
@@ -594,10 +603,11 @@ public class SshJcraftWrapper {
     }
 
     // Routine does reads until it has read 'nchars' or times out.
-    public void receiveUntilBufferFlush(int ncharsSent, int timeout, String command) throws IOException {
+    public String receiveUntilBufferFlush(int ncharsSent, int timeout, String command) throws IOException {
         log.debug("ncharsSent={0}, timeout={1}, message={2}", ncharsSent, timeout, command);
         int ncharsTotalReceived = 0;
         int ncharsRead = 0;
+        StringBuilder received = new StringBuilder();
 
         long deadline = new Date().getTime() + timeout;
         logMemoryUsage();
@@ -609,6 +619,9 @@ public class SshJcraftWrapper {
                     throw new TimedOutException("Routine has timed out");
                 }
                 ncharsRead = reader.read(charBuffer, 0, readBufferSizeBytes);
+                if(ncharsRead >=0) {
+                    received.append(charBuffer, 0, ncharsRead);
+                }
                 if (listener != null) {
                     listener.receivedString(String.copyValueOf(charBuffer, 0, ncharsRead));
                 }
@@ -618,7 +631,7 @@ public class SshJcraftWrapper {
                     log.debug("Received the correct number of characters, ncharsSent={0}, ncharsTotalReceived={1}",
                         ncharsSent, ncharsTotalReceived);
                     logMemoryUsage();
-                    return;
+                    return received.toString();
                 }
             }
         } catch (JSchException e) {
@@ -882,43 +895,55 @@ public class SshJcraftWrapper {
 
     public String send(String cmd, String delimiter) throws IOException {
         try (OutputStream os = channel.getOutputStream(); DataOutputStream dos = new DataOutputStream(os)) {
-            sendSshCommand(cmd, dos);
-            return receiveUntil(delimiter, 300000, cmd);
+            String command = enhanceCommandWithEOL(cmd);
+            int length = command.length();
+            log.debug("Sending ssh command: length={0}, payload: {1}", command.length(), command);
+            if(isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
+                return sendSshCommandInChunks(command, dos);
+            } else {
+                sendSshCommand(command, dos);
+                return receiveUntil(delimiter, 300000, cmd);
+            }
         }
     }
 
-    private void sendSshCommand(@Nonnull String originalCommand, @Nonnull DataOutputStream channelOutputStream)
+    private void sendSshCommand(@Nonnull String command, @Nonnull DataOutputStream channelOutputStream)
         throws IOException {
-        String command = enhanceCommandWithEOL(originalCommand);
-        int length = command.length(); // 2,937,706
-        int charsChunkSize = 300000;
-        int charsTotalSent = 0;
+        channelOutputStream.writeBytes(command);
+        channelOutputStream.flush();
+    }
 
-        log.debug("Sending ssh command: length={0}, payload: {1}", length, command);
-        if (isCmdLengthEnoughToSendInChunks(length, charsChunkSize)) {
-            int timeout = 9000;
-            for (int i = 0; i < length; i += charsChunkSize) {
-                String commandChunk = command.substring(i, Math.min(length, i + charsChunkSize));
-                int numCharsSentInChunk = commandChunk.length();
-                charsTotalSent = charsTotalSent + commandChunk.length();
-                log.debug("Iteration nr:{0}, sending command chunk: {1}", i, numCharsSentInChunk);
-                channelOutputStream.writeBytes(commandChunk);
-                channelOutputStream.flush();
-                try {
-                    if (numCharsSentInChunk < length) {
-                        receiveUntilBufferFlush(numCharsSentInChunk, timeout, originalCommand);
-                    } else {
-                        log.trace("i={0}, flush immediately", i);
-                        channelOutputStream.flush();
-                    }
-                } catch (IOException ex) {
-                    log.warn("IOException occurred: nothing to flush out", ex);
+    private String sendSshCommandInChunks(@Nonnull String command, @Nonnull DataOutputStream channelOutputStream) throws IOException {
+        StringBuilder received =  new StringBuilder();
+        int charsTotalSent = 0;
+        int length = command.length();
+        for (int i = 0; i < length; i += charsChunkSize) {
+            String commandChunk = command.substring(i, Math.min(length, i + charsChunkSize));
+            int numCharsSentInChunk = commandChunk.length();
+            charsTotalSent = charsTotalSent + commandChunk.length();
+            log.debug("Iteration nr:{0}, sending command chunk: {1}", i, numCharsSentInChunk);
+            channelOutputStream.writeBytes(commandChunk);
+            channelOutputStream.flush();
+            try {
+                if (numCharsSentInChunk < length) {
+                    received.append(receiveUntilBufferFlush(numCharsSentInChunk, sessionTimeoutMs, command));
+                } else {
+                    log.trace("i={0}, flush immediately", i);
+                    channelOutputStream.flush();
                 }
+            } catch (IOException ex) {
+                log.warn("IOException occurred: nothing to flush out", ex);
             }
-        } else {
-            channelOutputStream.writeBytes(command);
         }
-        channelOutputStream.flush();
+        return received.toString();
+    }
+
+    public void setSessionTimeoutMs(int sessionTimeoutMs) {
+        this.sessionTimeoutMs = sessionTimeoutMs;
+    }
+
+    void setCharsChunkSize(int charsChunkSize) {
+        this.charsChunkSize = charsChunkSize;
     }
 
     private boolean isCmdLengthEnoughToSendInChunks(int length, int chunkSize) {
index 76b4c62..4047e93 100644 (file)
@@ -33,11 +33,14 @@ 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.atLeastOnce;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
 
 import com.jcraft.jsch.ChannelShell;
 import com.jcraft.jsch.ChannelSubsystem;
@@ -49,8 +52,10 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.URL;
 
+import org.apache.commons.lang.StringUtils;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Ignore;
@@ -87,6 +92,8 @@ public class SshJcraftWrapperTest {
     private ChannelSubsystem channelSubsystem;
     @Mock
     private InputStream channelIs;
+    @Mock
+    private OutputStream channelOs;
 
     @Before
     public void setUpTest() throws Exception {
@@ -121,14 +128,14 @@ public class SshJcraftWrapperTest {
     public void testStripOffCmdFromRouterResponse(){
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         String result = wrapper.stripOffCmdFromRouterResponse("test\nsuccess");
-        Assert.assertEquals("success\n", result);            
+        Assert.assertEquals("success\n", result);
     }
-    
+
     //@Test
     public void testGetLastFewLinesOfFile() throws FileNotFoundException, IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
         URL path = SshJcraftWrapperTest.class.getResource("Test");
-        File file = new File(path.getFile());        
+        File file = new File(path.getFile());
         String value = wrapper.getLastFewLinesOfFile(file,1);
         Assert.assertEquals("\nTest data 3", value);
     }
@@ -137,7 +144,7 @@ public class SshJcraftWrapperTest {
     @Test(expected=Exception.class)
     public void testSetRouterCommandType() throws IOException{
         SshJcraftWrapper wrapper = new SshJcraftWrapper();
-        wrapper.setRouterCommandType("test");    
+        wrapper.setRouterCommandType("test");
         wrapper.receiveUntil("test", 2, "test");
     }
 
@@ -164,7 +171,7 @@ public class SshJcraftWrapperTest {
         StringBuilder sb = new StringBuilder();
         sb.append("test");
         wrapper.appendToRouterFile("Test.txt", sb);
-        wrapper.receiveUntilBufferFlush(3, 4, "test");        
+        wrapper.receiveUntilBufferFlush(3, 4, "test");
     }
 
     @Ignore
@@ -680,4 +687,201 @@ public class SshJcraftWrapperTest {
         assertTrue(file.isFile());
     }
 
+    @Test
+    public void send_withReceive_shouldWriteCommandToChannelOutputStream_andReturnReceivedCommand() throws Exception {
+        //given
+        String command = "sdc";
+        String delimiter = ":";
+        InOrder inOrder = inOrder(channelOs);
+        provideConnectedSubsystemInstanceWithStreamContent(command+delimiter);
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+        //when
+        String result = cut.send(command, delimiter);
+
+        //then
+        verifySdcCommandSent(inOrder);
+        assertEquals(command+delimiter, result);
+    }
+
+    @Test
+    public void send_shouldWriteCommandToChannelOutputStream() throws Exception {
+        //given
+        String command = "sdc";
+        InOrder inOrder = inOrder(channelOs);
+        provideConnectedSubsystemInstance();
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+        //when
+        cut.send(command);
+
+        //then
+        verifySdcCommandSent(inOrder);
+    }
+
+    private void verifySdcCommandSent(InOrder inOrder) throws IOException {
+        inOrder.verify(channelOs).write('s');
+        inOrder.verify(channelOs).write('d');
+        inOrder.verify(channelOs).write('c');
+        inOrder.verify(channelOs, atLeastOnce()).flush();
+        inOrder.verify(channelOs, atLeastOnce()).close();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void send_withReceive_shouldWriteCommandInChunksToChannelOutputStream_andReturnReceivedCommand() throws Exception {
+        //given
+        cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+        cut.setCharsChunkSize(1);
+        String command = "sdc";
+        String delimiter = ":";
+        int timeout = 9000;
+        provideConnectedSubsystemInstanceWithStreamContent(command+delimiter+SshJcraftWrapper.EOL);
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        InOrder inOrder = inOrder(channelOs, session);
+
+        //when
+        String result = cut.send(command, delimiter);
+
+        //then
+        verifySdcCommandSentInChunk(inOrder, timeout);
+        assertEquals(command+delimiter, result);
+    }
+
+    @Test
+    public void send_shouldWriteCommandInChunksToChannelOutputStream() throws Exception {
+        //given
+        cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+        cut.setCharsChunkSize(1);
+        String command = "sdc";
+        int timeout = 9000;
+        provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        InOrder inOrder = inOrder(channelOs, session);
+
+        //when
+        cut.send(command);
+
+        //then
+        verifySdcCommandSentInChunk(inOrder, timeout);
+    }
+
+    private void verifySdcCommandSentInChunk(InOrder inOrder, int timeout) throws Exception{
+        inOrder.verify(channelOs).write('s');
+        inOrder.verify(channelOs).flush();
+        inOrder.verify(session).setTimeout(timeout);
+        inOrder.verify(channelOs).write('d');
+        inOrder.verify(channelOs).flush();
+        inOrder.verify(session).setTimeout(timeout);
+        inOrder.verify(channelOs).write('c');
+        inOrder.verify(channelOs).flush();
+        inOrder.verify(session).setTimeout(timeout);
+        inOrder.verify(channelOs, atLeastOnce()).flush();
+        inOrder.verify(channelOs, atLeastOnce()).close();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void send_withReceive_shouldReturnActualResult_whenTimeoutReached() throws Exception {
+        //given
+        cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+        cut.setCharsChunkSize(1);
+        cut.setSessionTimeoutMs(-1);
+        String command = "sdc";
+        String delimiter = ":";
+        provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+
+        //when
+        String result = cut.send(command, delimiter);
+
+        //then
+        assertEquals(StringUtils.EMPTY, result);
+    }
+
+    @Test
+    public void send_withReceive_shouldReturnActualResult_whenCouldNotSetSessionTimeout() throws Exception {
+        //given
+        cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
+        cut.setCharsChunkSize(1);
+        String command = "sdc";
+        String delimiter = ":";
+        provideConnectedSubsystemInstanceWithStreamContent(command+SshJcraftWrapper.EOL);
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        doThrow(new JSchException("failed to set session timeout")).when(session).setTimeout(anyInt());
+
+        //when
+        String result = cut.send(command, delimiter);
+
+        //then
+        assertEquals(StringUtils.EMPTY, result);
+    }
+
+    @Test
+    public void sendChar_shouldWriteCharacterToChannelOutputStream() throws Exception {
+        //given
+        int charNum = 100;
+        provideConnectedSubsystemInstance();
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        InOrder inOrder = inOrder(channelOs);
+
+        //when
+        cut.sendChar(charNum);
+
+        //then
+        inOrder.verify(channelOs).write(charNum);
+        inOrder.verify(channelOs, atLeastOnce()).flush();
+        inOrder.verify(channelOs, atLeastOnce()).close();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test(expected = IOException.class)
+    public void sendChar_shouldRethrowIOException_whenOccurs() throws Exception {
+        //given
+        int charNum = 100;
+        provideConnectedSubsystemInstance();
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        doThrow(new IOException()).when(channelOs).write(charNum);
+
+        //when
+        cut.sendChar(charNum);
+
+        //then
+        fail("IOException should be thrown");
+    }
+
+    @Test
+    public void send_withByteBuffer_shouldWriteBufferToChannelOutputStream() throws Exception {
+        //given
+        byte[] buffer = "Command".getBytes();
+        int offset = 5;
+        provideConnectedSubsystemInstance();
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        InOrder inOrder = inOrder(channelOs);
+
+        //when
+        cut.send(buffer,offset,buffer.length);
+
+        //then
+        inOrder.verify(channelOs).write(buffer, offset, buffer.length);
+        inOrder.verify(channelOs, atLeastOnce()).flush();
+        inOrder.verify(channelOs, atLeastOnce()).close();
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test(expected = IOException.class)
+    public void send_withByteBuffer_shouldRethrowIOException_whenOccurs() throws Exception {
+        //given
+        byte[] buffer = "Command".getBytes();
+        int offset = 5;
+        provideConnectedSubsystemInstance();
+        given(channelSubsystem.getOutputStream()).willReturn(channelOs);
+        doThrow(new IOException()).when(channelOs).write(buffer, offset, buffer.length);
+
+        //when
+        cut.send(buffer,offset,buffer.length);
+
+        //then
+        fail("IOException should be thrown");
+    }
 }