Jetty 9.4.x 3337 session serialization tests (#3409)

* Issue #3337 Session serialization tests

Signed-off-by: Jan Bartel <janb@webtide.com>
This commit is contained in:
Jan Bartel 2019-03-06 10:13:20 +11:00 committed by GitHub
parent c23303c05a
commit 11755539e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 237 additions and 47 deletions

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.server.session;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/**
* FileSessionDataStoreTest
@ -68,7 +69,17 @@ public class FileSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionExists(SessionData data) throws Exception
{
return (FileTestHelper.getFile(data.getId()) != null);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return (FileTestHelper.getFile(data.getId()) != null);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
/**
@ -77,7 +88,29 @@ public class FileSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return FileTestHelper.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return FileTestHelper.checkSessionPersisted(data);
}
catch (Throwable e)
{
e.printStackTrace();
throw e;
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
@Override
@Test
public void testStoreSession() throws Exception
{
super.testStoreSession();
}
}

View File

@ -96,7 +96,16 @@ public class GCloudSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return __testSupport.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return __testSupport.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
}

View File

@ -152,6 +152,15 @@ public class HazelcastSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return _testHelper.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return _testHelper.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
}

View File

@ -152,7 +152,16 @@ public class InfinispanSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return __testSupport.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return __testSupport.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
}

View File

@ -96,7 +96,16 @@ public class RemoteInfinispanSessionDataStoreTest extends AbstractSessionDataSto
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return __testSupport.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return __testSupport.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}

View File

@ -89,7 +89,17 @@ public class JDBCSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return JdbcTestHelper.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return JdbcTestHelper.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}
}

View File

@ -92,7 +92,16 @@ public class MongoSessionDataStoreTest extends AbstractSessionDataStoreTest
@Override
public boolean checkSessionPersisted(SessionData data) throws Exception
{
return MongoTestHelper.checkSessionPersisted(data);
ClassLoader old = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader (_contextClassLoader);
try
{
return MongoTestHelper.checkSessionPersisted(data);
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
}

View File

@ -58,7 +58,7 @@ public class MongoTestHelper
try
{
_mongoClient =
new MongoClient( System.getProperty( "embedmongo.host" ), Integer.getInteger( "embedmongoPort" ) );
new MongoClient( System.getProperty( "embedmongo.host" ), Integer.getInteger( "embedmongoPort" ) );
}
catch ( UnknownHostException e )
{

View File

@ -28,13 +28,20 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.jupiter.api.Test;
/**
@ -54,6 +61,7 @@ public abstract class AbstractSessionDataStoreTest
public static final long ANCIENT_TIMESTAMP = 100L;
public static final long RECENT_TIMESTAMP = System.currentTimeMillis() - TimeUnit.SECONDS.toMillis(3*GRACE_PERIOD_SEC);
protected URLClassLoader _contextClassLoader;
@ -70,31 +78,86 @@ public abstract class AbstractSessionDataStoreTest
/**
* Test that the store can persist a session.
* Test that the store can persist a session. The session uses an attribute
* class that is only known to the webapp classloader. This tests that
* we use the webapp loader when we serialize the session data (ie save the session).
*
* @throws Exception
*/
@Test
public void testStoreSession() throws Exception
{
//Use a class that would only be known to the webapp classloader
InputStream foostream = Thread.currentThread().getContextClassLoader().getResourceAsStream("Foo.clazz");
File foodir = new File (MavenTestingUtils.getTargetDir(), "foo");
foodir.mkdirs();
File fooclass = new File (foodir, "Foo.class");
IO.copy(foostream, new FileOutputStream(fooclass));
assertTrue(fooclass.exists());
assertTrue(fooclass.length() != 0);
URL[] foodirUrls = new URL[]{foodir.toURI().toURL()};
_contextClassLoader = new URLClassLoader(foodirUrls, Thread.currentThread().getContextClassLoader());
//create the SessionDataStore
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/test");
context.setContextPath("/test");
//use the classloader with the special class in it
context.setClassLoader(_contextClassLoader);
SessionDataStoreFactory factory = createSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
store.initialize(sessionContext);
store.start();
ClassLoader old = Thread.currentThread().getContextClassLoader();
SessionData data = null;
try
{
Thread.currentThread().setContextClassLoader(_contextClassLoader);
Class fooclazz = Class.forName("Foo", true, _contextClassLoader);
//create a session
long now = System.currentTimeMillis();
data = store.newSessionData("1234", 100, now, now-1, -1);//never expires
data.setLastNode(sessionContext.getWorkerName());
//Make an attribute that uses the class only known to the webapp classloader
data.setAttribute("a", fooclazz.getConstructor(null).newInstance());
}
finally
{
Thread.currentThread().setContextClassLoader(old);
}
//store the session, using a different thread to ensure
//that the thread is adorned with the webapp classloader
//before serialization
final SessionData finalData = data;
//create a session
long now = System.currentTimeMillis();
SessionData data = store.newSessionData("1234", 100, now, now-1, -1);//never expires
data.setAttribute("a", "b");
data.setLastNode(sessionContext.getWorkerName());
store.store("1234", data);
Runnable r = new Runnable()
{
@Override
public void run()
{
try
{
store.store("1234", finalData);
}
catch (Exception e)
{
fail(e);
}
}
};
Thread t = new Thread(r, "saver");
t.start();
t.join(TimeUnit.SECONDS.toMillis(10));
//check that the store contains all of the session data
assertTrue(checkSessionPersisted(data));
@ -148,33 +211,31 @@ public abstract class AbstractSessionDataStoreTest
*
* @throws Exception
*/
@Test
public void testStoreObjectAttributes() throws Exception
{
//create the SessionDataStore
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
context.setContextPath("/test");
SessionDataStoreFactory factory = createSessionDataStoreFactory();
((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(GRACE_PERIOD_SEC);
SessionDataStore store = factory.getSessionDataStore(context.getSessionHandler());
SessionContext sessionContext = new SessionContext("foo", context.getServletContext());
store.initialize(sessionContext);
store.start();
//create a session
SessionData data = store.newSessionData("1234", 100, 200, 199, -1);//never expires
TestFoo testFoo = new TestFoo();
testFoo.setInt(33);
FooInvocationHandler handler = new FooInvocationHandler(testFoo);
Foo foo = (Foo)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[] {Foo.class}, handler);
data.setAttribute("foo", foo);
data.setLastNode(sessionContext.getWorkerName());
//test that it can be persisted
store.store("1234", data);
checkSessionPersisted(data);
}
/*
* @Test public void testStoreObjectAttributes() throws Exception { //create
* the SessionDataStore ServletContextHandler context = new
* ServletContextHandler(ServletContextHandler.SESSIONS);
* context.setContextPath("/test"); SessionDataStoreFactory factory =
* createSessionDataStoreFactory();
* ((AbstractSessionDataStoreFactory)factory).setGracePeriodSec(
* GRACE_PERIOD_SEC); SessionDataStore store =
* factory.getSessionDataStore(context.getSessionHandler()); SessionContext
* sessionContext = new SessionContext("foo", context.getServletContext());
* store.initialize(sessionContext);
*
* store.start();
*
* //create a session SessionData data = store.newSessionData("1234", 100,
* 200, 199, -1);//never expires TestFoo testFoo = new TestFoo();
* testFoo.setInt(33); FooInvocationHandler handler = new
* FooInvocationHandler(testFoo); Foo foo =
* (Foo)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(
* ), new Class[] {Foo.class}, handler); data.setAttribute("foo", foo);
* data.setLastNode(sessionContext.getWorkerName());
*
* //test that it can be persisted store.store("1234", data);
* checkSessionPersisted(data); }
*/
/**
* Test that we can load a persisted session.

View File

@ -0,0 +1,41 @@
//
// ========================================================================
// Copyright (c) 1995-2019 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.
// ========================================================================
//
public class Foo implements java.io.Serializable
{
int myI = 0;
public Foo()
{
}
public void setI(int i)
{
myI = i;
}
public int getI()
{
return myI;
}
public boolean equals(Object o)
{
return ((Foo)o).getI() == myI;
}
}