2 * ============LICENSE_START======================================================================
3 * Copyright (C) 2018-2023 Nordix Foundation. All rights reserved.
4 * Copyright (C) 2020 Nokia. All rights reserved.
5 * ===============================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7 * in compliance with the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software distributed under the License
12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing permissions and limitations under
15 * ============LICENSE_END========================================================================
18 package org.oran.datafile.ftp;
20 import static org.assertj.core.api.Assertions.assertThatThrownBy;
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.doThrow;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.times;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.verifyNoMoreInteractions;
29 import static org.mockito.Mockito.when;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.io.OutputStream;
34 import java.nio.file.Path;
35 import java.nio.file.Paths;
37 import javax.net.ssl.KeyManager;
38 import javax.net.ssl.TrustManager;
40 import org.apache.commons.net.ftp.FTP;
41 import org.apache.commons.net.ftp.FTPSClient;
42 import org.junit.jupiter.api.BeforeEach;
43 import org.junit.jupiter.api.Test;
44 import org.mockito.ArgumentMatchers;
45 import org.oran.datafile.model.FileServerData;
46 import org.springframework.http.HttpStatus;
48 public class FtpesClientTest {
50 private static final String REMOTE_FILE_PATH = "/dir/sample.txt";
51 private static final Path LOCAL_FILE_PATH = Paths.get("target/sample.txt");
52 private static final String XNF_ADDRESS = "127.0.0.1";
53 private static final int PORT = 8021;
54 private static final String FTP_KEY_PATH = "ftpKeyPath";
55 private static final String FTP_KEY_PASSWORD_PATH = "ftpKeyPasswordPath";
56 private static final Path TRUSTED_CA_PATH = Paths.get("trustedCaPath");
57 private static final String TRUSTED_CA_PASSWORD = "trustedCaPassword";
59 private static final String USERNAME = "bob";
60 private static final String PASSWORD = "123";
62 private FTPSClient ftpsClientMock = mock(FTPSClient.class);
63 private KeyManager keyManagerMock = mock(KeyManager.class);
64 private TrustManager trustManagerMock = mock(TrustManager.class);
65 private InputStream inputStreamMock = mock(InputStream.class);
66 private OutputStream outputStreamMock = mock(OutputStream.class);
68 FtpesClient clientUnderTestSpy;
70 private FileServerData createFileServerData() {
71 return FileServerData.builder() //
72 .serverAddress(XNF_ADDRESS) //
73 .userId(USERNAME).password(PASSWORD) //
79 protected void setUp() throws Exception {
80 clientUnderTestSpy = spy(new FtpesClient(createFileServerData(), Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH,
81 TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD));
82 clientUnderTestSpy.realFtpsClient = ftpsClientMock;
85 private void verifyFtpsClientMock_openOk() throws Exception {
86 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
88 when(ftpsClientMock.retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH),
89 ArgumentMatchers.any(OutputStream.class))).thenReturn(true);
90 verify(ftpsClientMock).setNeedClientAuth(true);
91 verify(ftpsClientMock).setKeyManager(keyManagerMock);
92 verify(ftpsClientMock).setTrustManager(trustManagerMock);
93 verify(ftpsClientMock).connect(XNF_ADDRESS, PORT);
94 verify(ftpsClientMock).login(USERNAME, PASSWORD);
95 verify(ftpsClientMock).getReplyCode();
96 verify(ftpsClientMock, times(1)).enterLocalPassiveMode();
97 verify(ftpsClientMock).execPBSZ(0);
98 verify(ftpsClientMock).execPROT("P");
99 verify(ftpsClientMock).setFileType(FTP.BINARY_FILE_TYPE);
100 verify(ftpsClientMock).setBufferSize(1024 * 1024);
104 public void collectFile_allOk() throws Exception {
106 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
107 doReturn(trustManagerMock).when(clientUnderTestSpy).getTrustManager(TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD);
108 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
109 doReturn(true).when(ftpsClientMock).login(USERNAME, PASSWORD);
110 doReturn(HttpStatus.OK.value()).when(ftpsClientMock).getReplyCode();
112 clientUnderTestSpy.open();
114 doReturn(true).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
115 clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH);
117 doReturn(true).when(ftpsClientMock).isConnected();
118 clientUnderTestSpy.close();
120 verifyFtpsClientMock_openOk();
121 verify(ftpsClientMock, times(1)).isConnected();
122 verify(ftpsClientMock, times(1)).logout();
123 verify(ftpsClientMock, times(1)).disconnect();
124 verify(ftpsClientMock, times(1)).retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH), any());
125 verifyNoMoreInteractions(ftpsClientMock);
129 public void collectFileFaultyOwnKey_shouldFail() throws Exception {
131 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
132 assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection:");
134 verify(ftpsClientMock).setNeedClientAuth(true);
136 doReturn(false).when(ftpsClientMock).isConnected();
137 clientUnderTestSpy.close();
138 verify(ftpsClientMock).isConnected();
139 verifyNoMoreInteractions(ftpsClientMock);
143 public void collectFileFaultTrustedCA_shouldFail_no_trustedCA_file() throws Exception {
145 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
146 doThrow(new IOException("problem")).when(clientUnderTestSpy).createInputStream(TRUSTED_CA_PATH);
148 assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection:");
153 public void collectFileFaultTrustedCA_shouldFail_empty_trustedCA_file() throws Exception {
155 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
156 doReturn(inputStreamMock).when(clientUnderTestSpy).createInputStream(TRUSTED_CA_PATH);
158 assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection: ");
162 public void collectFileFaultyLogin_shouldFail() throws Exception {
164 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
165 doReturn(trustManagerMock).when(clientUnderTestSpy).getTrustManager(TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD);
166 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
167 doReturn(false).when(ftpsClientMock).login(USERNAME, PASSWORD);
169 assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessage("Unable to log in to xNF. 127.0.0.1");
171 verify(ftpsClientMock).setNeedClientAuth(true);
172 verify(ftpsClientMock).setKeyManager(keyManagerMock);
173 verify(ftpsClientMock).setTrustManager(trustManagerMock);
174 verify(ftpsClientMock).connect(XNF_ADDRESS, PORT);
175 verify(ftpsClientMock).login(USERNAME, PASSWORD);
179 public void collectFileBadRequestResponse_shouldFail() throws Exception {
180 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
181 doReturn(trustManagerMock).when(clientUnderTestSpy).getTrustManager(TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD);
182 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
183 doReturn(true).when(ftpsClientMock).login(USERNAME, PASSWORD);
184 doReturn(503).when(ftpsClientMock).getReplyCode();
186 assertThatThrownBy(() -> clientUnderTestSpy.open())
187 .hasMessage("Unable to connect to xNF. 127.0.0.1 xNF reply code: 503");
189 verify(ftpsClientMock).setNeedClientAuth(true);
190 verify(ftpsClientMock).setKeyManager(keyManagerMock);
191 verify(ftpsClientMock).setTrustManager(trustManagerMock);
192 verify(ftpsClientMock).connect(XNF_ADDRESS, PORT);
193 verify(ftpsClientMock).login(USERNAME, PASSWORD);
194 verify(ftpsClientMock, times(2)).getReplyCode();
195 verifyNoMoreInteractions(ftpsClientMock);
199 public void collectFile_shouldFail() throws Exception {
200 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
201 doReturn(trustManagerMock).when(clientUnderTestSpy).getTrustManager(TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD);
202 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
203 doReturn(true).when(ftpsClientMock).login(USERNAME, PASSWORD);
204 doReturn(HttpStatus.OK.value()).when(ftpsClientMock).getReplyCode();
205 clientUnderTestSpy.open();
207 doReturn(false).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
209 assertThatThrownBy(() -> clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH))
210 .hasMessageContaining(REMOTE_FILE_PATH).hasMessageContaining("No retry");
212 verifyFtpsClientMock_openOk();
213 verify(ftpsClientMock, times(1)).retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH), any());
214 verifyNoMoreInteractions(ftpsClientMock);
218 public void collectFile_shouldFail_ioexception() throws Exception {
219 doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
220 doReturn(trustManagerMock).when(clientUnderTestSpy).getTrustManager(TRUSTED_CA_PATH, TRUSTED_CA_PASSWORD);
221 doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
222 doReturn(true).when(ftpsClientMock).login(USERNAME, PASSWORD);
223 doReturn(HttpStatus.OK.value()).when(ftpsClientMock).getReplyCode();
224 clientUnderTestSpy.open();
225 when(ftpsClientMock.isConnected()).thenReturn(false);
227 doThrow(new IOException("problem")).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
229 assertThatThrownBy(() -> clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH))
230 .hasMessage("Could not fetch file: java.io.IOException: problem");
232 verifyFtpsClientMock_openOk();
233 verify(ftpsClientMock, times(1)).retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH), any());
234 verifyNoMoreInteractions(ftpsClientMock);