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

bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 62136a0695 Add HTTP/2 no_activity_timeout tests (#9763)
62136a0695 is described below

commit 62136a06950cab13d866f3c0cfdfe8990a7d6a1e
Author: Brian Neradt <[email protected]>
AuthorDate: Sat Jun 3 13:13:26 2023 -0500

    Add HTTP/2 no_activity_timeout tests (#9763)
    
    This adds autest coverage of the HTTP/2 no_activity_timeout_(in|out)
    configurations.
---
 proxy/http2/Http2ClientSession.cc                  |   2 +-
 proxy/http2/Http2ServerSession.cc                  |   1 +
 .../timeout/http2_no_activity_timeout.test.py      | 164 +++++++++++++++++++++
 .../replay/http2_no_activity_timeout.replay.yaml   |  91 ++++++++++++
 4 files changed, 257 insertions(+), 1 deletion(-)

diff --git a/proxy/http2/Http2ClientSession.cc 
b/proxy/http2/Http2ClientSession.cc
index 42300aa2a6..56ce64928f 100644
--- a/proxy/http2/Http2ClientSession.cc
+++ b/proxy/http2/Http2ClientSession.cc
@@ -196,7 +196,7 @@ Http2ClientSession::main_event_handler(int event, void 
*edata)
   case VC_EVENT_INACTIVITY_TIMEOUT:
   case VC_EVENT_ERROR:
   case VC_EVENT_EOS:
-    Http2SsnDebug("Closing event %d", event);
+    Http2SsnDebug("Closing event: %s", HttpDebugNames::get_event_name(event));
     this->set_dying_event(event);
     this->do_io_close();
     retval     = 0;
diff --git a/proxy/http2/Http2ServerSession.cc 
b/proxy/http2/Http2ServerSession.cc
index 42bb4e8e1e..054cb676d5 100644
--- a/proxy/http2/Http2ServerSession.cc
+++ b/proxy/http2/Http2ServerSession.cc
@@ -189,6 +189,7 @@ Http2ServerSession::main_event_handler(int event, void 
*edata)
   case VC_EVENT_INACTIVITY_TIMEOUT:
   case VC_EVENT_ERROR:
   case VC_EVENT_EOS:
+    Http2SsnDebug("Closing event: %s", HttpDebugNames::get_event_name(event));
     this->set_dying_event(event);
     this->do_io_close();
     retval = 0;
diff --git a/tests/gold_tests/timeout/http2_no_activity_timeout.test.py 
b/tests/gold_tests/timeout/http2_no_activity_timeout.test.py
new file mode 100644
index 0000000000..fbb5683a05
--- /dev/null
+++ b/tests/gold_tests/timeout/http2_no_activity_timeout.test.py
@@ -0,0 +1,164 @@
+#  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.
+
+from typing import Optional
+import re
+
+
+Test.Summary = 'Verify http2.no_activity_timeout_(in|out)'
+
+
+class Test_http2_no_activity_timeout:
+    """Configure a test for http2 no_activity_timeout_(in|out)."""
+
+    replay_file = "replay/http2_no_activity_timeout.replay.yaml"
+    client_counter: int = 0
+    ts_counter: int = 0
+    server_counter: int = 0
+
+    def __init__(self,
+                 name: str,
+                 replay_keys: Optional[str] = None,
+                 no_activity_timeout_in: Optional[int] = None,
+                 expect_in_timeout=False,
+                 no_activity_timeout_out: Optional[int] = None,
+                 expect_out_timeout=False):
+        """Initialize the test.
+
+        :param name: The name of the test.
+        :param replay_keys: The set of keys to replay from the replay file. If
+          not provided, all keys will be replayed.
+        :param no_activity_timeout_in: Configuration value for
+          ts.http2.no_activity_timeout_in. None means that the default value 
will
+          be used.
+        :param expect_in_timeout: True if there is an expected inbound timeout.
+        :param no_activity_timeout_out: Configuration value for
+          ts.http2.no_activity_timeout_out. None means that the default value 
will
+          be used.
+        :param expect_out_timeout: True if there is an expected outbound 
timeout.
+        """
+        self._name = name
+        self._replay_keys = replay_keys
+        self._no_activity_timeout_in = no_activity_timeout_in
+        self._expect_in_timeout = expect_in_timeout
+        self._no_activity_timeout_out = no_activity_timeout_out
+        self._expect_out_timeout = expect_out_timeout
+
+    def _configure_server(self, tr: 'TestRun'):
+        """Configure the server.
+
+        :param tr: The TestRun object to associate the server process with.
+        """
+        self._server = tr.AddVerifierServerProcess(
+            f"server_{Test_http2_no_activity_timeout.server_counter}",
+            self.replay_file)
+        Test_http2_no_activity_timeout.server_counter += 1
+
+    def _configure_traffic_server(self, tr: 'TestRun'):
+        """Configure Traffic Server.
+
+        :param tr: The TestRun object to associate the ts process with.
+        """
+        self._ts = tr.MakeATSProcess(
+            f"ts-{Test_http2_no_activity_timeout.ts_counter}",
+            enable_tls=True,
+            enable_cache=False)
+        Test_http2_no_activity_timeout.ts_counter += 1
+
+        self._ts.addSSLfile("ssl/cert.crt")
+        self._ts.addSSLfile("ssl/private-key.key")
+        self._ts.Disk.ssl_multicert_config.AddLine(
+            f'dest_ip=* ssl_cert_name={self._ts.Variables.SSLDir}/cert.crt '
+            f'ssl_key_name={self._ts.Variables.SSLDir}/private-key.key'
+        )
+
+        self._ts.Disk.records_config.update({
+            'proxy.config.diags.debug.enabled': 1,
+            'proxy.config.diags.debug.tags': 'http|socket|inactivity_cop',
+            'proxy.config.ssl.server.cert.path': self._ts.Variables.SSLDir,
+            'proxy.config.ssl.server.private_key.path': 
self._ts.Variables.SSLDir,
+            "proxy.config.ssl.client.verify.server.policy": 'PERMISSIVE',
+            'proxy.config.ssl.client.alpn_protocols': 'h2,http/1.1',
+        })
+
+        if self._no_activity_timeout_in is not None:
+            self._ts.Disk.records_config.update({
+                'proxy.config.http2.no_activity_timeout_in': 
self._no_activity_timeout_in,
+            })
+        if self._no_activity_timeout_out is not None:
+            self._ts.Disk.records_config.update({
+                'proxy.config.http2.no_activity_timeout_out': 
self._no_activity_timeout_out,
+            })
+
+        self._ts.Disk.remap_config.AddLine(f'map / 
https://127.0.0.1:{self._server.Variables.https_port}')
+
+    def run(self):
+        """Run the test."""
+        tr = Test.AddTestRun(self._name)
+        self._configure_server(tr)
+        self._configure_traffic_server(tr)
+
+        tr.Processes.Default.StartBefore(self._server)
+        tr.Processes.Default.StartBefore(self._ts)
+
+        tr.AddVerifierClientProcess(
+            f'client-{Test_http2_no_activity_timeout.client_counter}',
+            self.replay_file,
+            https_ports=[self._ts.Variables.ssl_port],
+            keys=self._replay_keys)
+        Test_http2_no_activity_timeout.client_counter += 1
+
+        if self._expect_in_timeout:
+            tr.Processes.Default.Streams.All += Testers.IncludesExpression(
+                "SSL_read error",
+                "The client should have a read error due to an ATS timeout.")
+            self._ts.Disk.traffic_out.Content += Testers.IncludesExpression(
+                "http2_cs.*Closing event:.*TIMEOUT",
+                "We should detect a client side timeout.")
+        elif self._expect_out_timeout:
+            # There should be two origin connections:
+            # 1. For the first no delay transaction.
+            # 2. Another after a timeout, closing the first.
+            self._server.Streams.All += Testers.IncludesExpression(
+                "Negotiated ALPN from client ALPN.*Negotiated ALPN from client 
ALPN",
+                "A second server side connection should be needed after the 
first times out.",
+                reflags=re.MULTILINE | re.DOTALL)
+            self._ts.Disk.traffic_out.Content += Testers.IncludesExpression(
+                "http2_cs.*Closing event:.*TIMEOUT",
+                "We should detect a server side timeout.")
+
+
+test0 = Test_http2_no_activity_timeout(
+    "Default no activity timeout",
+    expect_in_timeout=False,
+    expect_out_timeout=False)
+test0.run()
+
+test1 = Test_http2_no_activity_timeout(
+    "Client (in) side inactivity timeout",
+    no_activity_timeout_in=1,
+    replay_keys="no_delay 3_second_request_delay",
+    expect_in_timeout=True,
+    expect_out_timeout=False)
+test1.run()
+
+test2 = Test_http2_no_activity_timeout(
+    "Server (out) side inactivity timeout",
+    no_activity_timeout_out=1,
+    replay_keys="no_delay 3_second_request_delay",
+    expect_in_timeout=False,
+    expect_out_timeout=True)
+test2.run()
diff --git 
a/tests/gold_tests/timeout/replay/http2_no_activity_timeout.replay.yaml 
b/tests/gold_tests/timeout/replay/http2_no_activity_timeout.replay.yaml
new file mode 100644
index 0000000000..0cc88b140e
--- /dev/null
+++ b/tests/gold_tests/timeout/replay/http2_no_activity_timeout.replay.yaml
@@ -0,0 +1,91 @@
+#  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.
+
+meta:
+  version: "1.0"
+
+sessions:
+- protocol:
+  - name: http
+    version: 2
+  - name: tls
+    sni: example.com
+  transactions:
+
+  - client-request:
+      headers:
+        fields:
+        - [ :method, GET]
+        - [ :scheme, https]
+        - [ :authority, example.com]
+        - [ :path, /path/test1]
+        - [ uuid, no_delay ]
+        - [ X-Request-Delay, 0seconds ]
+
+    server-response:
+      headers:
+        fields:
+        - [ :status, 200]
+        - [ X-Response-Delay, 0seconds ]
+      content:
+        data: had_no_delay
+
+    proxy-response:
+      status: 200
+
+  - client-request:
+      delay: 3s
+      headers:
+        fields:
+        - [ :method, GET]
+        - [ :scheme, https]
+        - [ :authority, example.com]
+        - [ :path, /path/test2]
+        - [ uuid, 3_second_request_delay ]
+        - [ X-Request-Delay, 3seconds ]
+
+    server-response:
+      headers:
+        fields:
+        - [ :status, 200]
+        - [ X-Response-Delay, 0seconds ]
+      content:
+        data: 3_second_request_delay
+
+    proxy-response:
+      status: 200
+
+  - client-request:
+      headers:
+        fields:
+        - [ :method, GET]
+        - [ :scheme, https]
+        - [ :authority, example.com]
+        - [ :path, /path/test3]
+        - [ uuid, 3_second_response_delay ]
+        - [ X-Request-Delay, 0seconds ]
+
+    server-response:
+      delay: 3s
+      headers:
+        fields:
+        - [ :status, 200]
+        - [ X-Response-Delay, 3seconds ]
+      content:
+        data: 3_second_response_delay
+
+    proxy-response:
+      status: 200

Reply via email to