Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java')
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java304
1 files changed, 237 insertions, 67 deletions
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
index 8312da2368..8e67c62bc3 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
@@ -18,116 +18,286 @@
package org.eclipse.jetty.server;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.lessThan;
+import static org.junit.Assert.assertThat;
+
+import java.io.EOFException;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.ConnectException;
import java.net.Socket;
-import java.nio.charset.StandardCharsets;
+import java.nio.channels.ClosedChannelException;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.IO;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.Assert;
-import org.junit.Before;
import org.junit.Test;
-public class GracefulStopTest
+public class GracefulStopTest
{
- private Server server;
-
- @Before
- public void setup() throws Exception
+ /**
+ * Test of standard graceful timeout mechanism when a block request does
+ * not complete
+ * @throws Exception on test failure
+ */
+ @Test
+ public void testGracefulNoWaiter() throws Exception
{
- server = new Server(0);
- StatisticsHandler stats = new StatisticsHandler();
- TestHandler test=new TestHandler();
- server.setHandler(stats);
- stats.setHandler(test);
- server.setStopTimeout(10 * 1000);
-
+ Server server= new Server();
+ server.setStopTimeout(1000);
+
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ TestHandler handler = new TestHandler();
+ server.setHandler(handler);
+
server.start();
+ final int port=connector.getLocalPort();
+ Socket client = new Socket("127.0.0.1", port);
+ client.getOutputStream().write((
+ "POST / HTTP/1.0\r\n"+
+ "Host: localhost:"+port+"\r\n" +
+ "Content-Type: plain/text\r\n" +
+ "Content-Length: 10\r\n" +
+ "\r\n"+
+ "12345"
+ ).getBytes());
+ client.getOutputStream().flush();
+ handler.latch.await();
+
+ long start = System.nanoTime();
+ server.stop();
+ long stop = System.nanoTime();
+
+ // No Graceful waiters
+ assertThat(TimeUnit.NANOSECONDS.toMillis(stop-start),lessThan(900L));
+
+ assertThat(client.getInputStream().read(),Matchers.is(-1));
+
+ assertThat(handler.handling.get(),Matchers.is(false));
+ assertThat(handler.thrown.get(),
+ Matchers.anyOf(
+ instanceOf(ClosedChannelException.class),
+ instanceOf(EofException.class),
+ instanceOf(EOFException.class))
+ );
+
+ client.close();
}
+ /**
+ * Test of standard graceful timeout mechanism when a block request does
+ * not complete
+ * @throws Exception on test failure
+ */
@Test
- public void testGraceful() throws Exception
+ public void testGracefulTimeout() throws Exception
{
- new Thread()
- {
- @Override
- public void run()
- {
- try
- {
- TimeUnit.SECONDS.sleep(1);
- server.stop();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }.start();
+ Server server= new Server();
+ server.setStopTimeout(1000);
+
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
- try(Socket socket = new Socket("localhost",server.getBean(NetworkConnector.class).getLocalPort());)
+ TestHandler handler = new TestHandler();
+ StatisticsHandler stats = new StatisticsHandler();
+ server.setHandler(stats);
+ stats.setHandler(handler);
+
+ server.start();
+ final int port=connector.getLocalPort();
+ Socket client = new Socket("127.0.0.1", port);
+ client.getOutputStream().write((
+ "POST / HTTP/1.0\r\n"+
+ "Host: localhost:"+port+"\r\n" +
+ "Content-Type: plain/text\r\n" +
+ "Content-Length: 10\r\n" +
+ "\r\n"+
+ "12345"
+ ).getBytes());
+ client.getOutputStream().flush();
+ handler.latch.await();
+
+ long start = System.nanoTime();
+ try
{
- socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
- String out = IO.toString(socket.getInputStream());
- Assert.assertThat(out,Matchers.containsString("200 OK"));
+ server.stop();
+ Assert.fail();
}
+ catch(TimeoutException e)
+ {
+ long stop = System.nanoTime();
+ // No Graceful waiters
+ assertThat(TimeUnit.NANOSECONDS.toMillis(stop-start),greaterThan(900L));
+ }
+
+ assertThat(client.getInputStream().read(),Matchers.is(-1));
+
+ assertThat(handler.handling.get(),Matchers.is(false));
+ assertThat(handler.thrown.get(),instanceOf(ClosedChannelException.class));
+
+ client.close();
}
-
+
+
+ /**
+ * Test of standard graceful timeout mechanism when a block request does
+ * complete. Note that even though the request completes after 100ms, the
+ * stop always takes 1000ms
+ * @throws Exception on test failure
+ */
@Test
- public void testGracefulTimout() throws Exception
+ public void testGracefulComplete() throws Exception
{
- server.setStopTimeout(100);
- new Thread()
+ Server server= new Server();
+ server.setStopTimeout(10000);
+
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ TestHandler handler = new TestHandler();
+ StatisticsHandler stats = new StatisticsHandler();
+ server.setHandler(stats);
+ stats.setHandler(handler);
+
+ server.start();
+ final int port=connector.getLocalPort();
+
+ try(final Socket client1 = new Socket("127.0.0.1", port);final Socket client2 = new Socket("127.0.0.1", port);)
{
- @Override
- public void run()
+ client1.getOutputStream().write((
+ "POST / HTTP/1.0\r\n"+
+ "Host: localhost:"+port+"\r\n" +
+ "Content-Type: plain/text\r\n" +
+ "Content-Length: 10\r\n" +
+ "\r\n"+
+ "12345"
+ ).getBytes());
+ client1.getOutputStream().flush();
+ handler.latch.await();
+
+ new Thread()
{
- try
- {
- TimeUnit.SECONDS.sleep(1);
- server.stop();
- }
- catch (Exception e)
+ @Override
+ public void run()
{
- //e.printStackTrace();
+ long now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+ long end = now+500;
+
+
+
+ try
+ {
+ Thread.sleep(100);
+
+ // Try creating a new connection
+ try
+ {
+ new Socket("127.0.0.1", port);
+ throw new IllegalStateException();
+ }
+ catch(ConnectException e)
+ {
+
+ }
+
+ // Try another request on existing connection
+
+ client2.getOutputStream().write((
+ "GET / HTTP/1.0\r\n"+
+ "Host: localhost:"+port+"\r\n" +
+ "\r\n"
+ ).getBytes());
+ client2.getOutputStream().flush();
+ String response2 = IO.toString(client2.getInputStream());
+ assertThat(response2, containsString(" 503 "));
+
+ now = TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+ Thread.sleep(end-now);
+ client1.getOutputStream().write("567890".getBytes());
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
}
- }
- }.start();
+ }.start();
- try(Socket socket = new Socket("localhost",server.getBean(NetworkConnector.class).getLocalPort());)
- {
- socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
- String out = IO.toString(socket.getInputStream());
- Assert.assertEquals("",out);
+ long start = System.nanoTime();
+ server.stop();
+ long stop = System.nanoTime();
+ assertThat(TimeUnit.NANOSECONDS.toMillis(stop-start),greaterThan(490L));
+ assertThat(TimeUnit.NANOSECONDS.toMillis(stop-start),lessThan(10000L));
+
+ String response = IO.toString(client1.getInputStream());
+
+ assertThat(handler.handling.get(),Matchers.is(false));
+ assertThat(response, containsString(" 200 OK"));
+ assertThat(response, containsString("read 10/10"));
+
+ assertThat(stats.getRequests(),Matchers.is(2));
+ assertThat(stats.getResponses5xx(),Matchers.is(1));
}
}
- private static class TestHandler extends AbstractHandler
- {
+
+ static class TestHandler extends AbstractHandler
+ {
+ final CountDownLatch latch = new CountDownLatch(1);
+ final AtomicReference<Throwable> thrown = new AtomicReference<Throwable>();
+ final AtomicBoolean handling = new AtomicBoolean(false);
+
@Override
- public void handle(final String s, final Request request, final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse)
- throws IOException, ServletException
+ public void handle(String target, Request baseRequest,
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException
{
+ handling.set(true);
+ latch.countDown();
+ int c=0;
try
{
- TimeUnit.SECONDS.sleep(2);
+ int content_length = request.getContentLength();
+ InputStream in = request.getInputStream();
+
+ while(true)
+ {
+ if (in.read()<0)
+ break;
+ c++;
+ }
+
+ baseRequest.setHandled(true);
+ response.setStatus(200);
+ response.getWriter().printf("read %d/%d%n",c,content_length);
}
- catch (InterruptedException e)
+ catch(Throwable th)
{
+ thrown.set(th);
+ }
+ finally
+ {
+ handling.set(false);
}
-
- httpServletResponse.getWriter().write("OK");
- httpServletResponse.setStatus(200);
- request.setHandled(true);
}
}

Back to the top