596bec82f08c4ab4015078eaf9746b604dfbf63b
[nonrtric/plt/ranpm.git] / datafilecollector / src / test / java / org / onap / dcaegen2 / collectors / datafile / ftp / SftpClientTest.java
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2020 Nokia. All rights reserved.
4  * ===============================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
6  * except in compliance with the License. You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software distributed under the
11  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12  * either express or implied. See the License for the specific language governing permissions
13  * and limitations under the License.
14  * ============LICENSE_END========================================================================
15  */
16
17 package org.onap.dcaegen2.collectors.datafile.ftp;
18
19 import static org.assertj.core.api.Assertions.assertThatThrownBy;
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21 import static org.junit.jupiter.api.Assertions.assertThrows;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.ArgumentMatchers.anyString;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.doThrow;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.verifyNoMoreInteractions;
29 import static org.mockito.Mockito.when;
30
31 import com.jcraft.jsch.ChannelSftp;
32 import com.jcraft.jsch.JSch;
33 import com.jcraft.jsch.JSchException;
34 import com.jcraft.jsch.Session;
35 import com.jcraft.jsch.SftpException;
36
37 import java.nio.file.Paths;
38
39 import org.junit.jupiter.api.Test;
40 import org.junit.jupiter.api.extension.ExtendWith;
41 import org.mockito.Mock;
42 import org.mockito.junit.jupiter.MockitoExtension;
43 import org.onap.dcaegen2.collectors.datafile.commons.FileServerData;
44 import org.onap.dcaegen2.collectors.datafile.configuration.SftpConfig;
45 import org.onap.dcaegen2.collectors.datafile.exceptions.DatafileTaskException;
46 import org.onap.dcaegen2.collectors.datafile.exceptions.NonRetryableDatafileTaskException;
47
48 @ExtendWith(MockitoExtension.class)
49 public class SftpClientTest {
50
51     private static final String HOST = "127.0.0.1";
52     private static final int SFTP_PORT = 1021;
53     private static final String USERNAME = "bob";
54     private static final String PASSWORD = "123";
55
56     @Mock
57     private JSch jschMock;
58
59     @Mock
60     private Session sessionMock;
61
62     @Mock
63     private ChannelSftp channelMock;
64
65     @Test
66     public void openWithPort_success() throws Exception {
67         FileServerData expectedFileServerData = FileServerData.builder() //
68             .serverAddress(HOST) //
69             .userId(USERNAME) //
70             .password(PASSWORD) //
71             .port(SFTP_PORT) //
72             .build();
73
74         SftpClient sftpClientSpy = spy(new SftpClient(expectedFileServerData, createSampleSftpClientSettings()));
75
76         doReturn(jschMock).when(sftpClientSpy).createJsch();
77         when(jschMock.getSession(anyString(), anyString(), anyInt())).thenReturn(sessionMock);
78         when(sessionMock.openChannel(anyString())).thenReturn(channelMock);
79
80         sftpClientSpy.open();
81
82         verify(jschMock).getSession(USERNAME, HOST, SFTP_PORT);
83         verify(sessionMock).setConfig("StrictHostKeyChecking", "no");
84         verify(sessionMock).setPassword(PASSWORD);
85         verify(sessionMock).connect();
86         verify(sessionMock).openChannel("sftp");
87         verifyNoMoreInteractions(sessionMock);
88
89         verify(channelMock).connect();
90         verifyNoMoreInteractions(channelMock);
91     }
92
93     @Test
94     public void openWithoutPort_success() throws Exception {
95         FileServerData expectedFileServerData = FileServerData.builder() //
96             .serverAddress(HOST) //
97             .userId(USERNAME) //
98             .password(PASSWORD) //
99             .port(null) //
100             .build();
101
102         SftpClient sftpClientSpy = spy(new SftpClient(expectedFileServerData, createSampleSftpClientSettings()));
103
104         doReturn(jschMock).when(sftpClientSpy).createJsch();
105         when(jschMock.getSession(anyString(), anyString(), anyInt())).thenReturn(sessionMock);
106         when(sessionMock.openChannel(anyString())).thenReturn(channelMock);
107
108         sftpClientSpy.open();
109
110         verify(jschMock).getSession(USERNAME, HOST, 22);
111     }
112
113     @Test
114     public void open_throwsExceptionWithRetry() throws Exception {
115         FileServerData expectedFileServerData = FileServerData.builder() //
116             .serverAddress(HOST) //
117             .userId(USERNAME) //
118             .password(PASSWORD) //
119             .port(SFTP_PORT) //
120             .build();
121
122         SftpClient sftpClientSpy = spy(new SftpClient(expectedFileServerData, createSampleSftpClientSettings()));
123
124         doReturn(jschMock).when(sftpClientSpy).createJsch();
125         when(jschMock.getSession(anyString(), anyString(), anyInt())).thenThrow(new JSchException("Failed"));
126
127         DatafileTaskException exception = assertThrows(DatafileTaskException.class, () -> sftpClientSpy.open());
128         assertEquals("Could not open Sftp client. com.jcraft.jsch.JSchException: Failed", exception.getMessage());
129     }
130
131     @Test
132     public void openAuthFail_throwsExceptionWithoutRetry() throws Exception {
133         FileServerData expectedFileServerData = FileServerData.builder() //
134             .serverAddress(HOST) //
135             .userId(USERNAME) //
136             .password(PASSWORD) //
137             .port(SFTP_PORT) //
138             .build();
139
140         SftpClient sftpClientSpy = spy(new SftpClient(expectedFileServerData, createSampleSftpClientSettings()));
141
142         doReturn(jschMock).when(sftpClientSpy).createJsch();
143         when(jschMock.getSession(anyString(), anyString(), anyInt())).thenThrow(new JSchException("Auth fail"));
144
145         NonRetryableDatafileTaskException exception =
146             assertThrows(NonRetryableDatafileTaskException.class, () -> sftpClientSpy.open());
147         assertEquals(
148             "Could not open Sftp client, no retry attempts will be done. com.jcraft.jsch.JSchException: Auth fail",
149             exception.getMessage());
150     }
151
152     @SuppressWarnings("resource")
153     @Test
154     public void collectFile_success() throws DatafileTaskException, SftpException {
155         FileServerData expectedFileServerData = FileServerData.builder() //
156             .serverAddress(HOST) //
157             .userId(USERNAME) //
158             .password(PASSWORD) //
159             .port(SFTP_PORT) //
160             .build();
161         SftpClient sftpClient = new SftpClient(expectedFileServerData, createSampleSftpClientSettings());
162
163         sftpClient.sftpChannel = channelMock;
164
165         sftpClient.collectFile("remote.xml", Paths.get("local.xml"));
166
167         verify(channelMock).get("remote.xml", "local.xml");
168         verifyNoMoreInteractions(channelMock);
169     }
170
171     @Test
172     public void collectFile_throwsExceptionWithRetry() throws SftpException {
173         FileServerData expectedFileServerData = FileServerData.builder() //
174             .serverAddress(HOST) //
175             .userId(USERNAME) //
176             .password(PASSWORD) //
177             .port(SFTP_PORT) //
178             .build();
179
180         try (SftpClient sftpClient = new SftpClient(expectedFileServerData, createSampleSftpClientSettings())) {
181             sftpClient.sftpChannel = channelMock;
182             doThrow(new SftpException(ChannelSftp.SSH_FX_BAD_MESSAGE, "Failed")).when(channelMock).get(anyString(),
183                 anyString());
184
185             assertThatThrownBy(() -> sftpClient.collectFile("remoteFile", Paths.get("localFile")))
186                 .isInstanceOf(DatafileTaskException.class).hasMessageStartingWith("Unable to get file from xNF. ")
187                 .hasMessageContaining(HOST);
188         }
189     }
190
191     @Test
192     public void collectFileFileMissing_throwsExceptionWithoutRetry() throws SftpException {
193         FileServerData expectedFileServerData = FileServerData.builder() //
194             .serverAddress(HOST) //
195             .userId(USERNAME) //
196             .password(PASSWORD) //
197             .port(SFTP_PORT) //
198             .build();
199
200         try (SftpClient sftpClient = new SftpClient(expectedFileServerData, createSampleSftpClientSettings())) {
201             sftpClient.sftpChannel = channelMock;
202             doThrow(new SftpException(ChannelSftp.SSH_FX_NO_SUCH_FILE, "Failed")).when(channelMock).get(anyString(),
203                 anyString());
204
205             assertThatThrownBy(() -> sftpClient.collectFile("remoteFile", Paths.get("localFile")))
206                 .isInstanceOf(NonRetryableDatafileTaskException.class)
207                 .hasMessageStartingWith("Unable to get file from xNF. No retry attempts will be done")
208                 .hasMessageContaining("" + SFTP_PORT);
209         }
210     }
211
212     @Test
213     public void close_success() {
214         SftpClient sftpClient = new SftpClient(null, createSampleSftpClientSettings());
215
216         sftpClient.session = sessionMock;
217         sftpClient.sftpChannel = channelMock;
218
219         sftpClient.close();
220
221         verify(sessionMock).disconnect();
222         verifyNoMoreInteractions(sessionMock);
223
224         verify(channelMock).exit();;
225         verifyNoMoreInteractions(channelMock);
226     }
227
228     private SftpClientSettings createSampleSftpClientSettings() {
229         return new SftpClientSettings(createSampleSftpConfigNoStrictHostChecking());
230     }
231
232     private SftpConfig createSampleSftpConfigNoStrictHostChecking() {
233         return SftpConfig.builder() //
234             .strictHostKeyChecking(false).knownHostsFilePath("N/A").build();
235     }
236
237 }