Added tests for missing CONTINUE 100, error response, and timeout

This commit is contained in:
Michael Gorovoy 2011-08-23 16:56:05 -04:00
parent da517c815a
commit 5aced83287
2 changed files with 169 additions and 49 deletions

View File

@ -744,8 +744,10 @@ public class HttpConnection extends AbstractConnection implements Dumpable
} }
} }
/* ------------------------------------------------------------ */
private class ConnectionIdleTask extends Timeout.Task private class ConnectionIdleTask extends Timeout.Task
{ {
/* ------------------------------------------------------------ */
@Override @Override
public void expired() public void expired()
{ {
@ -758,41 +760,52 @@ public class HttpConnection extends AbstractConnection implements Dumpable
} }
/* ------------------------------------------------------------ */
private class NonFinalResponseListener implements HttpEventListener private class NonFinalResponseListener implements HttpEventListener
{ {
final HttpExchange _exchange; final HttpExchange _exchange;
final HttpEventListener _next; final HttpEventListener _next;
/* ------------------------------------------------------------ */
public NonFinalResponseListener(HttpExchange exchange) public NonFinalResponseListener(HttpExchange exchange)
{ {
_exchange=exchange; _exchange=exchange;
_next=exchange.getEventListener(); _next=exchange.getEventListener();
} }
/* ------------------------------------------------------------ */
public void onRequestCommitted() throws IOException public void onRequestCommitted() throws IOException
{ {
} }
/* ------------------------------------------------------------ */
public void onRequestComplete() throws IOException public void onRequestComplete() throws IOException
{ {
} }
/* ------------------------------------------------------------ */
public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{ {
} }
/* ------------------------------------------------------------ */
public void onResponseHeader(Buffer name, Buffer value) throws IOException public void onResponseHeader(Buffer name, Buffer value) throws IOException
{ {
_next.onResponseHeader(name,value);
} }
/* ------------------------------------------------------------ */
public void onResponseHeaderComplete() throws IOException public void onResponseHeaderComplete() throws IOException
{ {
_next.onResponseHeaderComplete();
} }
/* ------------------------------------------------------------ */
public void onResponseContent(Buffer content) throws IOException public void onResponseContent(Buffer content) throws IOException
{ {
} }
/* ------------------------------------------------------------ */
public void onResponseComplete() throws IOException public void onResponseComplete() throws IOException
{ {
_exchange.setEventListener(_next); _exchange.setEventListener(_next);
@ -800,25 +813,32 @@ public class HttpConnection extends AbstractConnection implements Dumpable
_parser.reset(); _parser.reset();
} }
/* ------------------------------------------------------------ */
public void onConnectionFailed(Throwable ex) public void onConnectionFailed(Throwable ex)
{ {
_exchange.setEventListener(_next);
_next.onConnectionFailed(ex);
} }
/* ------------------------------------------------------------ */
public void onException(Throwable ex) public void onException(Throwable ex)
{ {
_exchange.setEventListener(_next); _exchange.setEventListener(_next);
_next.onException(ex); _next.onException(ex);
} }
/* ------------------------------------------------------------ */
public void onExpire() public void onExpire()
{ {
_exchange.setEventListener(_next); _exchange.setEventListener(_next);
_next.onExpire(); _next.onExpire();
} }
/* ------------------------------------------------------------ */
public void onRetry() public void onRetry()
{ {
_exchange.setEventListener(_next);
_next.onRetry();
} }
} }
} }

View File

