Merge changes from topics "VID-14", "VID-13", "VID-12"
[vid.git] / vid-app-common / src / test / java / org / onap / vid / controller / PromiseEcompRequestIdFilterTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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=========================================================
19  */
20
21 package org.onap.vid.controller;
22
23 import com.google.common.collect.ImmutableMap;
24 import org.mockito.ArgumentCaptor;
25 import org.mockito.Mockito;
26 import org.mockito.stubbing.Answer;
27 import org.onap.portalsdk.core.web.support.UserUtils;
28 import org.onap.vid.controller.filter.PromiseEcompRequestIdFilter;
29 import org.springframework.mock.web.MockHttpServletResponse;
30 import org.testng.annotations.Test;
31
32 import javax.servlet.FilterChain;
33 import javax.servlet.ServletException;
34 import javax.servlet.ServletRequest;
35 import javax.servlet.ServletResponse;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38 import java.io.IOException;
39 import java.util.*;
40 import java.util.function.Function;
41
42 import static org.apache.commons.lang3.StringUtils.equalsIgnoreCase;
43 import static org.hamcrest.CoreMatchers.is;
44 import static org.hamcrest.MatcherAssert.assertThat;
45 import static org.hamcrest.Matchers.*;
46 import static org.mockito.ArgumentMatchers.any;
47 import static org.mockito.ArgumentMatchers.argThat;
48 import static org.onap.portalsdk.core.util.SystemProperties.ECOMP_REQUEST_ID;
49
50 @Test
51 public class PromiseEcompRequestIdFilterTest {
52
53     private final String anotherHeader = "ANDREI_RUBLEV";
54     private final String anotherValue = "foo value";
55     private final String mixedCaseHeader = "x-ecomp-REQUESTID";
56
57     @Test
58     public void givenRequestIdHeader_headerValueNotChanged() throws IOException, ServletException {
59
60         final String someTxId = "863850e2-8545-4efd-94b8-afba5f52b3d5";
61
62         final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
63                 anotherHeader, anotherValue,
64                 ECOMP_REQUEST_ID, someTxId
65         );
66
67         buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, specificTxId(someTxId));
68     }
69
70
71     @Test
72     public void givenRequestIdHeaderThatIsNotAUUID_headerValueChanged() throws IOException, ServletException {
73
74         final String someTxId = "863850e28544efd94b8afba5f52b3d5";
75
76         final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
77                 anotherHeader, anotherValue,
78                 ECOMP_REQUEST_ID, someTxId
79         );
80
81         buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, UserUtils::getRequestId);
82     }
83
84
85     @Test
86     public void givenMixedCaseRequestIdHeader_headerValueNotChanged() throws IOException, ServletException {
87
88         final String someTxId = "729bbd8d-b0c2-4809-a794-dcccd9cda2c0";
89
90         final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
91                 mixedCaseHeader, someTxId,
92                 anotherHeader, anotherValue
93         );
94
95         buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, specificTxId(someTxId));
96     }
97
98     @Test
99     public void givenNoRequestIdHeader_headerValueWasGenerated() throws IOException, ServletException {
100
101         final ImmutableMap<String, String> incomingRequestHeaders = ImmutableMap.of(
102                 anotherHeader, anotherValue
103         );
104
105         buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(incomingRequestHeaders, UserUtils::getRequestId);
106     }
107
108     
109     private void buildRequestThenRunThroughFilterAndAssertResultRequestHeaders(
110             ImmutableMap<String, String> originalRequestHeaders,
111             Function<HttpServletRequest, String> txIdExtractor
112     ) throws IOException, ServletException {
113         HttpServletRequest servletRequest = createMockedHttpServletRequest(originalRequestHeaders);
114         HttpServletResponse servletResponse = createMockedHttpServletResponse();
115
116         final FilterChain capturingFilterChain = Mockito.mock(FilterChain.class);
117
118         //////////////////
119         //
120         // doFilter() is the function under test
121         //
122         new PromiseEcompRequestIdFilter().doFilter(servletRequest, servletResponse, capturingFilterChain);
123         //
124         //////////////////
125
126         final ServletRequest capturedServletRequest = extractCapturedServletRequest(capturingFilterChain);
127         final ServletResponse capturedServletResponse = extractCapturedServletResponse(capturingFilterChain);
128         final String expectedTxId = txIdExtractor.apply((HttpServletRequest) capturedServletRequest);
129
130         assertRequestObjectHeaders(capturedServletRequest, expectedTxId);
131         assertResponseObjectHeaders(capturedServletResponse, expectedTxId);
132     }
133
134
135     private void assertRequestObjectHeaders(ServletRequest request, String expectedTxId) {
136         /*
137         Assert that:
138         - Two headers are in place
139         - Direct value extraction is as expected
140         - UserUtils.getRequestId() returns correct and valid value
141          */
142         final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
143
144         assertThat(Collections.list(httpServletRequest.getHeaderNames()),
145                 containsInAnyOrder(equalToIgnoringCase(ECOMP_REQUEST_ID), equalToIgnoringCase(anotherHeader)));
146
147         assertThat(httpServletRequest.getHeader(anotherHeader), is(anotherValue));
148
149         assertThat(httpServletRequest.getHeader(ECOMP_REQUEST_ID), is(expectedTxId));
150         assertThat(httpServletRequest.getHeader(mixedCaseHeader), is(expectedTxId));
151
152         assertThat(UserUtils.getRequestId(httpServletRequest), is(expectedTxId));
153         assertThat(UserUtils.getRequestId(httpServletRequest), is(not(emptyOrNullString())));
154     }
155
156     private void assertResponseObjectHeaders(ServletResponse response, String txId) {
157         final String REQUEST_ID_HEADER_NAME_IN_RESPONSE = mixedCaseHeader + "-echo";
158         final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
159
160         assertThat("header " + REQUEST_ID_HEADER_NAME_IN_RESPONSE.toLowerCase() + " in response must be provided",
161                 httpServletResponse.getHeader(REQUEST_ID_HEADER_NAME_IN_RESPONSE), is(txId));
162     }
163
164
165
166     private HttpServletRequest createMockedHttpServletRequest(Map<String, String> requestHeaders) {
167         HttpServletRequest servletRequest = Mockito.mock(HttpServletRequest.class);
168         requestHeaders.forEach((k, v) -> {
169             Mockito.when(servletRequest.getHeader(argThat(s -> equalsIgnoreCase(s, k)))).thenReturn(v);
170             Mockito.when(servletRequest.getHeaders(argThat(s -> equalsIgnoreCase(s, k)))).then(returnEnumerationAnswer(v));
171         });
172         Mockito.when(servletRequest.getHeaderNames()).then(returnEnumerationAnswer(requestHeaders.keySet()));
173         return servletRequest;
174     }
175
176     private HttpServletResponse createMockedHttpServletResponse() {
177         return new MockHttpServletResponse();
178     }
179
180     private static Answer<Enumeration<String>> returnEnumerationAnswer(String ... items) {
181         return returnEnumerationAnswer(Arrays.asList(items));
182     }
183
184     private static Answer<Enumeration<String>> returnEnumerationAnswer(Collection<String> items) {
185         return invocation -> Collections.enumeration(items);
186     }
187
188     private Function<HttpServletRequest, String> specificTxId(String someTxId) {
189         return r -> someTxId;
190     }
191
192     private ServletRequest extractCapturedServletRequest(FilterChain capturingFilterChain) throws IOException, ServletException {
193         ArgumentCaptor<ServletRequest> captor = ArgumentCaptor.forClass(ServletRequest.class);
194         Mockito.verify(capturingFilterChain).doFilter(captor.capture(), any());
195         return captor.getValue();
196     }
197
198     private ServletResponse extractCapturedServletResponse(FilterChain capturingFilterChain) throws IOException, ServletException {
199         ArgumentCaptor<ServletResponse> captor = ArgumentCaptor.forClass(ServletResponse.class);
200         Mockito.verify(capturingFilterChain).doFilter(any(), captor.capture());
201         return captor.getValue();
202     }
203
204 }