This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 31ab0b3974e6f0eaa429b16b049b60cc30db5579
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Fri Jan 20 17:06:12 2023 +0000

    Add a unit test for RFC 9218 priority handling
---
 test/org/apache/coyote/http2/Http2TestBase.java |  27 ++++
 test/org/apache/coyote/http2/TestRfc9218.java   | 165 ++++++++++++++++++++++++
 2 files changed, 192 insertions(+)

diff --git a/test/org/apache/coyote/http2/Http2TestBase.java 
b/test/org/apache/coyote/http2/Http2TestBase.java
index b068520a80..4dc566fb9a 100644
--- a/test/org/apache/coyote/http2/Http2TestBase.java
+++ b/test/org/apache/coyote/http2/Http2TestBase.java
@@ -947,6 +947,33 @@ public abstract class Http2TestBase extends TomcatBaseTest 
{
     }
 
 
+    void sendPriorityUpdate(int streamId, int urgency, boolean incremental) 
throws IOException {
+        // Need to know the payload length first
+        StringBuilder sb = new StringBuilder("u=");
+        sb.append(urgency);
+        if (incremental) {
+            sb.append(", i");
+        }
+        byte[] payload = sb.toString().getBytes(StandardCharsets.US_ASCII);
+
+        byte[] priorityUpdateFrame = new byte[13 + payload.length];
+
+        // length
+        ByteUtil.setThreeBytes(priorityUpdateFrame, 0, 4 + payload.length);
+        // type
+        priorityUpdateFrame[3] = FrameType.PRIORITY_UPDATE.getIdByte();
+        // Stream ID
+        ByteUtil.set31Bits(priorityUpdateFrame, 5, 0);
+
+        // Payload
+        ByteUtil.set31Bits(priorityUpdateFrame, 9, streamId);
+        System.arraycopy(payload, 0, priorityUpdateFrame, 13, payload.length);
+
+        os.write(priorityUpdateFrame);
+        os.flush();
+    }
+
+
     void sendSettings(int streamId, boolean ack, SettingValue... settings) 
