2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.vid.mso.rest;
23 import static org.apache.commons.io.IOUtils.toInputStream;
24 import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
25 import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
26 import static org.hamcrest.CoreMatchers.is;
27 import static org.hamcrest.CoreMatchers.startsWith;
28 import static org.hamcrest.MatcherAssert.assertThat;
29 import static org.hamcrest.Matchers.allOf;
30 import static org.hamcrest.Matchers.hasItem;
31 import static org.hamcrest.Matchers.hasToString;
32 import static org.hamcrest.Matchers.instanceOf;
33 import static org.hamcrest.Matchers.matchesPattern;
34 import static org.junit.Assert.assertEquals;
35 import static org.junit.Assert.assertNotEquals;
36 import static org.mockito.ArgumentMatchers.any;
37 import static org.mockito.ArgumentMatchers.anyMap;
38 import static org.mockito.ArgumentMatchers.anyString;
39 import static org.mockito.ArgumentMatchers.eq;
40 import static org.mockito.Mockito.mock;
41 import static org.mockito.Mockito.reset;
42 import static org.mockito.Mockito.when;
44 import com.google.common.collect.ImmutableList;
45 import io.joshworks.restclient.http.HttpResponse;
46 import java.nio.charset.StandardCharsets;
48 import java.util.Optional;
50 import java.util.UUID;
51 import java.util.function.Consumer;
52 import java.util.stream.Collectors;
53 import java.util.stream.Stream;
54 import javax.servlet.http.HttpServletRequest;
55 import javax.ws.rs.client.Client;
56 import javax.ws.rs.client.Invocation;
57 import javax.ws.rs.client.Invocation.Builder;
58 import javax.ws.rs.core.MultivaluedMap;
59 import org.apache.commons.lang3.reflect.FieldUtils;
60 import org.mockito.ArgumentCaptor;
61 import org.mockito.Captor;
62 import org.mockito.InjectMocks;
63 import org.mockito.Matchers;
64 import org.mockito.Mock;
65 import org.mockito.Mockito;
66 import org.mockito.MockitoAnnotations;
67 import org.onap.portalsdk.core.util.SystemProperties;
68 import org.onap.vid.aai.util.HttpsAuthClient;
69 import org.onap.vid.aai.util.ServletRequestHelper;
70 import org.onap.vid.aai.util.SystemPropertyHelper;
71 import org.onap.vid.client.SyncRestClient;
72 import org.onap.vid.controller.filter.PromiseRequestIdFilter;
73 import org.onap.vid.logging.Headers;
74 import org.onap.vid.mso.MsoProperties;
75 import org.onap.vid.mso.RestMsoImplementation;
76 import org.onap.vid.testUtils.TestUtils;
77 import org.onap.vid.utils.Logging;
78 import org.onap.vid.utils.SystemPropertiesWrapper;
79 import org.springframework.http.HttpMethod;
80 import org.springframework.mock.web.MockHttpServletRequest;
81 import org.springframework.web.context.request.RequestContextHolder;
82 import org.springframework.web.context.request.ServletRequestAttributes;
83 import org.testng.annotations.BeforeClass;
84 import org.testng.annotations.BeforeMethod;
85 import org.testng.annotations.DataProvider;
86 import org.testng.annotations.Test;
89 public class OutgoingRequestHeadersTest {
91 private static final PromiseRequestIdFilter promiseRequestIdFilter = new PromiseRequestIdFilter();
94 private RestMsoImplementation restMsoImplementation;
96 private MsoRestClientNew msoRestClientNew;
99 private SystemPropertyHelper systemPropertyHelper;
102 private SystemPropertiesWrapper systemPropertiesWrapper;
105 private HttpsAuthClient httpsAuthClient;
108 private ServletRequestHelper servletRequestHelper;
111 private Logging loggingService;
114 SyncRestClient syncRestClient;
117 private ArgumentCaptor<MultivaluedMap<String, Object>> multivaluedMapArgumentCaptor;
120 public void initMocks() {
121 MockitoAnnotations.initMocks(this);
122 String oneIncomingRequestId = UUID.randomUUID().toString();
123 when(servletRequestHelper.extractOrGenerateRequestId()).thenReturn(oneIncomingRequestId);
124 when(systemPropertiesWrapper.getProperty(MsoProperties.MSO_PASSWORD)).thenReturn("OBF:1vub1ua51uh81ugi1u9d1vuz");
125 when(systemPropertiesWrapper.getProperty(SystemProperties.APP_DISPLAY_NAME)).thenReturn("vid");
126 //the ctor of MsoRestClientNew require the above lines as preconditions
127 msoRestClientNew = new MsoRestClientNew(syncRestClient, "baseUrl",systemPropertiesWrapper);
131 private void setup() {
132 putRequestInSpringContext();
135 public static void putRequestInSpringContext() {
136 RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(
137 (HttpServletRequest) promiseRequestIdFilter.wrapIfNeeded(new MockHttpServletRequest())));
141 public Object[][] msoMethods() {
142 return Stream.<ThrowingConsumer<RestMsoImplementation>>of(
143 client -> client.GetForObject("/any path", Object.class),
144 client -> client.restCall(HttpMethod.DELETE, Object.class, "some payload", "/any path", Optional.of("userId")),
145 client -> client.PostForObject("some payload", "/any path", Object.class)
146 ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
150 public void whenProvideMsoRestCallUserId_builderHasXRequestorIDHeader() throws Exception {
152 final TestUtils.JavaxRsClientMocks mocks = setAndGetMocksInsideRestImpl(restMsoImplementation);
153 String randomUserName = randomAlphabetic(10);
155 restMsoImplementation.restCall(HttpMethod.DELETE, String.class, null, "abc", Optional.of(randomUserName));
156 assertEquals(randomUserName, captureHeaderKeyAndReturnItsValue(mocks.getFakeBuilder(), "X-RequestorID"));
160 public Object[][] msoRestClientNewMethods() {
161 return Stream.<ThrowingConsumer<MsoRestClientNew>>of(
162 client -> client.createInstance(new Object(), "/any path")
163 ).map(l -> ImmutableList.of(l).toArray()).collect(Collectors.toList()).toArray(new Object[][]{});
166 @Test(dataProvider = "msoRestClientNewMethods")
167 public void msoRestClientNewHeadersTest(Consumer<MsoRestClientNew> f) throws Exception {
168 Map[] captor = setMocksForMsoRestClientNew();
170 f.accept(msoRestClientNew);
171 Map headers = captor[0];
173 String ecompRequestId = assertRequestHeaderIsUUID(headers, "X-ECOMP-RequestID");
174 String onapRequestID = assertRequestHeaderIsUUID(headers, "X-ONAP-RequestID");
175 assertEquals(ecompRequestId, onapRequestID);
178 String invocationId1 = assertRequestHeaderIsUUID(headers, "X-InvocationID");
179 assertThat((String) headers.get("Authorization"), startsWith("Basic "));
180 assertThat(headers.get("X-ONAP-PartnerName"), is("VID.VID"));
182 //verify requestId is same in next call but invocationId is different
185 captor = setMocksForMsoRestClientNew();
188 f.accept(msoRestClientNew);
192 assertEquals(headers.get("X-ONAP-RequestID"), onapRequestID);
193 String invocationId2 = assertRequestHeaderIsUUID(headers, "X-InvocationID");
194 assertNotEquals(invocationId1, invocationId2);
198 private Map[] setMocksForMsoRestClientNew() {
199 reset(syncRestClient);
200 HttpResponse<String> httpResponse = mock(HttpResponse.class);
201 String expectedResponse = "myResponse";
202 when(httpResponse.getStatus()).thenReturn(202);
203 when(httpResponse.getBody()).thenReturn(expectedResponse);
204 when(httpResponse.getRawBody()).thenReturn(toInputStream(expectedResponse, StandardCharsets.UTF_8));
205 final Map[] headersCapture = new Map[1];
206 when(syncRestClient.post(anyString(), anyMap(), any(), eq(String.class))).thenAnswer(
208 headersCapture[0] = (Map)invocation.getArguments()[1];
212 return headersCapture;
215 // @Test(dataProvider = "schedulerMethods")
216 // public void scheduler(Consumer<AAIRestInterface> f) throws Exception {
218 // This test os not feasible in the wat acheduler is implemented today,
219 // as Scheduler's client is rewritten in every call.
225 private String verifyXEcompRequestIdHeaderWasAdded(Invocation.Builder fakeBuilder) {
226 final String requestIdHeader = "x-ecomp-requestid";
227 return assertRequestHeaderIsUUID(fakeBuilder, requestIdHeader);
230 private String assertRequestHeaderIsUUID(Invocation.Builder fakeBuilder, String headerName) {
231 Object headerValue = captureHeaderKeyAndReturnItsValue(fakeBuilder, headerName);
232 return assertRequestHeaderIsUUID(headerName, headerValue);
235 private String assertRequestHeaderIsUUID(Map headers, String headerName) {
236 return assertRequestHeaderIsUUID(headerName, headers.get(headerName));
239 private String assertRequestHeaderIsUUID(String headerName, Object headerValue) {
240 final String uuidRegex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}";
241 assertThat("header '" + headerName + "' should be a uuid", headerValue,
242 allOf(instanceOf(String.class), hasToString(matchesPattern(uuidRegex))));
243 return (String)headerValue;
246 private void verifyXOnapPartnerNameHeaderWasAdded(Invocation.Builder fakeBuilder) {
248 captureHeaderKeyAndReturnItsValue(fakeBuilder, Headers.PARTNER_NAME.getHeaderName()),
253 private Object captureHeaderKeyAndReturnItsValue(Invocation.Builder fakeBuilder, String headerName) {
254 // Checks that the builder was called with either one of header("x-ecomp-requestid", uuid)
255 // or the plural brother: headers(Map.of("x-ecomp-requestid", Set.of(uuid))
258 // The 'verify()' will capture the request id. If no match -- AssertionError will
259 // catch for a second chance -- another 'verify()'.
262 ArgumentCaptor<Object> argumentCaptor = ArgumentCaptor.forClass(Object.class);
263 Mockito.verify(fakeBuilder)
265 Matchers.argThat(s -> equalsIgnoreCase(s, headerName)),
266 argumentCaptor.capture()
268 requestId = argumentCaptor.getValue();
270 } catch (AssertionError e) {
271 Mockito.verify(fakeBuilder).headers(multivaluedMapArgumentCaptor.capture());
273 final MultivaluedMap<String, Object> headersMap = multivaluedMapArgumentCaptor.getValue();
274 final String thisRequestIdHeader = getFromSetCaseInsensitive(headersMap.keySet(), headerName);
276 assertThat(headersMap.keySet(), hasItem(thisRequestIdHeader));
277 requestId = headersMap.getFirst(thisRequestIdHeader);
279 } catch (AssertionError e) {
280 throw new AssertionError("header not captured: " + headerName, e);
285 private String getFromSetCaseInsensitive(Set<String> set, String key) {
287 .filter(anotherString -> anotherString.equalsIgnoreCase(key))
292 private TestUtils.JavaxRsClientMocks setAndGetMocksInsideRestImpl(Class<?> clazz) throws IllegalAccessException {
293 TestUtils.JavaxRsClientMocks mocks = new TestUtils.JavaxRsClientMocks();
294 Client fakeClient = mocks.getFakeClient();
296 FieldUtils.writeStaticField(clazz, "client", fakeClient, true);
301 private TestUtils.JavaxRsClientMocks setAndGetMocksInsideRestImpl(Object instance) throws IllegalAccessException {
302 TestUtils.JavaxRsClientMocks mocks = new TestUtils.JavaxRsClientMocks();
303 Client fakeClient = mocks.getFakeClient();
305 FieldUtils.writeField(instance, "client", fakeClient, true);
311 public interface ThrowingConsumer<T> extends Consumer<T> {
313 default void accept(T t) {
316 } catch (Exception e) {
317 throw new RuntimeException(e);
321 void acceptThrows(T t) throws Exception;
324 private class HeadersVerifier {
326 private String firstRequestId;
327 private String firstInvocationId;
330 HeadersVerifier verifyFirstCall(Builder fakeBuilder) {
331 firstRequestId = verifyXEcompRequestIdHeaderWasAdded(fakeBuilder);
332 assertEquals(firstRequestId, captureHeaderKeyAndReturnItsValue(fakeBuilder, "X-ONAP-RequestID"));
333 firstInvocationId = assertRequestHeaderIsUUID(fakeBuilder, "X-InvocationID");
334 verifyXOnapPartnerNameHeaderWasAdded(fakeBuilder);
338 void verifySecondCall(Builder fakeBuilder) {
339 String secondRequestId = verifyXEcompRequestIdHeaderWasAdded(fakeBuilder);
340 assertEquals(firstRequestId, secondRequestId);
342 Object secondInvocationId = assertRequestHeaderIsUUID(fakeBuilder, "X-InvocationID");
343 assertNotEquals(firstInvocationId, secondInvocationId);