1 package org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client;
3 import static org.mockito.ArgumentMatchers.any;
4 import static org.mockito.ArgumentMatchers.nullable;
5 import static org.mockito.Mockito.when;
7 import io.reactivex.rxjava3.observers.TestObserver;
8 import java.io.ByteArrayInputStream;
9 import java.io.IOException;
10 import java.time.ZoneId;
11 import java.util.Arrays;
12 import java.util.concurrent.CompletableFuture;
13 import java.util.concurrent.Future;
14 import java.util.zip.ZipInputStream;
15 import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
16 import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
17 import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
18 import org.apache.hc.core5.concurrent.FutureCallback;
19 import org.apache.hc.core5.http.ContentType;
20 import org.apache.hc.core5.http.HttpStatus;
21 import org.junit.jupiter.api.MethodOrderer;
22 import org.junit.jupiter.api.Test;
23 import org.junit.jupiter.api.TestMethodOrder;
24 import org.mockito.stubbing.Answer;
25 import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.api.HttpRestClient;
26 import org.o.ran.oam.nf.oam.adopter.pm.rest.manager.pojos.Adapter;
27 import org.o.ran.oam.nf.oam.adopter.pm.sb.rest.client.properties.PmEndpointsUrlsProperties;
28 import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.boot.context.properties.EnableConfigurationProperties;
30 import org.springframework.boot.test.context.SpringBootTest;
31 import org.springframework.boot.test.mock.mockito.MockBean;
32 import org.springframework.test.annotation.DirtiesContext;
33 import org.springframework.test.annotation.DirtiesContext.MethodMode;
35 @SpringBootTest(classes = {DefaultHttpRestClient.class, PmEndpointsUrlsProperties.class})
36 @EnableConfigurationProperties
37 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
38 class DefaultHttpRestClientTest {
40 private static final Adapter ADAPTER =
41 Adapter.builder().hostIpAddress("150.62.25.26").username("admin").password("secretPassword").build();
43 public HttpRestClient restClient;
46 CloseableHttpAsyncClient client;
49 @DirtiesContext(methodMode = MethodMode.BEFORE_METHOD)
50 void testGetFailedToken() {
51 final SimpleHttpResponse response =
52 SimpleHttpResponse.create(HttpStatus.SC_UNAUTHORIZED, "error", ContentType.APPLICATION_JSON);
54 when(client.execute(any(SimpleHttpRequest.class), nullable(FutureCallback.class)))
55 .thenAnswer((Answer<Future<SimpleHttpResponse>>) invocation -> {
56 final SimpleHttpRequest req = (SimpleHttpRequest) invocation.getArguments()[0];
57 if ("/auth/token".equals(req.getPath())) {
58 return CompletableFuture.completedFuture(response);
60 throw new IllegalStateException("Unexpected value: " + req.getPath());
64 final TestObserver<ZoneId> observer = restClient.getTimeZone(ADAPTER).test();
65 observer.assertError(throwable -> throwable.getMessage()
66 .equals("Failed to obtain a token for host https://150.62.25.26: HTTP/1.1 401 Unauthorized"));
70 void testReadFiles() throws IOException {
71 final String tokenJson = JsonUtils.readJson("/json/tokenResponse.json");
72 final SimpleHttpResponse response =
73 SimpleHttpResponse.create(HttpStatus.SC_OK, tokenJson, ContentType.APPLICATION_JSON);
75 final SimpleHttpResponse zipResponse =
76 SimpleHttpResponse.create(HttpStatus.SC_OK, "mockZip", ContentType.APPLICATION_OCTET_STREAM);
78 when(client.execute(any(SimpleHttpRequest.class), nullable(FutureCallback.class)))
79 .thenAnswer((Answer<Future<SimpleHttpResponse>>) invocation -> {
80 final SimpleHttpRequest req = (SimpleHttpRequest) invocation.getArguments()[0];
81 switch (req.getPath()) {
83 return CompletableFuture.completedFuture(response);
85 return CompletableFuture.completedFuture(zipResponse);
87 throw new IllegalStateException("Unexpected value: " + req.getPath());
92 final TestObserver<ZipInputStream> observer = restClient.readFiles(ADAPTER).test();
93 final ZipInputStream expected = new ZipInputStream(new ByteArrayInputStream("mockZip".getBytes()));
94 observer.assertValue(zip -> Arrays.equals(zip.readAllBytes(), expected.readAllBytes()));
98 void testReadFilesResponseFail() throws IOException {
99 final String tokenJson = JsonUtils.readJson("/json/tokenResponse.json");
100 final SimpleHttpResponse response =
101 SimpleHttpResponse.create(HttpStatus.SC_OK, tokenJson, ContentType.APPLICATION_JSON);
103 final SimpleHttpResponse zipResponse = SimpleHttpResponse.create(HttpStatus.SC_BAD_REQUEST, "mockZip",
104 ContentType.APPLICATION_OCTET_STREAM);
106 when(client.execute(any(SimpleHttpRequest.class), nullable(FutureCallback.class)))
107 .thenAnswer((Answer<Future<SimpleHttpResponse>>) invocation -> {
108 final SimpleHttpRequest req = (SimpleHttpRequest) invocation.getArguments()[0];
109 switch (req.getPath()) {
111 return CompletableFuture.completedFuture(response);
113 return CompletableFuture.completedFuture(zipResponse);
115 throw new IllegalStateException("Unexpected value: " + req.getPath());
120 final TestObserver<ZipInputStream> observer = restClient.readFiles(ADAPTER).test();
121 observer.assertError(throwable -> throwable.getMessage()
122 .equals("Download files from 150.62.25.26 failed: HTTP/1.1 400 Bad Request"));
126 void testGetTimeOffset() throws IOException {
127 final String tokenJson = JsonUtils.readJson("/json/tokenResponse.json");
128 final SimpleHttpResponse response =
129 SimpleHttpResponse.create(HttpStatus.SC_OK, tokenJson, ContentType.APPLICATION_JSON);
131 final String timeZoneOFfsetResponseJson = JsonUtils.readJson("/json/timeZoneOffsetResponse.json");
132 final SimpleHttpResponse timeOffsetResponse =
133 SimpleHttpResponse.create(HttpStatus.SC_OK, timeZoneOFfsetResponseJson, ContentType.APPLICATION_JSON);
135 when(client.execute(any(SimpleHttpRequest.class), nullable(FutureCallback.class)))
136 .thenAnswer((Answer<Future<SimpleHttpResponse>>) invocation -> {
137 final SimpleHttpRequest req = (SimpleHttpRequest) invocation.getArguments()[0];
138 switch (req.getPath()) {
140 return CompletableFuture.completedFuture(response);
141 case "/system/timeZone":
142 return CompletableFuture.completedFuture(timeOffsetResponse);
144 throw new IllegalStateException("Unexpected value: " + req.getPath());
149 final TestObserver<ZoneId> observer = restClient.getTimeZone(ADAPTER).test();
150 observer.assertValues(ZoneId.of("+02:00"));
154 void testGetTimeOffsetFail() throws IOException {
155 final String tokenJson = JsonUtils.readJson("/json/tokenResponse.json");
156 final SimpleHttpResponse response =
157 SimpleHttpResponse.create(HttpStatus.SC_OK, tokenJson, ContentType.APPLICATION_JSON);
159 final SimpleHttpResponse timeOffsetResponse =
160 SimpleHttpResponse.create(HttpStatus.SC_OK, "", ContentType.APPLICATION_JSON);
162 when(client.execute(any(SimpleHttpRequest.class), nullable(FutureCallback.class)))
163 .thenAnswer((Answer<Future<SimpleHttpResponse>>) invocation -> {
164 final SimpleHttpRequest req = (SimpleHttpRequest) invocation.getArguments()[0];
165 switch (req.getPath()) {
167 return CompletableFuture.completedFuture(response);
168 case "/system/timeZone":
169 return CompletableFuture.completedFuture(timeOffsetResponse);
171 throw new IllegalStateException("Unexpected value: " + req.getPath());
176 final TestObserver<ZoneId> observer = restClient.getTimeZone(ADAPTER).test();
177 observer.assertError(throwable -> throwable.getMessage()
178 .equals("Get Zone offset failed for 150.62.25.26 . Empty output received"));
182 void testGetTimeOffsetFailExecutionException() {
183 final TestObserver<ZoneId> observer = restClient.getTimeZone(ADAPTER).test();
184 observer.assertError(throwable -> throwable.getMessage().equals("Failed to get Zone ID for 150.62.25.26"));