From 6e70ee42119a3ecc504e135700b1a50ebbcac63e Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Mon, 26 Nov 2012 15:25:47 +0100 Subject: [PATCH 1/4] 394370 Add integration test for client resetting SPDY push SYN's --- .../server/http/ReferrerPushStrategyTest.java | 140 ++++++++++-------- 1 file changed, 78 insertions(+), 62 deletions(-) diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java index 220f5d8174e..98ce863d837 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java @@ -34,11 +34,13 @@ import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.ReplyInfo; +import org.eclipse.jetty.spdy.api.RstInfo; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Session; import org.eclipse.jetty.spdy.api.SessionFrameListener; import org.eclipse.jetty.spdy.api.Stream; import org.eclipse.jetty.spdy.api.StreamFrameListener; +import org.eclipse.jetty.spdy.api.StreamStatus; import org.eclipse.jetty.spdy.api.SynInfo; import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory; import org.eclipse.jetty.util.Fields; @@ -51,13 +53,15 @@ import static org.junit.Assert.assertThat; public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest { - private final String mainResource = "/index.html"; private final int referrerPushPeriod = 1000; + private final String mainResource = "/index.html"; private final String cssResource = "/style.css"; private InetSocketAddress serverAddress; private ReferrerPushStrategy pushStrategy; private ConnectionFactory defaultFactory; private Fields mainRequestHeaders; + private Fields associatedCSSRequestHeaders; + private Fields associatedJSRequestHeaders; public ReferrerPushStrategyTest(short version) { @@ -83,6 +87,8 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest else connector.setDefaultProtocol(defaultFactory.getProtocol()); mainRequestHeaders = createHeadersWithoutReferrer(mainResource); + associatedCSSRequestHeaders = createHeaders(cssResource); + associatedJSRequestHeaders = createHeaders("/application.js"); } @Test @@ -92,6 +98,47 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest run2ndClientRequests(true, true); } + @Test + public void testClientResetsPushStreams() throws Exception + { + sendMainRequestAndCSSRequest(); + final CountDownLatch pushDataLatch = new CountDownLatch(1); + final CountDownLatch pushSynHeadersValid = new CountDownLatch(1); + Session session = startClient(version, serverAddress, new SessionFrameListener.Adapter() + { + @Override + public StreamFrameListener onSyn(Stream stream, SynInfo synInfo) + { + validateHeaders(synInfo.getHeaders(), pushSynHeadersValid); + + assertThat("Stream is unidirectional", stream.isUnidirectional(), is(true)); + assertThat("URI header ends with css", synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version)) + .value().endsWith + ("" + + ".css"), + is(true)); + stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM)); + return new StreamFrameListener.Adapter() + { + + @Override + public void onData(Stream stream, DataInfo dataInfo) + { + dataInfo.consume(dataInfo.length()); + pushDataLatch.countDown(); + } + }; + } + }); + // Send main request. That should initiate the push syn's which get reset by the client + sendRequest(session, mainRequestHeaders); + + assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false)); + assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true)); + + sendRequest(session, associatedCSSRequestHeaders); + } + @Test public void testUserAgentBlackList() throws Exception { @@ -103,11 +150,11 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest @Test public void testReferrerPushPeriod() throws Exception { - Session session1 = sendMainRequestAndCSSRequest(); + Session session = sendMainRequestAndCSSRequest(); // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource Thread.sleep(referrerPushPeriod + 1); - sendJSRequest(session1); + sendRequest(session, associatedJSRequestHeaders); run2ndClientRequests(false, true); } @@ -119,9 +166,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest connector.addConnectionFactory(defaultFactory); connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right - Session session1 = sendMainRequestAndCSSRequest(); + Session session = sendMainRequestAndCSSRequest(); - sendJSRequest(session1); + sendRequest(session, associatedJSRequestHeaders); run2ndClientRequests(false, true); } @@ -148,62 +195,43 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest private Session sendMainRequestAndCSSRequest() throws Exception { - Session session1 = startClient(version, serverAddress, null); + Session session = startClient(version, serverAddress, null); - final CountDownLatch mainResourceLatch = new CountDownLatch(1); - session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter() - { - @Override - public void onData(Stream stream, DataInfo dataInfo) - { - dataInfo.consume(dataInfo.length()); - if (dataInfo.isClose()) - mainResourceLatch.countDown(); - } - }); - Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS)); + sendRequest(session, mainRequestHeaders); + sendRequest(session, associatedCSSRequestHeaders); - final CountDownLatch associatedResourceLatch1 = new CountDownLatch(1); - Fields associatedRequestHeaders1 = createHeaders(cssResource); - session1.syn(new SynInfo(associatedRequestHeaders1, true), new StreamFrameListener.Adapter() - { - @Override - public void onData(Stream stream, DataInfo dataInfo) - { - dataInfo.consume(dataInfo.length()); - if (dataInfo.isClose()) - associatedResourceLatch1.countDown(); - } - }); - Assert.assertTrue(associatedResourceLatch1.await(5, TimeUnit.SECONDS)); - return session1; + return session; } - - private void sendJSRequest(Session session1) throws InterruptedException + private void sendRequest(Session session, Fields requestHeaders) throws InterruptedException { - final CountDownLatch associatedResourceLatch2 = new CountDownLatch(1); - String jsResource = "/application.js"; - Fields associatedRequestHeaders2 = createHeaders(jsResource); - session1.syn(new SynInfo(associatedRequestHeaders2, true), new StreamFrameListener.Adapter() + final CountDownLatch dataReceivedLatch = new CountDownLatch(1); + final CountDownLatch received200OKLatch = new CountDownLatch(1); + session.syn(new SynInfo(requestHeaders, true), new StreamFrameListener.Adapter() { + @Override + public void onReply(Stream stream, ReplyInfo replyInfo) + { + if ("200 OK".equals(replyInfo.getHeaders().get(HTTPSPDYHeader.STATUS.name(version)).value())) + received200OKLatch.countDown(); + super.onReply(stream, replyInfo); + } + @Override public void onData(Stream stream, DataInfo dataInfo) { dataInfo.consume(dataInfo.length()); if (dataInfo.isClose()) - associatedResourceLatch2.countDown(); + dataReceivedLatch.countDown(); } }); - Assert.assertTrue(associatedResourceLatch2.await(5, TimeUnit.SECONDS)); + Assert.assertTrue(received200OKLatch.await(5, TimeUnit.SECONDS)); + Assert.assertTrue(dataReceivedLatch.await(5, TimeUnit.SECONDS)); } private void run2ndClientRequests(final boolean validateHeaders, boolean expectPushResource) throws Exception { - // Create another client, and perform the same request for the main resource, - // we expect the css being pushed, but not the js - final CountDownLatch mainStreamLatch = new CountDownLatch(2); final CountDownLatch pushDataLatch = new CountDownLatch(1); final CountDownLatch pushSynHeadersValid = new CountDownLatch(1); @@ -215,11 +243,11 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest if (validateHeaders) validateHeaders(synInfo.getHeaders(), pushSynHeadersValid); - assertThat("Stream is unidirectional",stream.isUnidirectional(),is(true)); + assertThat("Stream is unidirectional", stream.isUnidirectional(), is(true)); assertThat("URI header ends with css", synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version)) .value().endsWith - ("" + - ".css"), + ("" + + ".css"), is(true)); return new StreamFrameListener.Adapter() { @@ -252,13 +280,13 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest } }); - assertThat("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS), is(true)); + assertThat("Main request reply and/or data received", mainStreamLatch.await(5, TimeUnit.SECONDS), is(true)); if (expectPushResource) - assertThat("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS), is(true)); + assertThat("Pushed data received", pushDataLatch.await(5, TimeUnit.SECONDS), is(true)); else assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false)); if (validateHeaders) - assertThat("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true)); + assertThat("Push syn headers valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true)); } @Test @@ -295,19 +323,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest }); Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS)); - final CountDownLatch associatedResourceLatch = new CountDownLatch(1); - Fields associatedRequestHeaders = createHeaders(cssResource); - session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter() - { - @Override - public void onData(Stream stream, DataInfo dataInfo) - { - dataInfo.consume(dataInfo.length()); - if (dataInfo.isClose()) - associatedResourceLatch.countDown(); - } - }); - Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS)); + sendRequest(session1, createHeaders(cssResource)); // Create another client, and perform the same request for the main resource, we expect the css being pushed From 0ec793bee5962faadf6e79e64f4270c3342e09ab Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 28 Nov 2012 17:40:43 +0100 Subject: [PATCH 2/4] 395312 Avoid that streams get committed twice --- .../http/HttpTransportOverSPDYTest.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDYTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDYTest.java index 267a58de97d..046f9437d6d 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDYTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDYTest.java @@ -18,15 +18,18 @@ package org.eclipse.jetty.spdy.server.http; +import java.io.IOException; import java.nio.ByteBuffer; import java.util.Random; import java.util.concurrent.TimeUnit; import org.eclipse.jetty.http.HttpGenerator; +import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.spdy.api.ByteBufferDataInfo; +import org.eclipse.jetty.spdy.api.DataInfo; import org.eclipse.jetty.spdy.api.ReplyInfo; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Session; @@ -45,7 +48,6 @@ import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -79,6 +81,7 @@ public class HttpTransportOverSPDYTest { httpTransportOverSPDY = new HttpTransportOverSPDY(connector, httpConfiguration, endPoint, pushStrategy, stream, new Fields()); + when(responseInfo.getStatus()).thenReturn(HttpStatus.OK_200); when(stream.getSession()).thenReturn(session); when(session.getVersion()).thenReturn(SPDY.V3); when(stream.isClosed()).thenReturn(false); @@ -169,7 +172,7 @@ public class HttpTransportOverSPDYTest ByteBuffer content = null; boolean lastContent = true; - // when stream.isClosed() is called a 2nd time, the teply has closed the stream already + // when stream.isClosed() is called a 2nd time, the reply has closed the stream already when(stream.isClosed()).thenReturn(false).thenReturn(true); httpTransportOverSPDY.send(responseInfo, content, lastContent, callback); @@ -234,6 +237,23 @@ public class HttpTransportOverSPDYTest assertThat("ByteBuffer length is 4096", dataInfoCaptor.getValue().length(), is(4096)); } + @Test + public void testVerifyThatAStreamIsNotCommittedTwice() throws IOException + { + ByteBuffer content = createRandomByteBuffer(); + boolean lastContent = false; + + httpTransportOverSPDY.send(responseInfo,content,lastContent, callback); + ArgumentCaptor replyInfoCaptor = ArgumentCaptor.forClass(ReplyInfo.class); + verify(stream, times(1)).reply(replyInfoCaptor.capture()); + assertThat("ReplyInfo close is false", replyInfoCaptor.getValue().isClose(), is(false)); + + httpTransportOverSPDY.send(HttpGenerator.RESPONSE_500_INFO, null,true); + + verify(stream, times(0)).data(any(DataInfo.class)); + verify(stream, times(1)).data(any(DataInfo.class), anyLong(), any(TimeUnit.class), any(Callback.class)); + } + private ByteBuffer createRandomByteBuffer() { ByteBuffer content = BufferUtil.allocate(8192); From 68afcbba6c2a95e3894efda3ea01458b52abae60 Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 28 Nov 2012 17:41:44 +0100 Subject: [PATCH 3/4] 395313 HttpTransportOverSPDY.send() does not rethrow exceptions, but call Callback.failed() only --- .../server/http/HttpTransportOverSPDY.java | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java index 7e3126de97a..5deac20f771 100644 --- a/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java +++ b/jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpTransportOverSPDY.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Set; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpGenerator; @@ -32,10 +34,12 @@ import org.eclipse.jetty.io.EofException; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpTransport; +import org.eclipse.jetty.spdy.StreamException; import org.eclipse.jetty.spdy.api.ByteBufferDataInfo; import org.eclipse.jetty.spdy.api.ReplyInfo; import org.eclipse.jetty.spdy.api.SPDY; import org.eclipse.jetty.spdy.api.Stream; +import org.eclipse.jetty.spdy.api.StreamStatus; import org.eclipse.jetty.spdy.api.SynInfo; import org.eclipse.jetty.util.BlockingCallback; import org.eclipse.jetty.util.BufferUtil; @@ -56,6 +60,7 @@ public class HttpTransportOverSPDY implements HttpTransport private final Stream stream; private final Fields requestHeaders; private final BlockingCallback streamBlocker = new BlockingCallback(); + private final AtomicBoolean committed = new AtomicBoolean(); public HttpTransportOverSPDY(Connector connector, HttpConfiguration configuration, EndPoint endPoint, PushStrategy pushStrategy, Stream stream, Fields requestHeaders) { @@ -71,9 +76,9 @@ public class HttpTransportOverSPDY implements HttpTransport public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback) { if (LOG.isDebugEnabled()) - LOG.debug("send {} {} {} {} last={}%n",this,stream,info,BufferUtil.toDetailString(content),lastContent); + LOG.debug("send {} {} {} {} last={}",this,stream,info,BufferUtil.toDetailString(content),lastContent); - if (stream.isClosed() || stream.isReset() ) + if (stream.isClosed() || stream.isReset()) { callback.failed(new EofException("stream closed")); return; @@ -93,6 +98,11 @@ public class HttpTransportOverSPDY implements HttpTransport if (info!=null) { + if(!committed.compareAndSet(false, true)){ + callback.failed(new StreamException(stream.getId(), StreamStatus.PROTOCOL_ERROR, + "Stream already committed!")); + return; + } short version = stream.getSession().getVersion(); Fields headers = new Fields(); @@ -157,20 +167,16 @@ public class HttpTransportOverSPDY implements HttpTransport } @Override - public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws IOException + public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent) throws EofException { send(info,content,lastContent,streamBlocker); try { streamBlocker.block(); } - catch (IOException e) + catch (InterruptedException | TimeoutException | IOException e) { - throw e; - } - catch (Exception e) - { - throw new EofException(e); + LOG.debug(e); } } From 30091ccd897bbe35ba0a6c6367fc1b39e0e68721 Mon Sep 17 00:00:00 2001 From: Thomas Becker Date: Wed, 28 Nov 2012 17:43:53 +0100 Subject: [PATCH 4/4] 395314 Add missing flush() call after StandardSession.complete() has been called. Some test cleanup. --- .../eclipse/jetty/spdy/StandardSession.java | 8 +- .../server/http/ConcurrentStreamsTest.java | 28 +++--- .../spdy/server/http/ServerHTTPSPDYTest.java | 94 +++++++------------ 3 files changed, 57 insertions(+), 73 deletions(-) diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java index 7cb049b25be..a54b1e068d7 100644 --- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java +++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java @@ -1060,15 +1060,19 @@ public class StandardSession implements ISession, Parser.Listener, Dumpable execute(new Runnable() { @Override - public void run() { callback.succeeded() ; } + public void run() + { + callback.succeeded(); + flush(); + } }); - } @Override public void call(Callback callback) { callback.succeeded(); + flush(); } } diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ConcurrentStreamsTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ConcurrentStreamsTest.java index c3a5f31179f..e6f6e63d0c6 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ConcurrentStreamsTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ConcurrentStreamsTest.java @@ -48,6 +48,8 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest { final CountDownLatch slowServerLatch = new CountDownLatch(1); final CountDownLatch fastServerLatch = new CountDownLatch(1); + final String fastPath = "/fast"; + final String slowPath = "/slow"; Session session = startClient(version, startHTTPServer(version, new AbstractHandler() { @Override @@ -59,11 +61,11 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest request.setHandled(true); switch (target) { - case "/slow": + case slowPath: Assert.assertTrue(fastServerLatch.await(10, TimeUnit.SECONDS)); slowServerLatch.countDown(); break; - case "/fast": + case fastPath: fastServerLatch.countDown(); break; default: @@ -79,11 +81,7 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest }), null); // Perform slow request. This will wait on server side until the fast request wakes it up - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "GET"); - headers.put(HTTPSPDYHeader.URI.name(version), "/slow"); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders(slowPath); final CountDownLatch slowClientLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -97,11 +95,7 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest }); // Perform the fast request. This will wake up the slow request - headers.clear(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "GET"); - headers.put(HTTPSPDYHeader.URI.name(version), "/fast"); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + headers = createHeaders(fastPath); final CountDownLatch fastClientLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -119,4 +113,14 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest Assert.assertTrue(fastClientLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(slowClientLatch.await(5, TimeUnit.SECONDS)); } + + private Fields createHeaders(String path) + { + Fields headers = new Fields(); + headers.put(HTTPSPDYHeader.METHOD.name(version), "GET"); + headers.put(HTTPSPDYHeader.URI.name(version), path); + headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); + headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + return headers; + } } diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java index 1986338fa81..42c41057446 100644 --- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java +++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java @@ -36,6 +36,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.continuation.Continuation; import org.eclipse.jetty.continuation.ContinuationSupport; +import org.eclipse.jetty.server.HttpChannel; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.spdy.api.BytesDataInfo; @@ -47,6 +48,7 @@ import org.eclipse.jetty.spdy.api.StreamFrameListener; import org.eclipse.jetty.spdy.api.StringDataInfo; import org.eclipse.jetty.spdy.api.SynInfo; import org.eclipse.jetty.util.Fields; +import org.eclipse.jetty.util.log.StdErrLog; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -58,7 +60,6 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest super(version); } - @Test public void testSimpleGET() throws Exception { final String path = "/foo"; @@ -78,12 +79,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "GET"); - headers.put(HTTPSPDYHeader.URI.name(version), path); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("GET", path); final CountDownLatch replyLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -122,12 +118,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "GET"); - headers.put(HTTPSPDYHeader.URI.name(version), uri); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("GET", uri); final CountDownLatch replyLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -163,12 +154,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "HEAD"); - headers.put(HTTPSPDYHeader.URI.name(version), path); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("HEAD", path); final CountDownLatch replyLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -213,12 +199,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "POST"); - headers.put(HTTPSPDYHeader.URI.name(version), path); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("POST", path); headers.put("content-type", "application/x-www-form-urlencoded"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() @@ -259,12 +240,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "POST"); - headers.put(HTTPSPDYHeader.URI.name(version), path); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("POST", path); headers.put("content-type", "application/x-www-form-urlencoded"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() @@ -308,12 +284,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = new Fields(); - headers.put(HTTPSPDYHeader.METHOD.name(version), "POST"); - headers.put(HTTPSPDYHeader.URI.name(version), path); - headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); - headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); - headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); + Fields headers = createHeaders("POST", path); headers.put("content-type", "application/x-www-form-urlencoded"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() @@ -354,7 +325,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -400,7 +371,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -451,7 +422,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(2); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -506,7 +477,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -559,7 +530,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -612,7 +583,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -670,7 +641,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -723,7 +694,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -760,7 +731,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -792,18 +763,20 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest @Test public void testGETWithException() throws Exception { + StdErrLog log = StdErrLog.getLogger(HttpChannel.class); + log.setHideStacks(true); + Session session = startClient(version, startHTTPServer(version, new AbstractHandler() { @Override public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException { - // TODO suppress stack from test log throw new NullPointerException("thrown_explicitly_by_the_test"); } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -830,6 +803,8 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest }); Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(latch.await(5, TimeUnit.SECONDS)); + + log.setHideStacks(false); } @Test @@ -855,7 +830,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(2); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -937,7 +912,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() @@ -993,7 +968,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("GET"); + Fields headers = createHeaders("GET", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); final CountDownLatch dataLatch = new CountDownLatch(1); final AtomicInteger contentLength = new AtomicInteger(); @@ -1057,7 +1032,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() { @@ -1100,7 +1075,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter() { @@ -1145,7 +1120,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() { @@ -1213,7 +1188,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch replyLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() { @@ -1281,7 +1256,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch responseLatch = new CountDownLatch(2); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() { @@ -1322,7 +1297,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest } }), null); - Fields headers = createHeaders("POST"); + Fields headers = createHeaders("POST", "/foo"); final CountDownLatch responseLatch = new CountDownLatch(1); Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter() { @@ -1341,14 +1316,15 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest Assert.assertTrue(responseLatch.await(5, TimeUnit.SECONDS)); } - private Fields createHeaders(String httpMethod) + private Fields createHeaders(String httpMethod, String path) { Fields headers = new Fields(); headers.put(HTTPSPDYHeader.METHOD.name(version), httpMethod); - headers.put(HTTPSPDYHeader.URI.name(version), "/foo"); + headers.put(HTTPSPDYHeader.URI.name(version), path); headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1"); headers.put(HTTPSPDYHeader.SCHEME.name(version), "http"); headers.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort()); return headers; } + }