From f2cee7829ae7d8fae58239dd0018b2aa790c0251 Mon Sep 17 00:00:00 2001 From: olegb Date: Mon, 19 Feb 2018 16:24:54 +0200 Subject: Added JAX-RS filters for logging Change-Id: I57ab333278d4ea26530e916ef89670df8b51b555 Issue-ID: SDC-772 Signed-off-by: olegb Signed-off-by: vempo --- .../sdc/logging/servlet/LoggingFilterTest.java | 199 ++++++++++++++++ .../sdc/logging/servlet/jaxrs/HttpHeaderTest.java | 98 ++++++++ .../servlet/jaxrs/LoggingRequestFilterTest.java | 262 +++++++++++++++++++++ .../servlet/jaxrs/LoggingResponseFilterTest.java | 234 ++++++++++++++++++ 4 files changed, 793 insertions(+) create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java create mode 100644 openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java (limited to 'openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test') diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java new file mode 100644 index 0000000000..535a50ca42 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/LoggingFilterTest.java @@ -0,0 +1,199 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.servlet; + +import static org.easymock.EasyMock.anyObject; +import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_PARTNER_NAME_HEADER; +import static org.openecomp.sdc.logging.LoggingConstants.DEFAULT_REQUEST_ID_HEADER; +import static org.openecomp.sdc.logging.servlet.LoggingFilter.PARTNER_NAME_HEADERS_PARAM; +import static org.openecomp.sdc.logging.servlet.LoggingFilter.REQUEST_ID_HEADERS_PARAM; + +import java.io.IOException; +import java.util.UUID; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.easymock.EasyMock; +import org.openecomp.sdc.logging.api.ContextData; +import org.openecomp.sdc.logging.api.LoggingContext; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.testng.PowerMockTestCase; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +/** + * Unit-tests logging filter for initialization and data retrieval. + * + * @author evitaliy + * @since 17 Aug 2016 + */ +@PrepareForTest(LoggingContext.class) +public class LoggingFilterTest extends PowerMockTestCase { + + private static final String RANDOM_REQUEST_URI = UUID.randomUUID().toString(); + private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString(); + private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString(); + + /** + * Verify all mocks after each test. + */ + @AfterMethod + public void verifyMocks(ITestResult result) { + + try { + PowerMock.verifyAll(); + } catch (AssertionError e) { + throw new AssertionError("Expectations failed in: " + result.getMethod().getMethodName(), e); + } + } + + + @Test + public void filterPopulatesValuesWhenNoInitParamsAndNoHeaders() throws Exception { + + mockLoggingContext(); + LoggingFilter loggingFilter = new LoggingFilter(); + loggingFilter.init(mockFilterConfig(null, null)); + loggingFilter.doFilter(new MockRequestBuilder().build(), mockResponse(), mockChain()); + } + + @Test + public void filterPopulatesValuesWhenNoInitParamsAndExistingHeaders() throws Exception { + + mockLoggingContext(); + + LoggingFilter loggingFilter = new LoggingFilter(); + loggingFilter.init(mockFilterConfig(null, null)); + + HttpServletRequest mockRequest = new MockRequestBuilder().partnerName(RANDOM_PARTNER_NAME) + .requestId(RANDOM_REQUEST_ID).build(); + loggingFilter.doFilter(mockRequest, mockResponse(), mockChain()); + } + + @Test + public void filterPopulatesValuesWhenCustomInitParamsAndNoHeaders() throws Exception { + + mockLoggingContext(); + + final String requestIdHeader = "x-request"; + final String partnerNameHeader = "x-partner"; + + LoggingFilter loggingFilter = new LoggingFilter(); + FilterConfig mockConfig = mockFilterConfig(requestIdHeader, partnerNameHeader); + loggingFilter.init(mockConfig); + + HttpServletRequest mockRequest = new MockRequestBuilder().requestIdHeader(requestIdHeader) + .partnerNameHeader(partnerNameHeader).build(); + loggingFilter.doFilter(mockRequest, mockResponse(), mockChain()); + } + + @Test + public void filterPopulatesValuesWhenCustomInitParamsAndExistingHeaders() throws Exception { + + mockLoggingContext(); + + final String requestIdHeader = "x-request-id"; + final String partnerNameHeader = "x-partner-name"; + + LoggingFilter loggingFilter = new LoggingFilter(); + FilterConfig mockConfig = mockFilterConfig(requestIdHeader, partnerNameHeader); + loggingFilter.init(mockConfig); + + HttpServletRequest mockRequest = new MockRequestBuilder() + .partnerNameHeader(partnerNameHeader).partnerName(RANDOM_PARTNER_NAME) + .requestIdHeader(requestIdHeader).requestId(RANDOM_REQUEST_ID).build(); + loggingFilter.doFilter(mockRequest, mockResponse(), mockChain()); + } + + private FilterConfig mockFilterConfig(String requestIdHeader, String partnerNameHeader) { + FilterConfig config = EasyMock.mock(FilterConfig.class); + EasyMock.expect(config.getInitParameter(REQUEST_ID_HEADERS_PARAM)).andReturn(requestIdHeader); + EasyMock.expect(config.getInitParameter(PARTNER_NAME_HEADERS_PARAM)).andReturn(partnerNameHeader); + EasyMock.replay(config); + return config; + } + + private FilterChain mockChain() throws IOException, ServletException { + FilterChain chain = EasyMock.mock(FilterChain.class); + chain.doFilter(anyObject(ServletRequest.class), anyObject(ServletResponse.class)); + EasyMock.expectLastCall().once(); + EasyMock.replay(chain); + return chain; + } + + private ServletResponse mockResponse() { + HttpServletResponse servletResponse = EasyMock.mock(HttpServletResponse.class); + EasyMock.replay(servletResponse); + return servletResponse; + } + + private void mockLoggingContext() { + + PowerMock.mockStatic(LoggingContext.class); + + LoggingContext.clear(); + EasyMock.expectLastCall().times(2); + + LoggingContext.put(anyObject(ContextData.class)); + EasyMock.expectLastCall().once(); + + PowerMock.replay(LoggingContext.class); + } + + private static class MockRequestBuilder { + + private String requestIdHeader = DEFAULT_REQUEST_ID_HEADER; + private String partnerNameHeader = DEFAULT_PARTNER_NAME_HEADER; + private String requestId = null; + private String partnerName = null; + + MockRequestBuilder requestIdHeader(String h) { + this.requestIdHeader = h; + return this; + } + + MockRequestBuilder requestId(String id) { + this.requestId = id; + return this; + } + + MockRequestBuilder partnerNameHeader(String h) { + this.partnerNameHeader = h; + return this; + } + + MockRequestBuilder partnerName(String name) { + this.partnerName = name; + return this; + } + + HttpServletRequest build() { + HttpServletRequest mockRequest = EasyMock.mock(HttpServletRequest.class); + EasyMock.expect(mockRequest.getRequestURI()).andReturn(RANDOM_REQUEST_URI); + EasyMock.expect(mockRequest.getHeader(requestIdHeader)).andReturn(requestId); + EasyMock.expect(mockRequest.getHeader(partnerNameHeader)).andReturn(partnerName); + EasyMock.replay(mockRequest); + return mockRequest; + } + } +} diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java new file mode 100644 index 0000000000..3376c922e4 --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/HttpHeaderTest.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.servlet.jaxrs; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import java.util.function.Function; +import org.openecomp.sdc.logging.servlet.HttpHeader; +import org.testng.annotations.Test; + +/** + * Unit tests mutliple-option headers. + * + * @author evitaliy + * @since 25 Mar 2018 + */ +public class HttpHeaderTest { + + @Test + public void valueReturnedWhenSinglePossibleHeader() { + + final String key = "Head"; + final String value = "1234"; + + Function reader = createReader(key, value); + HttpHeader header = new HttpHeader(key); + assertEquals(header.getAny(reader), value); + } + + @Test + public void nullReturnedWhenSingleNoMatchingHeader() { + + final String key = "Head"; + + Function reader = createReader(key, null); + HttpHeader header = new HttpHeader(key); + assertNull(header.getAny(reader)); + } + + @Test + public void nullReturnedWhenNoneHeaderMatches() { + Function reader = createReader("None", "Value"); + HttpHeader header = new HttpHeader("A", "B", "C"); + assertNull(header.getAny(reader)); + } + + @Test + public void valueReturnedWhenLastHeaderMatches() { + + final String lastKey = "Last"; + final String value = "1234"; + + Function reader = createReader(lastKey, value); + HttpHeader header = new HttpHeader("First", "Second", lastKey); + assertEquals(header.getAny(reader), value); + } + + @Test + public void valueReturnedWhenFirstHeaderMatches() { + + final String firstKey = "First"; + final String value = "1234"; + + Function reader = createReader(firstKey, value); + HttpHeader header = new HttpHeader(firstKey, "Second", "Third"); + assertEquals(header.getAny(reader), value); + } + + @Test + public void valueReturnedWhenMiddleHeaderMatches() { + + final String middleKey = "Second"; + final String value = "1234"; + + Function reader = createReader(middleKey, value); + HttpHeader header = new HttpHeader("First", middleKey, "Third"); + assertEquals(header.getAny(reader), value); + } + + private Function createReader(String key, String value) { + return h -> h.equals(key) ? value : null; + } +} \ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java new file mode 100644 index 0000000000..0e0be017df --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingRequestFilterTest.java @@ -0,0 +1,262 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.servlet.jaxrs; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.anyString; +import static org.openecomp.sdc.logging.servlet.jaxrs.LoggingRequestFilter.START_TIME_KEY; + +import java.lang.reflect.Method; +import java.util.UUID; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ResourceInfo; +import org.easymock.EasyMock; +import org.openecomp.sdc.logging.LoggingConstants; +import org.openecomp.sdc.logging.api.ContextData; +import org.openecomp.sdc.logging.api.LoggingContext; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.testng.PowerMockTestCase; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + +/** + * Unit testing JAX-RS request filter. + * + * @author evitaliy + * @since 19 Mar 2018 + */ +@PrepareForTest({LoggingContext.class, ContextData.class}) +public class LoggingRequestFilterTest extends PowerMockTestCase { + + private static final Class RESOURCE_CLASS = MockResource.class; + private static final Method RESOURCE_METHOD = MockResource.class.getDeclaredMethods()[0]; + private static final String RESOURCE_NAME = RESOURCE_CLASS.getName() + "." + RESOURCE_METHOD.getName(); + + private static final String RANDOM_REQUEST_ID = UUID.randomUUID().toString(); + private static final String RANDOM_PARTNER_NAME = UUID.randomUUID().toString(); + + /** + * Verify all mocks after each test. + */ + @AfterMethod + public void verifyMocks(ITestResult result) { + + try { + PowerMock.verifyAll(); + } catch (AssertionError e) { + throw new AssertionError("Expectations failed in: " + result.getMethod().getMethodName(), e); + } + } + + @Test + public void notHandledWhenNoMatchingResource() { + + PowerMock.mockStatic(LoggingContext.class); + PowerMock.replay(LoggingContext.class); + + new LoggingRequestFilter().filter(mockEmptyContainerRequestContext()); + } + + @Test + public void serviceNamePopulatedWhenThereIsMatchingResource() { + + mockContextDataBuilder(null, RESOURCE_NAME, null); + mockLoggingContext(); + + LoggingRequestFilter filter = new LoggingRequestFilter(); + filter.setResource(mockResource()); + + filter.filter(mockContainerRequestContext( + new RequestIdHeader(null), + new PartnerHeader(null))); + } + + @Test + public void partnerNamePopulatedWhenPresentInDefaultHeader() { + + mockContextDataBuilder(null, RESOURCE_NAME, RANDOM_PARTNER_NAME); + mockLoggingContext(); + + LoggingRequestFilter filter = new LoggingRequestFilter(); + filter.setResource(mockResource()); + + filter.filter(mockContainerRequestContext( + new RequestIdHeader(null), + new PartnerHeader(RANDOM_PARTNER_NAME))); + } + + @Test + public void partnerNamePopulatedWhenPresentInCustomHeader() { + + final String partnerHeader = "x-partner-header"; + mockContextDataBuilder(null, RESOURCE_NAME, RANDOM_PARTNER_NAME); + mockLoggingContext(); + + LoggingRequestFilter filter = new LoggingRequestFilter(); + filter.setResource(mockResource()); + filter.setPartnerNameHeaders(partnerHeader); + + filter.filter(mockContainerRequestContext( + new RequestIdHeader(null), + new PartnerHeader(partnerHeader, RANDOM_PARTNER_NAME))); + } + + @Test + public void requestIdPopulatedWhenPresentInDefaultHeader() { + + mockContextDataBuilder(RANDOM_REQUEST_ID, RESOURCE_NAME, null); + mockLoggingContext(); + + LoggingRequestFilter filter = new LoggingRequestFilter(); + filter.setResource(mockResource()); + + filter.filter(mockContainerRequestContext( + new RequestIdHeader(RANDOM_REQUEST_ID), + new PartnerHeader(null))); + } + + @Test + public void requestIdPopulatedWhenPresentInCustomHeader() { + + final String requestIdHeader = "x-request-id"; + mockContextDataBuilder(RANDOM_REQUEST_ID, RESOURCE_NAME, null); + mockLoggingContext(); + + LoggingRequestFilter filter = new LoggingRequestFilter(); + filter.setResource(mockResource()); + filter.setRequestIdHeaders(requestIdHeader); + + filter.filter(mockContainerRequestContext( + new RequestIdHeader(requestIdHeader, RANDOM_REQUEST_ID), + new PartnerHeader(null))); + } + + private ResourceInfo mockResource() { + ResourceInfo resource = EasyMock.mock(ResourceInfo.class); + //noinspection unchecked + EasyMock.expect(resource.getResourceClass()).andReturn(RESOURCE_CLASS); + EasyMock.expect(resource.getResourceMethod()).andReturn(RESOURCE_METHOD); + EasyMock.replay(resource); + return resource; + } + + private ContainerRequestContext mockEmptyContainerRequestContext() { + ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class); + EasyMock.replay(requestContext); + return requestContext; + } + + private ContainerRequestContext mockContainerRequestContext(Header... headers) { + + ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class); + + for (Header h : headers) { + EasyMock.expect(requestContext.getHeaderString(h.key)).andReturn(h.value); + } + + requestContext.setProperty(EasyMock.eq(START_TIME_KEY), EasyMock.anyLong()); + EasyMock.expectLastCall(); + + EasyMock.replay(requestContext); + return requestContext; + } + + private void mockContextDataBuilder(String requestId, String serviceName, String partnerName) { + + ContextData.ContextDataBuilder mockBuilder = EasyMock.mock(ContextData.ContextDataBuilder.class); + + if (requestId != null) { + EasyMock.expect(mockBuilder.requestId(requestId)).andReturn(mockBuilder); + } else { + EasyMock.expect(mockBuilder.requestId(anyString())).andReturn(mockBuilder); + } + + if (serviceName != null) { + EasyMock.expect(mockBuilder.serviceName(serviceName)).andReturn(mockBuilder); + } + + if (partnerName != null) { + EasyMock.expect(mockBuilder.partnerName(partnerName)).andReturn(mockBuilder); + } + + EasyMock.expect(mockBuilder.build()).andReturn(EasyMock.mock(ContextData.class)); + EasyMock.replay(mockBuilder); + + PowerMock.mockStatic(ContextData.class); + + ContextData.builder(); + PowerMock.expectLastCall().andReturn(mockBuilder); + + PowerMock.replay(ContextData.class); + } + + private void mockLoggingContext() { + + PowerMock.mockStatic(LoggingContext.class); + + LoggingContext.clear(); + EasyMock.expectLastCall().once(); + + LoggingContext.put(anyObject(ContextData.class)); + EasyMock.expectLastCall().once(); + + PowerMock.replay(LoggingContext.class); + } + + private abstract static class Header { + + private final String key; + private final String value; + + private Header(String key, String value) { + this.key = key; + this.value = value; + } + } + + private static class PartnerHeader extends Header { + + private PartnerHeader(String value) { + super(LoggingConstants.DEFAULT_PARTNER_NAME_HEADER, value); + } + + private PartnerHeader(String key, String value) { + super(key, value); + } + } + + private static class RequestIdHeader extends Header { + + private RequestIdHeader(String value) { + super(LoggingConstants.DEFAULT_REQUEST_ID_HEADER, value); + } + + private RequestIdHeader(String key, String value) { + super(key, value); + } + } + + private static class MockResource { + + @SuppressWarnings("EmptyMethod") + void process() { + // no-op + } + } +} \ No newline at end of file diff --git a/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java new file mode 100644 index 0000000000..37627d5d5a --- /dev/null +++ b/openecomp-be/lib/openecomp-sdc-logging-lib/openecomp-sdc-logging-api/src/test/java/org/openecomp/sdc/logging/servlet/jaxrs/LoggingResponseFilterTest.java @@ -0,0 +1,234 @@ +/* + * Copyright © 2016-2018 European Support Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openecomp.sdc.logging.servlet.jaxrs; + +import static org.easymock.EasyMock.anyObject; +import static org.easymock.EasyMock.anyString; + +import java.util.Comparator; +import java.util.Objects; +import java.util.function.Consumer; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerResponseContext; +import javax.ws.rs.core.Response; +import org.easymock.EasyMock; +import org.easymock.LogicalOperator; +import org.openecomp.sdc.logging.api.AuditData; +import org.openecomp.sdc.logging.api.Logger; +import org.openecomp.sdc.logging.api.LoggerFactory; +import org.openecomp.sdc.logging.api.LoggingContext; +import org.openecomp.sdc.logging.api.StatusCode; +import org.powermock.api.easymock.PowerMock; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.testng.PowerMockTestCase; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.Test; + + +/** + * Unit testing JAX-RS response filter. + * + * @author evitaliy + * @since 19 Mar 2018 + */ +@PrepareForTest({LoggingContext.class, LoggerFactory.class}) +public class LoggingResponseFilterTest extends PowerMockTestCase { + + /** + * Verify all mocks after each test. + */ + @AfterMethod + public void verifyMocks(ITestResult result) { + + try { + PowerMock.verifyAll(); + } catch (AssertionError e) { + throw new AssertionError("Expectations failed in: " + result.getMethod().getMethodName(), e); + } + } + + @Test + public void noAuditWhenAuditDisabled() { + mockLogger(false, AuditData.builder().build()); + mockLoggingContext(); + new LoggingResponseFilter().filter(mockDisabledRequestContext(), mockDisabledResponseContext()); + } + + private void mockLogger(boolean enabled, AuditData auditData, Consumer... additionalMockings) { + + Logger logger = EasyMock.mock(Logger.class); + + EasyMock.expect(logger.isAuditEnabled()).andReturn(enabled).atLeastOnce(); + + if (enabled) { + logger.audit(EasyMock.cmp(auditData, new AuditDataComparator(), LogicalOperator.EQUAL)); + EasyMock.expectLastCall(); + } + + for (Consumer mocking : additionalMockings) { + mocking.accept(logger); + } + + EasyMock.replay(logger); + + PowerMock.mockStatic(LoggerFactory.class); + LoggerFactory.getLogger(LoggingResponseFilter.class); + PowerMock.expectLastCall().andReturn(logger); + PowerMock.replay(LoggerFactory.class); + } + + private void mockLoggingContext() { + PowerMock.mockStatic(LoggingContext.class); + LoggingContext.clear(); + EasyMock.expectLastCall().once(); + PowerMock.replay(LoggingContext.class); + } + + private ContainerRequestContext mockDisabledRequestContext() { + ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class); + EasyMock.replay(requestContext); + return requestContext; + } + + private ContainerResponseContext mockDisabledResponseContext() { + ContainerResponseContext responseContext = EasyMock.mock(ContainerResponseContext.class); + EasyMock.replay(responseContext); + return responseContext; + } + + @Test + public void startTimeReadWhenPresentInRequestContext() { + + final String clientIp = "10.56.56.10"; + final long startTime = 12345L; + final Response.Status ok = Response.Status.OK; + + mockLogger(true, buildAuditData(startTime, clientIp, ok, StatusCode.COMPLETE)); + + mockLoggingContext(); + LoggingResponseFilter filter = new LoggingResponseFilter(); + filter.setHttpRequest(mockHttpRequest(clientIp)); + + filter.filter(mockRequestContext(startTime), mockResponseContext(ok)); + } + + private AuditData buildAuditData(long startTime, String clientIp, Response.Status responseStatus, + StatusCode status) { + return AuditData.builder().startTime(startTime).responseCode(Integer.toString(responseStatus.getStatusCode())) + .responseDescription(responseStatus.getReasonPhrase()).clientIpAddress(clientIp) + .statusCode(status).build(); + } + + private HttpServletRequest mockHttpRequest(String clientIp) { + HttpServletRequest servletRequest = EasyMock.mock(HttpServletRequest.class); + EasyMock.expect(servletRequest.getRemoteAddr()).andReturn(clientIp); + EasyMock.replay(servletRequest); + return servletRequest; + } + + private ContainerRequestContext mockRequestContext(Object startTime) { + ContainerRequestContext requestContext = EasyMock.mock(ContainerRequestContext.class); + EasyMock.expect(requestContext.getProperty(LoggingRequestFilter.START_TIME_KEY)).andReturn(startTime); + EasyMock.replay(requestContext); + return requestContext; + } + + private ContainerResponseContext mockResponseContext(Response.StatusType statusInfo) { + ContainerResponseContext responseContext = EasyMock.mock(ContainerResponseContext.class); + EasyMock.expect(responseContext.getStatusInfo()).andReturn(statusInfo); + EasyMock.replay(responseContext); + return responseContext; + } + + @Test + public void startTimeZeroWhenNotPresentInRequestContext() { + + final String clientIp = "10.56.56.12"; + final Response.Status ok = Response.Status.OK; + + AuditData expectedAuditData = buildAuditData(0, clientIp, ok, StatusCode.COMPLETE); + + mockLogger(true, expectedAuditData, logger -> { + logger.error(anyString(), anyObject(Object[].class)); + EasyMock.expectLastCall(); + }); + + mockLoggingContext(); + LoggingResponseFilter filter = new LoggingResponseFilter(); + filter.setHttpRequest(mockHttpRequest(clientIp)); + + filter.filter(mockRequestContext(null), mockResponseContext(ok)); + } + + @Test + public void startTimeZeroWhenIncorrectObjectType() { + + final String clientIp = "10.56.56.13"; + final Response.Status accepted = Response.Status.ACCEPTED; + + AuditData expectedAuditData = buildAuditData(0, clientIp, accepted, StatusCode.COMPLETE); + + mockLogger(true, expectedAuditData, logger -> { + logger.error(anyString(), new Object[] {anyString(), anyString()}); + EasyMock.expectLastCall(); + }); + + mockLoggingContext(); + LoggingResponseFilter filter = new LoggingResponseFilter(); + filter.setHttpRequest(mockHttpRequest(clientIp)); + + filter.filter(mockRequestContext("string object"), mockResponseContext(accepted)); + } + + @Test + public void statusErrorWhenHttpResponseGreaterThan399() { + + final Response.Status error = Response.Status.BAD_REQUEST; + final String clientIp = "10.56.56.13"; + final long startTime = 88668603L; + + AuditData expectedAuditData = buildAuditData(startTime, clientIp, error, StatusCode.ERROR); + + mockLogger(true, expectedAuditData); + + mockLoggingContext(); + LoggingResponseFilter filter = new LoggingResponseFilter(); + filter.setHttpRequest(mockHttpRequest(clientIp)); + + filter.filter(mockRequestContext(startTime), mockResponseContext(error)); + } + + private static class AuditDataComparator implements Comparator { + + @Override + public int compare(AuditData one, AuditData two) { + + // don't compare end time as it changes + if (Objects.equals(one.getClientIpAddress(), two.getClientIpAddress()) && Objects + .equals(one.getResponseCode(), two.getResponseCode()) && Objects + .equals(one.getResponseDescription(), one.getResponseDescription()) && one.getStartTime() == two + .getStartTime() && Objects.equals(one.getStatusCode(), two.getStatusCode())) { + + return 0; + } + + return -1; + } + } +} \ No newline at end of file -- cgit 1.2.3-korg