Merge remote-tracking branch 'origin/jetty-9.3.x' into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2016-11-17 17:00:58 -07:00
commit b5cd3cfca1
1 changed files with 104 additions and 14 deletions

View File

@ -27,22 +27,37 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.Socket; import java.net.Socket;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.LeakTrackingByteBufferPool;
import org.eclipse.jetty.io.MappedByteBufferPool;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestTracker; import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.Scheduler;
import org.junit.After; import org.junit.After;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class ThreadStarvationTest public class ThreadStarvationTest
{ {
final static int BUFFER_SIZE=1024*1024; final static int BUFFER_SIZE=1024*1024;
@ -51,10 +66,86 @@ public class ThreadStarvationTest
final static int THREADS=5; final static int THREADS=5;
@Rule @Rule
public TestTracker tracker = new TestTracker(); public TestTracker tracker = new TestTracker();
interface ConnectorProvider {
ServerConnector newConnector(Server server, int acceptors, int selectors);
}
interface ClientSocketProvider {
Socket newSocket(String host, int port) throws IOException;
}
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> params()
{
List<Object[]> params = new ArrayList<>();
// HTTP
ConnectorProvider http = (server, acceptors, selectors) -> new ServerConnector(server, acceptors, selectors);
ClientSocketProvider httpClient = (host, port) -> new Socket(host, port);
params.add(new Object[]{ "http", http, httpClient });
// HTTPS/SSL/TLS
ConnectorProvider https = (server, acceptors, selectors) -> {
Path keystorePath = MavenTestingUtils.getTestResourcePath("keystore");
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath(keystorePath.toString());
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setKeyManagerPassword("keypwd");
sslContextFactory.setTrustStorePath(keystorePath.toString());
sslContextFactory.setTrustStorePassword("storepwd");
ByteBufferPool pool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory();
ServerConnector connector = new ServerConnector(server,(Executor)null,(Scheduler)null,
pool, acceptors, selectors,
AbstractConnectionFactory.getFactories(sslContextFactory,httpConnectionFactory));
SecureRequestCustomizer secureRequestCustomer = new SecureRequestCustomizer();
secureRequestCustomer.setSslSessionAttribute("SSL_SESSION");
httpConnectionFactory.getHttpConfiguration().addCustomizer(secureRequestCustomer);
return connector;
};
ClientSocketProvider httpsClient = new ClientSocketProvider()
{
private SSLContext sslContext;
{
try
{
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session)-> true);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, SslContextFactory.TRUST_ALL_CERTS, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
}
catch(Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public Socket newSocket(String host, int port) throws IOException
{
return sslContext.getSocketFactory().createSocket(host,port);
}
};
params.add(new Object[]{ "https/ssl/tls", https, httpsClient });
return params;
}
private final ConnectorProvider connectorProvider;
private final ClientSocketProvider clientSocketProvider;
private QueuedThreadPool _threadPool; private QueuedThreadPool _threadPool;
private Server _server; private Server _server;
private ServerConnector _connector; private ServerConnector _connector;
public ThreadStarvationTest(String testType, ConnectorProvider connectorProvider, ClientSocketProvider clientSocketProvider)
{
this.connectorProvider = connectorProvider;
this.clientSocketProvider = clientSocketProvider;
}
private Server prepareServer(Handler handler) private Server prepareServer(Handler handler)
{ {
_threadPool = new QueuedThreadPool(); _threadPool = new QueuedThreadPool();
@ -64,7 +155,7 @@ public class ThreadStarvationTest
_server = new Server(_threadPool); _server = new Server(_threadPool);
int acceptors = 1; int acceptors = 1;
int selectors = 1; int selectors = 1;
_connector = new ServerConnector(_server, acceptors, selectors); _connector = connectorProvider.newConnector(_server, acceptors, selectors);
_server.addConnector(_connector); _server.addConnector(_connector);
_server.setHandler(handler); _server.setHandler(handler);
return _server; return _server;
@ -80,13 +171,13 @@ public class ThreadStarvationTest
public void testReadInput() throws Exception public void testReadInput() throws Exception
{ {
prepareServer(new ReadHandler()).start(); prepareServer(new ReadHandler()).start();
try(Socket client = new Socket("localhost", _connector.getLocalPort())) try(Socket client = clientSocketProvider.newSocket("localhost", _connector.getLocalPort()))
{ {
client.setSoTimeout(10000); client.setSoTimeout(10000);
OutputStream os = client.getOutputStream(); OutputStream os = client.getOutputStream();
InputStream is = client.getInputStream(); InputStream is = client.getInputStream();
String request = "" + String request = "" +
"GET / HTTP/1.0\r\n" + "GET / HTTP/1.0\r\n" +
"Host: localhost\r\n" + "Host: localhost\r\n" +
@ -95,7 +186,7 @@ public class ThreadStarvationTest
"0123456789\r\n"; "0123456789\r\n";
os.write(request.getBytes(StandardCharsets.UTF_8)); os.write(request.getBytes(StandardCharsets.UTF_8));
os.flush(); os.flush();
String response = IO.toString(is); String response = IO.toString(is);
assertEquals(-1, is.read()); assertEquals(-1, is.read());
assertThat(response, containsString("200 OK")); assertThat(response, containsString("200 OK"));
@ -115,7 +206,7 @@ public class ThreadStarvationTest
for (int i = 0; i < client.length; i++) for (int i = 0; i < client.length; i++)
{ {
client[i] = new Socket("localhost", _connector.getLocalPort()); client[i] = clientSocketProvider.newSocket("localhost", _connector.getLocalPort());
client[i].setSoTimeout(10000); client[i].setSoTimeout(10000);
os[i] = client[i].getOutputStream(); os[i] = client[i].getOutputStream();
@ -162,9 +253,8 @@ public class ThreadStarvationTest
int r = 0; int r = 0;
while (r < l) while (r < l)
{ {
if (request.getInputStream().read() < 0) if (request.getInputStream().read() >= 0)
break; r++;
r++;
} }
response.getOutputStream().write(("Read Input " + r + "\r\n").getBytes()); response.getOutputStream().write(("Read Input " + r + "\r\n").getBytes());
@ -184,7 +274,7 @@ public class ThreadStarvationTest
for (int i = 0; i < client.length; i++) for (int i = 0; i < client.length; i++)
{ {
client[i] = new Socket("localhost", _connector.getLocalPort()); client[i] = clientSocketProvider.newSocket("localhost", _connector.getLocalPort());
client[i].setSoTimeout(10000); client[i].setSoTimeout(10000);
os[i] = client[i].getOutputStream(); os[i] = client[i].getOutputStream();
@ -242,10 +332,10 @@ public class ThreadStarvationTest
case '\n': case '\n':
switch(state) switch(state)
{ {
case 1: case 1:
state=2; state=2;
break; break;
case 3: case 3:
header=new String(content,0,j,StandardCharsets.ISO_8859_1); header=new String(content,0,j,StandardCharsets.ISO_8859_1);
assertThat(header,containsString(" 200 OK")); assertThat(header,containsString(" 200 OK"));
break loop; break loop;
@ -259,7 +349,7 @@ public class ThreadStarvationTest
} }
// Read the rest of the body // Read the rest of the body
while(len>0) while(len>0)
{ {
len=is[c].read(content); len=is[c].read(content);
if (len>0) if (len>0)