bundle/src/test/java/com/adobe/acs/commons/http/headers/impl/AbstractDispatcherCacheHeaderFilterTest.java
/*
* ACS AEM Commons
*
* Copyright (C) 2013 - 2023 Adobe
*
* 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 com.adobe.acs.commons.http.headers.impl;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.hamcrest.MockitoHamcrest.argThat;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
public class AbstractDispatcherCacheHeaderFilterTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
AbstractDispatcherCacheHeaderFilter filter;
Dictionary<String, Object> properties = null;
@SuppressWarnings("rawtypes")
Map params = null;
Set<String> agents = null;
String pattern = "/content/.*";
private String headerName = "Header Name";
private String headerValue = "Header Value";
@Mock
ComponentContext componentContext;
@Mock
BundleContext bundleContext;
@Mock
ServiceRegistration serviceRegistration;
@Mock
HttpServletRequest request;
@Mock
HttpServletResponse response;
@Mock
FilterChain chain;
@Before
@SuppressWarnings("rawtypes")
public void setup() throws Exception {
properties = new Hashtable<String, Object>();
String[] patterns = new String[] { pattern };
properties.put(AbstractDispatcherCacheHeaderFilter.PROP_FILTER_PATTERN, patterns);
params = new HashMap();
agents = new HashSet<String>();
filter = new AbstractDispatcherCacheHeaderFilter() {
@Override
protected String getHeaderName() {
return headerName;
}
@Override
protected String getHeaderValue(HttpServletRequest request) {
return headerValue;
}
@Override
protected void doActivate(ComponentContext context) throws Exception {
}
};
when(componentContext.getProperties()).thenReturn(properties);
when(componentContext.getBundleContext()).thenReturn(bundleContext);
when(bundleContext.registerService(anyString(), any(), (Dictionary) any())).thenReturn(serviceRegistration);
when(request.getMethod()).thenReturn("GET");
when(request.getParameterMap()).thenReturn(params);
final Map<String, Object> attributes = new HashMap<>();
doAnswer(i -> attributes.put(i.getArgument(0), i.getArgument(1))).when(request).setAttribute(any(), any());
when(request.getAttribute(any())).thenAnswer(i -> attributes.get(i.getArgument(0)));
}
@After
public void tearDown() throws Exception {
properties = null;
params = null;
agents = null;
reset(componentContext, bundleContext, serviceRegistration, request, response, chain);
}
@Test
public void testActivateSuccess() throws Exception {
final BaseMatcher<Dictionary<String, Object>> filterPropsMatcher = new BaseMatcher<Dictionary<String, Object>>() {
@Override
public void describeTo(Description description) {
// do nothing
}
@Override
@SuppressWarnings("unchecked")
public boolean matches(Object item) {
return StringUtils.equals(pattern, ((Dictionary<String, Object>) item).get(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX).toString());
}
};
filter.activate(componentContext);
verify(componentContext).getProperties();
verify(componentContext).getBundleContext();
verify(bundleContext).registerService(eq(Filter.class.getName()), eq(filter), argThat(filterPropsMatcher));
verifyNoMoreInteractions(componentContext, bundleContext, serviceRegistration);
}
@Test
public void testActivateMultipleFilters() throws Exception {
final ServiceRegistration secondRegistration = mock(ServiceRegistration.class);
final String secondPattern = "/content/dam/.*";
properties.put(AbstractDispatcherCacheHeaderFilter.PROP_FILTER_PATTERN,
new String[] { pattern, secondPattern });
final BaseMatcher<Dictionary<String, Object>> firstPropsMatcher = new BaseMatcher<Dictionary<String, Object>>() {
@Override
public void describeTo(Description description) {
// do nothing
}
@Override
@SuppressWarnings("unchecked")
public boolean matches(Object item) {
return StringUtils.equals(pattern, ((Dictionary<String, Object>) item).get(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX).toString());
}
};
final BaseMatcher<Dictionary<String, Object>> secondPropsMatcher = new BaseMatcher<Dictionary<String, Object>>() {
@Override
public void describeTo(Description description) {
// do nothing
}
@Override
@SuppressWarnings("unchecked")
public boolean matches(Object item) {
return StringUtils.equals(secondPattern, ((Dictionary<String, Object>) item).get(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX).toString());
}
};
filter.activate(componentContext);
verify(componentContext).getProperties();
verify(componentContext, times(2)).getBundleContext();
verify(bundleContext).registerService(eq(Filter.class.getName()), eq(filter), argThat(firstPropsMatcher));
verify(bundleContext).registerService(eq(Filter.class.getName()), eq(filter), argThat(secondPropsMatcher));
verifyNoMoreInteractions(componentContext, bundleContext, serviceRegistration, secondRegistration);
}
@Test(expected = ConfigurationException.class)
public void testActivateNoFilters() throws Exception {
properties.remove(AbstractDispatcherCacheHeaderFilter.PROP_FILTER_PATTERN);
when(componentContext.getProperties()).thenReturn(properties);
filter.activate(componentContext);
}
@Test
public void testDeactivate() throws Exception {
filter.activate(componentContext);
filter.deactivate(componentContext);
filter.deactivate(componentContext);
verify(serviceRegistration).unregister();
verifyNoMoreInteractions(serviceRegistration);
}
@Test
@SuppressWarnings("rawtypes")
public void testDeactivateMultipleFilters() throws Exception {
ServiceRegistration secondRegistration = mock(ServiceRegistration.class);
final String secondPattern = "/content/dam/.*";
properties.put(AbstractDispatcherCacheHeaderFilter.PROP_FILTER_PATTERN,
new String[] { pattern, secondPattern });
when(bundleContext.registerService(anyString(), any(), (Dictionary) any())).thenReturn(serviceRegistration,
secondRegistration);
filter.activate(componentContext);
filter.deactivate(componentContext);
verify(serviceRegistration).unregister();
verify(secondRegistration).unregister();
verifyNoMoreInteractions(serviceRegistration, secondRegistration);
}
@Test
public void testDoFilterInvalidRequest() throws Exception {
ServletRequest request = mock(ServletRequest.class);
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
public void testDoFilterInvalidResponse() throws Exception {
ServletResponse response = mock(ServletResponse.class);
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verifyNoMoreInteractions(request, response, this.response, chain);
}
@Test
public void testDoFilterInvalidMethod() throws Exception {
when(request.getMethod()).thenReturn("POST");
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verify(request).getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME);
verify(request).getMethod();
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
@SuppressWarnings("unchecked")
public void testDoFilterHashParams() throws Exception {
params.put("parameter", "value");
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verify(request).getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME);
verify(request).getMethod();
verify(request, times(2)).getParameterMap();
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
public void testDoFilterNoServerAgent() throws Exception {
when(request.getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME))
.thenReturn(Collections.enumeration(agents));
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verify(request).getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME);
verify(request).getMethod();
verify(request).getParameterMap();
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
public void testDoFilterInvalidServerAgent() throws Exception {
agents.add("Not-Day-Communique-Dispatcher");
when(request.getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME))
.thenReturn(Collections.enumeration(agents));
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verify(request).getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME);
verify(request).getMethod();
verify(request).getParameterMap();
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
public void testDoFilterSuccess() throws Exception {
agents.add(AbstractDispatcherCacheHeaderFilter.DISPATCHER_AGENT_HEADER_VALUE);
when(request.getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME))
.thenReturn(Collections.enumeration(agents));
filter.doFilter(request, response, chain);
verify(chain).doFilter(request, response);
verify(request).getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME);
verify(request).getMethod();
verify(request).getParameterMap();
verify(request).getAttribute("com.adobe.acs.commons.http.headers.impl.AbstractDispatcherCacheHeaderFilter.header.Header Name");
verify(request).setAttribute(eq("com.adobe.acs.commons.http.headers.impl.AbstractDispatcherCacheHeaderFilter.header.Header Name"), any());
verify(response).addHeader(headerName, headerValue);
verifyNoMoreInteractions(request, this.request, response, chain);
}
@Test
public void testMultipleFilters() throws Exception {
agents.add(AbstractDispatcherCacheHeaderFilter.DISPATCHER_AGENT_HEADER_VALUE);
when(request.getHeaders(AbstractDispatcherCacheHeaderFilter.SERVER_AGENT_NAME))
.thenAnswer(i -> Collections.enumeration(agents));
filter.doFilter(request, response, chain);
filter.doFilter(request, response, chain);
verify(response, times(1)).addHeader(headerName, headerValue);
}
}