blob: 36f62582b71284979f5b7422306414b8e916450e [file] [log] [blame]
/**
* Copyright (C) 2011 Google Inc.
*
* 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.inject.servlet;
import static org.easymock.EasyMock.createControl;
import static org.easymock.EasyMock.expect;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Scopes;
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import junit.framework.TestCase;
import org.easymock.IMocksControl;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Tests to make sure that servlets with a context path are handled right. */
public class ContextPathTest extends TestCase {
@Inject @Named("foo")
private TestServlet fooServlet;
@Inject @Named("bar")
private TestServlet barServlet;
private IMocksControl globalControl;
private Injector injector;
private ServletContext servletContext;
private FilterConfig filterConfig;
private GuiceFilter guiceFilter;
@Override
public final void setUp() throws Exception {
injector = Guice.createInjector(new ServletModule() {
@Override
protected void configureServlets() {
bind(TestServlet.class).annotatedWith(Names.named("foo"))
.to(TestServlet.class).in(Scopes.SINGLETON);
bind(TestServlet.class).annotatedWith(Names.named("bar"))
.to(TestServlet.class).in(Scopes.SINGLETON);
serve("/foo/*").with(Key.get(TestServlet.class, Names.named("foo")));
serve("/bar/*").with(Key.get(TestServlet.class, Names.named("bar")));
// TODO: add a filter(..) call and validate it is correct
}
});
injector.injectMembers(this);
assertNotNull(fooServlet);
assertNotNull(barServlet);
assertNotSame(fooServlet, barServlet);
globalControl = createControl();
servletContext = globalControl.createMock(ServletContext.class);
filterConfig = globalControl.createMock(FilterConfig.class);
expect(servletContext.getAttribute(GuiceServletContextListener.INJECTOR_NAME))
.andReturn(injector).anyTimes();
expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
globalControl.replay();
guiceFilter = new GuiceFilter();
guiceFilter.init(filterConfig);
}
@Override
public final void tearDown() {
assertNotNull(fooServlet);
assertNotNull(barServlet);
fooServlet = null;
barServlet = null;
guiceFilter.destroy();
guiceFilter = null;
injector = null;
filterConfig = null;
servletContext = null;
globalControl.verify();
}
public void testSimple() throws Exception {
IMocksControl testControl = createControl();
TestFilterChain testFilterChain = new TestFilterChain();
HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
expect(req.getMethod()).andReturn("GET").anyTimes();
expect(req.getRequestURI()).andReturn("/bar/foo").anyTimes();
expect(req.getServletPath()).andReturn("/bar/foo").anyTimes();
expect(req.getContextPath()).andReturn("").anyTimes();
testControl.replay();
guiceFilter.doFilter(req, res, testFilterChain);
assertFalse(testFilterChain.isTriggered());
assertFalse(fooServlet.isTriggered());
assertTrue(barServlet.isTriggered());
testControl.verify();
}
//
// each of the following "runTest" calls takes three path parameters:
//
// The value of "getRequestURI()"
// The value of "getServletPath()"
// The value of "getContextPath()"
//
// these values have been captured using a filter in Apache Tomcat 6.0.32
// and are used for real-world values that a servlet container would send into
// the GuiceFilter.
//
// the remaining three booleans are:
//
// True if the request gets passed down the filter chain
// True if the request hits the "foo" servlet
// True if the request hits the "bar" sevlet
//
// After adjusting the request URI for the web app deployment location, all
// calls
// should always produce the same result.
//
// ROOT Web app, using Tomcat default servlet
public void testRootDefault() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
runTest("/", "/", "", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/bar/", "/bar/", "", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/foo/xxx", "/foo/xxx", "", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/xxx", "/xxx", "", true, false, false);
}
// ROOT Web app, using explicit backing servlet mounted at /*
public void testRootExplicit() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
runTest("/", "", "", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/bar/", "", "", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/foo/xxx", "", "", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/xxx", "", "", true, false, false);
}
// ROOT Web app, using two backing servlets, mounted at /bar/* and /foo/*
public void testRootSpecific() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
runTest("/", "/", "", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/bar/", "/bar", "", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/foo/xxx", "/foo", "", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/xxx", "/xxx", "", true, false, false);
}
// Web app located at /webtest, using Tomcat default servlet
public void testWebtestDefault() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
runTest("/webtest/", "/", "/webtest", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/webtest/bar/", "/bar/", "/webtest", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/webtest/foo/xxx", "/foo/xxx", "/webtest", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
}
// Web app located at /webtest, using explicit backing servlet mounted at /*
public void testWebtestExplicit() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and /bar/*).
runTest("/webtest/", "", "/webtest", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/webtest/bar/", "", "/webtest", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/webtest/foo/xxx", "", "/webtest", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/webtest/xxx", "", "/webtest", true, false, false);
}
// Web app located at /webtest, using two backing servlets, mounted at /bar/*
// and /foo/*
public void testWebtestSpecific() throws Exception {
// fetching /. Should go up the filter chain (only mappings on /foo/* and
// /bar/*).
runTest("/webtest/", "/", "/webtest", true, false, false);
// fetching /bar/. Should hit the bar servlet
runTest("/webtest/bar/", "/bar", "/webtest", false, false, true);
// fetching /foo/xxx. Should hit the foo servlet
runTest("/webtest/foo/xxx", "/foo", "/webtest", false, true, false);
// fetching /xxx. Should go up the chain
runTest("/webtest/xxx", "/xxx", "/webtest", true, false, false);
}
private void runTest(final String requestURI, final String servletPath, final String contextPath,
final boolean filterResult, final boolean fooResult, final boolean barResult)
throws Exception {
IMocksControl testControl = createControl();
barServlet.clear();
fooServlet.clear();
TestFilterChain testFilterChain = new TestFilterChain();
HttpServletRequest req = testControl.createMock(HttpServletRequest.class);
HttpServletResponse res = testControl.createMock(HttpServletResponse.class);
expect(req.getMethod()).andReturn("GET").anyTimes();
expect(req.getRequestURI()).andReturn(requestURI).anyTimes();
expect(req.getServletPath()).andReturn(servletPath).anyTimes();
expect(req.getContextPath()).andReturn(contextPath).anyTimes();
testControl.replay();
guiceFilter.doFilter(req, res, testFilterChain);
assertEquals(filterResult, testFilterChain.isTriggered());
assertEquals(fooResult, fooServlet.isTriggered());
assertEquals(barResult, barServlet.isTriggered());
testControl.verify();
}
public static class TestServlet extends HttpServlet {
private boolean triggered = false;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
triggered = true;
}
public boolean isTriggered() {
return triggered;
}
public void clear() {
triggered = false;
}
}
public static class TestFilterChain implements FilterChain {
private boolean triggered = false;
public void doFilter(ServletRequest request, ServletResponse response) throws IOException,
ServletException {
triggered = true;
}
public boolean isTriggered() {
return triggered;
}
public void clear() {
triggered = false;
}
}
}