ef3310adc9ae4aa9908d3396547a3f1001811f55
[nonrtric/plt/ranpm.git] / datafilecollector / src / test / java / org / oran / datafile / ftp / FtpesClientTest.java
1 /*
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
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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
14  * the License.
15  * ============LICENSE_END========================================================================
16  */
17
18 package org.oran.datafile.ftp;
19
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;
30
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;
36
37 import javax.net.ssl.KeyManager;
38 import javax.net.ssl.TrustManager;
39
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;
47
48 public class FtpesClientTest {
49
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";
58
59     private static final String USERNAME = "bob";
60     private static final String PASSWORD = "123";
61
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);
67
68     FtpesClient clientUnderTestSpy;
69
70     private FileServerData createFileServerData() {
71         return FileServerData.builder() //
72             .serverAddress(XNF_ADDRESS) //
73             .userId(USERNAME).password(PASSWORD) //
74             .port(PORT) //
75             .build();
76     }
77
78     @BeforeEach
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;
83     }
84
85     private void verifyFtpsClientMock_openOk() throws Exception {
86         doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
87
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);
101     }
102
103     @Test
104     public void collectFile_allOk() throws Exception {
105
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();
111
112         clientUnderTestSpy.open();
113
114         doReturn(true).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
115         clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH);
116
117         doReturn(true).when(ftpsClientMock).isConnected();
118         clientUnderTestSpy.close();
119
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);
126     }
127
128     @Test
129     public void collectFileFaultyOwnKey_shouldFail() throws Exception {
130
131         doReturn(outputStreamMock).when(clientUnderTestSpy).createOutputStream(LOCAL_FILE_PATH);
132         assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection:");
133
134         verify(ftpsClientMock).setNeedClientAuth(true);
135
136         doReturn(false).when(ftpsClientMock).isConnected();
137         clientUnderTestSpy.close();
138         verify(ftpsClientMock).isConnected();
139         verifyNoMoreInteractions(ftpsClientMock);
140     }
141
142     @Test
143     public void collectFileFaultTrustedCA_shouldFail_no_trustedCA_file() throws Exception {
144
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);
147
148         assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection:");
149
150     }
151
152     @Test
153     public void collectFileFaultTrustedCA_shouldFail_empty_trustedCA_file() throws Exception {
154
155         doReturn(keyManagerMock).when(clientUnderTestSpy).getKeyManager(Paths.get(FTP_KEY_PATH), FTP_KEY_PASSWORD_PATH);
156         doReturn(inputStreamMock).when(clientUnderTestSpy).createInputStream(TRUSTED_CA_PATH);
157
158         assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessageContaining("Could not open connection: ");
159     }
160
161     @Test
162     public void collectFileFaultyLogin_shouldFail() throws Exception {
163
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);
168
169         assertThatThrownBy(() -> clientUnderTestSpy.open()).hasMessage("Unable to log in to xNF. 127.0.0.1");
170
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);
176     }
177
178     @Test
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();
185
186         assertThatThrownBy(() -> clientUnderTestSpy.open())
187             .hasMessage("Unable to connect to xNF. 127.0.0.1 xNF reply code: 503");
188
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);
196     }
197
198     @Test
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();
206
207         doReturn(false).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
208
209         assertThatThrownBy(() -> clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH))
210             .hasMessageContaining(REMOTE_FILE_PATH).hasMessageContaining("No retry");
211
212         verifyFtpsClientMock_openOk();
213         verify(ftpsClientMock, times(1)).retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH), any());
214         verifyNoMoreInteractions(ftpsClientMock);
215     }
216
217     @Test
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);
226
227         doThrow(new IOException("problem")).when(ftpsClientMock).retrieveFile(REMOTE_FILE_PATH, outputStreamMock);
228
229         assertThatThrownBy(() -> clientUnderTestSpy.collectFile(REMOTE_FILE_PATH, LOCAL_FILE_PATH))
230             .hasMessage("Could not fetch file: java.io.IOException: problem");
231
232         verifyFtpsClientMock_openOk();
233         verify(ftpsClientMock, times(1)).retrieveFile(ArgumentMatchers.eq(REMOTE_FILE_PATH), any());
234         verifyNoMoreInteractions(ftpsClientMock);
235     }
236 }