throws IOException {
         // length
         int settingsCount;
diff --git a/test/org/apache/coyote/http2/TestRfc9218.java 
b/test/org/apache/coyote/http2/TestRfc9218.java
new file mode 100644
index 0000000000..85dd834eee
--- /dev/null
+++ b/test/org/apache/coyote/http2/TestRfc9218.java
@@ -0,0 +1,165 @@
+/*
+ *  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;
+
+public class TestRfc9218 extends Http2TestBase {
+
+    @Test
+    public void testPriority() throws Exception {
+        http2Connect();
+
+        /*
+         * This test uses small window updates and data frames that will 
trigger the excessive overhead protection so
+         * disable it.
+         */
+        http2Protocol.setOverheadWindowUpdateThreshold(0);
+        http2Protocol.setOverheadDataThreshold(0);
+
+        // Default connection window size is 64k - 1. Initial request will 
have used 8k (56k -1). Increase it to 57k.
+        sendWindowUpdate(0, 1 + 1024);
+
+        // Consume 56k of the connection window
+        for (int i = 3; i < 17; i += 2) {
+            sendSimpleGetRequest(i);
+            readSimpleGetResponse();
+        }
+
+        // At this point the connection window should be 1k
+
+        // Process a request on stream 17. This should consume the connection 
window.
+        sendSimpleGetRequest(17);
+        // 17-headers, 17-1k-body
+        parser.readFrame();
+        parser.readFrame();
+        output.clearTrace();
+
+        // Send additional requests. Connection window is empty so only 
headers will be returned.
+        sendSimpleGetRequest(19);
+        sendSimpleGetRequest(21);
+
+        // 19-headers, 21-headers
+        parser.readFrame();
+        parser.readFrame();
+        output.clearTrace();
+
+        // At this point 17, 19 and 21 are all blocked because the connection 
window is zero.
+        // 17 - 7k body left
+        // 19 - 8k body left
+        // 21 - 8k body left
+
+        // Add 1k to the connection window. Should be used for stream 17.
+        sendWindowUpdate(0, 1024);
+        parser.readFrame();
+        Assert.assertEquals("17-Body-1024\n", output.getTrace());
+        output.clearTrace();
+
+        // 17 - 6k body left
+        // 19 - 8k body left
+        // 21 - 8k body left
+
+        // Re-order the priorities
+        sendPriorityUpdate(19, 2, false);
+        sendPriorityUpdate(21, 1, false);
+
+        // Add 1k to the connection window. Should be used for stream 21.
+        sendWindowUpdate(0, 1024);
+        parser.readFrame();
+
+        Assert.assertEquals("21-Body-1024\n", output.getTrace());
+        output.clearTrace();
+
+        // 17 - 6k body left
+        // 19 - 8k body left
+        // 21 - 7k body left
+
+        // Re-order the priorities
+        sendPriorityUpdate(17, 3, true);
+        sendPriorityUpdate(19, 3, true);
+        sendPriorityUpdate(21, 3, true);
+
+        // Add 3k to the connection window. Should be split between 17, 19 and 
21.
+        sendWindowUpdate(0, 1024 * 3);
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+
+        String trace = output.getTrace();
+        Assert.assertTrue(trace.contains("17-Body-877\n"));
+        trace = trace.replace("17-Body-877\n", "");
+        Assert.assertTrue(trace.contains("19-Body-1170\n"));
+        trace = trace.replace("19-Body-1170\n", "");
+        Assert.assertTrue(trace.contains("21-Body-1024\n"));
+        trace = trace.replace("21-Body-1024\n", "");
+        Assert.assertEquals(0, trace.length());
+        output.clearTrace();
+
+        // 1 byte unallocated in connection window
+        // 17 - 5267 body left
+        // 19 - 7022 body left
+        // 21 - 6144 body left
+
+        // Add 1 byte to the connection window. Due to rounding up, each 
stream should get 1 byte.
+        sendWindowUpdate(0, 1);
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+
+        trace = output.getTrace();
+        Assert.assertTrue(trace.contains("17-Body-1\n"));
+        trace = trace.replace("17-Body-1\n", "");
+        Assert.assertTrue(trace.contains("19-Body-1\n"));
+        trace = trace.replace("19-Body-1\n", "");
+        Assert.assertTrue(trace.contains("21-Body-1\n"));
+        trace = trace.replace("21-Body-1\n", "");
+        Assert.assertEquals(0, trace.length());
+        output.clearTrace();
+
+        // 1 byte over allocated in connection window
+        // 17 - 5266 body left
+        // 19 - 7021 body left
+        // 21 - 6143 body left
+
+        // Re-order the priorities
+        sendPriorityUpdate(17, 2, true);
+
+        /*
+         * Add 8k to the connection window. Should clear the connection window 
over allocation and fully allocate 17
+         * with the remainder split equally between 17 and 21.
+         */
+        sendWindowUpdate(0, 1024 * 8);
+        parser.readFrame();
+        parser.readFrame();
+        parser.readFrame();
+
+        trace = output.getTrace();
+        System.out.println(trace);
+        Assert.assertTrue(trace.contains("17-Body-5266\n"));
+        trace = trace.replace("17-Body-5266\n", "");
+        Assert.assertTrue(trace.contains("17-EndOfStream\n"));
+        trace = trace.replace("17-EndOfStream\n", "");
+        Assert.assertTrue(trace.contains("19-Body-1560\n"));
+        trace = trace.replace("19-Body-1560\n", "");
+        Assert.assertTrue(trace.contains("21-Body-1365\n"));
+        trace = trace.replace("21-Body-1365\n", "");
+        Assert.assertEquals(0, trace.length());
+
+        // Test doesn't read the read of the body for streams 19 and 21.
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to