| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // 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.google.gerrit.httpd; |
| |
| import static org.easymock.EasyMock.anyObject; |
| import static org.easymock.EasyMock.capture; |
| import static org.easymock.EasyMock.eq; |
| |
| import com.google.gerrit.extensions.registration.DynamicSet; |
| import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle; |
| import com.google.gerrit.server.plugins.Plugin; |
| import com.google.gerrit.util.http.testutil.FakeHttpServletRequest; |
| import com.google.gerrit.util.http.testutil.FakeHttpServletResponse; |
| import com.google.inject.Key; |
| import com.google.inject.util.Providers; |
| import javax.servlet.FilterChain; |
| import javax.servlet.FilterConfig; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import org.easymock.Capture; |
| import org.easymock.EasyMockSupport; |
| import org.easymock.IMocksControl; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| public class AllRequestFilterFilterProxyTest { |
| /** |
| * Set of filters for FilterProxy |
| * |
| * <p>This set is used to as set of filters when fetching an {@link AllRequestFilter.FilterProxy} |
| * instance through {@link #getFilterProxy()}. |
| */ |
| private DynamicSet<AllRequestFilter> filters; |
| |
| @Before |
| public void setUp() throws Exception { |
| // Force starting each test with an initially empty set of filters. |
| // Filters get added by the tests themselves. |
| filters = new DynamicSet<>(); |
| } |
| |
| // The wrapping of {@link #getFilterProxy()} and |
| // {@link #addFilter(AllRequestFilter)} into separate methods may seem |
| // overengineered at this point. However, if in the future we decide to not |
| // test the inner class directly, but rather test from the outside using |
| // Guice Injectors, it is now sufficient to change only those two methods, |
| // and we need not mess with the individual tests. |
| |
| /** |
| * Obtain a FilterProxy with a known DynamicSet of filters |
| * |
| * <p>The returned {@link AllRequestFilter.FilterProxy} can have new filters added dynamically by |
| * calling {@link #addFilter(AllRequestFilter)}. |
| */ |
| private AllRequestFilter.FilterProxy getFilterProxy() { |
| return new AllRequestFilter.FilterProxy(filters); |
| } |
| |
| /** |
| * Add a filter to created FilterProxy instances |
| * |
| * <p>This method adds the given filter to all {@link AllRequestFilter.FilterProxy} instances |
| * created by {@link #getFilterProxy()}. |
| */ |
| private ReloadableRegistrationHandle<AllRequestFilter> addFilter(final AllRequestFilter filter) { |
| Key<AllRequestFilter> key = Key.get(AllRequestFilter.class); |
| return filters.add(key, Providers.of(filter)); |
| } |
| |
| @Test |
| public void noFilters() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req = new FakeHttpServletRequest(); |
| HttpServletResponse res = new FakeHttpServletResponse(); |
| |
| FilterChain chain = ems.createMock(FilterChain.class); |
| chain.doFilter(req, res); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req, res, chain); |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void singleFilterNoBubbling() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock("config", FilterConfig.class); |
| HttpServletRequest req = new FakeHttpServletRequest(); |
| HttpServletResponse res = new FakeHttpServletResponse(); |
| |
| FilterChain chain = ems.createMock("chain", FilterChain.class); |
| |
| AllRequestFilter filter = ems.createStrictMock("filter", AllRequestFilter.class); |
| filter.init(config); |
| filter.doFilter(eq(req), eq(res), anyObject(FilterChain.class)); |
| filter.destroy(); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| addFilter(filter); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req, res, chain); |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void singleFilterBubbling() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req = new FakeHttpServletRequest(); |
| HttpServletResponse res = new FakeHttpServletResponse(); |
| |
| IMocksControl mockControl = ems.createStrictControl(); |
| FilterChain chain = mockControl.createMock(FilterChain.class); |
| |
| Capture<FilterChain> capturedChain = new Capture<>(); |
| |
| AllRequestFilter filter = mockControl.createMock(AllRequestFilter.class); |
| filter.init(config); |
| filter.doFilter(eq(req), eq(res), capture(capturedChain)); |
| chain.doFilter(req, res); |
| filter.destroy(); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| addFilter(filter); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req, res, chain); |
| capturedChain.getValue().doFilter(req, res); |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void twoFiltersNoBubbling() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req = new FakeHttpServletRequest(); |
| HttpServletResponse res = new FakeHttpServletResponse(); |
| |
| IMocksControl mockControl = ems.createStrictControl(); |
| FilterChain chain = mockControl.createMock(FilterChain.class); |
| |
| AllRequestFilter filterA = mockControl.createMock(AllRequestFilter.class); |
| |
| AllRequestFilter filterB = mockControl.createMock(AllRequestFilter.class); |
| filterA.init(config); |
| filterB.init(config); |
| filterA.doFilter(eq(req), eq(res), anyObject(FilterChain.class)); |
| filterA.destroy(); |
| filterB.destroy(); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| addFilter(filterA); |
| addFilter(filterB); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req, res, chain); |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void twoFiltersBubbling() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req = new FakeHttpServletRequest(); |
| HttpServletResponse res = new FakeHttpServletResponse(); |
| |
| IMocksControl mockControl = ems.createStrictControl(); |
| FilterChain chain = mockControl.createMock(FilterChain.class); |
| |
| Capture<FilterChain> capturedChainA = new Capture<>(); |
| Capture<FilterChain> capturedChainB = new Capture<>(); |
| |
| AllRequestFilter filterA = mockControl.createMock(AllRequestFilter.class); |
| AllRequestFilter filterB = mockControl.createMock(AllRequestFilter.class); |
| |
| filterA.init(config); |
| filterB.init(config); |
| filterA.doFilter(eq(req), eq(res), capture(capturedChainA)); |
| filterB.doFilter(eq(req), eq(res), capture(capturedChainB)); |
| chain.doFilter(req, res); |
| filterA.destroy(); |
| filterB.destroy(); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| addFilter(filterA); |
| addFilter(filterB); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req, res, chain); |
| capturedChainA.getValue().doFilter(req, res); |
| capturedChainB.getValue().doFilter(req, res); |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void postponedLoading() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req1 = new FakeHttpServletRequest(); |
| HttpServletRequest req2 = new FakeHttpServletRequest(); |
| HttpServletResponse res1 = new FakeHttpServletResponse(); |
| HttpServletResponse res2 = new FakeHttpServletResponse(); |
| |
| IMocksControl mockControl = ems.createStrictControl(); |
| FilterChain chain = mockControl.createMock("chain", FilterChain.class); |
| |
| Capture<FilterChain> capturedChainA1 = new Capture<>(); |
| Capture<FilterChain> capturedChainA2 = new Capture<>(); |
| Capture<FilterChain> capturedChainB = new Capture<>(); |
| |
| AllRequestFilter filterA = mockControl.createMock("filterA", AllRequestFilter.class); |
| AllRequestFilter filterB = mockControl.createMock("filterB", AllRequestFilter.class); |
| |
| filterA.init(config); |
| filterA.doFilter(eq(req1), eq(res1), capture(capturedChainA1)); |
| chain.doFilter(req1, res1); |
| |
| filterA.doFilter(eq(req2), eq(res2), capture(capturedChainA2)); |
| filterB.init(config); // <-- This is crucial part. filterB got loaded |
| // after filterProxy's init finished. Nonetheless filterB gets initialized. |
| filterB.doFilter(eq(req2), eq(res2), capture(capturedChainB)); |
| chain.doFilter(req2, res2); |
| |
| filterA.destroy(); |
| filterB.destroy(); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| addFilter(filterA); |
| |
| filterProxy.init(config); |
| filterProxy.doFilter(req1, res1, chain); |
| capturedChainA1.getValue().doFilter(req1, res1); |
| |
| addFilter(filterB); // <-- Adds filter after filterProxy's init got called. |
| filterProxy.doFilter(req2, res2, chain); |
| capturedChainA2.getValue().doFilter(req2, res2); |
| capturedChainB.getValue().doFilter(req2, res2); |
| |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| |
| @Test |
| public void dynamicUnloading() throws Exception { |
| EasyMockSupport ems = new EasyMockSupport(); |
| |
| FilterConfig config = ems.createMock(FilterConfig.class); |
| HttpServletRequest req1 = new FakeHttpServletRequest(); |
| HttpServletRequest req2 = new FakeHttpServletRequest(); |
| HttpServletRequest req3 = new FakeHttpServletRequest(); |
| HttpServletResponse res1 = new FakeHttpServletResponse(); |
| HttpServletResponse res2 = new FakeHttpServletResponse(); |
| HttpServletResponse res3 = new FakeHttpServletResponse(); |
| |
| Plugin plugin = ems.createMock(Plugin.class); |
| |
| IMocksControl mockControl = ems.createStrictControl(); |
| FilterChain chain = mockControl.createMock("chain", FilterChain.class); |
| |
| Capture<FilterChain> capturedChainA1 = new Capture<>(); |
| Capture<FilterChain> capturedChainB1 = new Capture<>(); |
| Capture<FilterChain> capturedChainB2 = new Capture<>(); |
| |
| AllRequestFilter filterA = mockControl.createMock("filterA", AllRequestFilter.class); |
| AllRequestFilter filterB = mockControl.createMock("filterB", AllRequestFilter.class); |
| |
| filterA.init(config); |
| filterB.init(config); |
| |
| filterA.doFilter(eq(req1), eq(res1), capture(capturedChainA1)); |
| filterB.doFilter(eq(req1), eq(res1), capture(capturedChainB1)); |
| chain.doFilter(req1, res1); |
| |
| filterA.destroy(); // Cleaning up of filterA after it got unloaded |
| |
| filterB.doFilter(eq(req2), eq(res2), capture(capturedChainB2)); |
| chain.doFilter(req2, res2); |
| |
| filterB.destroy(); // Cleaning up of filterA after it got unloaded |
| |
| chain.doFilter(req3, res3); |
| |
| ems.replayAll(); |
| |
| AllRequestFilter.FilterProxy filterProxy = getFilterProxy(); |
| ReloadableRegistrationHandle<AllRequestFilter> handleFilterA = addFilter(filterA); |
| ReloadableRegistrationHandle<AllRequestFilter> handleFilterB = addFilter(filterB); |
| |
| filterProxy.init(config); |
| |
| // Request #1 with filterA and filterB |
| filterProxy.doFilter(req1, res1, chain); |
| capturedChainA1.getValue().doFilter(req1, res1); |
| capturedChainB1.getValue().doFilter(req1, res1); |
| |
| // Unloading filterA |
| handleFilterA.remove(); |
| filterProxy.onStopPlugin(plugin); |
| |
| // Request #1 only with filterB |
| filterProxy.doFilter(req2, res2, chain); |
| capturedChainA1.getValue().doFilter(req2, res2); |
| |
| // Unloading filterB |
| handleFilterB.remove(); |
| filterProxy.onStopPlugin(plugin); |
| |
| // Request #1 with no additional filters |
| filterProxy.doFilter(req3, res3, chain); |
| |
| filterProxy.destroy(); |
| |
| ems.verifyAll(); |
| } |
| } |