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.controller;
23 import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
24 import static org.hamcrest.CoreMatchers.is;
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.hamcrest.Matchers.containsInAnyOrder;
27 import static org.hamcrest.Matchers.emptyOrNullString;
28 import static org.hamcrest.Matchers.equalToIgnoringCase;
29 import static org.hamcrest.Matchers.not;
30 import static org.mockito.ArgumentMatchers.any;
31 import static org.mockito.ArgumentMatchers.argThat;
32 import static org.onap.portalsdk.core.util.SystemProperties.ECOMP_REQUEST_ID;
34 import com.google.common.collect.ImmutableMap;
35 import java.io.IOException;
36 import java.util.Arrays;
37 import java.util.Collection;
38 import java.util.Collections;
39 import java.util.Enumeration;
41 import java.util.function.Function;
42 import javax.servlet.FilterChain;
43 import javax.servlet.ServletException;
44 import javax.servlet.ServletRequest;
45 import javax.servlet.ServletResponse;
46 import javax.servlet.http.HttpServletRequest;
47 import javax.servlet.http.HttpServletResponse;
48 import org.mockito.ArgumentCaptor;
49 import org.mockito.Mockito;
50 import org.mockito.stubbing.Answer;
51 import org.onap.portalsdk.core.web.support.UserUtils;
52 import org.onap.vid.controller.filter.PromiseRequestIdFilter;
53 import org.springframework.mock.web.MockHttpServletResponse;
54 import org.testng.annotations.Test;
57 public class PromiseRequestIdFilterTest {
59 private final String anotherHeader = "ANDREI_RUBLEV";
60 private final String anotherValue = "foo value";
61 private final String mixedCaseHeader = "x-ecomp-REQUESTID";
64 public void givenRequestIdHeader_headerValueNotChanged() throws IOException, ServletException {
66 final String someTxId = "863850e2-8545-4efd-94b8-afba5f52b3d5";
68 final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
69 anotherHeader, anotherValue,
70 ECOMP_REQUEST_ID, someTxId
73 buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, specificTxId(someTxId));
78 public void givenRequestIdHeaderThatIsNotAUUID_headerValueChanged() throws IOException, ServletException {
80 final String someTxId = "863850e28544efd94b8afba5f52b3d5";
82 final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
83 anotherHeader, anotherValue,
84 ECOMP_REQUEST_ID, someTxId
87 buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, UserUtils::getRequestId);
92 public void givenMixedCaseRequestIdHeader_headerValueNotChanged() throws IOException, ServletException {
94 final String someTxId = "729bbd8d-b0c2-4809-a794-dcccd9cda2c0";
96 final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
97 mixedCaseHeader, someTxId,
98 anotherHeader, anotherValue
101 buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, specificTxId(someTxId));
105 public void givenNoRequestIdHeader_headerValueWasGenerated() throws IOException, ServletException {
107 final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
108 anotherHeader, anotherValue
111 buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, UserUtils::getRequestId);
115 private void buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(
116 ImmutableMap<String, String> originalRequestHeaders,
117 Function<HttpServletRequest, String> txIdExtractor
118 ) throws IOException, ServletException {
119 HttpServletRequest servletRequest = createMockedHttpServletRequest(originalRequestHeaders);
120 HttpServletResponse servletResponse = createMockedHttpServletResponse();
122 final FilterChain capturingFilterChain = Mockito.mock(FilterChain.class);
126 // doFilter() is the function under test
128 new PromiseRequestIdFilter().doFilter(servletRequest, servletResponse, capturingFilterChain);
132 final ServletRequest capturedServletRequest = extractCapturedServletRequest(capturingFilterChain);
133 final ServletResponse capturedServletResponse = extractCapturedServletResponse(capturingFilterChain);
134 final String expectedTxId = txIdExtractor.apply((HttpServletRequest) capturedServletRequest);
136 assertRequestObjectHeaders(capturedServletRequest, expectedTxId);
137 assertResponseObjectHeaders(capturedServletResponse, expectedTxId);
141 private void assertRequestObjectHeaders(ServletRequest request, String expectedTxId) {
144 - Two headers are in place
145 - Direct value extraction is as expected
146 - UserUtils.getRequestId() returns correct and valid value
148 final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
150 assertThat(Collections.list(httpServletRequest.getHeaderNames()),
151 containsInAnyOrder(equalToIgnoringCase(ECOMP_REQUEST_ID), equalToIgnoringCase(anotherHeader)));
153 assertThat(httpServletRequest.getHeader(anotherHeader), is(anotherValue));
155 assertThat(httpServletRequest.getHeader(ECOMP_REQUEST_ID), is(expectedTxId));
156 assertThat(httpServletRequest.getHeader(mixedCaseHeader), is(expectedTxId));
158 assertThat(UserUtils.getRequestId(httpServletRequest), is(expectedTxId));
159 assertThat(UserUtils.getRequestId(httpServletRequest), is(not(emptyOrNullString())));
162 private void assertResponseObjectHeaders(ServletResponse response, String txId) {
163 final String REQUEST_ID_HEADER_NAME_IN_RESPONSE = mixedCaseHeader + "-echo";
164 final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
166 assertThat("header " + REQUEST_ID_HEADER_NAME_IN_RESPONSE.toLowerCase() + " in response must be provided",
167 httpServletResponse.getHeader(REQUEST_ID_HEADER_NAME_IN_RESPONSE), is(txId));
172 private HttpServletRequest createMockedHttpServletRequest(Map<String, String> requestHeaders) {
173 HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
174 requestHeaders.forEach((k, v) -> {
175 Mockito.when(servletRequest.getHeader(argThat(s -> equalsIgnoreCase(s, k)))).thenReturn(v);
176 Mockito.when(servletRequest.getHeaders(argThat(s -> equalsIgnoreCase(s, k)))).then(returnEnumerationAnswer(v));
178 Mockito.when(servletRequest.getHeaderNames()).then(returnEnumerationAnswer(requestHeaders.keySet()));
179 return servletRequest;
182 private HttpServletResponse createMockedHttpServletResponse() {
183 return new MockHttpServletResponse();
186 private static Answer<Enumeration<String>> returnEnumerationAnswer(String ... items) {
187 return returnEnumerationAnswer(Arrays.asList(items));
190 private static Answer<Enumeration<String>> returnEnumerationAnswer(Collection<String> items) {
191 return invocation -> Collections.enumeration(items);
194 private Function<HttpServletRequest, String> specificTxId(String someTxId) {
195 return r -> someTxId;
198 private ServletRequest extractCapturedServletRequest(FilterChain capturingFilterChain) throws IOException, ServletException {
199 ArgumentCaptor<ServletRequest> captor = ArgumentCaptor.forClass(ServletRequest.class);
200 Mockito.verify(capturingFilterChain).doFilter(captor.capture(), any());
201 return captor.getValue();
204 private ServletResponse extractCapturedServletResponse(FilterChain capturingFilterChain) throws IOException, ServletException {
205 ArgumentCaptor<ServletResponse> captor = ArgumentCaptor.forClass(ServletResponse.class);
206 Mockito.verify(capturingFilterChain).doFilter(any(), captor.capture());
207 return captor.getValue();