Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2010-10-01 18:25:14 +0000
committerSimone Bordet2010-10-01 18:25:14 +0000
commit5f96d981d369475b30961c5b059c940b10bb7cd5 (patch)
treeb98fa9456a15be5fa81b6cb565cc5773c9512f35
parent21d371f1beb0e6870f6974f80775432b7989669b (diff)
downloadorg.eclipse.jetty.project-5f96d981d369475b30961c5b059c940b10bb7cd5.tar.gz
org.eclipse.jetty.project-5f96d981d369475b30961c5b059c940b10bb7cd5.tar.xz
org.eclipse.jetty.project-5f96d981d369475b30961c5b059c940b10bb7cd5.zip
Added tests to check SSL memory leaks.
git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2307 7e9141cc-0065-0410-87d8-b60c137991c4
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java302
1 files changed, 302 insertions, 0 deletions
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
new file mode 100644
index 0000000000..05bc8322d1
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
@@ -0,0 +1,302 @@
+package org.eclipse.jetty.server.ssl;
+
+import java.io.BufferedReader;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.security.KeyStore;
+import java.util.Arrays;
+import java.util.Random;
+import java.util.concurrent.Future;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManagerFactory;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SSLSelectChannelConnectorLoadTest
+{
+ private static Server server;
+ private static SslSelectChannelConnector connector;
+ private static SSLContext sslContext;
+
+ @BeforeClass
+ public static void startServer() throws Exception
+ {
+ server = new Server();
+ connector = new SslSelectChannelConnector();
+ server.addConnector(connector);
+
+ String keystorePath = System.getProperty("basedir", ".") + "/src/test/resources/keystore";
+ connector.setKeystore(keystorePath);
+ connector.setPassword("storepwd");
+ connector.setKeyPassword("keypwd");
+ connector.setTruststore(keystorePath);
+ connector.setTrustPassword("storepwd");
+
+ server.setHandler(new EmptyHandler());
+
+ server.start();
+
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(keystore);
+ sslContext = SSLContext.getInstance("SSL");
+ sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
+ }
+
+ @AfterClass
+ public static void stopServer() throws Exception
+ {
+ server.stop();
+ server.join();
+ }
+
+ @Test
+ public void testLongLivedConnections() throws Exception
+ {
+ Worker.totalIterations.set(0);
+
+ int mebiByte = 1048510;
+ int clients = 1;
+ int iterations = 2;
+ ThreadPoolExecutor threadPool = new ThreadPoolExecutor(clients, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
+ threadPool.prestartAllCoreThreads();
+ Worker[] workers = new Worker[clients];
+ Future[] tasks = new Future[clients];
+ for (int i = 0; i < clients; ++i)
+ {
+ workers[i] = new Worker(sslContext, iterations, false, mebiByte, 64 * mebiByte);
+ workers[i].open();
+ tasks[i] = threadPool.submit(workers[i]);
+ }
+
+ long start = System.currentTimeMillis();
+ while (true)
+ {
+ Thread.sleep(1000);
+ boolean done = true;
+ for (Future task : tasks)
+ done &= task.isDone();
+ System.err.print("\rIterations: " + Worker.totalIterations.get() + "/" + clients * iterations);
+ if (done)
+ break;
+ }
+ long end = System.currentTimeMillis();
+ System.err.println();
+ System.err.println("Elapsed time: " + TimeUnit.MILLISECONDS.toSeconds(end - start) + "s");
+
+ for (Worker worker : workers)
+ worker.close();
+
+ threadPool.shutdown();
+
+ // Throw exceptions if any
+ for (Future task : tasks)
+ task.get();
+
+ // Keep the JVM running
+// new CountDownLatch(1).await();
+ }
+
+ @Test
+ public void testShortLivedConnections() throws Exception
+ {
+ Worker.totalIterations.set(0);
+
+ int mebiByte = 1048510;
+ int clients = 1;
+ int iterations = 2;
+ ThreadPoolExecutor threadPool = new ThreadPoolExecutor(clients, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
+ threadPool.prestartAllCoreThreads();
+ Worker[] workers = new Worker[clients];
+ Future[] tasks = new Future[clients];
+ for (int i = 0; i < clients; ++i)
+ {
+ workers[i] = new Worker(sslContext, iterations, true, mebiByte, 64 * mebiByte);
+ tasks[i] = threadPool.submit(workers[i]);
+ }
+
+ long start = System.currentTimeMillis();
+ while (true)
+ {
+ Thread.sleep(1000);
+ boolean done = true;
+ for (Future task : tasks)
+ done &= task.isDone();
+ System.err.print("\rIterations: " + Worker.totalIterations.get() + "/" + clients * iterations);
+ if (done)
+ break;
+ }
+ long end = System.currentTimeMillis();
+ System.err.println();
+ System.err.println("Elapsed time: " + TimeUnit.MILLISECONDS.toSeconds(end - start) + "s");
+
+ threadPool.shutdown();
+
+ // Throw exceptions if any
+ for (Future task : tasks)
+ task.get();
+
+ // Keep the JVM running
+// new CountDownLatch(1).await();
+ }
+
+ private static class Worker implements Runnable
+ {
+ private static final AtomicLong totalIterations = new AtomicLong();
+ private final SSLContext sslContext;
+ private volatile SSLSocket sslSocket;
+ private final int iterations;
+ private final boolean closeConnection;
+ private final int minContent;
+ private final int maxContent;
+
+ public Worker(SSLContext sslContext, int iterations, boolean closeConnection, int minContent, int maxContent)
+ {
+ this.sslContext = sslContext;
+ this.iterations = iterations;
+ this.closeConnection = closeConnection;
+ this.minContent = minContent;
+ this.maxContent = maxContent;
+ }
+
+ public void open() throws IOException
+ {
+ this.sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket("localhost", connector.getLocalPort());
+ }
+
+ public void close() throws IOException
+ {
+ sslSocket.close();
+ }
+
+ public void run()
+ {
+ try
+ {
+ Random random = new Random();
+
+ StringBuilder builder = new StringBuilder();
+ OutputStream out = null;
+ InputStream in = null;
+ if (!closeConnection)
+ {
+ open();
+ out = sslSocket.getOutputStream();
+ in = sslSocket.getInputStream();
+ }
+
+ for (int i = 0; i < iterations; ++i)
+ {
+ if (closeConnection)
+ {
+ open();
+ out = sslSocket.getOutputStream();
+ in = sslSocket.getInputStream();
+ }
+
+ int contentSize = random.nextInt(maxContent - minContent) + minContent;
+// System.err.println("Writing " + content + " request bytes");
+ out.write("POST / HTTP/1.1\r\n".getBytes());
+ out.write("Host: localhost\r\n".getBytes());
+ out.write(("Content-Length: " + contentSize + "\r\n").getBytes());
+ out.write("Content-Type: application/octect-stream\r\n".getBytes());
+ if (closeConnection)
+ out.write("Connection: close\r\n".getBytes());
+ out.write("\r\n".getBytes());
+ out.flush();
+ byte[] contentChunk = new byte[minContent];
+ int content = contentSize;
+ while (content > 0)
+ {
+ int chunk = Math.min(content, contentChunk.length);
+ Arrays.fill(contentChunk, 0, chunk, (byte)'x');
+ out.write(contentChunk, 0, chunk);
+ content -= chunk;
+ }
+ out.flush();
+
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ int responseLength = 0;
+ String line;
+ while ((line = reader.readLine()) != null)
+ {
+// System.err.println(line);
+ String contentLength = "Content-Length:";
+ if (line.startsWith(contentLength))
+ {
+ responseLength = Integer.parseInt(line.substring(contentLength.length()).trim());
+ }
+ else if (line.length() == 0)
+ {
+ if (responseLength == 0)
+ line = reader.readLine();
+ break;
+ }
+ }
+
+ builder.setLength(0);
+ if (responseLength > 0)
+ {
+ for (int j = 0; j < responseLength; ++j)
+ builder.append((char)reader.read());
+ }
+ else
+ {
+ builder.append(line);
+ }
+
+ if (closeConnection)
+ close();
+
+ if (contentSize != Integer.parseInt(builder.toString()))
+ throw new IllegalStateException();
+
+ Thread.sleep(random.nextInt(1000));
+
+ totalIterations.incrementAndGet();
+ }
+
+ if (!closeConnection)
+ close();
+ }
+ catch (Exception x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+ }
+
+ private static class EmptyHandler extends AbstractHandler
+ {
+ public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
+ {
+ request.setHandled(true);
+
+ InputStream in = request.getInputStream();
+ int total = 0;
+ byte[] b = new byte[1024 * 1024];
+ int read;
+ while ((read = in.read(b)) >= 0)
+ total += read;
+// System.err.println("Read " + total + " request bytes");
+ httpResponse.getOutputStream().write(String.valueOf(total).getBytes());
+ }
+ }
+}

Back to the top