diff options
Diffstat (limited to 'jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java')
-rw-r--r-- | jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java new file mode 100644 index 0000000000..27db82a2db --- /dev/null +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutExchangeTest.java @@ -0,0 +1,379 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.client; + +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import junit.framework.Assert; + +import org.eclipse.jetty.http.HttpMethods; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.io.ByteArrayBuffer; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TimeoutExchangeTest +{ + private static HttpClient _httpClient; + private static Server _server; + private static int _port; + + @BeforeClass + public static void startServer() throws Exception + { + _server = new Server(); + _server.setGracefulShutdown(500); + Connector _connector = new SelectChannelConnector(); + _server.addConnector(_connector); + Handler handler = new AbstractHandler() + { + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + try + { + Long sleep = Long.parseLong(request.getParameter("sleep")); + Thread.sleep(sleep); + response.setContentType("text/html"); + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println("<h1>Hello</h1>"); + baseRequest.setHandled(true); + } + catch (InterruptedException x) + { + Thread.currentThread().interrupt(); + throw new ServletException(x); + } + } + }; + _server.setHandler(handler); + _server.start(); + _port = _connector.getLocalPort(); + } + + @AfterClass + public static void stopServer() throws Exception + { + _server.stop(); + _server.join(); + _server = null; + } + + @After + public void stopClient() throws Exception + { + if (_httpClient != null) + { + _httpClient.stop(); + _httpClient = null; + } + } + + private void startClient(long clientTimeout) throws Exception + { + startClient(clientTimeout, 20000); + } + + private void startClient(long clientTimeout, long maxIdleTimeout) throws Exception + { + _httpClient = new HttpClient(); + _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); + _httpClient.setMaxConnectionsPerAddress(2); + _httpClient.setTimeout(clientTimeout); + _httpClient.setIdleTimeout(maxIdleTimeout); + _httpClient.start(); + } + + @Test + public void testDefaultTimeoutNotExpiring() throws Exception + { + startClient(300); + long serverSleep = 100; + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(4 * serverSleep, TimeUnit.MILLISECONDS)); + Assert.assertFalse(httpExchange.isTimeoutOccurred()); + Assert.assertTrue(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + @Test + public void testDefaultTimeoutExpiring() throws Exception + { + startClient(100); + long serverSleep = 200; + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); + Assert.assertTrue(httpExchange.isTimeoutOccurred()); + Assert.assertFalse(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + @Test + public void testExchangeTimeoutNotExpiring() throws Exception + { + startClient(100); + long serverSleep = 200; + long exchangeTimeout = 300; + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + httpExchange.setTimeout(exchangeTimeout); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(2 * exchangeTimeout, TimeUnit.MILLISECONDS)); + Assert.assertFalse(httpExchange.isTimeoutOccurred()); + Assert.assertTrue(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + @Test + public void testExchangeTimeoutExpiring() throws Exception + { + startClient(500); + + long serverSleep = 300; + long exchangeTimeout = 100; + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + httpExchange.setTimeout(exchangeTimeout); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); + Assert.assertTrue(httpExchange.isTimeoutOccurred()); + Assert.assertFalse(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + @Test + public void testDefaultTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception + { + startClient(500,150); + long serverSleep = 300; + + // The idle timeout is shorter than the default timeout, but will be + // temporarily increased on the endpoint in order for the exchange to complete. + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); + Assert.assertFalse(httpExchange.isTimeoutOccurred()); + Assert.assertTrue(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + @Test + public void testExchangeTimeoutWithSmallerIdleTimeoutNotExpiring() throws Exception + { + startClient(500,150); + long serverSleep = 150; + long exchangeTimeout = 300; + + // The idle timeout is shorter than the default timeout, but will be + // temporarily increased on the endpoint in order for the exchange to complete. + + CustomContentExchange httpExchange = new CustomContentExchange(); + httpExchange.setURL("http://localhost:" + _port + "/?sleep=" + serverSleep); + httpExchange.setMethod(HttpMethods.POST); + httpExchange.setRequestContent(new ByteArrayBuffer("<h1>??</h1>")); + httpExchange.setTimeout(exchangeTimeout); + _httpClient.send(httpExchange); + + Assert.assertTrue(httpExchange.getDoneLatch().await(2 * serverSleep, TimeUnit.MILLISECONDS)); + Assert.assertFalse(httpExchange.isTimeoutOccurred()); + Assert.assertTrue(httpExchange.isResponseReceived()); + Assert.assertFalse(httpExchange.isErrorOccurred()); + } + + private class CustomContentExchange extends ContentExchange + { + private final CountDownLatch _doneLatch = new CountDownLatch(1); + private boolean _errorOccurred = false; + private boolean _timeoutOccurred = false; + private boolean _responseReceived = false; + + public boolean isErrorOccurred() + { + return _errorOccurred; + } + + public boolean isTimeoutOccurred() + { + return _timeoutOccurred; + } + + public boolean isResponseReceived() + { + return _responseReceived; + } + + public CustomContentExchange() + { + super(true); + } + + @Override + protected void onResponseComplete() throws IOException + { + try + { + super.onResponseComplete(); + } + finally + { + doTaskCompleted(); + } + } + + @Override + protected void onExpire() + { + try + { + super.onExpire(); + } + finally + { + doTaskCompleted(); + } + } + + @Override + protected void onException(Throwable ex) + { + try + { + super.onException(ex); + } + finally + { + doTaskCompleted(ex); + } + } + + @Override + protected void onConnectionFailed(Throwable ex) + { + try + { + super.onConnectionFailed(ex); + } + finally + { + doTaskCompleted(ex); + } + } + + protected void doTaskCompleted() + { + int exchangeState = getStatus(); + + try + { + if (exchangeState == HttpExchange.STATUS_COMPLETED) + { + // process the response as the state is ok + try + { + int responseCode = getResponseStatus(); + + if (responseCode >= HttpStatus.CONTINUE_100 && responseCode < HttpStatus.MULTIPLE_CHOICES_300) + { + _responseReceived = true; + } + else + { + _errorOccurred = true; + } + } + catch (Exception e) + { + _errorOccurred = true; + e.printStackTrace(); + } + } + else if (exchangeState == HttpExchange.STATUS_EXPIRED) + { + _timeoutOccurred = true; + } + else + { + _errorOccurred = true; + } + } + finally + { + // make sure to lower the latch + getDoneLatch().countDown(); + } + } + + protected void doTaskCompleted(Throwable ex) + { + try + { + _errorOccurred = true; + } + finally + { + // make sure to lower the latch + getDoneLatch().countDown(); + } + } + + public CountDownLatch getDoneLatch() + { + return _doneLatch; + } + } +} |