import static org.onap.vid.client.SyncRestClientInterface.HEADERS.AUTHORIZATION;
import static org.onap.vid.client.SyncRestClientInterface.HEADERS.CONTENT_TYPE;
import static org.onap.vid.client.SyncRestClientInterface.HEADERS.X_ECOMP_INSTANCE_ID;
+import static org.onap.vid.client.UnirestPatchKt.extractRawAsString;
import static org.onap.vid.utils.Logging.REQUEST_ID_HEADER_KEY;
import static org.onap.vid.utils.Logging.logRequest;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.ResponseProcessingException;
import org.onap.portalsdk.core.util.SystemProperties;
import org.onap.vid.aai.ExceptionWithRequestInfo;
import org.onap.vid.aai.HttpResponseWithRequestInfo;
@Override
public Path getServiceToscaModel(UUID uuid) throws AsdcCatalogException {
- InputStream inputStream = Try
- .of(() -> getServiceInputStream(uuid, false))
- .getOrElseThrow(AsdcCatalogException::new)
- .getResponse()
- .getBody();
-
- return createTmpFile(inputStream);
+ try {
+ HttpResponseWithRequestInfo<InputStream> responseWithRequestInfo = getServiceInputStream(uuid, false);
+
+ if (responseWithRequestInfo.getResponse().getStatus()>399) {
+ Logging.logResponse(LOGGER, HttpMethod.GET,
+ responseWithRequestInfo.getRequestUrl(), responseWithRequestInfo.getResponse());
+
+ String body = extractRawAsString(responseWithRequestInfo.getResponse());
+ throw new AsdcCatalogException(String.format("Http bad status code: %s, body: %s",
+ responseWithRequestInfo.getResponse().getStatus(),
+ body));
+ }
+
+ final InputStream csarInputStream = responseWithRequestInfo.getResponse().getBody();
+ Path toscaFilePath = createTmpFile(csarInputStream);
+ LOGGER.debug("Received {} {} . Tosca file was saved at: {}",
+ responseWithRequestInfo.getRequestHttpMethod().name(),
+ responseWithRequestInfo.getRequestUrl(),
+ toscaFilePath.toAbsolutePath());
+ return toscaFilePath;
+ } catch (ResponseProcessingException e) {
+ //Couldn't convert response to Java type
+ throw new AsdcCatalogException("ASDC response could not be processed", e);
+ } catch (ProcessingException e) {
+ //IO problems during request
+ throw new AsdcCatalogException("Failed to get a response from ASDC service. Cause: " + e.getMessage(), e);
+ } catch (RuntimeException e) {
+ throw new AsdcCatalogException(e);
+ }
}
@Override
import io.joshworks.restclient.http.Headers
import io.joshworks.restclient.http.HttpResponse
+import org.apache.commons.io.IOUtils
import org.apache.http.HttpVersion
import org.apache.http.message.BasicHttpResponse
import java.io.InputStream
+import java.nio.charset.StandardCharsets
/// Patch NPE in joshworks's Unirest HttpResponse::getBody when getRawBody is null
fun <T> patched(httpResponse: HttpResponse<T>) =
private val dummyHttpResponse = BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "ok")
+fun extractRawAsString(response: HttpResponse<*>?): String {
+ try {
+ if (response == null || response.rawBody==null) return ""
+ response.rawBody.reset()
+ return IOUtils.toString(response.rawBody, StandardCharsets.UTF_8.name())
+ } catch (e: Exception) {
+ //Nothing to do here
+ }
+
+ return ""
+}
/**
* This class inherits HttpResponse to have compatible interface,
* but implementation is done through delegation to another
package org.onap.vid.model.probes;
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
+import static org.onap.vid.client.UnirestPatchKt.extractRawAsString;
import com.google.common.base.MoreObjects;
-import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.onap.vid.aai.ExceptionWithRequestInfo;
import org.onap.vid.aai.HttpResponseWithRequestInfo;
this.url = response.getRequestUrl();
this.httpCode = response.getResponse().getStatus();
if (readRawData) {
- try {
- response.getResponse().getRawBody().reset();
- this.rawData = IOUtils.toString(response.getResponse().getRawBody(), StandardCharsets.UTF_8.name());
- } catch (Exception e) {
- //Nothing to do here
- }
+ this.rawData = extractRawAsString(response.getResponse());
}
}
-
public HttpMethod getHttpMethod() {
return httpMethod;
}
package org.onap.vid.asdc.rest;
+import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import static org.onap.vid.testUtils.TestUtils.mockGetRawBodyWithStringBody;
import static org.testng.AssertJUnit.fail;
import io.joshworks.restclient.http.HttpResponse;
public void whenJavaxClientThrowException_then_getServiceToscaModelRethrowException(Class<? extends Throwable> expectedType, Consumer<SyncRestClient> setupMocks) throws Exception {
/*
Call chain is like:
- this test -> RestfulAsdcClient -> javax's Client
+ this test -> SdcRestClient -> SdcRestClient -> joshworks client which return joshworks HttpResponse
- In this test, *RestfulAsdcClient* is under test (actual implementation is used), while javax's Client is
- mocked to return pseudo-responses or - better - throw exceptions.
+ In this test, *SdcRestClient* is under test (actual implementation is used), while SdcRestClient is
+ mocked to return pseudo joshworks HttpResponse or - better - throw exceptions.
*/
/// TEST:
fail("exception shall rethrown by getServiceToscaModel once javax client throw exception ");
}
+ @DataProvider
+ public static Object[][] badResponses() {
+ return new Object[][] {
+ {(Consumer<HttpResponse>) response -> {
+ when(response.getStatus()).thenReturn(404);
+ mockGetRawBodyWithStringBody(response,"");},
+ ""
+ },
+ {(Consumer<HttpResponse>) response -> {
+ when(response.getStatus()).thenReturn(405);
+ when(response.getRawBody()).thenThrow(ClassCastException.class);},
+ ""
+ },
+ {(Consumer<HttpResponse>) response -> {
+ when(response.getStatus()).thenReturn(500);
+ mockGetRawBodyWithStringBody(response,"some message");},
+ "some message"
+ },
+ };
+ }
+
+ @Test(dataProvider = "badResponses")
+ public void whenJavaxClientReturnBadCode_then_getServiceToscaModelThrowException(Consumer<HttpResponse> setupMocks, String exceptedBody) throws Exception {
+ /*
+ Call chain is like:
+ this test -> SdcRestClient -> SdcRestClient -> joshworks client which return joshworks HttpResponse
+
+ In this test, *SdcRestClient* is under test (actual implementation is used), while SdcRestClient is
+ mocked to return pseudo joshworks HttpResponse
+ */
+
+ HttpResponse<InputStream> mockResponse = mock(HttpResponse.class);
+ SyncRestClient syncRestClient = mock(SyncRestClient.class);
+ when(syncRestClient.getStream(anyString(), anyMap(), anyMap())).thenReturn(mockResponse);
+
+ // prepare real RestfulAsdcClient (Under test)
+
+ setupMocks.accept(mockResponse);
+
+ try {
+ new SdcRestClient(SAMPLE_BASE_URL, SAMPLE_AUTH, syncRestClient).getServiceToscaModel(UUID.randomUUID());
+ } catch (AsdcCatalogException e) {
+ assertThat(e.getMessage(), containsString(String.valueOf(mockResponse.getStatus())));
+ assertThat(e.getMessage(), containsString(exceptedBody));
+ return; //OK
+ }
+
+ fail("exception shall be thrown by getServiceToscaModel once response contains error code ");
+ }
+
+
}
--- /dev/null
+package org.onap.vid.client
+
+import org.onap.vid.testUtils.TestUtils
+import org.testng.Assert.assertEquals
+import org.testng.annotations.Test
+
+class UnirestPatchKtTest {
+
+ @Test
+ fun givenHttpResponseIsNull_whenExtractRawAsString_emptyStringIsReturn() {
+ val result = extractRawAsString(null)
+ assertEquals(result, "")
+ }
+
+ @Test
+ fun givenHttpResponseBodyIsNull_whenExtractRawAsString_emptyStringIsReturn() {
+ val result = extractRawAsString(TestUtils.createTestHttpResponse(200, null))
+ assertEquals(result, "")
+ }
+
+ @Test
+ fun givenHttpResponseBodyIsString_whenExtractRawAsString_sameStringIsReturn() {
+ val body = "someBody"
+ val result = extractRawAsString(TestUtils.createTestHttpResponse(200, body))
+ assertEquals(result, body)
+ }
+
+ @Test
+ fun givenHttpResponseBodyIsString_whenReadBodyAndExtractRawAsString_sameStringIsReturn() {
+ val body = "someBody"
+ val httpResponse = TestUtils.createTestHttpResponse(200, body);
+ assertEquals(httpResponse.body, body) //read body once
+ val result = extractRawAsString(httpResponse)
+ assertEquals(result, body)
+ }
+}
import io.joshworks.restclient.http.HttpResponse;
import java.io.IOException;
import java.net.URL;
-import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import org.onap.vid.mso.rest.RequestDetails;
import org.onap.vid.mso.rest.RequestDetailsWrapper;
import org.onap.vid.mso.rest.Task;
+import org.onap.vid.testUtils.TestUtils;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.test.context.ContextConfiguration;
HttpResponse<String> httpResponse = mockForGetOrchestrationRequest();
when(httpResponse.getStatus()).thenReturn(statusCode);
when(httpResponse.getBody()).thenReturn(body);
- try {
- when(httpResponse.getRawBody()).thenReturn(IOUtils.toInputStream(body, StandardCharsets.UTF_8.name()));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ TestUtils.mockGetRawBodyWithStringBody(httpResponse, body);
return httpResponse;
}
package org.onap.vid.mso;
-import io.joshworks.restclient.http.HttpResponse;
-import org.apache.http.HttpResponseFactory;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.DefaultHttpResponseFactory;
-import org.apache.http.message.BasicStatusLine;
-import org.testng.annotations.Test;
-
import static org.apache.http.HttpStatus.SC_OK;
-import static org.apache.http.HttpVersion.HTTP_1_1;
import static org.assertj.core.api.Assertions.assertThat;
+import io.joshworks.restclient.http.HttpResponse;
+import org.onap.vid.testUtils.TestUtils;
+import org.testng.annotations.Test;
+
public class MsoUtilTest {
@Test
@Test
public void shouldWrapHttpResponse() throws Exception {
// given
- HttpResponse<String> httpResponse = createTestHttpResponse(SC_OK, null);
+ HttpResponse<String> httpResponse = TestUtils.createTestHttpResponse(SC_OK, null);
// when
MsoResponseWrapper result = MsoUtil.wrapResponse(httpResponse);
// then
public void shouldWrapHttpResponseWithEntity() throws Exception {
// given
String entity = "entity";
- HttpResponse<String> httpResponse = createTestHttpResponse(SC_OK, entity);
+ HttpResponse<String> httpResponse = TestUtils.createTestHttpResponse(SC_OK, entity);
// when
MsoResponseWrapper result = MsoUtil.wrapResponse(httpResponse);
// then
assertThat(result.getStatus()).isEqualTo(SC_OK);
}
- private HttpResponse<String> createTestHttpResponse(int statusCode, String entity) throws Exception {
- HttpResponseFactory factory = new DefaultHttpResponseFactory();
- org.apache.http.HttpResponse response = factory.newHttpResponse(new BasicStatusLine(HTTP_1_1, statusCode, null), null);
- if (entity != null) {
- response.setEntity(new StringEntity(entity));
- }
- return new HttpResponse<>(response, String.class, null);
- }
}
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
import static org.apache.commons.text.CharacterPredicates.DIGITS;
import static org.apache.commons.text.CharacterPredicates.LETTERS;
-import static org.mockito.Matchers.any;
+import static org.apache.http.HttpVersion.HTTP_1_1;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.RETURNS_DEFAULTS;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.code.beanmatchers.BeanMatchers;
import com.google.common.collect.ImmutableList;
+import io.joshworks.restclient.http.HttpResponse;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.core.Response;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.apache.commons.text.RandomStringGenerator;
+import org.apache.http.HttpResponseFactory;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.message.BasicStatusLine;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
import org.onap.portalsdk.core.util.SystemProperties;
import org.onap.vid.asdc.AsdcCatalogException;
import org.onap.vid.asdc.beans.Service;
), CloudConfiguration.class);
}
+ public static OngoingStubbing<InputStream> mockGetRawBodyWithStringBody(HttpResponse<String> httpResponse, String body) {
+ try {
+ return when(httpResponse.getRawBody()).thenReturn(IOUtils.toInputStream(body, StandardCharsets.UTF_8.name()));
+ } catch (IOException e) {
+ ExceptionUtils.rethrow(e);
+ }
+ return null; //never shall get here
+ }
+
+ public static HttpResponse<String> createTestHttpResponse(int statusCode, String entity) throws Exception {
+ HttpResponseFactory factory = new DefaultHttpResponseFactory();
+ org.apache.http.HttpResponse response = factory.newHttpResponse(new BasicStatusLine(HTTP_1_1, statusCode, null), null);
+ if (entity != null) {
+ response.setEntity(new StringEntity(entity));
+ }
+ return new HttpResponse<>(response, String.class, null);
+ }
+
public static class JavaxRsClientMocks {
private final javax.ws.rs.client.Client fakeClient;