diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java index e419b32300d..98e0bc38c55 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java @@ -275,13 +275,8 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor // The loop is controlled by the call to async.unhandle in the // finally block below. Unhandle will return false only if an async dispatch has // already happened when unhandle is called. - while (!getServer().isStopped()) + loop: while (!getServer().isStopped()) { - // Early exit out of the loop if the action - // is a terminal one to skip unhandle(). - if (action == Action.TERMINATED || action == Action.WAIT) - break; - boolean error=false; try { @@ -290,6 +285,10 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor switch(action) { + case TERMINATED: + case WAIT: + break loop; + case DISPATCH: { if (!_request.hasMetaData()) @@ -379,7 +378,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor break; } - case COMPLETING: + case COMPLETE: { try { @@ -387,33 +386,18 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor _response.sendError(404); else _response.closeOutput(); -// _state=COMPLETE; } - catch (Throwable x) + finally { -// state = ERROR; + _state.onComplete(); } - break; - // async.complete(); - // state -> COMPLETING - // flush output - // try { flush(); state -> COMPLETED; } - // catch (x) { state -> ERROR } - // unhandle(); - // COMPLETED -> call asyncListeners.onComplete() -> TERMINATED - // ERROR -> call asyncListeners.onError(); -> TERMINATED - // unhandle(); - // TERMINATED -> break out of loop. - } - case COMPLETED: - { - _state.onComplete(); + // TODO: verify this code is needed and whether // TODO: it's needed for onError() case too. _request.setHandled(true); onCompleted(); - // TODO: set action to TERMINATED. - break; + + break loop; } default: @@ -458,18 +442,17 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor handleException(e); } } - finally - { - if (error && _state.isAsyncStarted()) - _state.errorComplete(); - action = _state.unhandle(); - } + + if (error && _state.isAsyncStarted()) + _state.errorComplete(); + action = _state.unhandle(); } if (LOG.isDebugEnabled()) LOG.debug("{} handle exit, result {}", this, action); - return action!=Action.WAIT; + boolean suspended=action==Action.WAIT; + return !suspended; } /** @@ -611,7 +594,7 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor finally { // TODO: review whether it's the right state to check. - if (_state.unhandle()==Action.COMPLETING) + if (_state.unhandle()==Action.COMPLETE) _state.onComplete(); else throw new IllegalStateException(); // TODO: don't throw from finally blocks ! diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java index 6540700246f..39d2b2e1806 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelState.java @@ -70,8 +70,7 @@ public class HttpChannelState ASYNC_ERROR, // handle an async error WRITE_CALLBACK, // handle an IO write callback READ_CALLBACK, // handle an IO read callback - COMPLETING, // Completing the response - COMPLETED, // Response completed + COMPLETE, // Complete the response TERMINATED, // No further actions WAIT, // Wait for further events } @@ -197,10 +196,10 @@ public class HttpChannelState return Action.DISPATCH; case COMPLETING: - return Action.COMPLETING; + return Action.COMPLETE; case COMPLETED: - return Action.WAIT; + return Action.TERMINATED; case ASYNC_WOKEN: if (_asyncReadPossible) @@ -210,7 +209,6 @@ public class HttpChannelState return Action.READ_CALLBACK; } - // TODO refactor the same as read if (_asyncWrite) { _state=State.ASYNC_IO; @@ -225,7 +223,7 @@ public class HttpChannelState { case COMPLETE: _state=State.COMPLETING; - return Action.COMPLETING; + return Action.COMPLETE; case DISPATCH: _state=State.DISPATCHED; _async=null; @@ -241,15 +239,21 @@ public class HttpChannelState case ERRORING: _state=State.DISPATCHED; return Action.ASYNC_ERROR; + default: - throw new IllegalStateException(String.valueOf(async)); + throw new IllegalStateException(getStatusStringLocked()); } } return Action.WAIT; - + + case ASYNC_IO: + case ASYNC_WAIT: + case DISPATCHED: + case UPGRADED: default: - return Action.WAIT; + throw new IllegalStateException(getStatusStringLocked()); + } } } @@ -316,7 +320,7 @@ public class HttpChannelState switch(_state) { case COMPLETED: - return Action.COMPLETED; + return Action.TERMINATED; case DISPATCHED: case ASYNC_IO: @@ -334,7 +338,7 @@ public class HttpChannelState case COMPLETE: _state=State.COMPLETING; _async=null; - action=Action.COMPLETING; + action=Action.COMPLETE; break; case DISPATCH: @@ -379,25 +383,25 @@ public class HttpChannelState case ERRORING: _state=State.DISPATCHED; - action=Action.ERROR_DISPATCH; + action=Action.ASYNC_ERROR; break; case ERRORED: _state=State.DISPATCHED; - action=Action.ASYNC_ERROR; + action=Action.ERROR_DISPATCH; _async=null; break; default: _state=State.COMPLETING; - action=Action.COMPLETING; + action=Action.COMPLETE; break; } } else { _state=State.COMPLETING; - action=Action.COMPLETING; + action=Action.COMPLETE; } } diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java index 26f694360c8..3c05f51808f 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; @@ -59,8 +61,10 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; @@ -76,6 +80,8 @@ public class AsyncServletTest protected List _log; protected int _expectedLogs; protected String _expectedCode; + protected static List __history=new ArrayList<>(); + protected static CountDownLatch __latch; @Before public void setUp() throws Exception @@ -105,6 +111,8 @@ public class AsyncServletTest _servletHandler.addServletWithMapping(new ServletHolder(new FwdServlet()),"/fwd/*"); _server.start(); _port=_connector.getLocalPort(); + __history.clear(); + __latch=new CountDownLatch(1); } @After @@ -119,26 +127,26 @@ public class AsyncServletTest public void testNormal() throws Exception { String response=process(null,null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial")); assertContains("NORMAL",response); - assertNotContains("history: onTimeout",response); - assertNotContains("history: onComplete",response); + assertFalse(__history.contains("onTimeout")); + assertFalse(__history.contains("onComplete")); } @Test public void testSleep() throws Exception { String response=process("sleep=200",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial")); assertContains("SLEPT",response); - assertNotContains("history: onTimeout",response); - assertNotContains("history: onComplete",response); + assertFalse(__history.contains("onTimeout")); + assertFalse(__history.contains("onComplete")); } @Test @@ -147,14 +155,14 @@ public class AsyncServletTest _expectedCode="500 "; String response=process("start=200",null); Assert.assertThat(response,Matchers.startsWith("HTTP/1.1 500 Async Timeout")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onComplete")); assertContains("ERROR DISPATCH: /ctx/path/info",response); } @@ -163,16 +171,16 @@ public class AsyncServletTest public void testStartOnTimeoutDispatch() throws Exception { String response=process("start=200&timeout=dispatch",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -182,17 +190,17 @@ public class AsyncServletTest { _expectedCode="500 "; String response=process("start=200&timeout=error",null); - assertThat(response,startsWith("HTTP/1.1 500 Async Exception\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: error\r\n"+ - "history: onError\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 500 Async Exception")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "error", + "onError", + "ERROR /ctx/path/info", + "!initial", + "onComplete")); assertContains("ERROR DISPATCH",response); } @@ -201,15 +209,16 @@ public class AsyncServletTest public void testStartOnTimeoutErrorComplete() throws Exception { String response=process("start=200&timeout=error&error=complete",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: error\r\n"+ - "history: onError\r\n"+ - "history: complete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "error", + "onError", + "complete", + "onComplete")); assertContains("COMPLETED",response); } @@ -218,18 +227,18 @@ public class AsyncServletTest public void testStartOnTimeoutErrorDispatch() throws Exception { String response=process("start=200&timeout=error&error=dispatch",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: error\r\n"+ - "history: onError\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "error", + "onError", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -238,14 +247,14 @@ public class AsyncServletTest public void testStartOnTimeoutComplete() throws Exception { String response=process("start=200&timeout=complete",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: complete\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "complete", + "onComplete")); assertContains("COMPLETED",response); } @@ -254,32 +263,31 @@ public class AsyncServletTest public void testStartWaitDispatch() throws Exception { String response=process("start=200&dispatch=10",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); - assertNotContains("history: onTimeout",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); + assertFalse(__history.contains("onTimeout")); } @Test public void testStartDispatch() throws Exception { String response=process("start=200&dispatch=0",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); - assertContains("history: onComplete",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); } @Test @@ -287,16 +295,16 @@ public class AsyncServletTest { _expectedCode="500 "; String response=process("start=200&throw=1",null); - assertThat(response,startsWith("HTTP/1.1 500 Server Error\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ + assertThat(response,startsWith("HTTP/1.1 500 Server Error")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", /* TODO should there be an onError call? - "history: onError\r\n"+ + "onError", "history: onComplete\r\n" - */"", - response); + */"" + )); assertContains("HTTP ERROR: 500",response); } @@ -304,52 +312,52 @@ public class AsyncServletTest public void testStartWaitComplete() throws Exception { String response=process("start=200&complete=50",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: complete\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "complete", + "onComplete")); assertContains("COMPLETED",response); - assertNotContains("history: onTimeout",response); - assertNotContains("history: !initial",response); + assertFalse(__history.contains("onTimeout")); + assertFalse(__history.contains("!initial")); } @Test public void testStartComplete() throws Exception { String response=process("start=200&complete=0",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: complete\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "complete", + "onComplete")); assertContains("COMPLETED",response); - assertNotContains("history: onTimeout",response); - assertNotContains("history: !initial",response); + assertFalse(__history.contains("onTimeout")); + assertFalse(__history.contains("!initial")); } @Test public void testStartWaitDispatchStartWaitDispatch() throws Exception { String response=process("start=1000&dispatch=10&start2=1000&dispatch2=10",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -357,18 +365,18 @@ public class AsyncServletTest public void testStartWaitDispatchStartComplete() throws Exception { String response=process("start=1000&dispatch=10&start2=1000&complete2=10",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: complete\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "complete", + "onComplete")); assertContains("COMPLETED",response); } @@ -378,19 +386,19 @@ public class AsyncServletTest _expectedCode="500 "; String response=process("start=1000&dispatch=10&start2=10",null); assertEquals("HTTP/1.1 500 Async Timeout",response.substring(0,26)); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onComplete")); assertContains("ERROR DISPATCH: /ctx/path/info",response); } @@ -398,20 +406,20 @@ public class AsyncServletTest public void testStartTimeoutStartDispatch() throws Exception { String response=process("start=10&start2=1000&dispatch2=10",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -419,18 +427,18 @@ public class AsyncServletTest public void testStartTimeoutStartComplete() throws Exception { String response=process("start=10&start2=1000&complete2=10",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: complete\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "complete", + "onComplete")); assertContains("COMPLETED",response); } @@ -439,19 +447,19 @@ public class AsyncServletTest { _expectedCode="500 "; String response=process("start=10&start2=10",null); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onStartAsync\r\n"+ - "history: start\r\n"+ - "history: onTimeout\r\n"+ - "history: ERROR /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onStartAsync", + "start", + "onTimeout", + "ERROR /ctx/path/info", + "!initial", + "onComplete")); assertContains("ERROR DISPATCH: /ctx/path/info",response); } @@ -459,16 +467,16 @@ public class AsyncServletTest public void testWrapStartDispatch() throws Exception { String response=process("wrap=true&start=200&dispatch=20",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: wrapped REQ RSP\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path/info", + "wrapped REQ RSP", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -477,15 +485,15 @@ public class AsyncServletTest public void testStartDispatchEncodedPath() throws Exception { String response=process("start=200&dispatch=20&path=/p%20th3",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/p%20th3\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "dispatch", + "ASYNC /ctx/p%20th3", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -494,17 +502,17 @@ public class AsyncServletTest public void testFwdStartDispatch() throws Exception { String response=process("fwd","start=200&dispatch=20",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: FWD REQUEST /ctx/fwd/info\r\n"+ - "history: FORWARD /ctx/path1\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: FWD ASYNC /ctx/fwd/info\r\n"+ - "history: FORWARD /ctx/path1\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "FWD REQUEST /ctx/fwd/info", + "FORWARD /ctx/path1", + "initial", + "start", + "dispatch", + "FWD ASYNC /ctx/fwd/info", + "FORWARD /ctx/path1", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -512,16 +520,16 @@ public class AsyncServletTest public void testFwdStartDispatchPath() throws Exception { String response=process("fwd","start=200&dispatch=20&path=/path2",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: FWD REQUEST /ctx/fwd/info\r\n"+ - "history: FORWARD /ctx/path1\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path2\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "FWD REQUEST /ctx/fwd/info", + "FORWARD /ctx/path1", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path2", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -529,17 +537,17 @@ public class AsyncServletTest public void testFwdWrapStartDispatch() throws Exception { String response=process("fwd","wrap=true&start=200&dispatch=20",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: FWD REQUEST /ctx/fwd/info\r\n"+ - "history: FORWARD /ctx/path1\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path1\r\n"+ - "history: wrapped REQ RSP\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "FWD REQUEST /ctx/fwd/info", + "FORWARD /ctx/path1", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path1", + "wrapped REQ RSP", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -547,17 +555,17 @@ public class AsyncServletTest public void testFwdWrapStartDispatchPath() throws Exception { String response=process("fwd","wrap=true&start=200&dispatch=20&path=/path2",null); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: FWD REQUEST /ctx/fwd/info\r\n"+ - "history: FORWARD /ctx/path1\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path2\r\n"+ - "history: wrapped REQ RSP\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "FWD REQUEST /ctx/fwd/info", + "FORWARD /ctx/path1", + "initial", + "start", + "dispatch", + "ASYNC /ctx/path2", + "wrapped REQ RSP", + "!initial", + "onComplete")); assertContains("DISPATCHED",response); } @@ -587,16 +595,16 @@ public class AsyncServletTest socket.getOutputStream().write(close.getBytes(StandardCharsets.ISO_8859_1)); String response = IO.toString(socket.getInputStream()); - assertThat(response,startsWith("HTTP/1.1 200 OK\r\n")); - assertContains( - "history: REQUEST /ctx/path/info\r\n"+ - "history: initial\r\n"+ - "history: start\r\n"+ - "history: async-read=10\r\n"+ - "history: dispatch\r\n"+ - "history: ASYNC /ctx/path/info\r\n"+ - "history: !initial\r\n"+ - "history: onComplete\r\n",response); + assertThat(response,startsWith("HTTP/1.1 200 OK")); + assertThat(__history,contains( + "REQUEST /ctx/path/info", + "initial", + "start", + "async-read=10", + "dispatch", + "ASYNC /ctx/path/info", + "!initial", + "onComplete")); } } @@ -628,7 +636,9 @@ public class AsyncServletTest socket.setSoTimeout(1000000); socket.getOutputStream().write(request.getBytes(StandardCharsets.UTF_8)); socket.getOutputStream().flush(); - return IO.toString(socket.getInputStream()); + String response = IO.toString(socket.getInputStream()); + __latch.await(1,TimeUnit.SECONDS); + return response; } catch(Exception e) { @@ -636,6 +646,7 @@ public class AsyncServletTest e.printStackTrace(); throw e; } + } protected void assertContains(String content,String response) @@ -653,9 +664,9 @@ public class AsyncServletTest @Override public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { - response.addHeader("history","FWD "+request.getDispatcherType()+" "+request.getRequestURI()); + __history.add("FWD "+request.getDispatcherType()+" "+request.getRequestURI()); if (request instanceof ServletRequestWrapper || response instanceof ServletResponseWrapper) - response.addHeader("history","wrapped"+((request instanceof ServletRequestWrapper)?" REQ":"")+((response instanceof ServletResponseWrapper)?" RSP":"")); + __history.add("wrapped"+((request instanceof ServletRequestWrapper)?" REQ":"")+((response instanceof ServletResponseWrapper)?" RSP":"")); request.getServletContext().getRequestDispatcher("/path1").forward(request,response); } } @@ -680,9 +691,9 @@ public class AsyncServletTest } // System.err.println(request.getDispatcherType()+" "+request.getRequestURI()); - response.addHeader("history",request.getDispatcherType()+" "+request.getRequestURI()); + __history.add(request.getDispatcherType()+" "+request.getRequestURI()); if (request instanceof ServletRequestWrapper || response instanceof ServletResponseWrapper) - response.addHeader("history","wrapped"+((request instanceof ServletRequestWrapper)?" REQ":"")+((response instanceof ServletResponseWrapper)?" RSP":"")); + __history.add("wrapped"+((request instanceof ServletRequestWrapper)?" REQ":"")+((response instanceof ServletResponseWrapper)?" RSP":"")); boolean wrap="true".equals(request.getParameter("wrap")); int read_before=0; @@ -716,7 +727,7 @@ public class AsyncServletTest if (request.getAttribute("State")==null) { request.setAttribute("State",new Integer(1)); - response.addHeader("history","initial"); + __history.add("initial"); if (read_before>0) { byte[] buf=new byte[read_before]; @@ -744,7 +755,7 @@ public class AsyncServletTest while(b!=-1) if((b=in.read())>=0) c++; - response.addHeader("history","async-read="+c); + __history.add("async-read="+c); } catch(Exception e) { @@ -760,7 +771,7 @@ public class AsyncServletTest if (start_for>0) async.setTimeout(start_for); async.addListener(__listener); - response.addHeader("history","start"); + __history.add("start"); if ("1".equals(request.getParameter("throw"))) throw new QuietServletException(new Exception("test throw in async 1")); @@ -776,7 +787,7 @@ public class AsyncServletTest { response.setStatus(200); response.getOutputStream().println("COMPLETED\n"); - response.addHeader("history","complete"); + __history.add("complete"); async.complete(); } catch(Exception e) @@ -794,7 +805,7 @@ public class AsyncServletTest { response.setStatus(200); response.getOutputStream().println("COMPLETED\n"); - response.addHeader("history","complete"); + __history.add("complete"); async.complete(); } else if (dispatch_after>0) @@ -804,7 +815,7 @@ public class AsyncServletTest @Override public void run() { - ((HttpServletResponse)async.getResponse()).addHeader("history","dispatch"); + __history.add("dispatch"); if (path!=null) { int q=path.indexOf('?'); @@ -824,7 +835,7 @@ public class AsyncServletTest } else if (dispatch_after==0) { - ((HttpServletResponse)async.getResponse()).addHeader("history","dispatch"); + __history.add("dispatch"); if (path!=null) async.dispatch(path); else @@ -853,7 +864,7 @@ public class AsyncServletTest } else { - response.addHeader("history","!initial"); + __history.add("!initial"); if (start2_for>=0 && request.getAttribute("2nd")==null) { @@ -865,7 +876,7 @@ public class AsyncServletTest { async.setTimeout(start2_for); } - response.addHeader("history","start"); + __history.add("start"); if ("2".equals(request.getParameter("throw"))) throw new QuietServletException(new Exception("test throw in async 2")); @@ -881,7 +892,7 @@ public class AsyncServletTest { response.setStatus(200); response.getOutputStream().println("COMPLETED\n"); - response.addHeader("history","complete"); + __history.add("complete"); async.complete(); } catch(Exception e) @@ -899,7 +910,7 @@ public class AsyncServletTest { response.setStatus(200); response.getOutputStream().println("COMPLETED\n"); - response.addHeader("history","complete"); + __history.add("complete"); async.complete(); } else if (dispatch2_after>0) @@ -909,7 +920,7 @@ public class AsyncServletTest @Override public void run() { - response.addHeader("history","dispatch"); + __history.add("dispatch"); async.dispatch(); } }; @@ -920,7 +931,7 @@ public class AsyncServletTest } else if (dispatch2_after==0) { - response.addHeader("history","dispatch"); + __history.add("dispatch"); async.dispatch(); } } @@ -943,11 +954,11 @@ public class AsyncServletTest @Override public void onTimeout(AsyncEvent event) throws IOException { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onTimeout"); + __history.add("onTimeout"); String action=event.getSuppliedRequest().getParameter("timeout"); if (action!=null) { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history",action); + __history.add(action); switch(action) { @@ -969,17 +980,17 @@ public class AsyncServletTest @Override public void onStartAsync(AsyncEvent event) throws IOException { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onStartAsync"); + __history.add("onStartAsync"); } @Override public void onError(AsyncEvent event) throws IOException { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onError"); + __history.add("onError"); String action=event.getSuppliedRequest().getParameter("error"); if (action!=null) { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history",action); + __history.add(action); switch(action) { @@ -998,7 +1009,8 @@ public class AsyncServletTest @Override public void onComplete(AsyncEvent event) throws IOException { - ((HttpServletResponse)event.getSuppliedResponse()).addHeader("history","onComplete"); + __history.add("onComplete"); + __latch.countDown(); } };