Author: markt Date: Wed Jun 17 14:45:36 2015 New Revision: 1686028 URL: http://svn.apache.org/r1686028 Log: Add a unit test for a simple request with a body
Added: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java (with props) Modified: tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_1.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_3.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_1.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_2.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_3.java tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_5.java 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=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/Http2TestBase.java Wed Jun 17 14:45:36 2015 @@ -16,6 +16,8 @@ */ package org.apache.coyote.http2; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -37,6 +39,7 @@ import org.apache.catalina.LifecycleExce import org.apache.catalina.connector.Connector; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.catalina.util.IOTools; import org.apache.coyote.http2.HpackDecoder.HeaderEmitter; import org.apache.coyote.http2.Http2Parser.Input; import org.apache.coyote.http2.Http2Parser.Output; @@ -105,35 +108,35 @@ public abstract class Http2TestBase exte } - protected void sendSimpleRequest(int streamId) throws IOException { + protected void sendSimpleGetRequest(int streamId) throws IOException { byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequest(frameHeader, headersPayload, streamId); + buildSimpleGetRequest(frameHeader, headersPayload, streamId); writeFrame(frameHeader, headersPayload); } - protected void sendLargeRequest(int streamId) throws IOException { + protected void sendLargeGetRequest(int streamId) throws IOException { byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildLargeRequest(frameHeader, headersPayload, streamId); + buildLargeGetRequest(frameHeader, headersPayload, streamId); writeFrame(frameHeader, headersPayload); } - protected void buildSimpleRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { - buildRequest(frameHeader, headersPayload, streamId, "/simple"); + protected void buildSimpleGetRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { + buildGetRequest(frameHeader, headersPayload, streamId, "/simple"); } - protected void buildLargeRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { - buildRequest(frameHeader, headersPayload, streamId, "/large"); + protected void buildLargeGetRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { + buildGetRequest(frameHeader, headersPayload, streamId, "/large"); } - protected void buildRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId, + protected void buildGetRequest(byte[] frameHeader, ByteBuffer headersPayload, int streamId, String url) { MimeHeaders headers = new MimeHeaders(); headers.addValue(":method").setString("GET"); @@ -153,7 +156,7 @@ public abstract class Http2TestBase exte } - protected void buildSimpleRequestPart1(byte[] frameHeader, ByteBuffer headersPayload, + protected void buildSimpleGetRequestPart1(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { MimeHeaders headers = new MimeHeaders(); headers.addValue(":method").setString("GET"); @@ -172,7 +175,7 @@ public abstract class Http2TestBase exte } - protected void buildSimpleRequestPart2(byte[] frameHeader, ByteBuffer headersPayload, + protected void buildSimpleGetRequestPart2(byte[] frameHeader, ByteBuffer headersPayload, int streamId) { MimeHeaders headers = new MimeHeaders(); headers.addValue(":authority").setString("localhost:" + getPort()); @@ -190,6 +193,51 @@ public abstract class Http2TestBase exte } + protected void sendSimplePostRequest(int streamId) throws IOException { + byte[] headersFrameHeader = new byte[9]; + ByteBuffer headersPayload = ByteBuffer.allocate(128); + byte[] dataFrameHeader = new byte[9]; + ByteBuffer dataPayload = ByteBuffer.allocate(128); + + buildPostRequest(headersFrameHeader, headersPayload, + dataFrameHeader, dataPayload, streamId); + writeFrame(headersFrameHeader, headersPayload); + writeFrame(dataFrameHeader, dataPayload); + } + + + protected void buildPostRequest(byte[] headersFrameHeader, ByteBuffer headersPayload, + byte[] dataFrameHeader, ByteBuffer dataPayload, int streamId) { + MimeHeaders headers = new MimeHeaders(); + headers.addValue(":method").setString("POST"); + headers.addValue(":path").setString("/simple"); + headers.addValue(":authority").setString("localhost:" + getPort()); + hpackEncoder.encode(headers, headersPayload); + + headersPayload.flip(); + + ByteUtil.setThreeBytes(headersFrameHeader, 0, headersPayload.limit()); + // Header frame is type 0x01 + headersFrameHeader[3] = 0x01; + // Flags. end of headers (0x04) + headersFrameHeader[4] = 0x04; + // Stream id + ByteUtil.set31Bits(headersFrameHeader, 5, streamId); + + // Data + while (dataPayload.hasRemaining()) { + dataPayload.put((byte) 'x'); + } + dataPayload.flip(); + + // Size + ByteUtil.setThreeBytes(dataFrameHeader, 0, dataPayload.limit()); + // Data is type 0 + // End of stream + dataFrameHeader[4] = 0x01; + ByteUtil.set31Bits(dataFrameHeader, 5, streamId); + } + protected void writeFrame(byte[] header, ByteBuffer payload) throws IOException { os.write(header); @@ -198,7 +246,19 @@ public abstract class Http2TestBase exte } - protected void readSimpleResponse() throws Http2Exception, IOException { + protected void readSimpleGetResponse() throws Http2Exception, IOException { + // Headers + parser.readFrame(true); + // Body + parser.readFrame(true); + } + + + protected void readSimplePostResponse() throws Http2Exception, IOException { + // Connection window update after reading request body + parser.readFrame(true); + // Stream window update after reading request body + parser.readFrame(true); // Headers parser.readFrame(true); // Body @@ -660,6 +720,21 @@ public abstract class Http2TestBase exte os.write(data); } } + + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + // Do not do this at home. The unconstrained buffer is a DoS risk. + + // Have to read into a buffer because clients typically do not start + // to read the response until the request is fully written. + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOTools.flow(req.getInputStream(), baos); + + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + IOTools.flow(bais, resp.getOutputStream()); + } } Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_1.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_1.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_1.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_1.java Wed Jun 17 14:45:36 2015 @@ -41,8 +41,8 @@ public class TestHttp2Section_4_1 extend http2Connect(); os.write(UNKNOWN_FRAME); os.flush(); - sendSimpleRequest(3); - readSimpleResponse(); + sendSimpleGetRequest(3); + readSimpleGetResponse(); Assert.assertEquals(getSimpleResponseTrace(3), output.getTrace()); } @@ -58,7 +58,7 @@ public class TestHttp2Section_4_1 extend // Build the simple request byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequest(frameHeader, headersPayload, 3); + buildSimpleGetRequest(frameHeader, headersPayload, 3); // Tweak the header to set the reserved bit frameHeader[5] = (byte) (frameHeader[5] | 0x80); @@ -66,7 +66,7 @@ public class TestHttp2Section_4_1 extend // Process the request writeFrame(frameHeader, headersPayload); - readSimpleResponse(); + readSimpleGetResponse(); Assert.assertEquals(getSimpleResponseTrace(3), output.getTrace()); } } Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_3.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_3.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_3.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_4_3.java Wed Jun 17 14:45:36 2015 @@ -38,7 +38,7 @@ public class TestHttp2Section_4_3 extend // Build the simple request byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequest(frameHeader, headersPayload, 3); + buildSimpleGetRequest(frameHeader, headersPayload, 3); // Try and corrupt the headerPayload headersPayload.put(0, (byte) (headersPayload.get(0) + 128)); @@ -62,12 +62,12 @@ public class TestHttp2Section_4_3 extend // Part 1 byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequestPart1(frameHeader, headersPayload, 3); + buildSimpleGetRequestPart1(frameHeader, headersPayload, 3); writeFrame(frameHeader, headersPayload); // Part 2 headersPayload.clear(); - buildSimpleRequestPart2(frameHeader, headersPayload, 3); + buildSimpleGetRequestPart2(frameHeader, headersPayload, 3); writeFrame(frameHeader, headersPayload); // headers, body @@ -86,7 +86,7 @@ public class TestHttp2Section_4_3 extend // Part 1 byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequestPart1(frameHeader, headersPayload, 3); + buildSimpleGetRequestPart1(frameHeader, headersPayload, 3); writeFrame(frameHeader, headersPayload); sendPing(); Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_1.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_1.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_1.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_1.java Wed Jun 17 14:45:36 2015 @@ -65,8 +65,8 @@ public class TestHttp2Section_5_1 extend http2Connect(); // This half-closes the stream since it includes the end of stream flag - sendSimpleRequest(3); - readSimpleResponse(); + sendSimpleGetRequest(3); + readSimpleGetResponse(); Assert.assertEquals(getSimpleResponseTrace(3), output.getTrace()); output.clearTrace(); @@ -87,7 +87,7 @@ public class TestHttp2Section_5_1 extend // Build the simple request byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequest(frameHeader, headersPayload, 3); + buildSimpleGetRequest(frameHeader, headersPayload, 3); // Remove the end of stream and end of headers flags frameHeader[4] = 0; @@ -132,7 +132,7 @@ public class TestHttp2Section_5_1 extend // Part 1 byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequestPart1(frameHeader, headersPayload, 4); + buildSimpleGetRequestPart1(frameHeader, headersPayload, 4); writeFrame(frameHeader, headersPayload); // headers @@ -146,8 +146,8 @@ public class TestHttp2Section_5_1 extend @Test public void testClientSendOldStream() throws Exception { http2Connect(); - sendSimpleRequest(5); - readSimpleResponse(); + sendSimpleGetRequest(5); + readSimpleGetResponse(); Assert.assertEquals(getSimpleResponseTrace(5), output.getTrace()); output.clearTrace(); @@ -155,7 +155,7 @@ public class TestHttp2Section_5_1 extend // Build the simple request on an old stream byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequest(frameHeader, headersPayload, 3); + buildSimpleGetRequest(frameHeader, headersPayload, 3); os.write(frameHeader); os.flush(); @@ -175,14 +175,14 @@ public class TestHttp2Section_5_1 extend sendPriority(3, 0, 16); sendPriority(5, 0, 16); - sendSimpleRequest(5); - readSimpleResponse(); + sendSimpleGetRequest(5); + readSimpleGetResponse(); Assert.assertEquals(getSimpleResponseTrace(5), output.getTrace()); output.clearTrace(); // Should trigger an error since stream 3 should have been implicitly // closed. - sendSimpleRequest(3); + sendSimpleGetRequest(3); parser.readFrame(true); @@ -201,9 +201,9 @@ public class TestHttp2Section_5_1 extend sendClientPreface(); validateHttp2InitialResponse(); - sendLargeRequest(3); + sendLargeGetRequest(3); - sendSimpleRequest(5); + sendSimpleGetRequest(5); // Default connection window size is 64k - 1. Initial request will have // used 8k (56k -1). Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_2.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_2.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_2.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_2.java Wed Jun 17 14:45:36 2015 @@ -47,7 +47,7 @@ public class TestHttp2Section_5_2 extend output.clearTrace(); // Headers + 8k response - sendSimpleRequest(3); + sendSimpleGetRequest(3); // Headers parser.readFrame(true); Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_3.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_3.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_3.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_3.java Wed Jun 17 14:45:36 2015 @@ -57,8 +57,8 @@ public class TestHttp2Section_5_3 extend // Use up 56k of the connection window for (int i = 3; i < 17; i += 2) { - sendSimpleRequest(i); - readSimpleResponse(); + sendSimpleGetRequest(i); + readSimpleGetResponse(); } // Set the default window size to 1024 bytes @@ -77,7 +77,7 @@ public class TestHttp2Section_5_3 extend // First, process a request on stream 17. This should consume both // stream 17's window and the connection window. - sendSimpleRequest(17); + sendSimpleGetRequest(17); // 17-headers, 17-1k-body parser.readFrame(true); parser.readFrame(true); @@ -85,8 +85,8 @@ public class TestHttp2Section_5_3 extend // Send additional requests. Connection window is empty so only headers // will be returned. - sendSimpleRequest(19); - sendSimpleRequest(21); + sendSimpleGetRequest(19); + sendSimpleGetRequest(21); // Open up the flow control windows for stream 19 & 21 to more than the // size of a simple request (8k) Modified: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_5.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_5.java?rev=1686028&r1=1686027&r2=1686028&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_5.java (original) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_5_5.java Wed Jun 17 14:45:36 2015 @@ -85,7 +85,7 @@ public class TestHttp2Section_5_5 extend // Part 1 byte[] frameHeader = new byte[9]; ByteBuffer headersPayload = ByteBuffer.allocate(128); - buildSimpleRequestPart1(frameHeader, headersPayload, 3); + buildSimpleGetRequestPart1(frameHeader, headersPayload, 3); writeFrame(frameHeader, headersPayload); os.write(UNKNOWN_FRAME); Added: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java?rev=1686028&view=auto ============================================================================== --- tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java (added) +++ tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java Wed Jun 17 14:45:36 2015 @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.coyote.http2; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Unit tests for Section 6.1 of + * <a href="https://tools.ietf.org/html/rfc7540">RFC 7540</a>. + * <br> + * The order of tests in this class is aligned with the order of the + * requirements in the RFC. + */ +public class TestHttp2Section_6_1 extends Http2TestBase { + + @Test + public void testDataFrame() throws Exception { + http2Connect(); + + sendSimplePostRequest(3); + readSimplePostResponse(); + + Assert.assertEquals("0-WindowSize-[128]\n" + + "3-WindowSize-[128]\n" + + "3-HeadersStart\n" + + "3-Header-[:status]-[200]\n" + + "3-HeadersEnd\n" + + "3-Body-128\n" + + "3-EndOfStream\n", output.getTrace()); + } + + + // TODO: Remainder if section 6.1 tests +} Propchange: tomcat/trunk/test/org/apache/coyote/http2/TestHttp2Section_6_1.java ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org