Author: markt Date: Wed Aug 19 21:34:01 2015 New Revision: 1696671 URL: http://svn.apache.org/r1696671 Log: Add another test case for 6.9 Fix a bug where end of stream was never sent for responses with zero content length.
Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java Modified: tomcat/trunk/java/org/apache/coyote/http2/Stream.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/http2/Stream.java?rev=1696671&r1=1696670&r2=1696671&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/http2/Stream.java (original) +++ tomcat/trunk/java/org/apache/coyote/http2/Stream.java Wed Aug 19 21:34:01 2015 @@ -259,6 +259,7 @@ public class Stream extends AbstractStre void sentEndOfStream() { + outputBuffer.endOfStreamSent = true; state.sentEndOfStream(); } @@ -288,6 +289,7 @@ public class Stream extends AbstractStre private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); private volatile long written = 0; private volatile boolean closed = false; + private volatile boolean endOfStreamSent = false; /* The write methods are synchronized to ensure that only one thread at * a time is able to access the buffer. Without this protection, a @@ -331,6 +333,11 @@ public class Stream extends AbstractStre coyoteResponse.sendHeaders(); } if (buffer.position() == 0) { + if (closed && !endOfStreamSent) { + // Handling this special case here is simpler than trying + // to modify the following code to handle it. + handler.writeBody(Stream.this, buffer, 0, true); + } // Buffer is empty. Nothing to do. return; } Modified: tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java?rev=1696671&r1=1696670&r2=1696671&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Aug 19 21:34:01 2015 @@ -114,6 +114,15 @@ public abstract class Http2TestBase exte } + protected void sendEmptyGetRequest(int streamId) throws IOException { + byte[] frameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + + buildEmptyGetRequest(frameHeader, headersPayload, null, streamId); + writeFrame(frameHeader, headersPayload); + } + + protected void sendSimpleGetRequest(int streamId) throws IOException { sendSimpleGetRequest(streamId, null); } @@ -137,6 +146,12 @@ public abstract class Http2TestBase exte } + protected void buildEmptyGetRequest(byte[] frameHeader, ByteBuffer headersPayload, + byte[] padding, int streamId) { + buildGetRequest(frameHeader, headersPayload, padding, streamId, "/empty"); + } + + protected void buildSimpleGetRequest(byte[] frameHeader, ByteBuffer headersPayload, byte[] padding, int streamId) { buildGetRequest(frameHeader, headersPayload, padding, streamId, "/simple"); @@ -301,7 +316,17 @@ public abstract class Http2TestBase exte } + protected String getEmptyResponseTrace(int streamId) { + return getSingleResponseBodyFrameTrace(streamId, 0); + } + + protected String getSimpleResponseTrace(int streamId) { + return getSingleResponseBodyFrameTrace(streamId, 8192); + } + + + private String getSingleResponseBodyFrameTrace(int streamId, int bodySize) { StringBuilder result = new StringBuilder(); result.append(streamId); result.append("-HeadersStart\n"); @@ -310,7 +335,9 @@ public abstract class Http2TestBase exte result.append(streamId); result.append("-HeadersEnd\n"); result.append(streamId); - result.append("-Body-8192\n"); + result.append("-Body-"); + result.append(bodySize); + result.append("\n"); result.append(streamId); result.append("-EndOfStream\n"); @@ -338,6 +365,8 @@ public abstract class Http2TestBase exte Tomcat tomcat = getTomcatInstance(); Context ctxt = tomcat.addContext("", null); + Tomcat.addServlet(ctxt, "empty", new EmptyServlet()); + ctxt.addServletMapping("/empty", "empty"); Tomcat.addServlet(ctxt, "simple", new SimpleServlet()); ctxt.addServletMapping("/simple", "simple"); Tomcat.addServlet(ctxt, "large", new LargeServlet()); @@ -805,6 +834,20 @@ public abstract class Http2TestBase exte } } + + private static class EmptyServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // Generate an empty response + resp.setContentLength(0); + resp.flushBuffer(); + } + } + private static class SimpleServlet extends HttpServlet { Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java?rev=1696671&r1=1696670&r2=1696671&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_9.java Wed Aug 19 21:34:01 2015 @@ -94,5 +94,36 @@ public class TestHttp2Section_6_9 extend "0-Goaway-[1]-[" + Http2Error.FRAME_SIZE_ERROR.getCode() + "]-[")); } + + @Test + public void testEmptyDataFrameWithNoAvailableFlowControl() throws Exception { + http2Connect(); + + // Default connection window size is 64k - 1. Initial request will have + // used 8k (56k -1). + + // Use up the remaining connection window. These requests require 56k + // but there is only 56k - 1 available. + for (int i = 3; i < 17; i += 2) { + sendSimpleGetRequest(i); + readSimpleGetResponse(); + } + output.clearTrace(); + + // It should be possible to send a request that generates an empty + // response at this point + sendEmptyGetRequest(17); + // Headers + parser.readFrame(true); + // Body + parser.readFrame(true); + + // Release Stream 15 which is waiting for a single byte. + sendWindowUpdate(0, 1024); + + Assert.assertEquals(getEmptyResponseTrace(17), output.getTrace()); + } + + // TODO: Remaining 6.9 tests } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org