| /* |
| * 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 java.nio.ByteBuffer; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| 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(); |
| |
| // Disable overhead protection for window update as it breaks the test |
| http2Protocol.setOverheadWindowUpdateThreshold(0); |
| |
| sendSimplePostRequest(3, null); |
| readSimplePostResponse(false); |
| |
| Assert.assertEquals( |
| "0-WindowSize-[128]\n" + "3-WindowSize-[128]\n" + "3-HeadersStart\n" + "3-Header-[:status]-[200]\n" + |
| "3-Header-[content-length]-[128]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + |
| "3-HeadersEnd\n" + "3-Body-128\n" + "3-EndOfStream\n", |
| output.getTrace()); |
| } |
| |
| |
| @Test |
| public void testDataFrameWithPadding() throws Exception { |
| Logger.getLogger("org.apache.coyote").setLevel(Level.ALL); |
| Logger.getLogger("org.apache.tomcat.util.net").setLevel(Level.ALL); |
| try { |
| http2Connect(); |
| |
| // Disable overhead protection for window update as it breaks the |
| // test |
| http2Protocol.setOverheadWindowUpdateThreshold(0); |
| |
| byte[] padding = new byte[8]; |
| |
| sendSimplePostRequest(3, padding); |
| readSimplePostResponse(true); |
| |
| // The window updates for padding could occur anywhere since they |
| // happen on a different thread to the response. |
| // The connection window update is always present if there is |
| // padding. |
| String trace = output.getTrace(); |
| String paddingWindowUpdate = "0-WindowSize-[9]\n"; |
| Assert.assertTrue(trace, trace.contains(paddingWindowUpdate)); |
| trace = trace.replace(paddingWindowUpdate, ""); |
| |
| // The stream window update may or may not be present depending on |
| // timing. Remove it if present. |
| if (trace.contains("3-WindowSize-[9]\n")) { |
| trace = trace.replace("3-WindowSize-[9]\n", ""); |
| } |
| |
| Assert.assertEquals("0-WindowSize-[119]\n" + "3-WindowSize-[119]\n" + "3-HeadersStart\n" + |
| "3-Header-[:status]-[200]\n" + "3-Header-[content-length]-[119]\n" + |
| "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + "3-Body-119\n" + |
| "3-EndOfStream\n", trace); |
| } finally { |
| Logger.getLogger("org.apache.coyote").setLevel(Level.INFO); |
| Logger.getLogger("org.apache.tomcat.util.net").setLevel(Level.INFO); |
| } |
| } |
| |
| |
| @Test |
| public void testDataFrameWithPaddingAndContentLength() throws Exception { |
| Logger.getLogger("org.apache.coyote").setLevel(Level.ALL); |
| Logger.getLogger("org.apache.tomcat.util.net").setLevel(Level.ALL); |
| try { |
| http2Connect(); |
| |
| // Disable overhead protection for window update as it breaks the |
| // test |
| http2Protocol.setOverheadWindowUpdateThreshold(0); |
| |
| byte[] padding = new byte[8]; |
| |
| byte[] headersFrameHeader = new byte[9]; |
| ByteBuffer headersPayload = ByteBuffer.allocate(128); |
| byte[] dataFrameHeader = new byte[9]; |
| ByteBuffer dataPayload = ByteBuffer.allocate(128); |
| |
| // 128 byte payload, less 8 bytes padding, less 1 padding byte gives 119 bytes |
| buildPostRequest(headersFrameHeader, headersPayload, false, null, 119, "/simple", dataFrameHeader, |
| dataPayload, padding, false, 3); |
| writeFrame(headersFrameHeader, headersPayload); |
| writeFrame(dataFrameHeader, dataPayload); |
| |
| readSimplePostResponse(true); |
| |
| // The window updates for padding could occur anywhere since they |
| // happen on a different thread to the response. |
| // The connection window update is always present if there is |
| // padding. |
| String trace = output.getTrace(); |
| String paddingWindowUpdate = "0-WindowSize-[9]\n"; |
| Assert.assertTrue(trace, trace.contains(paddingWindowUpdate)); |
| trace = trace.replace(paddingWindowUpdate, ""); |
| |
| // The stream window update may or may not be present depending on |
| // timing. Remove it if present. |
| if (trace.contains("3-WindowSize-[9]\n")) { |
| trace = trace.replace("3-WindowSize-[9]\n", ""); |
| } |
| |
| Assert.assertEquals("0-WindowSize-[119]\n" + "3-WindowSize-[119]\n" + "3-HeadersStart\n" + |
| "3-Header-[:status]-[200]\n" + "3-Header-[content-length]-[119]\n" + |
| "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n" + "3-Body-119\n" + |
| "3-EndOfStream\n", trace); |
| } finally { |
| Logger.getLogger("org.apache.coyote").setLevel(Level.INFO); |
| Logger.getLogger("org.apache.tomcat.util.net").setLevel(Level.INFO); |
| } |
| } |
| |
| |
| @Test |
| public void testDataFrameWithNonZeroPadding() throws Exception { |
| http2Connect(); |
| |
| byte[] padding = new byte[8]; |
| padding[4] = 0x01; |
| |
| sendSimplePostRequest(3, padding); |
| |
| // May see Window updates depending on timing |
| skipWindowSizeFrames(); |
| |
| String trace = output.getTrace(); |
| Assert.assertTrue(trace, trace.startsWith("0-Goaway-[3]-[1]-[")); |
| } |
| |
| |
| @Test |
| public void testDataFrameOnStreamZero() throws Exception { |
| http2Connect(); |
| |
| byte[] dataFrame = new byte[10]; |
| |
| // Header |
| // length |
| ByteUtil.setThreeBytes(dataFrame, 0, 1); |
| // type (0 for data) |
| // flags (0) |
| // stream (0) |
| // payload (0) |
| |
| os.write(dataFrame); |
| os.flush(); |
| |
| handleGoAwayResponse(1); |
| } |
| |
| |
| @Test |
| public void testDataFrameTooMuchPadding() throws Exception { |
| http2Connect(); |
| |
| byte[] dataFrame = new byte[10]; |
| |
| // Header |
| // length |
| ByteUtil.setThreeBytes(dataFrame, 0, 1); |
| // type 0 (data) |
| // flags 8 (padded) |
| dataFrame[4] = 0x08; |
| // stream 3 |
| ByteUtil.set31Bits(dataFrame, 5, 3); |
| // payload (pad length of 1) |
| dataFrame[9] = 1; |
| |
| os.write(dataFrame); |
| os.flush(); |
| |
| handleGoAwayResponse(1); |
| } |
| |
| |
| @Test |
| public void testDataFrameWithZeroLengthPadding() throws Exception { |
| http2Connect(); |
| |
| // Disable overhead protection for window update as it breaks the test |
| http2Protocol.setOverheadWindowUpdateThreshold(0); |
| |
| byte[] padding = new byte[0]; |
| |
| sendSimplePostRequest(3, padding); |
| readSimplePostResponse(true); |
| |
| // The window updates for padding could occur anywhere since they |
| // happen on a different thread to the response. |
| // The connection window update is always present if there is |
| // padding. |
| String trace = output.getTrace(); |
| String paddingWindowUpdate = "0-WindowSize-[1]\n"; |
| Assert.assertTrue(trace, trace.contains(paddingWindowUpdate)); |
| trace = trace.replace(paddingWindowUpdate, ""); |
| |
| // The stream window update may or may not be present depending on |
| // timing. Remove it if present. |
| paddingWindowUpdate = "3-WindowSize-[1]\n"; |
| if (trace.contains(paddingWindowUpdate)) { |
| trace = trace.replace(paddingWindowUpdate, ""); |
| } |
| |
| Assert.assertEquals( |
| "0-WindowSize-[127]\n" + "3-WindowSize-[127]\n" + "3-HeadersStart\n" + "3-Header-[:status]-[200]\n" + |
| "3-Header-[content-length]-[127]\n" + "3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + |
| "3-HeadersEnd\n" + "3-Body-127\n" + "3-EndOfStream\n", |
| trace); |
| } |
| } |