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