579f41c3e613293a4212dd007b10f627b57415a2
[sdc.git] /
1 /*
2  * Copyright © 2016-2018 European Support Limited
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package org.openecomp.sdc.logging.servlet.jaxrs;
18
19 import static org.easymock.EasyMock.anyObject;
20 import static org.easymock.EasyMock.anyString;
21 import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.START_TIME_KEY;
22
23 import java.lang.reflect.Method;
24 import java.lang.reflect.Proxy;
25 import java.util.UUID;
26 import javax.ws.rs.container.ContainerRequestContext;
27 import javax.ws.rs.container.ResourceInfo;
28 import org.easymock.EasyMock;
29 import org.openecomp.sdc.logging.LoggingConstants;
30 import org.openecomp.sdc.logging.api.ContextData;
31 import org.openecomp.sdc.logging.api.LoggingContext;
32 import org.powermock.api.easymock.PowerMock;
33 import org.powermock.core.classloader.annotations.PrepareForTest;
34 import org.powermock.modules.testng.PowerMockTestCase;
35 import org.testng.ITestResult;
36 import org.testng.annotations.AfterMethod;
37 import org.testng.annotations.Test;
38
39 /**
40  * Unit testing JAX-RS request filter.
41  *
42  * @author evitaliy
43  * @since 19 Mar 2018
44  */
45 @PrepareForTest({LoggingContext.class, ContextData.class})
46 public class LoggingRequestFilterTest extends PowerMockTestCase {
47
48     private static final Class DEFAULT_RESOURCE_CLASS = MockResource.class;
49     private static final Method DEFAULT_RESOURCE_METHOD = MockResource.class.getDeclaredMethods()[0];
50     private static final String DEFAULT_SERVICE_NAME =
51             formatServiceName(DEFAULT_RESOURCE_CLASS, DEFAULT_RESOURCE_METHOD);
52
53     private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString();
54
55     private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString();
56
57     private static String formatServiceName(Class resourceClass, Method resourceMethod) {
58         return resourceClass.getName() + "#" + resourceMethod.getName();
59     }
60
61     /**
62      * Verify all mocks after each test.
63      */
64     @AfterMethod
65     public void verifyMocks(ITestResult result) {
66
67         try {
68             PowerMock.verifyAll();
69         } catch (AssertionError e) {
70             throw new AssertionError("Expectations failed in: " + result.getMethod().getMethodName(), e);
71         }
72     }
73
74     @Test
75     public void notHandledWhenNoMatchingResource() {
76
77         PowerMock.mockStatic(LoggingContext.class);
78         PowerMock.replay(LoggingContext.class);
79
80         new LoggingRequestFilter().filter(mockEmptyContainerRequestContext());
81     }
82
83     @Test
84     public void serviceNamePopulatedWhenThereIsMatchingResourceAndConcreteType() {
85
86         mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, null);
87         mockLoggingContext();
88
89         LoggingRequestFilter filter = new LoggingRequestFilter();
90         filter.setResource(mockResource());
91
92         filter.filter(mockContainerRequestContext(
93                 new RequestIdHeader(null),
94                 new PartnerHeader(null)));
95     }
96
97     @Test
98     public void serviceNamePopulatedWhenThereIsMatchingResourceAndJavaProxyType() throws NoSuchMethodException {
99
100         Object proxyResource = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
101                 new Class<?>[] {MockResource.class}, (proxy, method, arguments) -> null);
102
103         final String serviceName = formatServiceName(MockResource.class, DEFAULT_RESOURCE_METHOD);
104
105         mockContextDataBuilder(null, serviceName, null);
106         mockLoggingContext();
107
108         LoggingRequestFilter filter = new LoggingRequestFilter();
109
110         Class<?> proxyClass = proxyResource.getClass();
111         Method proxyMethod =
112                 proxyClass.getMethod(DEFAULT_RESOURCE_METHOD.getName(), DEFAULT_RESOURCE_METHOD.getParameterTypes());
113
114         filter.setResource(mockResource(proxyClass, proxyMethod));
115
116         filter.filter(mockContainerRequestContext(
117                 new RequestIdHeader(null),
118                 new PartnerHeader(null)));
119     }
120
121     @Test
122     public void serviceNameIncludesProxyClassnameWhenJavaProxyTypeAndNoMatchingInterface() {
123
124         Object proxyResource = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
125                 new Class<?>[] {Comparable.class}, (proxy, method, arguments) -> null);
126
127         final String serviceName = formatServiceName(proxyResource.getClass(), DEFAULT_RESOURCE_METHOD);
128
129         mockContextDataBuilder(null, serviceName, null);
130         mockLoggingContext();
131
132         LoggingRequestFilter filter = new LoggingRequestFilter();
133
134         Class<?> proxyClass = proxyResource.getClass();
135         filter.setResource(mockResource(proxyClass, DEFAULT_RESOURCE_METHOD));
136
137         filter.filter(mockContainerRequestContext(
138                 new RequestIdHeader(null),
139                 new PartnerHeader(null)));
140     }
141
142     @Test
143     public void partnerNamePopulatedWhenPresentInDefaultHeader() {
144
145         mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, RANDOM_PARTNER_NAME);
146         mockLoggingContext();
147
148         LoggingRequestFilter filter = new LoggingRequestFilter();
149         filter.setResource(mockResource());
150
151         filter.filter(mockContainerRequestContext(
152                 new RequestIdHeader(null),
153                 new PartnerHeader(RANDOM_PARTNER_NAME)));
154     }
155
156     @Test
157     public void partnerNamePopulatedWhenPresentInCustomHeader() {
158
159         final String partnerHeader = "x-partner-header";
160         mockContextDataBuilder(null, DEFAULT_SERVICE_NAME, RANDOM_PARTNER_NAME);
161         mockLoggingContext();
162
163         LoggingRequestFilter filter = new LoggingRequestFilter();
164         filter.setResource(mockResource());
165         filter.setPartnerNameHeaders(partnerHeader);
166
167         filter.filter(mockContainerRequestContext(
168                 new RequestIdHeader(null),
169                 new PartnerHeader(partnerHeader, RANDOM_PARTNER_NAME)));
170     }
171
172     @Test
173     public void requestIdPopulatedWhenPresentInDefaultHeader() {
174
175         mockContextDataBuilder(RANDOM_REQUEST_ID, DEFAULT_SERVICE_NAME, null);
176         mockLoggingContext();
177
178         LoggingRequestFilter filter = new LoggingRequestFilter();
179         filter.setResource(mockResource());
180
181         filter.filter(mockContainerRequestContext(
182                 new RequestIdHeader(RANDOM_REQUEST_ID),
183                 new PartnerHeader(null)));
184     }
185
186     @Test
187     public void requestIdPopulatedWhenPresentInCustomHeader() {
188
189         final String requestIdHeader = "x-request-id";
190         mockContextDataBuilder(RANDOM_REQUEST_ID, DEFAULT_SERVICE_NAME, null);
191         mockLoggingContext();
192
193         LoggingRequestFilter filter = new LoggingRequestFilter();
194         filter.setResource(mockResource());
195         filter.setRequestIdHeaders(requestIdHeader);
196
197         filter.filter(mockContainerRequestContext(
198                 new RequestIdHeader(requestIdHeader, RANDOM_REQUEST_ID),
199                 new PartnerHeader(null)));
200     }
201
202     private ResourceInfo mockResource() {
203         return mockResource(DEFAULT_RESOURCE_CLASS, DEFAULT_RESOURCE_METHOD);
204     }
205
206     private ResourceInfo mockResource(Class resourceType, Method resourceMethod) {
207         ResourceInfo resource = EasyMock.mock(ResourceInfo.class);
208         //noinspection unchecked
209         EasyMock.expect(resource.getResourceClass()).andReturn(resourceType);
210         EasyMock.expect(resource.getResourceMethod()).andReturn(resourceMethod);
211         EasyMock.replay(resource);
212         return resource;
213     }
214
215     private ContainerRequestContext mockEmptyContainerRequestContext() {
216         ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class);
217         EasyMock.replay(requestContext);
218         return requestContext;
219     }
220
221     private ContainerRequestContext mockContainerRequestContext(Header... headers) {
222
223         ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class);
224
225         for (Header h : headers) {
226             EasyMock.expect(requestContext.getHeaderString(h.key)).andReturn(h.value);
227         }
228
229         requestContext.setProperty(EasyMock.eq(START_TIME_KEY), EasyMock.anyLong());
230         EasyMock.expectLastCall();
231
232         EasyMock.replay(requestContext);
233         return requestContext;
234     }
235
236     private void mockContextDataBuilder(String requestId, String serviceName, String partnerName) {
237
238         ContextData.ContextDataBuilder mockBuilder = EasyMock.mock(ContextData.ContextDataBuilder.class);
239
240         if (requestId != null) {
241             EasyMock.expect(mockBuilder.requestId(requestId)).andReturn(mockBuilder);
242         } else {
243             EasyMock.expect(mockBuilder.requestId(anyString())).andReturn(mockBuilder);
244         }
245
246         if (serviceName != null) {
247             EasyMock.expect(mockBuilder.serviceName(serviceName)).andReturn(mockBuilder);
248         }
249
250         if (partnerName != null) {
251             EasyMock.expect(mockBuilder.partnerName(partnerName)).andReturn(mockBuilder);
252         }
253
254         EasyMock.expect(mockBuilder.build()).andReturn(EasyMock.mock(ContextData.class));
255         EasyMock.replay(mockBuilder);
256
257         PowerMock.mockStatic(ContextData.class);
258
259         ContextData.builder();
260         PowerMock.expectLastCall().andReturn(mockBuilder);
261
262         PowerMock.replay(ContextData.class);
263     }
264
265     private void mockLoggingContext() {
266
267         PowerMock.mockStatic(LoggingContext.class);
268
269         LoggingContext.clear();
270         EasyMock.expectLastCall().once();
271
272         LoggingContext.put(anyObject(ContextData.class));
273         EasyMock.expectLastCall().once();
274
275         PowerMock.replay(LoggingContext.class);
276     }
277
278     private abstract static class Header {
279
280         private final String key;
281         private final String value;
282
283         private Header(String key, String value) {
284             this.key = key;
285             this.value = value;
286         }
287     }
288
289     private static class PartnerHeader extends Header {
290
291         private PartnerHeader(String value) {
292             super(LoggingConstants.DEFAULT_PARTNER_NAME_HEADER, value);
293         }
294
295         private PartnerHeader(String key, String value) {
296             super(key, value);
297         }
298     }
299
300     private static class RequestIdHeader extends Header {
301
302         private RequestIdHeader(String value) {
303             super(LoggingConstants.DEFAULT_REQUEST_ID_HEADER, value);
304         }
305
306         private RequestIdHeader(String key, String value) {
307             super(key, value);
308         }
309     }
310
311     private interface MockResource {
312
313         @SuppressWarnings("EmptyMethod")
314         void process();
315     }
316
317     private static class MockResourceImpl implements MockResource {
318
319         @Override
320         public void process() {
321             // no-op
322         }
323     }
324
325
326 }