Add test for memcached session data.

This commit is contained in:
Jan Bartel 2016-06-17 13:18:27 +10:00
parent 07b0127587
commit 1b508e3714
5 changed files with 416 additions and 2 deletions

View File

@ -81,9 +81,9 @@ public class CachingSessionDataStore extends ContainerLifeCycle implements Sessi
/**
* @return the cache
* @return the fronting cache for session data
*/
public SessionDataMap getCache ()
public SessionDataMap getSessionDataMap ()
{
return _cache;
}

View File

@ -20,5 +20,6 @@
<module>test-mongodb-sessions</module>
<module>test-infinispan-sessions</module>
<module>test-gcloud-sessions</module>
<module>test-memcached-sessions</module>
</modules>
</project>

View File

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
<version>9.4.0-SNAPSHOT</version>
</parent>
<artifactId>test-memcached-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Memcached</name>
<url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.sessions.memcached</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<!-- DO NOT DEPLOY (or Release) -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.memcached</groupId>
<artifactId>jetty-memcached-sessions</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>memcached</id>
<activation>
<property>
<name>memcached.enabled</name>
<value>true</value>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>false</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,157 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.memcached.sessions;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.memcached.sessions.MemcachedTestServer.MockDataStore;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.CachingSessionDataStore;
import org.eclipse.jetty.server.session.SessionCache;
import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.server.session.SessionDataMap;
import org.eclipse.jetty.server.session.SessionDataStore;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.junit.Test;
/**
* CachingSessionDataStoreTest
*
*
*/
public class CachingSessionDataStoreTest
{
public AbstractTestServer createServer (int port, int max, int scavenge,int evictionPolicy)
{
return new MemcachedTestServer(port, max, scavenge, evictionPolicy);
}
@Test
public void testSessionCRUD () throws Exception
{
String servletMapping = "/server";
int scavengePeriod = -1;
int maxInactivePeriod = -1;
//Make sure sessions are evicted on request exit so they will need to be reloaded via cache/persistent store
AbstractTestServer server = createServer(0, maxInactivePeriod, scavengePeriod, SessionCache.EVICT_ON_SESSION_EXIT);
ServletContextHandler context = server.addContext("/");
context.addServlet(TestServlet.class, servletMapping);
String contextPath = "";
try
{
server.start();
int port=server.getPort();
HttpClient client = new HttpClient();
client.start();
try
{
//
//Create a session
//
ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create");
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
String sessionCookie = response.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
String id = AbstractTestServer.extractSessionId(sessionCookie);
//check that the memcache contains the session, and the session data store contains the session
CachingSessionDataStore ds = (CachingSessionDataStore)context.getSessionHandler().getSessionCache().getSessionDataStore();
assertNotNull(ds);
SessionDataStore persistentStore = ds.getSessionStore();
SessionDataMap dataMap = ds.getSessionDataMap();
//the backing persistent store contains the session
assertNotNull(persistentStore.load(id));
//the memcache cache contains the session
assertNotNull(dataMap.load(id));
//
//Update a session and check that is is NOT loaded via the persistent store
//
((MockDataStore)persistentStore).zeroLoadCount();
Request request = client.newRequest("http://localhost:" + port + contextPath + servletMapping + "?action=update");
request.header("Cookie", sessionCookie);
response = request.send();
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
assertEquals(0, ((MockDataStore)persistentStore).getLoadCount());
//check it was updated in the persistent store
SessionData sd = persistentStore.load(id);
assertNotNull(sd);
assertEquals("bar", sd.getAttribute("foo"));
//check it was updated in the cache
sd = dataMap.load(id);
assertNotNull(sd);
assertEquals("bar", sd.getAttribute("foo"));
}
finally
{
client.stop();
}
}
finally
{
server.stop();
}
}
public static class TestServlet extends HttpServlet
{
String id;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String action = request.getParameter("action");
if ("create".equals(action))
{
HttpSession session = request.getSession(true);
assertTrue(session.isNew());
id = session.getId();
return;
}
if ("update".equals(action))
{
HttpSession session = request.getSession(false);
assertNotNull(session);
session.setAttribute("foo", "bar");
return;
}
}
}
}

View File

@ -0,0 +1,167 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.memcached.sessions;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.jetty.memcached.session.MemcachedSessionDataMap;
import org.eclipse.jetty.server.session.AbstractSessionDataStore;
import org.eclipse.jetty.server.session.AbstractTestServer;
import org.eclipse.jetty.server.session.CachingSessionDataStore;
import org.eclipse.jetty.server.session.DefaultSessionCache;
import org.eclipse.jetty.server.session.SessionData;
import org.eclipse.jetty.server.session.SessionHandler;
/**
* MemcachedTestServer
*
*
*/
public class MemcachedTestServer extends AbstractTestServer
{
public static class MockDataStore extends AbstractSessionDataStore
{
private Map<String,SessionData> _store = new HashMap<>();
private int _loadCount = 0;
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#isPassivating()
*/
@Override
public boolean isPassivating()
{
return true;
}
/**
* @see org.eclipse.jetty.server.session.SessionDataStore#exists(java.lang.String)
*/
@Override
public boolean exists(String id) throws Exception
{
return _store.get(id) != null;
}
/**
* @see org.eclipse.jetty.server.session.SessionDataMap#load(java.lang.String)
*/
@Override
public SessionData load(String id) throws Exception
{
_loadCount++;
return _store.get(id);
}
public void zeroLoadCount()
{
_loadCount = 0;
}
public int getLoadCount()
{
return _loadCount;
}
/**
* @see org.eclipse.jetty.server.session.SessionDataMap#delete(java.lang.String)
*/
@Override
public boolean delete(String id) throws Exception
{
return (_store.remove(id) != null);
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doStore(java.lang.String, org.eclipse.jetty.server.session.SessionData, long)
*/
@Override
public void doStore(String id, SessionData data, long lastSaveTime) throws Exception
{
_store.put(id, data);
}
/**
* @see org.eclipse.jetty.server.session.AbstractSessionDataStore#doGetExpired(java.util.Set)
*/
@Override
public Set<String> doGetExpired(Set<String> candidates)
{
Set<String> expiredIds = new HashSet<>();
long now = System.currentTimeMillis();
if (candidates != null)
{
for (String id:candidates)
{
SessionData sd = _store.get(id);
if (sd == null)
expiredIds.add(id);
else if (sd.isExpiredAt(now))
expiredIds.add(id);
}
}
for (String id:_store.keySet())
{
SessionData sd = _store.get(id);
if (sd.isExpiredAt(now))
expiredIds.add(id);
}
return expiredIds;
}
}
/**
* @param port
* @param maxInactivePeriod
* @param scavengePeriod
* @param sessionIdMgrConfig
*/
public MemcachedTestServer(int port, int maxInactivePeriod, int scavengePeriod, int evictionPolicy)
{
super(port, maxInactivePeriod, scavengePeriod, evictionPolicy);
}
/**
* @see org.eclipse.jetty.server.session.AbstractTestServer#newSessionHandler(org.eclipse.jetty.server.SessionManager)
*/
@Override
public SessionHandler newSessionHandler()
{
SessionHandler handler = new SessionHandler();
handler.setSessionIdManager(_sessionIdManager);
MockDataStore persistentStore = new MockDataStore();
MemcachedSessionDataMap sdm = new MemcachedSessionDataMap("localhost", "11211");
CachingSessionDataStore cachingStore = new CachingSessionDataStore(sdm, persistentStore);
DefaultSessionCache ss = new DefaultSessionCache(handler);
ss.setSessionDataStore(cachingStore);
handler.setSessionCache(ss);
return handler;
}
}