/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You 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.apache.geode.modules.session.internal.filter; import org.apache.geode.cache.Region; import org.apache.geode.distributed.internal.DistributionConfig; import org.apache.geode.modules.session.filter.SessionCachingFilter; import org.apache.geode.modules.session.junit.PerTestClassLoaderRunner; import org.apache.geode.test.junit.categories.FlakyTest; import org.apache.geode.test.junit.categories.IntegrationTest; import org.apache.jasper.servlet.JspServlet; import org.eclipse.jetty.http.HttpTester; import org.eclipse.jetty.servlet.FilterHolder; import org.eclipse.jetty.servlet.ServletHolder; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.*; import java.util.concurrent.TimeUnit; import static org.junit.Assert.*; import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; /** * In-container testing using Jetty. This allows us to test context listener events as well as * dispatching actions. */ @Category(IntegrationTest.class) @RunWith(PerTestClassLoaderRunner.class) @SuppressWarnings("unchecked") public class SessionReplicationIntegrationJUnitTest { private MyServletTester tester; private HttpTester.Request request; private HttpTester.Response response; private ServletHolder servletHolder; private FilterHolder filterHolder; @Rule public TemporaryFolder tmpdir = new TemporaryFolder(); @Before public void setUp() throws Exception { File gemfireLogFile = new File(tmpdir.newFolder(), "gemfire_modules.log"); request = HttpTester.newRequest(); tester = new MyServletTester(); tester.setContextPath("/test"); filterHolder = tester.addFilter(SessionCachingFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST)); filterHolder.setInitParameter(DistributionConfig.GEMFIRE_PREFIX + "property.mcast-port", "0"); filterHolder.setInitParameter(DistributionConfig.GEMFIRE_PREFIX + "property.log-file", gemfireLogFile.getAbsolutePath()); filterHolder.setInitParameter("cache-type", "peer-to-peer"); servletHolder = tester.addServlet(BasicServlet.class, "/hello"); servletHolder.setInitParameter("test.callback", "callback_1"); /** * This starts the servlet. Our wrapped servlets *must* start immediately otherwise the * ServletContext is not captured correctly. */ servletHolder.setInitOrder(0); } @After public void tearDown() throws Exception { tester.stop(); } @Test public void testSanity() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter out = response.getWriter(); out.write("Hello World"); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals(200, response.getStatus()); assertEquals("Hello World", response.getContent()); } @Test public void testSessionGenerated() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter out = response.getWriter(); out.write(request.getSession().getId()); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertTrue("Not a correctly generated session id", response.getContent().endsWith("-GF")); List<Cookie> cookies = getCookies(response); assertEquals("Session id != JSESSIONID from cookie", response.getContent(), cookies.get(0).getValue()); Region r = getRegion(); assertNotNull("Session not found in region", r.get(cookies.get(0).getValue())); } /** * Test that getSession(false) does not create a new session */ @Test public void testSessionNotGenerated() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { String output = "OK"; HttpSession s = request.getSession(false); if (s != null) { output = s.getId(); } PrintWriter out = response.getWriter(); out.write(output); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("Session should not have been created", "OK", response.getContent()); } @Test public void testUnknownAttributeIsNull() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { Object o = request.getSession().getAttribute("unknown"); PrintWriter out = response.getWriter(); if (o == null) { out.write("null"); } else { out.write(o.toString()); } } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("Unknown attribute should be null", "null", response.getContent()); } @Test public void testSessionRemains1() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { String output = "null"; HttpSession session = request.getSession(); if (session.isNew()) { output = "new"; session.setAttribute("foo", output); } else { output = (String) session.getAttribute("foo"); if (output != null) { output = "old"; } } PrintWriter out = response.getWriter(); out.write(output); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("Session should be new", "new", response.getContent()); List<Cookie> cookies = getCookies(response); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("Session should be old", "old", response.getContent()); List<Cookie> cookies2 = getCookies(response); assertEquals("Session IDs should be the same", cookies.get(0).getValue(), cookies2.get(0).getValue()); Region r = getRegion(); assertNotNull("Session object should exist in region", r.get(cookies.get(0).getValue())); } /** * Test that attributes are updated on the backend */ @Test public void testAttributesUpdatedInRegion() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().setAttribute("foo", "bar"); } }; // This is the callback used to invalidate the session Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().setAttribute("foo", "baz"); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); servletHolder.setInitParameter("test.callback", "callback_1"); ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2"); sh2.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); List<Cookie> cookies = getCookies(response); Region r = getRegion(); assertEquals("bar", ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo")); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); request.setURI("/test/request2"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("baz", ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo")); } /** * Test setting an attribute to null deletes it */ @Category(FlakyTest.class) // GEODE-1015: uses Jetty HttpTester, uses static vars with class // loader isolation, TODO: rewrite test with JUnit 4 rules including // TemporaryFolder @Test public void testSetAttributeNullDeletesIt() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().setAttribute("foo", "bar"); } }; // This is the callback used to invalidate the session Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().setAttribute("foo", null); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); servletHolder.setInitParameter("test.callback", "callback_1"); ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2"); sh2.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); List<Cookie> cookies = getCookies(response); Region r = getRegion(); assertEquals("bar", ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo")); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); request.setURI("/test/request2"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertNull(((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo")); } /** * Test that a servlet can modify cookies */ @Test public void testUserCanModifyTheirOwnCookie() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { Cookie userCookie = findUserCookie(request.getCookies()); if (userCookie == null) { userCookie = new Cookie("myCookie", "0"); } else { userCookie = new Cookie("myCookie", Integer.toString(Integer.valueOf(userCookie.getValue()) + 1)); } response.addCookie(userCookie); request.getSession().setAttribute("dummy", "value"); } }; tester.setAttribute("callback_1", c); String url = tester.createConnector(true); tester.start(); WebConversation wc = new WebConversation(); WebRequest req = new GetMethodWebRequest(url + "/test/hello"); req.setHeaderField("Cookie", "myCookie=" + 5); final WebResponse webResponse = wc.getResponse(req); assertEquals("6", webResponse.getNewCookieValue("myCookie")); } private Cookie findUserCookie(Cookie[] cookies) { if (cookies == null) { return null; } Cookie userCookie = null; for (Cookie cookie : cookies) { if (cookie.getName().equals("myCookie")) { userCookie = cookie; } } return userCookie; } // Don't see how to do this currently as the SessionListener needs a full // web context to work in. // /** // * Test that sessions expire correctly // */ // public void testSessionExpiration() throws Exception { // Callback c_1 = new Callback() { // @Override // public void call(HttpServletRequest request, HttpServletResponse response) // throws IOException, ServletException { // HttpSession s = request.getSession(); // s.setAttribute("foo", "bar"); // s.setMaxInactiveInterval(1); // // PrintWriter out = response.getWriter(); // out.write(s.getId()); // } // }; // // // This is the callback used to check if the session is still there // Callback c_2 = new Callback() { // @Override // public void call(HttpServletRequest request, HttpServletResponse response) // throws IOException, ServletException { // HttpSession s = request.getSession(false); // String output; // if (s == null) { // output = "null"; // } else { // output = s.getId(); // } // // PrintWriter out = response.getWriter(); // out.write(output); // } // }; // // tester.addEventListener(new SessionListener()); // tester.setAttribute("callback_1", c_1); // tester.setAttribute("callback_2", c_2); // // servletHolder.setInitParameter("test.callback", "callback_1"); // // ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2"); // sh2.setInitParameter("test.callback", "callback_2"); // // tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); // // request.setMethod("GET"); // request.setURI("/test/hello"); // request.setHeader("Host", "tester"); // request.setVersion("HTTP/1.0"); // response.parse(tester.getResponses(request.generate())); // // String id = response.getContent(); // // // Wait for the session to expire // Thread.sleep(2000); // // request.setHeader("Cookie", "JSESSIONID=" + id); // request.setURI("/test/request2"); // response.parse(tester.getResponses(request.generate())); // // assertIndexDetailsEquals("null", response.getContent()); // // Region r = getRegion(); // assertNull("Region should not contain session", r.get(id)); // } /** * Test that invalidating a session destroys it as well as the backend object. */ @Category(FlakyTest.class) // GEODE-1015: uses Jetty HttpTester, uses static vars with class // loader isolation, TODO: rewrite test with JUnit 4 rules including // TemporaryFolder @Test public void testInvalidateSession1() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().setAttribute("foo", "bar"); } }; // This is the callback used to invalidate the session Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession(false).invalidate(); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); servletHolder.setInitParameter("test.callback", "callback_1"); ServletHolder sh2 = tester.addServlet(BasicServlet.class, "/request2"); sh2.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); List<Cookie> cookies = getCookies(response); Region r = getRegion(); assertEquals("bar", ((HttpSession) r.get(cookies.get(0).getValue())).getAttribute("foo")); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); request.setURI("/test/request2"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertNull("Region should not contain session", r.get(cookies.get(0).getValue())); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Test public void testInvalidateSession2() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.getAttribute("foo"); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Category(FlakyTest.class) // GEODE-1015: uses Jetty HttpTester, uses static vars with class // loader isolation, TODO: rewrite test with JUnit 4 rules including // TemporaryFolder @Test public void testInvalidateSession3() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.getAttributeNames(); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Test public void testInvalidateSession4() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.getCreationTime(); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session does not throw an exception for subsequent getId calls. */ @Test public void testInvalidateSession5() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); s.getId(); PrintWriter out = response.getWriter(); out.write("OK"); } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Test public void testInvalidateSession6() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.getLastAccessedTime(); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session does not throw an exception for subsequent * getMaxInactiveInterval calls. */ // I've commented this out for now as Jetty seems to want to throw an // Exception here where the HttpServlet api doesn't specify that. @Test public void testInvalidateSession7() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); s.getMaxInactiveInterval(); PrintWriter out = response.getWriter(); out.write("OK"); } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session does not throw an exception for subsequent getServletContext * calls. */ @Test public void testInvalidateSession8() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); s.getServletContext(); PrintWriter out = response.getWriter(); out.write("OK"); } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Category(FlakyTest.class) // GEODE-1943 @Test public void testInvalidateSession9() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.isNew(); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); String url = tester.createConnector(true); tester.start(); WebConversation wc = new WebConversation(); WebRequest req = new GetMethodWebRequest(url + "/test/hello"); req.setHeaderField("Host", "tester"); final WebResponse webResponse = wc.getResponse(req); assertEquals("OK", webResponse.getResponseMessage()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Test public void testInvalidateSession10() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.removeAttribute("foo"); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session throws an exception on subsequent access. */ @Test public void testInvalidateSession11() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); try { s.setAttribute("foo", "bar"); } catch (IllegalStateException iex) { out.write("OK"); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session does not throw an exception for subsequent * setMaxInactiveInterval calls. */ @Test public void testInvalidateSession12() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); s.setMaxInactiveInterval(1); PrintWriter out = response.getWriter(); out.write("OK"); } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that invalidating a session results in null being returned on subsequent getSession(false) * calls. */ @Test public void testInvalidateSession13() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); s = request.getSession(false); PrintWriter out = response.getWriter(); if (s == null) { out.write("OK"); } else { out.write(s.toString()); } } }; tester.setAttribute("callback_1", c_1); servletHolder.setInitParameter("test.callback", "callback_1"); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("OK", response.getContent()); } /** * Test that we can invalidate and then recreate a new session */ @Test public void testInvalidateAndRecreateSession() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter out = response.getWriter(); out.write(request.getSession().getId()); } }; Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.invalidate(); PrintWriter out = response.getWriter(); out.write(request.getSession().getId()); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch"); sh.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // sh.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); String session1 = response.getContent(); request.setHeader("Cookie", "JSESSIONID=" + session1); request.setURI("/test/request2"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); String session12 = response.getContent(); assertFalse("First and subsequent session ids must not be the same", session1.equals(session12)); } /** * Test that creation time does not change on subsequent access */ @Test public void testGetCreationTime() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); PrintWriter out = response.getWriter(); out.write(Long.toString(session.getCreationTime())); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); long time1 = Long.parseLong(response.getContent()); assertTrue("Creation time should be positive", time1 > 0); List<Cookie> cookies = getCookies(response); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); try { Thread.sleep(1000); } catch (Exception ex) { } response = HttpTester.parseResponse(tester.getResponses(request.generate())); long time2 = Long.parseLong(response.getContent()); assertTrue("Creation time should be the same across requests", time1 == time2); } /** * Test that the last accessed time is updated on subsequent access */ @Test public void testGetLastAccessedTime() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(); PrintWriter out = response.getWriter(); out.write(Long.toString(session.getLastAccessedTime())); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); long time1 = Long.parseLong(response.getContent()); // assertTrue("Last accessed time should be positive", time1 > 0); List<Cookie> cookies = getCookies(response); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); Thread.sleep(1000); response = HttpTester.parseResponse(tester.getResponses(request.generate())); long time2 = Long.parseLong(response.getContent()); assertTrue("Last accessed time should be increasing across requests", time2 > time1); } /** * Test that the underlying native session remains the same across requests */ @Test public void testNativeSessionRemainsUnchanged() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { GemfireHttpSession session = (GemfireHttpSession) request.getSession(); PrintWriter out = response.getWriter(); out.write(session.getNativeSession().getId()); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); String nativeSessionId = response.getContent(); List<Cookie> cookies = getCookies(response); String sessionId = cookies.get(0).getValue(); Region r = getRegion(); assertEquals("Cached native session id does not match servlet returned native session id", nativeSessionId, ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId()); request.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue()); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("Underlying native sessions must remain the same across requests", nativeSessionId, ((GemfireHttpSession) r.get(sessionId)).getNativeSession().getId()); } /** * Test session id embedded in the URL */ @Test public void testSessionIdEmbeddedInUrl() throws Exception { Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { GemfireHttpSession session = (GemfireHttpSession) request.getSession(); PrintWriter out = response.getWriter(); out.write(session.getId()); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); List<Cookie> cookies = getCookies(response); String sessionId = response.getContent(); assertEquals("Session ids should be the same", sessionId, cookies.get(0).getValue()); request.setURI("/test/hello;jsessionid=" + sessionId); response = HttpTester.parseResponse(tester.getResponses(request.generate())); cookies = getCookies(response); assertEquals("Session ids should be the same", sessionId, cookies.get(0).getValue()); } /** * Test that request forward dispatching works */ @Category(FlakyTest.class) // GEODE-1015: uses Jetty HttpTester, uses static vars with class // loader isolation, TODO: rewrite test with JUnit 4 rules including // TemporaryFolder @Test public void testDispatchingForward1() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { RequestDispatcher dispatcher = request.getRequestDispatcher("dispatch"); dispatcher.forward(request, response); // This should not appear in the output PrintWriter out = response.getWriter(); out.write("bang"); } }; // This is the callback used by the forward servlet Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { PrintWriter out = response.getWriter(); out.write("dispatched"); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch"); sh.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // sh.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("dispatched", response.getContent()); // ContextManager.getInstance().removeContext( // sh.getServlet().getServletConfig().getServletContext()); } /** * Test that request include dispatching works */ @Test public void testDispatchingInclude() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { RequestDispatcher dispatcher = request.getRequestDispatcher("dispatch"); dispatcher.include(request, response); // This *should* appear in the output PrintWriter out = response.getWriter(); out.write("_bang"); } }; // This is the callback used by the include servlet Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { PrintWriter out = response.getWriter(); out.write("dispatched"); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); ServletHolder sh = tester.addServlet(BasicServlet.class, "/dispatch"); sh.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // sh.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("dispatched_bang", response.getContent()); // ContextManager.getInstance().removeContext( // sh.getServlet().getServletConfig().getServletContext()); } /** * Test to try and simulate a failover scenario */ @Test public void testFailover1() throws Exception { Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession s = request.getSession(); s.setAttribute("foo", "bar"); PrintWriter out = response.getWriter(); out.write(request.getSession().getId()); } }; Callback c_2 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { HttpSession s = request.getSession(); PrintWriter out = response.getWriter(); out.write((String) s.getAttribute("foo")); } }; tester.setAttribute("callback_1", c_1); tester.setAttribute("callback_2", c_2); ServletHolder sh = tester.addServlet(BasicServlet.class, "/request2"); sh.setInitParameter("test.callback", "callback_2"); tester.start(); // ContextManager.getInstance().putContext( // sh.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); String id = response.getContent(); // Now we simulate the failover by removing the native session from // the stored session Region r = getRegion(); GemfireHttpSession sessObj = (GemfireHttpSession) r.get(id); sessObj.setNativeSession(null); r.put(id, sessObj); request.setHeader("Cookie", "JSESSIONID=" + id); request.setURI("/test/request2"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals("bar", response.getContent()); } @Test public void testHttpSessionListener1() throws Exception { HttpSessionListenerImpl listener = new HttpSessionListenerImpl(); tester.getContext().getSessionHandler().addEventListener(listener); Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); // This is set in HttpSessionListenerImpl String result = (String) s.getAttribute("gemfire-session-id"); response.getWriter().write(result); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals(200, response.getStatus()); List<Cookie> cookies = getCookies(response); // AbstractListener listener = RendezvousManager.getListener(); tester.stop(); assertTrue("Timeout waiting for events", listener.await(1, TimeUnit.SECONDS)); assertEquals(ListenerEventType.SESSION_CREATED, listener.events.get(0)); assertEquals(ListenerEventType.SESSION_DESTROYED, listener.events.get(1)); assertEquals(cookies.get(0).getValue(), response.getContent()); } @Test public void testHttpSessionListener2() throws Exception { HttpSessionListenerImpl2 listener = new HttpSessionListenerImpl2(); tester.getContext().getSessionHandler().addEventListener(listener); Callback c = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession s = request.getSession(); s.setAttribute("test01", "test01"); s = request.getSession(false); s.invalidate(); response.getWriter().write(s.getId()); } }; tester.setAttribute("callback_1", c); tester.start(); // ContextManager.getInstance().putContext( // servletHolder.getServlet().getServletConfig().getServletContext()); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals(200, response.getStatus()); List<Cookie> cookies = getCookies(response); tester.stop(); assertTrue("Timeout waiting for events", listener.await(1, TimeUnit.SECONDS)); assertEquals(ListenerEventType.SESSION_CREATED, listener.events.get(0)); assertEquals(ListenerEventType.SESSION_DESTROYED, listener.events.get(1)); assertEquals(cookies.get(0).getValue(), response.getContent()); } // @Test public void testJsp() throws Exception { tester.setResourceBase("target/test-classes"); ServletHolder jspHolder = tester.addServlet(JspServlet.class, "/test/*"); jspHolder.setInitOrder(1); jspHolder.setInitParameter("scratchdir", tmpdir.toString()); Callback c_1 = new Callback() { @Override public void call(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { request.getSession().setAttribute("foo", "bar"); request.setAttribute("foo", "baz"); RequestDispatcher dispatcher = request.getRequestDispatcher("pagecontext.jsp"); dispatcher.forward(request, response); } }; tester.getContext().setClassLoader(Thread.currentThread().getContextClassLoader()); tester.setAttribute("callback_1", c_1); tester.start(); request.setMethod("GET"); request.setURI("/test/hello"); request.setHeader("Host", "tester"); request.setVersion("HTTP/1.0"); response = HttpTester.parseResponse(tester.getResponses(request.generate())); assertEquals(200, response.getStatus()); assertEquals("baz", response.getContent().trim()); } //////////////////////////////////////////////////////////////////// // Private methods /** * Why doesn't HttpTester do this already?? */ private List<Cookie> getCookies(HttpTester.Response response) { List<Cookie> cookies = new ArrayList<Cookie>(); Enumeration e = response.getValues("Set-Cookie"); while (e != null && e.hasMoreElements()) { String header = (String) e.nextElement(); Cookie c = null; StringTokenizer st = new StringTokenizer(header, ";"); while (st.hasMoreTokens()) { String[] split = st.nextToken().split("="); String param = split[0].trim(); String value = null; if (split.length > 1) { value = split[1].trim(); } if ("version".equalsIgnoreCase(param)) { c.setVersion(Integer.parseInt(value)); } else if ("comment".equalsIgnoreCase(param)) { c.setComment(value); } else if ("domain".equalsIgnoreCase(param)) { c.setDomain(value); } else if ("max-age".equalsIgnoreCase(param)) { c.setMaxAge(Integer.parseInt(value)); } else if ("discard".equalsIgnoreCase(param)) { c.setMaxAge(-1); } else if ("path".equalsIgnoreCase(param)) { c.setPath(value); } else if ("secure".equalsIgnoreCase(param)) { c.setSecure(true); } else if ("httponly".equalsIgnoreCase(param)) { // Ignored?? } else { if (c == null) { c = new Cookie(param, value); } else { throw new IllegalStateException("Unknown cookie param: " + param); } } } if (c != null) { cookies.add(c); } } return cookies; } private Region getRegion() { // Yuck... return ((GemfireSessionManager) ((SessionCachingFilter) filterHolder.getFilter()) .getSessionManager()).getCache().getCache().getRegion("gemfire_modules_sessions"); } }