Made the test more robust.

This commit is contained in:
Simone Bordet 2013-05-02 18:50:24 +02:00
parent 0b15aa5a76
commit 827a7f48b8
1 changed files with 114 additions and 132 deletions

View File

@ -18,19 +18,11 @@
package org.eclipse.jetty.server.handler; package org.eclipse.jetty.server.handler;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier; import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.AsyncContext; import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent; import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener; import javax.servlet.AsyncListener;
@ -46,6 +38,12 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class StatisticsHandlerTest public class StatisticsHandlerTest
{ {
private Server _server; private Server _server;
@ -60,7 +58,7 @@ public class StatisticsHandlerTest
_server = new Server(); _server = new Server();
_connector = new LocalConnector(_server); _connector = new LocalConnector(_server);
_statistics=new ConnectorStatistics(); _statistics = new ConnectorStatistics();
_connector.addBean(_statistics); _connector.addBean(_statistics);
_server.addConnector(_connector); _server.addConnector(_connector);
@ -105,8 +103,8 @@ public class StatisticsHandlerTest
_server.start(); _server.start();
String request = "GET / HTTP/1.1\r\n" + String request = "GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" + "Host: localhost\r\n" +
"\r\n"; "\r\n";
_connector.executeRequest(request); _connector.executeRequest(request);
barrier[0].await(); barrier[0].await();
@ -174,8 +172,8 @@ public class StatisticsHandlerTest
assertEquals(2, _statsHandler.getResponses2xx()); assertEquals(2, _statsHandler.getResponses2xx());
_latchHandler.reset(2); _latchHandler.reset(2);
barrier[0]=new CyclicBarrier(3); barrier[0] = new CyclicBarrier(3);
barrier[1]=new CyclicBarrier(3); barrier[1] = new CyclicBarrier(3);
_connector.executeRequest(request); _connector.executeRequest(request);
_connector.executeRequest(request); _connector.executeRequest(request);
@ -208,37 +206,33 @@ public class StatisticsHandlerTest
assertEquals(0, _statsHandler.getAsyncDispatches()); assertEquals(0, _statsHandler.getAsyncDispatches());
assertEquals(0, _statsHandler.getExpires()); assertEquals(0, _statsHandler.getExpires());
assertEquals(4, _statsHandler.getResponses2xx()); assertEquals(4, _statsHandler.getResponses2xx());
} }
@Test @Test
public void testSuspendResume() throws Exception public void testSuspendResume() throws Exception
{ {
final long dispatchTime = 10;
final long requestTime = 50;
final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>(); final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>();
final CyclicBarrier barrier[] = { new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)}; final CyclicBarrier barrier[] = {new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)};
_statsHandler.setHandler(new AbstractHandler() _statsHandler.setHandler(new AbstractHandler()
{ {
@Override @Override
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{ {
request.setHandled(true); request.setHandled(true);
try try
{ {
barrier[0].await(); barrier[0].await();
Thread.sleep(10); Thread.sleep(dispatchTime);
if (asyncHolder.get() == null) if (asyncHolder.get() == null)
{
asyncHolder.set(request.startAsync()); asyncHolder.set(request.startAsync());
}
} }
catch (Exception x) catch (Exception x)
{ {
Thread.currentThread().interrupt(); throw new ServletException(x);
throw (IOException)new IOException().initCause(x);
} }
finally finally
{ {
@ -246,50 +240,41 @@ public class StatisticsHandlerTest
{ {
barrier[1].await(); barrier[1].await();
} }
catch (Exception x) catch (Exception ignored)
{ {
x.printStackTrace();
Thread.currentThread().interrupt();
fail();
} }
} }
} }
}); });
_server.start(); _server.start();
String request = "GET / HTTP/1.1\r\n" + String request = "GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" + "Host: localhost\r\n" +
"\r\n"; "\r\n";
_connector.executeRequest(request); _connector.executeRequest(request);
barrier[0].await(); barrier[0].await();
assertEquals(1, _statistics.getConnectionsOpen()); assertEquals(1, _statistics.getConnectionsOpen());
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
assertEquals(1, _statsHandler.getDispatchedActive()); assertEquals(1, _statsHandler.getDispatchedActive());
barrier[1].await(); barrier[1].await();
assertTrue(_latchHandler.await()); assertTrue(_latchHandler.await());
assertNotNull(asyncHolder.get()); assertNotNull(asyncHolder.get());
assertTrue(asyncHolder.get()!=null);
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
assertEquals(0, _statsHandler.getDispatchedActive()); assertEquals(0, _statsHandler.getDispatchedActive());
Thread.sleep(10);
_latchHandler.reset(); _latchHandler.reset();
barrier[0].reset(); barrier[0].reset();
barrier[1].reset(); barrier[1].reset();
Thread.sleep(50); Thread.sleep(requestTime);
asyncHolder.get().addListener(new AsyncListener() asyncHolder.get().addListener(new AsyncListener()
{ {
@ -297,30 +282,34 @@ public class StatisticsHandlerTest
public void onTimeout(AsyncEvent event) throws IOException public void onTimeout(AsyncEvent event) throws IOException
{ {
} }
@Override @Override
public void onStartAsync(AsyncEvent event) throws IOException public void onStartAsync(AsyncEvent event) throws IOException
{ {
} }
@Override @Override
public void onError(AsyncEvent event) throws IOException public void onError(AsyncEvent event) throws IOException
{ {
} }
@Override @Override
public void onComplete(AsyncEvent event) throws IOException public void onComplete(AsyncEvent event) throws IOException
{ {
try { barrier[2].await(); } catch(Exception e) {} try
{
barrier[2].await();
}
catch (Exception ignored)
{
}
} }
}); });
asyncHolder.get().dispatch(); asyncHolder.get().dispatch();
barrier[0].await(); // entered app handler barrier[0].await(); // entered app handler
assertEquals(1, _statistics.getConnectionsOpen()); assertEquals(1, _statistics.getConnectionsOpen());
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(2, _statsHandler.getDispatched()); assertEquals(2, _statsHandler.getDispatched());
@ -335,50 +324,49 @@ public class StatisticsHandlerTest
assertEquals(2, _statsHandler.getDispatched()); assertEquals(2, _statsHandler.getDispatched());
assertEquals(0, _statsHandler.getDispatchedActive()); assertEquals(0, _statsHandler.getDispatchedActive());
assertEquals(1, _statsHandler.getAsyncRequests()); assertEquals(1, _statsHandler.getAsyncRequests());
assertEquals(1, _statsHandler.getAsyncDispatches()); assertEquals(1, _statsHandler.getAsyncDispatches());
assertEquals(0, _statsHandler.getExpires()); assertEquals(0, _statsHandler.getExpires());
assertEquals(1, _statsHandler.getResponses2xx()); assertEquals(1, _statsHandler.getResponses2xx());
assertThat(_statsHandler.getRequestTimeTotal(), greaterThanOrEqualTo(requestTime * 3 / 4));
assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMax());
assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMean(), 0.01);
assertThat(_statsHandler.getRequestTimeTotal(),greaterThanOrEqualTo(50L)); assertThat(_statsHandler.getDispatchedTimeTotal(), greaterThanOrEqualTo(dispatchTime * 2 * 3 / 4));
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMax()); assertTrue(_statsHandler.getDispatchedTimeMean() + dispatchTime <= _statsHandler.getDispatchedTimeTotal());
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMean(), 0.01); assertTrue(_statsHandler.getDispatchedTimeMax() + dispatchTime <= _statsHandler.getDispatchedTimeTotal());
assertTrue(_statsHandler.getDispatchedTimeTotal()>=20);
assertTrue(_statsHandler.getDispatchedTimeMean()+10<=_statsHandler.getDispatchedTimeTotal());
assertTrue(_statsHandler.getDispatchedTimeMax()+10<=_statsHandler.getDispatchedTimeTotal());
} }
@Test @Test
public void testSuspendExpire() throws Exception public void testSuspendExpire() throws Exception
{ {
final long dispatchTime = 10;
final long timeout = 100;
final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>(); final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>();
final CyclicBarrier barrier[] = { new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)}; final CyclicBarrier barrier[] = {new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)};
_statsHandler.setHandler(new AbstractHandler() _statsHandler.setHandler(new AbstractHandler()
{ {
@Override @Override
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{ {
request.setHandled(true); request.setHandled(true);
try try
{ {
barrier[0].await(); barrier[0].await();
Thread.sleep(10);
Thread.sleep(dispatchTime);
if (asyncHolder.get() == null) if (asyncHolder.get() == null)
{ {
AsyncContext async=request.startAsync(); AsyncContext async = request.startAsync();
async.setTimeout(100);
asyncHolder.set(async); asyncHolder.set(async);
async.setTimeout(timeout);
} }
} }
catch (Exception x) catch (Exception x)
{ {
Thread.currentThread().interrupt(); throw new ServletException(x);
throw (IOException)new IOException().initCause(x);
} }
finally finally
{ {
@ -386,28 +374,22 @@ public class StatisticsHandlerTest
{ {
barrier[1].await(); barrier[1].await();
} }
catch (Exception x) catch (Exception ignored)
{ {
x.printStackTrace();
Thread.currentThread().interrupt();
fail();
} }
} }
} }
}); });
_server.start(); _server.start();
String request = "GET / HTTP/1.1\r\n" + String request = "GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" + "Host: localhost\r\n" +
"\r\n"; "\r\n";
_connector.executeRequest(request); _connector.executeRequest(request);
barrier[0].await(); barrier[0].await();
assertEquals(1, _statistics.getConnectionsOpen()); assertEquals(1, _statistics.getConnectionsOpen());
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
@ -423,31 +405,35 @@ public class StatisticsHandlerTest
{ {
event.getAsyncContext().complete(); event.getAsyncContext().complete();
} }
@Override @Override
public void onStartAsync(AsyncEvent event) throws IOException public void onStartAsync(AsyncEvent event) throws IOException
{ {
} }
@Override @Override
public void onError(AsyncEvent event) throws IOException public void onError(AsyncEvent event) throws IOException
{ {
} }
@Override @Override
public void onComplete(AsyncEvent event) throws IOException public void onComplete(AsyncEvent event) throws IOException
{ {
try { barrier[2].await(); } catch(Exception e) {} try
{
barrier[2].await();
}
catch (Exception ignored)
{
}
} }
}); });
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
assertEquals(0, _statsHandler.getDispatchedActive()); assertEquals(0, _statsHandler.getDispatchedActive());
barrier[2].await(); barrier[2].await();
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
@ -460,67 +446,40 @@ public class StatisticsHandlerTest
assertEquals(1, _statsHandler.getExpires()); assertEquals(1, _statsHandler.getExpires());
assertEquals(1, _statsHandler.getResponses2xx()); assertEquals(1, _statsHandler.getResponses2xx());
assertTrue(_statsHandler.getRequestTimeTotal() >= (timeout + dispatchTime) * 3 / 4);
assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMax());
assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMean(), 0.01);
assertTrue(_statsHandler.getRequestTimeTotal()>=30); assertThat(_statsHandler.getDispatchedTimeTotal(), greaterThanOrEqualTo(dispatchTime * 3 / 4));
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMax());
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMean(), 0.01);
assertThat(_statsHandler.getDispatchedTimeTotal(),greaterThanOrEqualTo(10L));
} }
@Test @Test
public void testSuspendComplete() throws Exception public void testSuspendComplete() throws Exception
{ {
final long dispatchTime = 10;
final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>(); final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>();
final CyclicBarrier barrier[] = { new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)}; final CyclicBarrier barrier[] = {new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)};
_statsHandler.setHandler(new AbstractHandler() _statsHandler.setHandler(new AbstractHandler()
{ {
@Override @Override
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{ {
request.setHandled(true); request.setHandled(true);
try try
{ {
barrier[0].await(); barrier[0].await();
Thread.sleep(10);
Thread.sleep(dispatchTime);
if (asyncHolder.get() == null) if (asyncHolder.get() == null)
{ {
AsyncContext async=request.startAsync(); AsyncContext async = request.startAsync();
async.setTimeout(1000);
asyncHolder.set(async); asyncHolder.set(async);
asyncHolder.get().addListener(new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
try { barrier[2].await(); } catch(Exception e) {}
}
});
} }
} }
catch (Exception x) catch (Exception x)
{ {
Thread.currentThread().interrupt(); throw new ServletException(x);
throw (IOException)new IOException().initCause(x);
} }
finally finally
{ {
@ -528,11 +487,8 @@ public class StatisticsHandlerTest
{ {
barrier[1].await(); barrier[1].await();
} }
catch (Exception x) catch (Exception ignored)
{ {
x.printStackTrace();
Thread.currentThread().interrupt();
fail();
} }
} }
@ -541,21 +497,18 @@ public class StatisticsHandlerTest
_server.start(); _server.start();
String request = "GET / HTTP/1.1\r\n" + String request = "GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" + "Host: localhost\r\n" +
"\r\n"; "\r\n";
_connector.executeRequest(request); _connector.executeRequest(request);
barrier[0].await(); barrier[0].await();
assertEquals(1, _statistics.getConnectionsOpen()); assertEquals(1, _statistics.getConnectionsOpen());
assertEquals(1, _statsHandler.getRequests()); assertEquals(1, _statsHandler.getRequests());
assertEquals(1, _statsHandler.getRequestsActive()); assertEquals(1, _statsHandler.getRequestsActive());
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
assertEquals(1, _statsHandler.getDispatchedActive()); assertEquals(1, _statsHandler.getDispatchedActive());
barrier[1].await(); barrier[1].await();
assertTrue(_latchHandler.await()); assertTrue(_latchHandler.await());
assertNotNull(asyncHolder.get()); assertNotNull(asyncHolder.get());
@ -565,7 +518,37 @@ public class StatisticsHandlerTest
assertEquals(1, _statsHandler.getDispatched()); assertEquals(1, _statsHandler.getDispatched());
assertEquals(0, _statsHandler.getDispatchedActive()); assertEquals(0, _statsHandler.getDispatchedActive());
Thread.sleep(10); asyncHolder.get().addListener(new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
try
{
barrier[2].await();
}
catch (Exception ignored)
{
}
}
});
long requestTime = 20;
Thread.sleep(requestTime);
asyncHolder.get().complete(); asyncHolder.get().complete();
barrier[2].await(); barrier[2].await();
@ -579,17 +562,16 @@ public class StatisticsHandlerTest
assertEquals(0, _statsHandler.getExpires()); assertEquals(0, _statsHandler.getExpires());
assertEquals(1, _statsHandler.getResponses2xx()); assertEquals(1, _statsHandler.getResponses2xx());
assertTrue(_statsHandler.getRequestTimeTotal()>=20); assertTrue(_statsHandler.getRequestTimeTotal() >= (dispatchTime + requestTime) * 3 / 4);
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMax()); assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMax());
assertEquals(_statsHandler.getRequestTimeTotal(),_statsHandler.getRequestTimeMean(), 0.01); assertEquals(_statsHandler.getRequestTimeTotal(), _statsHandler.getRequestTimeMean(), 0.01);
assertTrue(_statsHandler.getDispatchedTimeTotal()>=10); assertTrue(_statsHandler.getDispatchedTimeTotal() >= dispatchTime * 3 / 4);
assertTrue(_statsHandler.getDispatchedTimeTotal()<_statsHandler.getRequestTimeTotal()); assertTrue(_statsHandler.getDispatchedTimeTotal() < _statsHandler.getRequestTimeTotal());
assertEquals(_statsHandler.getDispatchedTimeTotal(),_statsHandler.getDispatchedTimeMax()); assertEquals(_statsHandler.getDispatchedTimeTotal(), _statsHandler.getDispatchedTimeMax());
assertEquals(_statsHandler.getDispatchedTimeTotal(),_statsHandler.getDispatchedTimeMean(), 0.01); assertEquals(_statsHandler.getDispatchedTimeTotal(), _statsHandler.getDispatchedTimeMean(), 0.01);
} }
/** /**
* This handler is external to the statistics handler and it is used to ensure that statistics handler's * This handler is external to the statistics handler and it is used to ensure that statistics handler's
* handle() is fully executed before asserting its values in the tests, to avoid race conditions with the * handle() is fully executed before asserting its values in the tests, to avoid race conditions with the
@ -602,7 +584,7 @@ public class StatisticsHandlerTest
@Override @Override
public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException public void handle(String path, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
{ {
final CountDownLatch latch=_latch; final CountDownLatch latch = _latch;
try try
{ {
super.handle(path, request, httpRequest, httpResponse); super.handle(path, request, httpRequest, httpResponse);
@ -615,12 +597,12 @@ public class StatisticsHandlerTest
private void reset() private void reset()
{ {
_latch=new CountDownLatch(1); _latch = new CountDownLatch(1);
} }
private void reset(int count) private void reset(int count)
{ {
_latch=new CountDownLatch(count); _latch = new CountDownLatch(count);
} }
private boolean await() throws InterruptedException private boolean await() throws InterruptedException