@ -19,9 +19,8 @@ import static org.junit.Assert.assertTrue;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Enumeration; import java.util.concurrent.CountDownLatch;
import java.util.HashMap; import java.util.concurrent.TimeUnit;
import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -34,14 +33,17 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After; import org.eclipse.jetty.util.log.Log;
import org.junit.Before; import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public class Http100ContinueTest public class Http100ContinueTest
{ {
private static final int TIMEOUT = 500;
private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. " private static final String CONTENT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "
+ "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque " + "Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "
+ "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. " + "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. "
@ -55,12 +57,15 @@ public class Http100ContinueTest
+ "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse " + "Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "
+ "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque."; + "et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private Server _server; private static TestFeature _feature;
private TestHandler _handler;
private int _port; private static Server _server;
private static TestHandler _handler;
@Before private static HttpClient _client;
public void init() throws Exception private static String _requestUrl;
@BeforeClass
public static void init() throws Exception
{ {
File docRoot = new File("target/test-output/docroot/"); File docRoot = new File("target/test-output/docroot/");
if (!docRoot.exists()) if (!docRoot.exists())
@ -76,47 +81,114 @@ public class Http100ContinueTest
_server.start(); _server.start();
_port = connector.getLocalPort(); _client = new HttpClient();
_client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_client.setTimeout(TIMEOUT);
_client.setMaxRetries(0);
_client.start();
_requestUrl = "http://localhost:" + connector.getLocalPort() + "/";
} }
@After @AfterClass
public void destroy() throws Exception public static void destroy() throws Exception
{ {
_client.stop();
_server.stop(); _server.stop();
_server.join(); _server.join();
} }
@Test @Test
public void testSelectConnector() throws Exception public void testSuccess() throws Exception
{ {
HttpClient httpClient = new HttpClient(); // Handler to send CONTINUE 100
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); _feature = TestFeature.CONTINUE;
httpClient.start();
try ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testMissingContinue() throws Exception
{
// Handler does not send CONTINUE 100
_feature = TestFeature.NORMAL;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
@Test
public void testError() throws Exception
{
// Handler sends NOT FOUND 404 response
_feature = TestFeature.NOTFOUND;
ContentExchange exchange = sendExchange();
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.NOT_FOUND_404,responseStatus);
}
@Test
public void testTimeout() throws Exception
{
// Handler delays response till client times out
_feature = TestFeature.TIMEOUT;
final CountDownLatch expires = new CountDownLatch(1);
ContentExchange exchange = new ContentExchange()
{ {
String requestUrl = "http://localhost:" + _port + "/header"; @Override
protected void onExpire()
{
expires.countDown();
}
};
configureExchange(exchange);
_client.send(exchange);
assertTrue(expires.await(TIMEOUT*10,TimeUnit.MILLISECONDS));
}
public ContentExchange sendExchange() throws Exception
{
ContentExchange exchange = new ContentExchange();
configureExchange(exchange);
_client.send(exchange);
return exchange;
}
ContentExchange exchange = new ContentExchange(); public void configureExchange(ContentExchange exchange)
exchange.setURL(requestUrl); {
exchange.setMethod(HttpMethods.GET); exchange.setURL(_requestUrl);
exchange.addRequestHeader("User-Agent","Jetty-Client/7.0"); exchange.setMethod(HttpMethods.GET);
exchange.addRequestHeader("Expect","100-continue"); //server to send CONTINUE 100 exchange.addRequestHeader("User-Agent","Jetty-Client/7.0");
exchange.addRequestHeader("Expect","100-continue"); //server to send CONTINUE 100
httpClient.send(exchange);
int state = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, state);
int responseStatus = exchange.getResponseStatus();
assertEquals(HttpStatus.OK_200,responseStatus);
String content = exchange.getResponseContent();
assertEquals(Http100ContinueTest.CONTENT,content);
}
finally
{
httpClient.stop();
}
} }
private static class TestHandler extends AbstractHandler private static class TestHandler extends AbstractHandler
@ -126,15 +198,43 @@ public class Http100ContinueTest
if (baseRequest.isHandled()) if (baseRequest.isHandled())
return; return;
// force 100 Continue response to be sent
request.getInputStream();
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
baseRequest.setHandled(true); baseRequest.setHandled(true);
switch (_feature)
{
case CONTINUE:
// force 100 Continue response to be sent
request.getInputStream();
// next send data
case NORMAL:
response.setContentType("text/plain");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(CONTENT);
break;
case NOTFOUND:
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
break;
case TIMEOUT:
try
{
Thread.sleep(TIMEOUT*4);
}
catch (InterruptedException ex)
{
Log.ignore(ex);
}
break;
}
} }
}
enum TestFeature {
CONTINUE,
NORMAL,
NOTFOUND,
TIMEOUT
} }
} }