2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.onap.appc.ccadaptor;
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.assertFalse;
31 import static org.junit.Assert.fail;
32 import static org.mockito.BDDMockito.given;
33 import static org.mockito.Matchers.any;
34 import static org.mockito.Matchers.anyInt;
35 import static org.mockito.Matchers.anyString;
36 import static org.mockito.Matchers.eq;
37 import static org.mockito.Mockito.atLeastOnce;
38 import static org.mockito.Mockito.doThrow;
39 import static org.mockito.Mockito.inOrder;
40 import static org.mockito.Mockito.never;
41 import static org.mockito.Mockito.spy;
42 import static org.mockito.Mockito.times;
43 import static org.mockito.Mockito.verify;
44 import static org.mockito.Mockito.verifyNoMoreInteractions;
46 import com.jcraft.jsch.ChannelSftp;
47 import com.jcraft.jsch.ChannelShell;
48 import com.jcraft.jsch.ChannelSubsystem;
49 import com.jcraft.jsch.JSch;
50 import com.jcraft.jsch.JSchException;
51 import com.jcraft.jsch.Session;
52 import com.jcraft.jsch.SftpException;
53 import com.jcraft.jsch.UserInfo;
55 import java.io.FileNotFoundException;
56 import java.io.IOException;
57 import java.io.InputStream;
58 import java.io.OutputStream;
61 import org.apache.commons.lang.StringUtils;
62 import org.junit.Assert;
63 import org.junit.Before;
64 import org.junit.Ignore;
65 import org.junit.Test;
66 import org.junit.runner.RunWith;
67 import org.mockito.InOrder;
68 import org.mockito.Mock;
69 import org.mockito.runners.MockitoJUnitRunner;
70 import org.apache.commons.io.IOUtils;
72 @RunWith(MockitoJUnitRunner.class)
73 public class SshJcraftWrapperTest {
75 private static final String USER = "username";
76 private static final String PASS = "pass";
77 private static final String HOST = "hostname";
78 private static final String SUBSYSTEM = "netconf";
79 private static final String PROMPT = "]]>]]>";
80 private static final String SEARCH_STR = "</rpc-reply>";
81 private static final String REMOTE_PATH = "/var/tmp/path/";
82 private static final String SOURCE_PATH = "/tmp/local/path/";
83 private static final String IO_EXCEPTION_MSG = "IOException should be thrown";
84 private static final int READ_TIMEOUT = 180_000;
85 private static final int PORT_NUM = 23;
86 private static final int SESSION_TIMEOUT = 30_000;
87 private static final int READ_INTERVAL_MS = 1;
88 private static final int READ_BUFFER_SIZE = 10;
90 private SshJcraftWrapper cut;
92 private JSch jSchMock;
94 private Session session;
96 private ChannelShell channelShell;
98 private ChannelSubsystem channelSubsystem;
100 private InputStream channelIs;
102 private OutputStream channelOs;
104 private ChannelSftp channelSftp;
107 public void setUpTest() throws Exception {
108 InputStream is = IOUtils.toInputStream("test input stream:~#", "UTF-8");
109 given(channelShell.getInputStream()).willReturn(is);
110 given(channelSubsystem.getInputStream()).willReturn(is);
111 given(session.openChannel(SshJcraftWrapper.CHANNEL_SHELL_TYPE)).willReturn(channelShell);
112 given(session.openChannel(SshJcraftWrapper.CHANNEL_SUBSYSTEM_TYPE)).willReturn(channelSubsystem);
113 given(jSchMock.getSession(anyString(), anyString(), anyInt())).willReturn(session);
114 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, READ_BUFFER_SIZE);
119 public void TestCheckIfReceivedStringMatchesDelimeter() {
120 SshJcraftWrapper wrapper = new SshJcraftWrapper();
121 wrapper.getTheDate();
122 boolean result = wrapper.checkIfReceivedStringMatchesDelimeter("#", "test#", "test#");
123 Assert.assertEquals(true, result);
128 public void testRemoveWhiteSpaceAndNewLineCharactersAroundString() {
129 SshJcraftWrapper wrapper = new SshJcraftWrapper();
130 String nameSpace = wrapper.removeWhiteSpaceAndNewLineCharactersAroundString("namespace ");
131 Assert.assertEquals("namespace", nameSpace);
136 public void testStripOffCmdFromRouterResponse() {
137 SshJcraftWrapper wrapper = new SshJcraftWrapper();
138 String result = wrapper.stripOffCmdFromRouterResponse("test\nsuccess");
139 Assert.assertEquals("success\n", result);
143 public void testGetLastFewLinesOfFile() throws FileNotFoundException, IOException {
144 SshJcraftWrapper wrapper = new SshJcraftWrapper();
145 URL path = SshJcraftWrapperTest.class.getResource("Test");
146 File file = new File(path.getFile());
147 String value = wrapper.getLastFewLinesOfFile(file, 1);
148 Assert.assertEquals("\nTest data 3", value);
152 @Test(expected = Exception.class)
153 public void testSetRouterCommandType() throws IOException {
154 SshJcraftWrapper wrapper = new SshJcraftWrapper();
155 wrapper.setRouterCommandType("test");
156 wrapper.receiveUntil("test", 2, "test");
161 public void testValues() throws IOException {
162 SshJcraftWrapper wrapper = new SshJcraftWrapper();
163 wrapper.setEquipNameCode("testcode");
164 wrapper.setRouterCommandType("testcommand");
165 String equipName = wrapper.getEquipNameCode();
166 wrapper.getHostName();
167 wrapper.getPassWord();
168 wrapper.getRouterName();
169 wrapper.getUserName();
170 wrapper.getTheDate();
171 Assert.assertEquals("testcode", equipName);
175 @Test(expected = Exception.class)
176 public void testSetRouterCommandType2() throws IOException {
177 SshJcraftWrapper wrapper = new SshJcraftWrapper();
178 wrapper.appendToRouterFile("test", 2);
179 StringBuilder sb = new StringBuilder();
181 wrapper.appendToRouterFile("Test.txt", sb);
182 wrapper.receiveUntilBufferFlush(3, 4, "test");
186 @Test(expected = Exception.class)
187 public void testSetRouterCommandType3() throws IOException {
188 SshJcraftWrapper wrapper = new SshJcraftWrapper();
189 wrapper.checkIfReceivedStringMatchesDelimeter(3, "test");
193 @Test(expected = IOException.class)
194 public void connect_shouldThrowIOException_whenJSchFails() throws Exception {
196 given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
199 cut.connect(HOST, USER, PASS);
202 fail(IO_EXCEPTION_MSG);
206 public void connect_shouldSetVariables() throws Exception {
208 cut.connect(HOST, USER, PASS);
211 assertEquals(HOST, cut.getHostName());
212 assertEquals(HOST, cut.getRouterName());
213 assertEquals(USER, cut.getUserName());
214 assertEquals(PASS, cut.getPassWord());
218 public void connect_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
220 InOrder inOrder = inOrder(session, channelShell);
223 cut.connect(HOST, USER, PASS);
226 verifySessionConfigurationOrderForChannelShellOpening(
227 inOrder, USER, HOST, PASS, SshJcraftWrapper.DEFAULT_PORT, SESSION_TIMEOUT);
231 public void connect_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
233 doThrow(new JSchException()).when(session).setTimeout(anyInt());
236 cut.connect(HOST, USER, PASS);
239 verify(session).setTimeout(anyInt());
242 @Test(expected = IOException.class)
243 public void connect_withSubsystem_shouldThrowIOException_whenJSchFails() throws Exception {
245 given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
248 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
251 fail(IO_EXCEPTION_MSG);
255 public void connect_withSubsystem_shouldSetRouterName() throws Exception {
257 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
260 assertEquals(HOST, cut.getRouterName());
264 public void connect_withSubsystem_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
266 InOrder inOrder = inOrder(session, channelSubsystem);
269 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
272 verify(jSchMock).getSession(USER, HOST, PORT_NUM);
273 inOrder.verify(session).setPassword(PASS);
274 inOrder.verify(session).setUserInfo(any(UserInfo.class));
275 inOrder.verify(session)
276 .setConfig(SshJcraftWrapper.STRICT_HOST_CHECK_KEY, SshJcraftWrapper.STRICT_HOST_CHECK_VALUE);
277 inOrder.verify(session).connect(SESSION_TIMEOUT);
278 inOrder.verify(session).setServerAliveCountMax(0);
279 inOrder.verify(session).openChannel(SshJcraftWrapper.CHANNEL_SUBSYSTEM_TYPE);
280 inOrder.verify(channelSubsystem).getInputStream();
281 inOrder.verify(channelSubsystem).connect(anyInt());
282 inOrder.verifyNoMoreInteractions();
283 verifyNoMoreInteractions(jSchMock);
286 @Test(expected = IOException.class)
287 public void connect_withPrompt_shouldThrowIOException_whenJSchFails() throws Exception {
289 given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
292 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
295 fail(IO_EXCEPTION_MSG);
299 public void connect_withPrompt_shouldSetVariables() throws Exception {
301 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
304 assertEquals(HOST, cut.getHostName());
305 assertEquals(HOST, cut.getRouterName());
306 assertEquals(USER, cut.getUserName());
307 assertEquals(PASS, cut.getPassWord());
311 public void connect_withPrompt_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
313 doThrow(new JSchException()).when(session).setTimeout(anyInt());
316 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
319 verify(session).setTimeout(anyInt());
323 public void connect_withPrompt_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
325 InOrder inOrder = inOrder(session, channelShell);
328 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT);
331 verifySessionConfigurationOrderForChannelShellOpening(
332 inOrder, USER, HOST, PASS, SshJcraftWrapper.DEFAULT_PORT, SESSION_TIMEOUT);
335 @Test(expected = IOException.class)
336 public void connect_withPort_shouldThrowIOException_whenJSchFails() throws Exception {
338 given(jSchMock.getSession(anyString(), anyString(), anyInt())).willThrow(new JSchException());
341 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
344 fail(IO_EXCEPTION_MSG);
348 public void connect_withPort_shouldSetVariables() throws Exception {
350 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
353 assertEquals(HOST, cut.getHostName());
354 assertEquals(HOST, cut.getRouterName());
355 assertEquals(USER, cut.getUserName());
356 assertEquals(PASS, cut.getPassWord());
360 public void connect_withPort_shouldFinishSuccessfully_whenExceptionThrownDuringReceivingPhase() throws Exception {
362 doThrow(new JSchException()).when(session).setTimeout(anyInt());
365 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
368 verify(session).setTimeout(anyInt());
372 public void connect_withPort_shouldSetUpSessionWithProperInvocationOrder() throws Exception {
374 InOrder inOrder = inOrder(session, channelShell);
377 cut.connect(HOST, USER, PASS, PROMPT, SESSION_TIMEOUT, PORT_NUM);
380 verifySessionConfigurationOrderForChannelShellOpening(inOrder, USER, HOST, PASS, PORT_NUM, SESSION_TIMEOUT);
383 private void verifySessionConfigurationOrderForChannelShellOpening(InOrder inOrder, String user, String host,
384 String pass, int port, int sessionTimeout) throws Exception {
385 verify(jSchMock).getSession(user, host, port);
386 inOrder.verify(session).setPassword(pass);
387 inOrder.verify(session).setUserInfo(any(UserInfo.class));
388 inOrder.verify(session)
389 .setConfig(SshJcraftWrapper.STRICT_HOST_CHECK_KEY, SshJcraftWrapper.STRICT_HOST_CHECK_VALUE);
390 inOrder.verify(session).connect(sessionTimeout);
391 inOrder.verify(session).setServerAliveCountMax(0);
392 inOrder.verify(session).openChannel(SshJcraftWrapper.CHANNEL_SHELL_TYPE);
393 inOrder.verify(channelShell).getInputStream();
394 inOrder.verify(channelShell).connect();
395 inOrder.verify(session).setTimeout(anyInt());
396 inOrder.verifyNoMoreInteractions();
397 verifyNoMoreInteractions(jSchMock);
401 public void closeConnection_shouldCloseReaderChannelAndSession_inAGivenOrder() throws Exception {
403 provideConnectedSubsystemInstance();
404 InOrder inOrder = inOrder(channelIs, channelSubsystem, session);
407 cut.closeConnection();
410 inOrder.verify(channelIs).close();
411 inOrder.verify(channelSubsystem).disconnect();
412 inOrder.verify(session).disconnect();
413 inOrder.verifyNoMoreInteractions();
417 public void closeConnection_shouldCloseChannelAndSession_whenClosingReaderFails() throws Exception {
419 doThrow(new IOException("failed to close reader")).when(channelIs).close();
420 provideConnectedSubsystemInstance();
423 cut.closeConnection();
426 verify(channelIs).close();
427 verify(channelSubsystem).disconnect();
428 verify(session).disconnect();
432 public void closeConnection_shouldBeIdempotent_whenRunOnNewInstance() throws Exception {
434 assertFalse(cut.isConnected());
437 cut.closeConnection();
440 assertFalse(cut.isConnected());
444 public void closeConnection_shouldBeIdempotent_whenRunTwiceOnConnectedInstance() throws Exception {
446 provideConnectedSubsystemInstance();
449 cut.closeConnection();
450 cut.closeConnection();
453 assertFalse(cut.isConnected());
457 public void closeConnection_shouldCloseResourcesOnce_whenRunTwiceOnConnectedInstance() throws Exception {
459 provideConnectedSubsystemInstance();
462 cut.closeConnection();
463 cut.closeConnection();
466 verify(channelIs, times(1)).close();
467 verify(channelSubsystem, times(1)).disconnect();
468 verify(session, times(1)).disconnect();
471 private void provideConnectedSubsystemInstance() throws Exception {
472 given(channelSubsystem.getInputStream()).willReturn(channelIs);
473 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
474 assertTrue(cut.isConnected());
477 //receiveUntil tests begin
478 @Test(expected = IllegalStateException.class)
479 public void receiveUntil_shouldThrowIllegalStateException_whenInstanceIsNotConnected() throws Exception {
481 assertFalse(cut.isConnected());
484 cut.receiveUntil(SEARCH_STR, READ_TIMEOUT, "");
487 fail("IllegalStateException should be thrown");
490 @Test(expected = IllegalStateException.class)
491 public void receiveUntil_shouldThrowIllegalStateException_whenJschReaderStreamIsNotAvailable() throws Exception {
493 provideConnectedSubsystemInstance();
494 given(channelIs.available()).willReturn(0);
497 cut.receiveUntil(SEARCH_STR, READ_TIMEOUT, "");
500 fail("IllegalStateException should be thrown");
503 @Test(expected = TimedOutException.class)
504 public void receiveUntil_shouldThrowTimedOutException_whenSessionFails() throws Exception {
506 given(channelSubsystem.getInputStream()).willReturn(IOUtils.toInputStream("test input stream:~#", "UTF-8"));
507 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
508 assertTrue(cut.isConnected());
509 doThrow(new JSchException("Session is not available")).when(session).setTimeout(anyInt());
512 cut.receiveUntil(SEARCH_STR, READ_TIMEOUT, "");
515 fail("TimedOutException should be thrown");
518 @Test(expected = TimedOutException.class)
519 public void receiveUntil_shouldThrowTimedOutException_whenReadFails() throws Exception {
521 provideConnectedSubsystemInstance();
522 given(channelIs.available()).willReturn(1);
523 given(channelIs.read(any(), anyInt(), anyInt())).willThrow(new IOException("Could not read stream"));
526 cut.receiveUntil(SEARCH_STR, READ_TIMEOUT, "");
529 fail("TimedOutException should be thrown");
532 @Test(expected = TimedOutException.class)
533 public void receiveUntil_shouldThrowException_whenTimeoutIsReached() throws Exception {
535 String streamContent = "test input stream:~#";
536 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
539 cut.receiveUntil(SEARCH_STR, -1000, " Some fake command\n");
542 fail("TimedOutException should be thrown");
545 @Test(expected = TimedOutException.class)
546 public void receiveUntil_shouldThrowException_whenReachedEndOfStream_andCouldNotReadMoreBytes() throws Exception {
548 provideConnectedSubsystemInstance();
549 given(channelIs.available()).willReturn(1);
550 given(channelIs.read(any(), anyInt(), anyInt())).willReturn(-1);
553 cut.receiveUntil(SEARCH_STR, READ_TIMEOUT, "");
556 fail("TimedOutException should be thrown");
560 public void receiveUntil_shouldReadUnderlyingStream_andStripOffFirstLine() throws Exception {
562 String command = "Command" + SshJcraftWrapper.EOL;
563 String reply = "Reply" + SshJcraftWrapper.EOL;
564 String streamContent = command + reply + PROMPT;
565 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
568 String result = cut.receiveUntil(PROMPT, SESSION_TIMEOUT, command);
571 assertEquals(reply + PROMPT, result);
575 public void receiveUntil_shouldReadUnderlyingStream_andReturnWholeReadString() throws Exception {
577 String streamContent = "Command and Reply in just one line" + PROMPT;
578 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
581 String result = cut.receiveUntil(PROMPT, SESSION_TIMEOUT, streamContent);
584 assertEquals(streamContent, result);
588 public void receiveUntil_shouldCutOffSpecialCharactersFromStream() throws Exception {
590 char special1 = Character.UNASSIGNED;
591 char special2 = Character.ENCLOSING_MARK;
592 char special3 = Character.LINE_SEPARATOR;
593 char special4 = Character.MODIFIER_SYMBOL;
594 StringBuilder sb = new StringBuilder("Command");
595 sb.append(special1).append("With").append(special2).append("Special")
596 .append(special3).append("Characters").append(special4).append("Set").append(PROMPT);
598 provideConnectedSubsystemInstanceWithStreamContent(sb.toString());
601 String result = cut.receiveUntil(PROMPT, SESSION_TIMEOUT, "");
604 assertEquals("CommandWithSpecialCharactersSet" + PROMPT, result);
608 public void receiveUntil_shouldReadUnderlyingStream_untilCLIDelimiterFound_whenProperDelimiterSet()
611 String cliDelimiter = "#$";
612 String delimiters = PROMPT + SshJcraftWrapper.DELIMITERS_SEPARATOR + cliDelimiter;
613 String streamContent = "Command for CLI invocation #";
614 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
617 String result = cut.receiveUntil(delimiters, SESSION_TIMEOUT, streamContent);
620 assertEquals(streamContent, result);
624 public void receiveUntil_shouldReadUnderlyingStream_untilCLIDelimiterFound_whenCLICommandSet() throws Exception {
626 String streamContent = "Command for CLI invocation #";
627 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
628 cut.setRouterCommandType("CLI");
631 String result = cut.receiveUntil("", SESSION_TIMEOUT, streamContent);
634 assertEquals(streamContent, result);
638 public void receiveUntil_shouldReadUnderlyingStream_untilCLIDelimiterFound_forShowConfigCommand() throws Exception {
640 String streamContent = "show config\nconfig content#";
641 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
644 String result = cut.receiveUntil("#", SESSION_TIMEOUT, streamContent);
647 assertEquals("config content#", result);
651 public void receiveUntil_shouldWriteOutputToRouterFile_whenReadingIOSXRswConfigFile_confirmFromFile()
653 receiveUntil_shouldWriteOutputToRouterFile_whenReadingIOSXRswConfigFile();
657 public void receiveUntil_shouldWriteOutputToRouterFile_whenReadingIOSXRswConfigFile_confirmFromBuffer()
660 int biggerBufferSize = 32;
661 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, biggerBufferSize);
663 receiveUntil_shouldWriteOutputToRouterFile_whenReadingIOSXRswConfigFile();
666 private void receiveUntil_shouldWriteOutputToRouterFile_whenReadingIOSXRswConfigFile() throws Exception {
668 String routerName = "router";
669 String command = "RP/0/RP0/CPU0: " + routerName + " #IOS_XR_uploadedSwConfigCmd";
670 String configFileEnding = "\nXML>";
671 String streamContent = "Config file\ncontent" + configFileEnding;
672 provideConnectedSubsystemInstanceWithStreamContent(streamContent);
675 String result = cut.receiveUntil("", SESSION_TIMEOUT, command);
678 assertNull(result); //TO-DO: it would be better to return empty string in this situation
679 assertFileExist(routerName);
682 teardownFile(routerName);
685 private void provideConnectedSubsystemInstanceWithStreamContent(String streamContent) throws Exception {
686 given(channelSubsystem.getInputStream()).willReturn(IOUtils.toInputStream(streamContent, "UTF-8"));
687 cut.connect(HOST, USER, PASS, SESSION_TIMEOUT, PORT_NUM, SUBSYSTEM);
688 assertTrue(cut.isConnected());
691 private void teardownFile(String routerName) {
692 File file = new File(routerName);
693 if (file.exists() && file.isFile()) {
698 private void assertFileExist(String fileName) {
699 File file = new File(fileName);
700 assertTrue(file.exists());
701 assertTrue(file.isFile());
705 public void send_withReceive_shouldWriteCommandToChannelOutputStream_andReturnReceivedCommand() throws Exception {
707 String command = "sdc";
708 String delimiter = ":";
709 InOrder inOrder = inOrder(channelOs);
710 provideConnectedSubsystemInstanceWithStreamContent(command + delimiter);
711 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
714 String result = cut.send(command, delimiter);
717 verifySdcCommandSent(inOrder);
718 assertEquals(command + delimiter, result);
722 public void send_shouldWriteCommandToChannelOutputStream() throws Exception {
724 String command = "sdc";
725 InOrder inOrder = inOrder(channelOs);
726 provideConnectedSubsystemInstance();
727 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
733 verifySdcCommandSent(inOrder);
736 private void verifySdcCommandSent(InOrder inOrder) throws IOException {
737 inOrder.verify(channelOs).write('s');
738 inOrder.verify(channelOs).write('d');
739 inOrder.verify(channelOs).write('c');
740 inOrder.verify(channelOs, atLeastOnce()).flush();
741 inOrder.verify(channelOs, atLeastOnce()).close();
742 inOrder.verifyNoMoreInteractions();
746 public void send_withReceive_shouldWriteCommandInChunksToChannelOutputStream_andReturnReceivedCommand()
749 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
750 cut.setCharsChunkSize(1);
751 String command = "sdc";
752 String delimiter = ":";
754 provideConnectedSubsystemInstanceWithStreamContent(command + delimiter + SshJcraftWrapper.EOL);
755 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
756 InOrder inOrder = inOrder(channelOs, session);
759 String result = cut.send(command, delimiter);
762 verifySdcCommandSentInChunk(inOrder, timeout);
763 assertEquals(command + delimiter, result);
767 public void send_shouldWriteCommandInChunksToChannelOutputStream() throws Exception {
769 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
770 cut.setCharsChunkSize(1);
771 String command = "sdc";
773 provideConnectedSubsystemInstanceWithStreamContent(command + SshJcraftWrapper.EOL);
774 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
775 InOrder inOrder = inOrder(channelOs, session);
781 verifySdcCommandSentInChunk(inOrder, timeout);
784 private void verifySdcCommandSentInChunk(InOrder inOrder, int timeout) throws Exception {
785 inOrder.verify(channelOs).write('s');
786 inOrder.verify(channelOs).flush();
787 inOrder.verify(session).setTimeout(timeout);
788 inOrder.verify(channelOs).write('d');
789 inOrder.verify(channelOs).flush();
790 inOrder.verify(session).setTimeout(timeout);
791 inOrder.verify(channelOs).write('c');
792 inOrder.verify(channelOs).flush();
793 inOrder.verify(session).setTimeout(timeout);
794 inOrder.verify(channelOs, atLeastOnce()).flush();
795 inOrder.verify(channelOs, atLeastOnce()).close();
796 inOrder.verifyNoMoreInteractions();
800 public void send_withReceive_shouldReturnActualResult_whenTimeoutReached() throws Exception {
802 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
803 cut.setCharsChunkSize(1);
804 cut.setSessionTimeoutMs(-1);
805 String command = "sdc";
806 String delimiter = ":";
807 provideConnectedSubsystemInstanceWithStreamContent(command + SshJcraftWrapper.EOL);
808 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
811 String result = cut.send(command, delimiter);
814 assertEquals(StringUtils.EMPTY, result);
818 public void send_withReceive_shouldReturnActualResult_whenCouldNotSetSessionTimeout() throws Exception {
820 cut = new SshJcraftWrapper(jSchMock, READ_INTERVAL_MS, 1);
821 cut.setCharsChunkSize(1);
822 String command = "sdc";
823 String delimiter = ":";
824 provideConnectedSubsystemInstanceWithStreamContent(command + SshJcraftWrapper.EOL);
825 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
826 doThrow(new JSchException("failed to set session timeout")).when(session).setTimeout(anyInt());
829 String result = cut.send(command, delimiter);
832 assertEquals(StringUtils.EMPTY, result);
836 public void sendChar_shouldWriteCharacterToChannelOutputStream() throws Exception {
839 provideConnectedSubsystemInstance();
840 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
841 InOrder inOrder = inOrder(channelOs);
844 cut.sendChar(charNum);
847 inOrder.verify(channelOs).write(charNum);
848 inOrder.verify(channelOs, atLeastOnce()).flush();
849 inOrder.verify(channelOs, atLeastOnce()).close();
850 inOrder.verifyNoMoreInteractions();
853 @Test(expected = IOException.class)
854 public void sendChar_shouldRethrowIOException_whenOccurs() throws Exception {
857 provideConnectedSubsystemInstance();
858 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
859 doThrow(new IOException()).when(channelOs).write(charNum);
862 cut.sendChar(charNum);
865 fail(IO_EXCEPTION_MSG);
869 public void send_withByteBuffer_shouldWriteBufferToChannelOutputStream() throws Exception {
871 byte[] buffer = "Command".getBytes();
873 provideConnectedSubsystemInstance();
874 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
875 InOrder inOrder = inOrder(channelOs);
878 cut.send(buffer, offset, buffer.length);
881 inOrder.verify(channelOs).write(buffer, offset, buffer.length);
882 inOrder.verify(channelOs, atLeastOnce()).flush();
883 inOrder.verify(channelOs, atLeastOnce()).close();
884 inOrder.verifyNoMoreInteractions();
887 @Test(expected = IOException.class)
888 public void send_withByteBuffer_shouldRethrowIOException_whenOccurs() throws Exception {
890 byte[] buffer = "Command".getBytes();
892 provideConnectedSubsystemInstance();
893 given(channelSubsystem.getOutputStream()).willReturn(channelOs);
894 doThrow(new IOException()).when(channelOs).write(buffer, offset, buffer.length);
897 cut.send(buffer, offset, buffer.length);
900 fail(IO_EXCEPTION_MSG);
904 public void getSftpConnection_shouldSetupSessionWithProperInvocationOrder() throws Exception {
906 SshJcraftWrapper instance = spy(cut);
907 given(instance.openSftpChannel(session)).willReturn(channelSftp);
908 InOrder inOrder = inOrder(session, channelSftp, instance);
911 ChannelSftp result = instance.getSftpConnection(HOST, USER, PASS);
914 verify(jSchMock).getSession(USER, HOST, SshJcraftWrapper.DEFAULT_PORT);
915 inOrder.verify(session).setPassword(PASS);
916 inOrder.verify(session).setUserInfo(any(UserInfo.class));
917 inOrder.verify(session)
918 .setConfig(SshJcraftWrapper.STRICT_HOST_CHECK_KEY, SshJcraftWrapper.STRICT_HOST_CHECK_VALUE);
919 inOrder.verify(session).connect(SESSION_TIMEOUT);
920 inOrder.verify(instance).openSftpChannel(session);
921 inOrder.verify(channelSftp).connect();
922 inOrder.verifyNoMoreInteractions();
923 assertEquals(channelSftp, result);
927 public void sftp_get_shouldReadFromChannelInputStream_andCloseConnection() throws Exception {
929 String streamContent = "test input stream content";
930 SshJcraftWrapper spyInstance = spy(cut);
931 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
932 given(channelSftp.get(REMOTE_PATH)).willReturn(IOUtils.toInputStream(streamContent, "UTF-8"));
935 String result = spyInstance.get(REMOTE_PATH, HOST, USER, PASS);
938 assertEquals(streamContent, result);
939 verify(channelSftp).disconnect();
940 verify(session).disconnect();
943 @Test(expected = IOException.class)
944 public void sftp_get_shouldThrowIOException_whenJschFails() throws Exception {
946 SshJcraftWrapper spyInstance = spy(cut);
947 doThrow(new JSchException()).when(spyInstance).openSftpChannel(session);
950 spyInstance.get(REMOTE_PATH, HOST, USER, PASS);
953 fail(IO_EXCEPTION_MSG);
956 @Test(expected = IOException.class)
957 public void sftp_get_shouldThrowIOException_whenSftpOperationFails() throws Exception {
959 SshJcraftWrapper spyInstance = spy(cut);
960 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
961 doThrow(new SftpException(0, "sftp error")).when(channelSftp).get(REMOTE_PATH);
964 spyInstance.get(REMOTE_PATH, HOST, USER, PASS);
967 fail(IO_EXCEPTION_MSG);
971 public void sftp_get_shouldCloseSessionAndChannel_whenExceptionOccursOnConnectedInstance() throws Exception {
973 SshJcraftWrapper spyInstance = spy(cut);
974 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
975 doThrow(new SftpException(0, "sftp error")).when(channelSftp).get(REMOTE_PATH);
976 boolean ioException = false;
980 spyInstance.get(REMOTE_PATH, HOST, USER, PASS);
981 } catch (IOException e) {
986 assertTrue(ioException);
987 verify(channelSftp).disconnect();
988 verify(session).disconnect();
992 public void sftp_get_shouldSkipClosingSessionAndChannel_whenExceptionOccursOnNotConnectedInstance() throws Exception {
994 doThrow(new JSchException()).when(jSchMock).getSession(anyString(), anyString(), anyInt());
995 boolean ioException = false;
999 cut.get(REMOTE_PATH, HOST, USER, PASS);
1000 } catch (IOException e) {
1005 assertTrue(ioException);
1006 verify(channelSftp, never()).disconnect();
1007 verify(session, never()).disconnect();
1011 public void sftp_put_withIs_shouldRemoveOldFilesFromDestinationPath_andPutNewData() throws Exception {
1013 InputStream is = IOUtils.toInputStream("test input stream content", "UTF-8");
1014 SshJcraftWrapper spyInstance = spy(cut);
1015 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1016 InOrder inOrder = inOrder(channelSftp, session);
1019 spyInstance.put(is, REMOTE_PATH, HOST, USER, PASS);
1022 inOrder.verify(channelSftp).rm(REMOTE_PATH + "*");
1023 inOrder.verify(channelSftp).put(is, REMOTE_PATH, ChannelSftp.OVERWRITE);
1024 inOrder.verify(channelSftp).disconnect();
1025 inOrder.verify(session).disconnect();
1026 inOrder.verifyNoMoreInteractions();
1030 public void sftp_put_withIs_shouldContinueInsertingNewData_whenFileNotFoundDuringRemoval() throws Exception {
1032 InputStream is = IOUtils.toInputStream("test input stream content", "UTF-8");
1033 SshJcraftWrapper spyInstance = spy(cut);
1034 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1035 doThrow(new SftpException(ChannelSftp.SSH_FX_NO_SUCH_FILE, "No such file/dir"))
1036 .when(channelSftp).rm(REMOTE_PATH + "*");
1039 spyInstance.put(is, REMOTE_PATH, HOST, USER, PASS);
1042 verify(channelSftp).rm(REMOTE_PATH + "*");
1043 verify(channelSftp).put(is, REMOTE_PATH, ChannelSftp.OVERWRITE);
1046 @Test(expected = IOException.class)
1047 public void sftp_put_withIs_shouldThrowIOException_whenSftpFails() throws Exception {
1049 InputStream is = IOUtils.toInputStream("test input stream content", "UTF-8");
1050 SshJcraftWrapper spyInstance = spy(cut);
1051 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1052 doThrow(new SftpException(ChannelSftp.SSH_FX_FAILURE, "general error"))
1053 .when(channelSftp).rm(anyString());
1056 spyInstance.put(is, REMOTE_PATH, HOST, USER, PASS);
1059 fail(IO_EXCEPTION_MSG);
1062 @Test(expected = IOException.class)
1063 public void sftp_put_withIs_shouldThrowIOException_whenJschFails() throws Exception {
1065 InputStream is = IOUtils.toInputStream("test input stream content", "UTF-8");
1066 SshJcraftWrapper spyInstance = spy(cut);
1067 doThrow(new JSchException()).when(spyInstance).openSftpChannel(session);
1070 spyInstance.put(is, REMOTE_PATH, HOST, USER, PASS);
1073 fail(IO_EXCEPTION_MSG);
1077 public void sftp_put_withSourcePath_shouldPutSrcPathToDestinationPath_andDisconnectAfterwards() throws Exception {
1079 SshJcraftWrapper spyInstance = spy(cut);
1080 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1083 spyInstance.put(SOURCE_PATH, REMOTE_PATH);
1086 verify(channelSftp).put(SOURCE_PATH, REMOTE_PATH, ChannelSftp.OVERWRITE);
1087 verify(channelSftp).disconnect();
1088 verify(session).disconnect();
1091 @Test(expected = IOException.class)
1092 public void sftp_put_withSourcePath_shouldThrowIOException_whenSftpFails() throws Exception {
1094 SshJcraftWrapper spyInstance = spy(cut);
1095 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1096 doThrow(new SftpException(ChannelSftp.SSH_FX_FAILURE, "general error"))
1097 .when(channelSftp).put(anyString(), anyString(), anyInt());
1100 spyInstance.put(SOURCE_PATH, REMOTE_PATH);
1103 fail(IO_EXCEPTION_MSG);
1106 @Test(expected = IOException.class)
1107 public void sftp_put_withSourcePath_shouldThrowIOException_whenJschFails() throws Exception {
1109 SshJcraftWrapper spyInstance = spy(cut);
1110 doThrow(new JSchException()).when(spyInstance).openSftpChannel(session);
1113 spyInstance.put(SOURCE_PATH, REMOTE_PATH);
1116 fail(IO_EXCEPTION_MSG);
1120 public void sftpPutStringData_shouldPutInputStreamToRemotePath() throws Exception {
1122 String inputData = "Test data";
1123 SshJcraftWrapper spyInstance = spy(cut);
1124 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1127 spyInstance.sftpPutStringData(inputData, REMOTE_PATH);
1130 verify(channelSftp).put(any(InputStream.class), eq(REMOTE_PATH), eq(ChannelSftp.OVERWRITE));
1131 verify(channelSftp).disconnect();
1132 verify(session).disconnect();
1135 @Test(expected = IOException.class)
1136 public void sftpPutStringData_shouldThrowIOException_whenJschFails() throws Exception {
1138 String inputData = "Test data";
1139 SshJcraftWrapper spyInstance = spy(cut);
1140 doThrow(new JSchException()).when(spyInstance).openSftpChannel(session);
1143 spyInstance.sftpPutStringData(inputData, REMOTE_PATH);
1146 fail(IO_EXCEPTION_MSG);
1149 @Test(expected = IOException.class)
1150 public void sftpPutStringData_shouldThrowIOException_whenSftpFails() throws Exception {
1152 String inputData = "Test data";
1153 SshJcraftWrapper spyInstance = spy(cut);
1154 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1155 doThrow(new SftpException(ChannelSftp.SSH_FX_FAILURE, "general error"))
1156 .when(channelSftp).put(any(InputStream.class), anyString(), anyInt());
1159 spyInstance.sftpPutStringData(inputData, REMOTE_PATH);
1162 fail(IO_EXCEPTION_MSG);
1166 public void sftpGet_shouldReadFromChannelInputStream_withInstanceCredentials() throws Exception {
1168 String remoteStreamContent = "test input stream content";
1169 SshJcraftWrapper spyInstance = spy(cut);
1170 given(spyInstance.openSftpChannel(session)).willReturn(channelSftp);
1171 given(channelSftp.get(REMOTE_PATH)).willReturn(IOUtils.toInputStream(remoteStreamContent, "UTF-8"));
1174 String result = spyInstance.sftpGet(REMOTE_PATH);
1177 assertEquals(remoteStreamContent, result);