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

zwoop pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/9.2.x by this push:
     new 92eebcd9f4 92x autest updates (#9952)
92eebcd9f4 is described below

commit 92eebcd9f42adad05d1a2386177fa51357f8e3b2
Author: Brian Neradt <[email protected]>
AuthorDate: Wed Jul 5 17:41:08 2023 -0500

    92x autest updates (#9952)
    
    * Fix autest for OpenSSL 3.0 (#9753)
    
    * Fix forward-non-http autest for OpenSSL 3.0
    
    * Fix tls-verify-override autest for OpenSSL 3.0
    
    * Fix tls_client_versions autest with OpenSSL 3.0
    
    * Update test-nc-s_client.sh
    
    Added an EOF to test-nc-s_client.sh
    
    (cherry picked from commit e6d2fb1235d351de2d8d8ac94757932778857163)
    
    Conflicts:
          tests/gold_tests/tls/test-nc-s_client.sh
    
    * Fix autests for fedora 38 (#9881)
    
    I ran autest on fedora:38 and noticed that all but three passed. This 
commit updates our autests to work with the newer openssl s_client and 
Python3.11.
    
    The most significant set of changes come from hyper being abandoned an no 
longer working on Python 3.11. This converts the ad-hoc clients we had written 
in hyper to the h2 framework.
    
    (cherry picked from commit 431052145e73c0b0d34dee9f24eac0fa3d8818a1)
    
    * Replace httpbin with go-httpbin (#9475)
    
    The Python httpbin is no longer maintained and has dependency issues upon 
an old Werkzeug from which we would like to unpin. This converts our tests to 
using go-httpbin instead of the Python httpbin module.
    
    (cherry picked from commit 796391e19eae3e9250111bb95935d96e68bde09e)
    
    Conflicts:
          tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold
          tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold
          tests/gold_tests/proxy_protocol/gold/test_case_2_stdout.gold
          tests/gold_tests/proxy_protocol/gold/test_case_3_stderr.gold
          tests/gold_tests/proxy_protocol/gold/test_case_3_stdout.gold
          tests/gold_tests/proxy_protocol/gold/test_case_4_stderr.gold
          tests/gold_tests/proxy_protocol/gold/test_case_4_stdout.gold
    
    * Updates for the new go-httpbin v2.6.0 release. (#9633)
    
    [email protected] fixes /bytes/0 to actually return 0 bytes. This patch
    accommodates our autests for that fix and any other behavioral changes.
    
    (cherry picked from commit a9cb994e6ff32bdcc8acff7045b40491e50a2da1)
    
    * Fix test_tsapi.cc shutdown crash
    
    The global namespace destructor for the test_tsapi.cc used in
    tsapi.test.py would crash on shutdown. This does the cleanup in a
    shutdown handler rather than in the global namespace.
    
    ---------
    
    Co-authored-by: midchildan <[email protected]>
---
 tests/Pipfile                                      |   8 +-
 tests/gold_tests/autest-site/httpbin.test.ext      |  17 ++-
 tests/gold_tests/cache/background_fill.test.py     |   6 +-
 .../gold_tests/connect/gold/connect_0_stderr.gold  |   1 -
 tests/gold_tests/h2/gold/bigfile.gold              |  19 ++-
 tests/gold_tests/h2/gold/chunked.gold              |   8 +-
 tests/gold_tests/h2/gold/httpbin_0_stderr.gold     |   7 +-
 tests/gold_tests/h2/gold/httpbin_1_stderr.gold     |   7 +-
 tests/gold_tests/h2/gold/httpbin_1_stdout.gold     |   1 +
 tests/gold_tests/h2/gold/httpbin_2_stderr.gold     |   6 +-
 tests/gold_tests/h2/gold/httpbin_2_stdout.gold     |   2 +-
 tests/gold_tests/h2/gold/httpbin_3_stdout.gold     |   4 +-
 tests/gold_tests/h2/gold/remap-200.gold            |  12 +-
 tests/gold_tests/h2/h2active_timeout.py            | 132 ++++++++++++++----
 tests/gold_tests/h2/h2bigclient.py                 |  85 ------------
 tests/gold_tests/h2/h2chunked.py                   |  71 ----------
 tests/gold_tests/h2/h2client.py                    | 153 +++++++++++++++++----
 tests/gold_tests/h2/http2.test.py                  |  10 +-
 tests/gold_tests/h2/httpbin.test.py                |   3 +-
 tests/gold_tests/headers/gold/bad_method.gold      |  12 +-
 tests/gold_tests/pluginTest/tsapi/test_tsapi.cc    |  42 +++---
 tests/gold_tests/pluginTest/tsapi/tsapi.test.py    |   7 +
 tests/gold_tests/post/post-continue.test.py        |  99 ++++++-------
 .../replay/post-continue.replay.yaml}              |  32 ++++-
 .../proxy_protocol/gold/test_case_0_stderr.gold    |   5 +-
 .../proxy_protocol/gold/test_case_0_stdout.gold    |   4 +-
 .../proxy_protocol/gold/test_case_1_stderr.gold    |   5 +-
 .../proxy_protocol/gold/test_case_1_stdout.gold    |   4 +-
 tests/gold_tests/tls/test-nc-s_client.sh           |  12 +-
 tests/gold_tests/tls/tls_client_versions.test.py   |   2 +-
 tests/gold_tests/tls/tls_forward_nonhttp.test.py   |   5 +-
 tests/gold_tests/tls/tls_verify_override.test.py   |   4 +-
 .../tls/tls_verify_override_base.test.py           |   2 +-
 33 files changed, 427 insertions(+), 360 deletions(-)

diff --git a/tests/Pipfile b/tests/Pipfile
index da0c5dd3aa..87e44ba910 100644
--- a/tests/Pipfile
+++ b/tests/Pipfile
@@ -29,12 +29,11 @@ pyflakes = "*"
 autest = "==1.10.2"
 
 traffic-replay = "*" # this should install TRLib, MicroServer, MicroDNS, 
Traffic-Replay
-hyper = "*"
+h2 = "*"
 dnslib = "*"
 # These are likely to be available via yum/dnf or apt-get
 requests = "*"
 gunicorn = "*"
-httpbin = "*"
 psutil = "*"
 
 # Keep init.cli.ext updated with this required microserver version.
@@ -43,11 +42,6 @@ microserver = ">=1.0.6"
 jsonschema = "*"
 python-jose = "*"
 
-# The latest version of Werkzeug (2.1.0) breaks httpbin because it removes
-# deprecated function `BaseResponse` that httpbin directly or indirectly
-# depends upon. Pinning Wekrzeug for now until httpbin or its dependencies is
-# updated for the changed API.
-Werkzeug = "==2.0.3"
 flask = "==2.1.3"
 
 [requires]
diff --git a/tests/gold_tests/autest-site/httpbin.test.ext 
b/tests/gold_tests/autest-site/httpbin.test.ext
index 144eeb3203..dcd1787f5b 100644
--- a/tests/gold_tests/autest-site/httpbin.test.ext
+++ b/tests/gold_tests/autest-site/httpbin.test.ext
@@ -19,24 +19,23 @@
 from ports import get_port
 
 
-def MakeHttpBinServer(self, name, port=False, ip=False, delay=False, 
public_ip=False, ssl=False, options={}):
+def MakeHttpBinServer(self, name, ip='127.0.0.1', port=None,
+                      options={}) -> 'Process':
     data_dir = os.path.join(self.RunDirectory, name)
     # create Process
     p = self.Processes.Process(name)
-    if (port == False):
+    if port is None:
         port = get_port(p, "Port")
-    if (ip == False):
-        ip = '127.0.0.1'
-    if (delay == False):
-        delay = 0
 
     self._RootRunable.SkipUnless(
-        Condition.HasProgram("gunicorn", "gunicorn needs be installed with 
httpbin package for this extension to run")
+        Condition.HasProgram(
+            "go-httpbin",
+            "go-httpbin needs be installed and in PATH for this extension to 
run")
     )
 
-    command = "gunicorn -b {0}:{1} httpbin:app".format(ip, port)
+    command = f"go-httpbin -host {ip} -port {port} "
     for flag, value in options.items():
-        command += " {} {}".format(flag, value)
+        command += f"{flag} {value} "
 
     # create process
     p.Command = command
diff --git a/tests/gold_tests/cache/background_fill.test.py 
b/tests/gold_tests/cache/background_fill.test.py
index 5be9047289..45d529f9f2 100644
--- a/tests/gold_tests/cache/background_fill.test.py
+++ b/tests/gold_tests/cache/background_fill.test.py
@@ -92,7 +92,7 @@ class BackgroundFillTest:
         tr.Processes.Default.Command = f"""
 curl -X PURGE --http1.1 -vs 
http://127.0.0.1:{self.ts.Variables.port}/drip?duration=4;
 timeout 2 curl --http1.1 -vs 
http://127.0.0.1:{self.ts.Variables.port}/drip?duration=4;
-sleep 2;
+sleep 4;
 curl --http1.1 -vs http://127.0.0.1:{self.ts.Variables.port}/drip?duration=4
 """
         tr.Processes.Default.ReturnCode = 0
@@ -108,7 +108,7 @@ curl --http1.1 -vs 
http://127.0.0.1:{self.ts.Variables.port}/drip?duration=4
         tr.Processes.Default.Command = f"""
 curl -X PURGE --http1.1 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4;
 timeout 2 curl --http1.1 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4;
-sleep 2;
+sleep 4;
 curl --http1.1 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4
 """
         tr.Processes.Default.ReturnCode = 0
@@ -124,7 +124,7 @@ curl --http1.1 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration
         tr.Processes.Default.Command = f"""
 curl -X PURGE --http2 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4;
 timeout 2 curl --http2 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4;
-sleep 2;
+sleep 4;
 curl --http2 -vsk 
https://127.0.0.1:{self.ts.Variables.ssl_port}/drip?duration=4
 """
         tr.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/connect/gold/connect_0_stderr.gold 
b/tests/gold_tests/connect/gold/connect_0_stderr.gold
index 33b04218a9..c114dc4cf4 100644
--- a/tests/gold_tests/connect/gold/connect_0_stderr.gold
+++ b/tests/gold_tests/connect/gold/connect_0_stderr.gold
@@ -18,4 +18,3 @@
 ``
 <``
 ``
-* Closing connection 0
diff --git a/tests/gold_tests/h2/gold/bigfile.gold 
b/tests/gold_tests/h2/gold/bigfile.gold
index 5fd92155be..55e3daaa87 100644
--- a/tests/gold_tests/h2/gold/bigfile.gold
+++ b/tests/gold_tests/h2/gold/bigfile.gold
@@ -1,12 +1,11 @@
-Content length = 191414
-
-Body length = 191414
-
+``
+  content-length: 191414
+``
+Response fully received: 191414 bytes
 Content success
-
-Content length = 191414
-
-Body length = 191414
-
+``
+  content-length: 191414
+``
+Response fully received: 191414 bytes
 Content success
-
+``
diff --git a/tests/gold_tests/h2/gold/chunked.gold 
b/tests/gold_tests/h2/gold/chunked.gold
index 836d51a288..c09ab52a60 100644
--- a/tests/gold_tests/h2/gold/chunked.gold
+++ b/tests/gold_tests/h2/gold/chunked.gold
@@ -1,6 +1,8 @@
-HTTP/2 200
-date: {}
-server: ATS/{}
+Response received:
+  :status: 200
+  server: ``
+  date: ``
+  age: ``
 ``
 microserverapachetrafficserver
 ``
diff --git a/tests/gold_tests/h2/gold/httpbin_0_stderr.gold 
b/tests/gold_tests/h2/gold/httpbin_0_stderr.gold
index 3ed2777919..4bf3431d7a 100644
--- a/tests/gold_tests/h2/gold/httpbin_0_stderr.gold
+++ b/tests/gold_tests/h2/gold/httpbin_0_stderr.gold
@@ -5,11 +5,10 @@
 > Accept: */*
 ``
 < HTTP/2 200 ``
-< server: ATS/``
-< date: ``
-< content-type: application/json
 ``
+< content-type: application/json; encoding=utf-8
+< date: ``
 < content-length: ``
 < age: ``
 < via: ``ApacheTrafficServer/``
-``
+< server: ATS/``
diff --git a/tests/gold_tests/h2/gold/httpbin_1_stderr.gold 
b/tests/gold_tests/h2/gold/httpbin_1_stderr.gold
index 8c6bc6cb77..677e8eeea4 100644
--- a/tests/gold_tests/h2/gold/httpbin_1_stderr.gold
+++ b/tests/gold_tests/h2/gold/httpbin_1_stderr.gold
@@ -5,11 +5,10 @@
 > Accept: */*
 ``
 < HTTP/2 200 ``
-< server: ATS/``
-< date: ``
-< content-type: application/octet-stream
 ``
-< content-length: 0``
+< content-length: 0
+< date: ``
 < age: ``
 < via: ``ApacheTrafficServer/``
+< server: ATS/``
 ``
diff --git a/tests/gold_tests/h2/gold/httpbin_1_stdout.gold 
b/tests/gold_tests/h2/gold/httpbin_1_stdout.gold
index e69de29bb2..cf637de588 100644
--- a/tests/gold_tests/h2/gold/httpbin_1_stdout.gold
+++ b/tests/gold_tests/h2/gold/httpbin_1_stdout.gold
@@ -0,0 +1 @@
+``
diff --git a/tests/gold_tests/h2/gold/httpbin_2_stderr.gold 
b/tests/gold_tests/h2/gold/httpbin_2_stderr.gold
index c53bba6a7b..5bd16ccf95 100644
--- a/tests/gold_tests/h2/gold/httpbin_2_stderr.gold
+++ b/tests/gold_tests/h2/gold/httpbin_2_stderr.gold
@@ -5,10 +5,10 @@
 > Accept: */*
 ``
 < HTTP/2 200 ``
-< server: ATS/``
-< date: ``
-< content-type: application/octet-stream
 ``
+< content-type: application/octet-stream
+< date: ``
 < age: ``
 < via: ``ApacheTrafficServer/``
+< server: ATS/``
 ``
diff --git a/tests/gold_tests/h2/gold/httpbin_2_stdout.gold 
b/tests/gold_tests/h2/gold/httpbin_2_stdout.gold
index 9345ad17fc..d24de92221 100644
--- a/tests/gold_tests/h2/gold/httpbin_2_stdout.gold
+++ b/tests/gold_tests/h2/gold/httpbin_2_stdout.gold
@@ -1 +1 @@
-b99e42637ce13160c48e9b2bc9ed2d4dd175bc6cf44c7814b01e4853f262b284  -
+7a884625d64511d986423b361d75a5d037d7fa62b9ecf0959b93adda1afe07ef  -
diff --git a/tests/gold_tests/h2/gold/httpbin_3_stdout.gold 
b/tests/gold_tests/h2/gold/httpbin_3_stdout.gold
index 610580810c..0a1227adb2 100644
--- a/tests/gold_tests/h2/gold/httpbin_3_stdout.gold
+++ b/tests/gold_tests/h2/gold/httpbin_3_stdout.gold
@@ -1,7 +1,9 @@
 {
   ``
   "form": {
-    "key": "value"
+    "key": [
+      "value"
+    ]
   },
   ``
 }
diff --git a/tests/gold_tests/h2/gold/remap-200.gold 
b/tests/gold_tests/h2/gold/remap-200.gold
index 5f7e6ecd5f..5275ee8321 100644
--- a/tests/gold_tests/h2/gold/remap-200.gold
+++ b/tests/gold_tests/h2/gold/remap-200.gold
@@ -1,4 +1,8 @@
-HTTP/2 200
-date: {}
-server: ATS/{}
-
+Response received:
+  :status: 200
+  server: ``
+  date: ``
+  age: ``
+Response fully received: 0 bytes
+Content success
+``
diff --git a/tests/gold_tests/h2/h2active_timeout.py 
b/tests/gold_tests/h2/h2active_timeout.py
index 01659d36c5..c19d00fcbb 100644
--- a/tests/gold_tests/h2/h2active_timeout.py
+++ b/tests/gold_tests/h2/h2active_timeout.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 
 '''
+An h2 client built to trigger active timeout.
 '''
 #  Licensed to the Apache Software Foundation (ASF) under one
 #  or more contributor license agreements.  See the NOTICE file
@@ -18,45 +19,130 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-from hyper import HTTPConnection
-import hyper
+import socket
+import ssl
+
+import h2.connection
+import h2.events
+
 import argparse
 import time
 
 
-def makerequest(port, active_timeout):
-    hyper.tls._context = hyper.tls.init_context()
-    hyper.tls._context.check_hostname = False
-    hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
+def get_socket(port: int) -> socket.socket:
+    """Create a TLS-wrapped socket.
+
+    :param port: The port to connect to.
+
+    :returns: A TLS-wrapped socket.
+    """
+
+    SERVER_NAME = 'localhost'
+    SERVER_PORT = port
+
+    # generic socket and ssl configuration
+    socket.setdefaulttimeout(15)
+
+    # Configure an ssl client side context which will not check the server's 
certificate.
+    ctx = ssl.create_default_context()
+    ctx.check_hostname = False
+    ctx.verify_mode = ssl.CERT_NONE
+    ctx.set_alpn_protocols(['h2'])
+
+    # open a socket to the server and initiate TLS/SSL
+    tls_socket = socket.create_connection((SERVER_NAME, SERVER_PORT))
+    tls_socket = ctx.wrap_socket(tls_socket, server_hostname=SERVER_NAME)
+    return tls_socket
+
+
+def makerequest(port: int, path: str, delay: int) -> None:
+    """Establish an HTTP/2 connection and send a request.
+
+    :param port: The port to connect to.
+    :param path: The path to request.
+    :param delay: The delay to wait between sending requests in a stream.
+    """
+
+    tls_socket = get_socket(port)
 
-    conn = HTTPConnection('localhost:{0}'.format(port), secure=True)
+    h2_connection = h2.connection.H2Connection()
+    h2_connection.initiate_connection()
+    tls_socket.sendall(h2_connection.data_to_send())
 
+    headers = [
+        (':method', 'GET'),
+        (':path', path),
+        (':authority', 'localhost'),
+        (':scheme', 'https'),
+    ]
+
+    h2_connection.send_headers(1, headers, end_stream=True)
+    tls_socket.sendall(h2_connection.data_to_send())
+
+    # delay, triggering ATS timeout.
+    time.sleep(delay)
+
+    # The following should fail due to the timeout.
     try:
-        # delay after sending the first request
-        # so the H2 session active timeout triggers
-        # Then the next request should fail
-        req_id = conn.request('GET', '/')
-        time.sleep(active_timeout)
-        response = conn.get_response(req_id)
-        req_id = conn.request('GET', '/')
-        response = conn.get_response(req_id)
-    except Exception:
-        print('CONNECTION_TIMEOUT')
-        return
+        # Send a second request.
+        h2_connection.send_headers(3, headers, end_stream=True)
+        tls_socket.sendall(h2_connection.data_to_send())
+
+        response_stream_ended = False
+        body = b''
+        while not response_stream_ended:
+            # read raw data from the socket
+            data = tls_socket.recv(65536 * 1024)
+            if not data:
+                break
+
+            # feed raw data into h2, and process resulting events
+            events = h2_connection.receive_data(data)
+            for event in events:
+                if isinstance(event, h2.events.ResponseReceived):
+                    # response headers received
+                    print("Response received:")
+                    for header in event.headers:
+                        print(f'  {header[0].decode()}: {header[1].decode()}')
+                if isinstance(event, h2.events.DataReceived):
+                    # update flow control so the server doesn't starve us
+                    
h2_connection.acknowledge_received_data(event.flow_controlled_length, 
event.stream_id)
+                    # more response body data received
+                    body += event.data
+                if isinstance(event, h2.events.StreamEnded):
+                    # response body completed, let's exit the loop
+                    response_stream_ended = True
+                    break
+            # send any pending data to the server
+            tls_socket.sendall(h2_connection.data_to_send())
 
-    print('NO_TIMEOUT')
+        print(f"Response fully received: {len(body)} bytes")
+
+        body_str = body.decode('utf-8')
+
+        # tell the server we are closing the h2 connection
+        h2_connection.close_connection()
+        tls_socket.sendall(h2_connection.data_to_send())
+
+        # close the socket
+        tls_socket.close()
+    except Exception:
+        print("CONNECTION_TIMEOUT")
 
 
 def main():
     parser = argparse.ArgumentParser()
-    parser.add_argument("--port", "-p",
+    parser.add_argument("port",
                         type=int,
                         help="Port to use")
-    parser.add_argument("--delay", "-d",
+    parser.add_argument("path",
+                        help="The path to request")
+    parser.add_argument("delay",
                         type=int,
-                        help="Time to delay in seconds")
+                        help="The number of seconds to delay betwen requests 
in a stream")
     args = parser.parse_args()
-    makerequest(args.port, args.delay)
+
+    makerequest(args.port, args.path, args.delay)
 
 
 if __name__ == '__main__':
diff --git a/tests/gold_tests/h2/h2bigclient.py 
b/tests/gold_tests/h2/h2bigclient.py
deleted file mode 100644
index ab73da24e0..0000000000
--- a/tests/gold_tests/h2/h2bigclient.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-
-'''
-'''
-#  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 hyper import HTTPConnection
-import hyper
-import argparse
-
-
-def getResponseString(response):
-    typestr = str(type(response))
-    if typestr.find('HTTP20') != -1:
-        string = "HTTP/2 {0}\r\n".format(response.status)
-    else:
-        string = "HTTP {0}\r\n".format(response.status)
-    string += 'date: ' + response.headers.get('date')[0].decode('utf-8') + 
"\r\n"
-    string += 'server: ' + response.headers.get('Server')[0].decode('utf-8') + 
"\r\n"
-    return string
-
-
-def makerequest(port):
-    hyper.tls._context = hyper.tls.init_context()
-    hyper.tls._context.check_hostname = False
-    hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
-
-    conn = HTTPConnection('localhost:{0}'.format(port), secure=True)
-
-    # Fetch the object twice so we know at least one time comes from cache
-    # Exploring timing options
-    sites = ['/bigfile', '/bigfile']
-    request_ids = []
-    for site in sites:
-        request_id = conn.request('GET', url=site)
-        request_ids.append(request_id)
-
-    # get responses
-    for req_id in request_ids:
-        response = conn.get_response(req_id)
-        body = response.read()
-        cl = response.headers.get('Content-Length')[0]
-        print("Content length = {}\r\n".format(int(cl)))
-        print("Body length = {}\r\n".format(len(body)))
-        error = 0
-        if chr(body[0]) != 'a':
-            error = 1
-            print("First char {}".format(body[0]))
-        i = 1
-        while i < len(body) and not error:
-            error = chr(body[i]) != 'b'
-            if error:
-                print("bad char {} at {}".format(body[i], i))
-            i = i + 1
-        if not error:
-            print("Content success\r\n")
-        else:
-            print("Content fail\r\n")
-
-
-def main():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--port", "-p",
-                        type=int,
-                        help="Port to use")
-    args = parser.parse_args()
-    makerequest(args.port)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/tests/gold_tests/h2/h2chunked.py b/tests/gold_tests/h2/h2chunked.py
deleted file mode 100644
index 975276115f..0000000000
--- a/tests/gold_tests/h2/h2chunked.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/env python3
-
-'''
-'''
-#  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 hyper import HTTPConnection
-import hyper
-import argparse
-
-
-def getResponseString(response):
-    typestr = str(type(response))
-    if typestr.find('HTTP20') != -1:
-        string = "HTTP/2 {0}\r\n".format(response.status)
-    else:
-        string = "HTTP {0}\r\n".format(response.status)
-    string += 'date: ' + response.headers.get('date')[0].decode('utf-8') + 
"\r\n"
-    string += 'server: ' + response.headers.get('Server')[0].decode('utf-8') + 
"\r\n"
-    return string
-
-
-def makerequest(port, _url):
-    hyper.tls._context = hyper.tls.init_context()
-    hyper.tls._context.check_hostname = False
-    hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
-
-    conn = HTTPConnection('localhost:{0}'.format(port), secure=True)
-
-    sites = {'/'}
-    request_ids = []
-    for _ in sites:
-        request_id = conn.request('GET', url=_url)
-        request_ids.append(request_id)
-
-    # get responses
-    for req_id in request_ids:
-        response = conn.get_response(req_id)
-        body = response.read()
-        print(getResponseString(response))
-        print(body.decode('utf-8'))
-
-
-def main():
-    parser = argparse.ArgumentParser()
-    parser.add_argument("--port", "-p",
-                        type=int,
-                        help="Port to use")
-    parser.add_argument("--url", "-u",
-                        type=str,
-                        help="url")
-    args = parser.parse_args()
-    makerequest(args.port, args.url)
-
-
-if __name__ == '__main__':
-    main()
diff --git a/tests/gold_tests/h2/h2client.py b/tests/gold_tests/h2/h2client.py
index b3599cf6d4..412a2e546d 100644
--- a/tests/gold_tests/h2/h2client.py
+++ b/tests/gold_tests/h2/h2client.py
@@ -1,6 +1,7 @@
 #!/usr/bin/env python3
 
 '''
+A basic, ad-hoc HTTP/2 client.
 '''
 #  Licensed to the Apache Software Foundation (ASF) under one
 #  or more contributor license agreements.  See the NOTICE file
@@ -18,48 +19,146 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 
-from hyper import HTTPConnection
-import hyper
+import socket
+import ssl
+
+import h2.connection
+import h2.events
+
 import argparse
 
 
-def getResponseString(response):
-    typestr = str(type(response))
-    if typestr.find('HTTP20') != -1:
-        string = "HTTP/2 {0}\r\n".format(response.status)
-    else:
-        string = "HTTP {0}\r\n".format(response.status)
-    string += 'date: ' + response.headers.get('date')[0].decode('utf-8') + 
"\r\n"
-    string += 'server: ' + response.headers.get('Server')[0].decode('utf-8') + 
"\r\n"
-    return string
+def get_socket(port: int) -> socket.socket:
+    """Create a TLS-wrapped socket.
+
+    :param port: The port to connect to.
+
+    :returns: A TLS-wrapped socket.
+    """
+
+    SERVER_NAME = 'localhost'
+    SERVER_PORT = port
+
+    # generic socket and ssl configuration
+    socket.setdefaulttimeout(15)
+
+    # Configure an ssl client side context which will not check the server's 
certificate.
+    ctx = ssl.create_default_context()
+    ctx.check_hostname = False
+    ctx.verify_mode = ssl.CERT_NONE
+    ctx.set_alpn_protocols(['h2'])
+
+    # open a socket to the server and initiate TLS/SSL
+    tls_socket = socket.create_connection((SERVER_NAME, SERVER_PORT))
+    tls_socket = ctx.wrap_socket(tls_socket, server_hostname=SERVER_NAME)
+    return tls_socket
+
+
+def makerequest(port: int, path: str, verify_default_body: bool, print_body: 
bool) -> None:
+    """Establish an HTTP/2 connection and send a request.
 
+    :param port: The port to connect to.
+    :param path: The path to request.
+    :param verify_default_body: Whether to verify the default response body.
+    :param print_body: Whether to print the response body.
+    """
 
-def makerequest(port):
-    hyper.tls._context = hyper.tls.init_context()
-    hyper.tls._context.check_hostname = False
-    hyper.tls._context.verify_mode = hyper.compat.ssl.CERT_NONE
+    tls_socket = get_socket(port)
 
-    conn = HTTPConnection('localhost:{0}'.format(port), secure=True)
+    h2_connection = h2.connection.H2Connection()
+    h2_connection.initiate_connection()
+    tls_socket.sendall(h2_connection.data_to_send())
 
-    sites = {'/'}
-    request_ids = []
-    for site in sites:
-        request_id = conn.request('GET', url=site)
-        request_ids.append(request_id)
+    headers = [
+        (':method', 'GET'),
+        (':path', path),
+        (':authority', 'localhost'),
+        (':scheme', 'https'),
+    ]
 
-    # get responses
-    for req_id in request_ids:
-        response = conn.get_response(req_id)
-        print(getResponseString(response))
+    h2_connection.send_headers(1, headers, end_stream=True)
+    tls_socket.sendall(h2_connection.data_to_send())
+
+    response_stream_ended = False
+    body = b''
+    while not response_stream_ended:
+        # read raw data from the socket
+        data = tls_socket.recv(65536 * 1024)
+        if not data:
+            break
+
+        # feed raw data into h2, and process resulting events
+        events = h2_connection.receive_data(data)
+        for event in events:
+            if isinstance(event, h2.events.ResponseReceived):
+                # response headers received
+                print("Response received:")
+                for header in event.headers:
+                    print(f'  {header[0].decode()}: {header[1].decode()}')
+            if isinstance(event, h2.events.DataReceived):
+                # update flow control so the server doesn't starve us
+                
h2_connection.acknowledge_received_data(event.flow_controlled_length, 
event.stream_id)
+                # more response body data received
+                body += event.data
+            if isinstance(event, h2.events.StreamEnded):
+                # response body completed, let's exit the loop
+                response_stream_ended = True
+                break
+        # send any pending data to the server
+        tls_socket.sendall(h2_connection.data_to_send())
+
+    print(f"Response fully received: {len(body)} bytes")
+
+    body_str = body.decode('utf-8')
+
+    if print_body:
+        print(body_str)
+
+    if verify_default_body:
+        body_ok = True
+        if len(body_str) > 0:
+            if body_str[0] != 'a':
+                print("ERROR: First byte of response body is not 'a'")
+                body_ok = False
+            for i in range(1, len(body_str)):
+                if body_str[i] != 'b':
+                    print(f"ERROR: Byte {i} of response body is not 'b'")
+                    body_ok = False
+                    break
+        if body_ok:
+            print("Content success")
+        else:
+            print("Content failure")
+
+    # tell the server we are closing the h2 connection
+    h2_connection.close_connection()
+    tls_socket.sendall(h2_connection.data_to_send())
+
+    # close the socket
+    tls_socket.close()
 
 
 def main():
     parser = argparse.ArgumentParser()
-    parser.add_argument("--port", "-p",
+    parser.add_argument("port",
                         type=int,
                         help="Port to use")
+    parser.add_argument("path",
+                        help="The path to request")
+    parser.add_argument("--repeat",
+                        type=int,
+                        default=1,
+                        help="Number of times to repeat the request")
+    parser.add_argument("--verify_default_body",
+                        action="store_true",
+                        help="Verify the default body content: abbb...")
+    parser.add_argument("--print_body",
+                        action="store_true",
+                        help="Print the response body")
     args = parser.parse_args()
-    makerequest(args.port)
+
+    for i in range(args.repeat):
+        makerequest(args.port, args.path, args.verify_default_body, 
args.print_body)
 
 
 if __name__ == '__main__':
diff --git a/tests/gold_tests/h2/http2.test.py 
b/tests/gold_tests/h2/http2.test.py
index 38476191d6..6f33d4cd53 100644
--- a/tests/gold_tests/h2/http2.test.py
+++ b/tests/gold_tests/h2/http2.test.py
@@ -135,8 +135,6 @@ ts.Disk.records_config.update({
 })
 
 ts.Setup.CopyAs('h2client.py', Test.RunDirectory)
-ts.Setup.CopyAs('h2bigclient.py', Test.RunDirectory)
-ts.Setup.CopyAs('h2chunked.py', Test.RunDirectory)
 ts.Setup.CopyAs('h2active_timeout.py', Test.RunDirectory)
 
 # ----
@@ -145,7 +143,7 @@ ts.Setup.CopyAs('h2active_timeout.py', Test.RunDirectory)
 
 # Test Case 1:  basic H2 interaction
 tr = Test.AddTestRun()
-tr.Processes.Default.Command = f'{sys.executable} h2client.py -p 
{ts.Variables.ssl_port}'
+tr.Processes.Default.Command = f'{sys.executable} h2client.py 
{ts.Variables.ssl_port} / --verify_default_body'
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.StartBefore(server)
 tr.Processes.Default.StartBefore(Test.Processes.ts)
@@ -154,14 +152,14 @@ tr.StillRunningAfter = server
 
 # Test Case 2: Make sure all the big file gets back.  Regression test for 
issue 1646
 tr = Test.AddTestRun()
-tr.Processes.Default.Command = f'{sys.executable} h2bigclient.py -p 
{ts.Variables.ssl_port}'
+tr.Processes.Default.Command = f'{sys.executable} h2client.py 
{ts.Variables.ssl_port} /bigfile --repeat 2 --verify_default_body'
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.Streams.stdout = "gold/bigfile.gold"
 tr.StillRunningAfter = server
 
 # Test Case 3: Chunked content
 tr = Test.AddTestRun()
-tr.Processes.Default.Command = f'{sys.executable} h2chunked.py -p 
{ts.Variables.ssl_port}  -u /test2'
+tr.Processes.Default.Command = f'{sys.executable} h2client.py 
{ts.Variables.ssl_port} /test2 --print_body'
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.Streams.stdout = "gold/chunked.gold"
 tr.StillRunningAfter = server
@@ -179,7 +177,7 @@ tr.StillRunningAfter = server
 
 # Test Case 5: h2_active_timeout
 tr = Test.AddTestRun()
-tr.Processes.Default.Command = f'{sys.executable} h2active_timeout.py -p 
{ts.Variables.ssl_port} -d 4'
+tr.Processes.Default.Command = f'{sys.executable} h2active_timeout.py 
{ts.Variables.ssl_port} / 4'
 tr.Processes.Default.ReturnCode = 0
 tr.Processes.Default.Streams.All = "gold/active_timeout.gold"
 tr.StillRunningAfter = server
diff --git a/tests/gold_tests/h2/httpbin.test.py 
b/tests/gold_tests/h2/httpbin.test.py
index 147b6551f3..ef9066c7be 100644
--- a/tests/gold_tests/h2/httpbin.test.py
+++ b/tests/gold_tests/h2/httpbin.test.py
@@ -96,7 +96,8 @@ test_run.Processes.Default.Streams.stdout = 
"gold/httpbin_0_stdout.gold"
 test_run.Processes.Default.Streams.stderr = 
Testers.GoldFile("gold/httpbin_0_stderr.gold", case_insensitive=True)
 test_run.StillRunningAfter = httpbin
 
-# Test Case 1: Empty response body
+# Test Case 1: Attempt an empty response body.
+# This test case requires [email protected] or later.
 test_run = Test.AddTestRun()
 test_run.Processes.Default.Command = 'curl -vs -k --http2 
https://127.0.0.1:{0}/bytes/0'.format(ts.Variables.ssl_port)
 test_run.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/headers/gold/bad_method.gold 
b/tests/gold_tests/headers/gold/bad_method.gold
index 3a9558b1cd..635506f6c9 100644
--- a/tests/gold_tests/headers/gold/bad_method.gold
+++ b/tests/gold_tests/headers/gold/bad_method.gold
@@ -1,23 +1,17 @@
 HTTP/1.1 501 Unsupported method ('gET')
 Content-Type: text/html;charset=utf-8
-Content-Length: 496
+Content-Length: ``
 Date: ``
 Age: 0
 Connection: keep-alive
 Server: ATS/``
 
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
-        "http://www.w3.org/TR/html4/strict.dtd";>
-<html>
-    <head>
-        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
-        <title>Error response</title>
-    </head>
+``
     <body>
         <h1>Error response</h1>
         <p>Error code: 501</p>
         <p>Message: Unsupported method ('gET').</p>
-        <p>Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does 
not support this operation.</p>
+        <p>``
     </body>
 </html>
 HTTP/1.1 200 OK
diff --git a/tests/gold_tests/pluginTest/tsapi/test_tsapi.cc 
b/tests/gold_tests/pluginTest/tsapi/test_tsapi.cc
index a3aad5b45d..447d344428 100644
--- a/tests/gold_tests/pluginTest/tsapi/test_tsapi.cc
+++ b/tests/gold_tests/pluginTest/tsapi/test_tsapi.cc
@@ -242,6 +242,22 @@ globalContFunc(TSCont, TSEvent event, void *eventData)
   return 0;
 }
 
+static int
+shutdown_handler(TSCont contp, TSEvent event, void *edata)
+{
+  if (event != TS_EVENT_LIFECYCLE_SHUTDOWN) {
+    return 0;
+  }
+  TSDebug(PIName, "Cleaning up global continuations.");
+  if (tCont) {
+    TSContDestroy(tCont);
+  }
+  if (gCont) {
+    TSContDestroy(gCont);
+  }
+  return 0;
+}
+
 } // end anonymous namespace
 
 TSReturnCode
@@ -286,6 +302,8 @@ TSRemapInit(TSRemapInterface *api_info, char *errbuf, int 
errbuf_size)
   TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, gCont);
 
   tCont = TSContCreate(transactionContFunc, mtx);
+
+  TSLifecycleHookAdd(TS_LIFECYCLE_SHUTDOWN_HOOK, 
TSContCreate(shutdown_handler, nullptr));
   return TS_SUCCESS;
 }
 
@@ -331,27 +349,3 @@ TSRemapDoRemap(void *instance, TSHttpTxn txnp, 
TSRemapRequestInfo *rri)
 
   return TSREMAP_NO_REMAP;
 }
-
-namespace
-{
-class Cleanup
-{
-public:
-  ~Cleanup()
-  {
-    // In practice it is not strictly necessary to destroy remaining 
continuations on program exit.
-
-    if (tCont) {
-      TSContDestroy(tCont);
-    }
-    if (gCont) {
-      TSContDestroy(gCont);
-    }
-  }
-};
-
-// Do any needed cleanup for this source file at program termination time.
-//
-Cleanup cleanup;
-
-} // end anonymous namespace
diff --git a/tests/gold_tests/pluginTest/tsapi/tsapi.test.py 
b/tests/gold_tests/pluginTest/tsapi/tsapi.test.py
index b992609e39..3ccfe84165 100644
--- a/tests/gold_tests/pluginTest/tsapi/tsapi.test.py
+++ b/tests/gold_tests/pluginTest/tsapi/tsapi.test.py
@@ -73,6 +73,13 @@ ts.Disk.remap_config.AddLine(
     "map https://myhost.test:123 http://127.0.0.1:{0} @plugin={1} 
@plugin={1}".format(server.Variables.Port, f"{plugin_name}.so")
 )
 
+# For some reason, without this delay, traffic_server cannot reliably open the 
cleartext port for listening without an
+# error.
+#
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = "sleep 3"
+tr.Processes.Default.ReturnCode = 0
+
 tr = Test.AddTestRun()
 # Probe server port to check if ready.
 tr.Processes.Default.StartBefore(server, 
ready=When.PortOpen(server.Variables.Port))
diff --git a/tests/gold_tests/post/post-continue.test.py 
b/tests/gold_tests/post/post-continue.test.py
index 82fc8f731d..d6d74859a8 100644
--- a/tests/gold_tests/post/post-continue.test.py
+++ b/tests/gold_tests/post/post-continue.test.py
@@ -33,7 +33,8 @@ Test.ContinueOnFail = True
 # ----
 # Setup httpbin Origin Server
 # ----
-httpbin = Test.MakeHttpBinServer("httpbin")
+replay_file = "replay/post-continue.replay.yaml"
+server = Test.MakeVerifierServerProcess("server", replay_file)
 
 # ----
 # Setup ATS
@@ -47,7 +48,7 @@ ts.addDefaultSSLFiles()
 ts2.addDefaultSSLFiles()
 
 ts.Disk.remap_config.AddLine(
-    'map / http://127.0.0.1:{0}'.format(httpbin.Variables.Port)
+    'map / http://127.0.0.1:{0}'.format(server.Variables.http_port)
 )
 ts.Disk.ssl_multicert_config.AddLine(
     'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
@@ -60,7 +61,7 @@ ts.Disk.records_config.update({
 
 })
 ts2.Disk.remap_config.AddLine(
-    'map / http://127.0.0.1:{0}'.format(httpbin.Variables.Port)
+    'map / http://127.0.0.1:{0}'.format(server.Variables.http_port)
 )
 ts2.Disk.ssl_multicert_config.AddLine(
     'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key'
@@ -79,165 +80,165 @@ big_post_body_file.write(big_post_body)
 big_post_body_file.close()
 
 test_run = Test.AddTestRun("http1.1 POST small body with Expect header")
-test_run.Processes.Default.StartBefore(httpbin, 
ready=When.PortOpen(httpbin.Variables.Port))
-test_run.Processes.Default.StartBefore(Test.Processes.ts)
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: 100-continue" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.StartBefore(server)
+test_run.Processes.Default.StartBefore(ts)
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: 100-continue" -d "small body" -k 
https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
-test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 Continue", "Has Expect header")
+test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("Expect: 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http1.1 POST large body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: 100-continue" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: 100-continue" -d @big_post_body -k 
https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
-test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 Continue", "Has Expect header")
+test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("Expect: 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http1.1 POST small body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect:" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect:" -d "small body" -k https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
-test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 Continue", "Does not have Expect header")
+test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 continue", "Does not have Expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("Expect: 
100-continue", "Does not have Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http1.1 POST large body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
-test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 Continue", "Does not have Expect header")
+test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 continue", "Does not have Expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("Expect: 
100-continue", "Does not have Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http2 POST small body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
100-continue" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: 100-continue" -d "small body" -k 
https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http2 POST large body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
100-continue" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: 100-continue" -d @big_post_body -k 
https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http2 POST small body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: " -d "small body" -k https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 test_run = Test.AddTestRun("http2 POST large body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
     ts.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts
 test_run.Processes.Default.ReturnCode = 0
 
 # Do them all again against the TS that will return 100-continue immediately
-test_run = Test.AddTestRun("http1.1 POST small body with Expect header")
+test_run = Test.AddTestRun("http1.1 POST small body with Expect header, 
immediate")
 test_run.Processes.Default.StartBefore(Test.Processes.ts2)
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: 100-continue" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: 100-continue" -d "small body" -k 
https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 Continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("Expect: 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http1.1 POST large body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: 100-continue" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http1.1 POST large body with Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: 100-continue" -d @big_post_body -k 
https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/1.1 
100 Continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("Expect: 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http1.1 POST small body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect:" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http1.1 POST small body w/o Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect:" -d "small body" -k https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 Continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("Expect 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http1.1 POST large body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H 
"Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http1.1 POST large body w/o Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http1.1 -H "uuid: 
post" -H "Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h1.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/1.1 
100 Continue", "Has Expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("Expect 
100-continue", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http2 POST small body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
100-continue" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http2 POST small body with Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: 100-continue" -d "small body" -k 
https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http2 POST large body with Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
100-continue" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http2 POST large body with Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: 100-continue" -d @big_post_body -k 
https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ContainsExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http2 POST small body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
" -d "small body" -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http2 POST small body w/o Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: " -d "small body" -k https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
 
-test_run = Test.AddTestRun("http2 POST large body w/o Expect header")
-test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "Expect: 
" -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
+test_run = Test.AddTestRun("http2 POST large body w/o Expect header, 
immediate")
+test_run.Processes.Default.Command = 'curl -v -o /dev/null --http2 -H "uuid: 
post" -H "Expect: " -d @big_post_body -k https://127.0.0.1:{0}/post'.format(
     ts2.Variables.ssl_port)
 test_run.Processes.Default.Streams.All = "gold/post-h2.gold"
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("xpect: 
100-continue", "Has expect header")
 test_run.Processes.Default.Streams.All += Testers.ExcludesExpression("HTTP/2 
100", "Has Expect header")
-test_run.StillRunningAfter = httpbin
+test_run.StillRunningAfter = server
 test_run.StillRunningAfter = ts2
 test_run.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/tls/test-nc-s_client.sh 
b/tests/gold_tests/post/replay/post-continue.replay.yaml
similarity index 54%
copy from tests/gold_tests/tls/test-nc-s_client.sh
copy to tests/gold_tests/post/replay/post-continue.replay.yaml
index 8aaf119298..884e25ff4f 100644
--- a/tests/gold_tests/tls/test-nc-s_client.sh
+++ b/tests/gold_tests/post/replay/post-continue.replay.yaml
@@ -1,5 +1,3 @@
-#!/bin/bash
-
 #  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
@@ -15,5 +13,31 @@
 #  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.
-nc -l -p $1 -c 'echo -e "This is a reply"' -o test.out &
-echo "This is a test" | openssl s_client -servername bar.com -connect 
localhost:$2 -ign_eof
+
+#
+# This replay file assumes that caching is enabled and
+# proxy.config.http.cache.ignore_server_no_cache is set to 1(meaning the
+# cache-control directives in responses to bypass the cache is ignored)
+meta:
+  version: "1.0"
+
+sessions:
+  - transactions:
+      # The client is actually curl
+      - client-request:
+          method: "POST"
+          version: "1.1"
+          headers:
+            fields:
+              - [uuid, post]
+              - [Expect, 100-continue]
+
+        proxy-request:
+          method: "POST"
+
+        server-response:
+          status: 200
+          reason: OK
+          headers:
+            fields:
+              - [Content-Length, 4]
diff --git a/tests/gold_tests/proxy_protocol/gold/test_case_0_stderr.gold 
b/tests/gold_tests/proxy_protocol/gold/test_case_0_stderr.gold
index f7ae430791..d613cd8957 100644
--- a/tests/gold_tests/proxy_protocol/gold/test_case_0_stderr.gold
+++ b/tests/gold_tests/proxy_protocol/gold/test_case_0_stderr.gold
@@ -4,7 +4,10 @@
 > User-Agent: curl/``
 ``
 < HTTP/1.1 200 OK
-< Server: ATS/``
+``
 < Date: ``
+``
 < Age: ``
 ``
+< Server: ATS/``
+``
diff --git a/tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold 
b/tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold
index 1039295033..d9314bdabe 100644
--- a/tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold
+++ b/tests/gold_tests/proxy_protocol/gold/test_case_0_stdout.gold
@@ -2,7 +2,9 @@
 ``
   "headers": {
 ``
-    "Forwarded": "for=127.0.0.1;proto=http",
+    "Forwarded": [
+      "for=127.0.0.1;proto=http"
+    ],
 ``
   },
 ``
diff --git a/tests/gold_tests/proxy_protocol/gold/test_case_1_stderr.gold 
b/tests/gold_tests/proxy_protocol/gold/test_case_1_stderr.gold
index f7ae430791..d613cd8957 100644
--- a/tests/gold_tests/proxy_protocol/gold/test_case_1_stderr.gold
+++ b/tests/gold_tests/proxy_protocol/gold/test_case_1_stderr.gold
@@ -4,7 +4,10 @@
 > User-Agent: curl/``
 ``
 < HTTP/1.1 200 OK
-< Server: ATS/``
+``
 < Date: ``
+``
 < Age: ``
 ``
+< Server: ATS/``
+``
diff --git a/tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold 
b/tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold
index b219208c79..3fc45653cc 100644
--- a/tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold
+++ b/tests/gold_tests/proxy_protocol/gold/test_case_1_stdout.gold
@@ -2,7 +2,9 @@
 ``
   "headers": {
 ``
-    "Forwarded": "for=127.0.0.1;proto=https",
+    "Forwarded": [
+      "for=127.0.0.1;proto=https"
+    ],
 ``
   },
 ``
diff --git a/tests/gold_tests/tls/test-nc-s_client.sh 
b/tests/gold_tests/tls/test-nc-s_client.sh
index 8aaf119298..f08574e045 100644
--- a/tests/gold_tests/tls/test-nc-s_client.sh
+++ b/tests/gold_tests/tls/test-nc-s_client.sh
@@ -15,5 +15,13 @@
 #  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.
-nc -l -p $1 -c 'echo -e "This is a reply"' -o test.out &
-echo "This is a test" | openssl s_client -servername bar.com -connect 
localhost:$2 -ign_eof
+
+
+# See https://github.com/apache/trafficserver/issues/9880
+ignore_unexpecte_eof=''
+if openssl s_client --help 2>&1 | grep -q ignore_unexpected_eof
+then
+  ignore_unexpected_eof='-ignore_unexpected_eof'
+fi
+nc -l -p "$1" -c 'echo -e "This is a reply"' -o test.out &
+echo "This is a test" | openssl s_client -servername bar.com -connect 
"localhost:$2" -ign_eof ${ignore_unexpected_eof} "${@:3}"
diff --git a/tests/gold_tests/tls/tls_client_versions.test.py 
b/tests/gold_tests/tls/tls_client_versions.test.py
index cd46ec0d8c..62e66eca8f 100644
--- a/tests/gold_tests/tls/tls_client_versions.test.py
+++ b/tests/gold_tests/tls/tls_client_versions.test.py
@@ -49,7 +49,7 @@ ts.Disk.ssl_multicert_config.AddLine(
 ts.Disk.records_config.update({
     'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir),
     'proxy.config.ssl.server.private_key.path': 
'{0}'.format(ts.Variables.SSLDir),
-    'proxy.config.ssl.server.cipher_suite': 
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2',
+    'proxy.config.ssl.server.cipher_suite': 
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2:@SECLEVEL=0',
     'proxy.config.ssl.client.CA.cert.path': '{0}'.format(ts.Variables.SSLDir),
     'proxy.config.url_remap.pristine_host_hdr': 1,
     'proxy.config.ssl.TLSv1': 0,
diff --git a/tests/gold_tests/tls/tls_forward_nonhttp.test.py 
b/tests/gold_tests/tls/tls_forward_nonhttp.test.py
index d3bd6a8b5f..7b96d71ace 100644
--- a/tests/gold_tests/tls/tls_forward_nonhttp.test.py
+++ b/tests/gold_tests/tls/tls_forward_nonhttp.test.py
@@ -64,7 +64,10 @@ ts.Disk.sni_yaml.AddLines([
 
 tr = Test.AddTestRun("forward-non-http")
 tr.Setup.Copy("test-nc-s_client.sh")
-tr.Processes.Default.Command = "sh test-nc-s_client.sh {1} 
{0}".format(ts.Variables.ssl_port, ts.Variables.s_client_port)
+cmd_args = ["sh", "test-nc-s_client.sh", str(ts.Variables.s_client_port), 
str(ts.Variables.ssl_port)]
+if Condition.HasOpenSSLVersion("3.0.0"):
+    cmd_args += ["-ignore_unexpected_eof"]
+tr.Processes.Default.Command = " ".join(cmd_args)
 tr.ReturnCode = 0
 tr.Processes.Default.StartBefore(nameserver)
 tr.Processes.Default.StartBefore(Test.Processes.ts)
diff --git a/tests/gold_tests/tls/tls_verify_override.test.py 
b/tests/gold_tests/tls/tls_verify_override.test.py
index 8e906d3856..3f4a895f53 100644
--- a/tests/gold_tests/tls/tls_verify_override.test.py
+++ b/tests/gold_tests/tls/tls_verify_override.test.py
@@ -73,7 +73,7 @@ ts.Disk.remap_config.AddLine(
     'map http://bar.com/overridesignature https://bar.com:{0} 
@plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.properties=SIGNATURE 
@plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
         server_foo.Variables.SSL_Port))
 ts.Disk.remap_config.AddLine(
-    'map http://bar.com/overridenone https://bar.com:{0} @plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.properties=NONE 
@plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED"'.format(
+    'map http://bar.com/overridenone https://bar.com:{0} @plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.properties=NONE 
@plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
         server_foo.Variables.SSL_Port))
 ts.Disk.remap_config.AddLine(
     'map http://bar.com/overrideenforced https://bar.com:{0} 
@plugin=conf_remap.so 
@pparam=proxy.config.ssl.client.verify.server.policy=ENFORCED'.format(
@@ -252,7 +252,7 @@ tr.Processes.Default.Streams.stdout = 
Testers.ExcludesExpression("Could not conn
 
 # checks on random.com should fail with message only
 ts.Disk.diags_log.Content = Testers.ContainsExpression(
-    r"WARNING: Core server certificate verification failed for \(random.com\). 
Action=Continue Error=self signed certificate server=random.com\(127.0.0.1\) 
depth=0",
+    r"WARNING: Core server certificate verification failed for \(random.com\). 
Action=Continue Error=self.signed certificate server=random.com\(127.0.0.1\) 
depth=0",
     "Warning for self signed certificate")
 # permissive failure for bar.com
 ts.Disk.diags_log.Content += Testers.ContainsExpression(
diff --git a/tests/gold_tests/tls/tls_verify_override_base.test.py 
b/tests/gold_tests/tls/tls_verify_override_base.test.py
index 0495ec54b7..7d78971fbe 100644
--- a/tests/gold_tests/tls/tls_verify_override_base.test.py
+++ b/tests/gold_tests/tls/tls_verify_override_base.test.py
@@ -239,7 +239,7 @@ tr.Processes.Default.Streams.stdout = 
Testers.ExcludesExpression("Could not conn
 
 # checks on random.com should fail with message only
 ts.Disk.diags_log.Content = Testers.ContainsExpression(
-    r"WARNING: Core server certificate verification failed for \(random.com\). 
Action=Continue Error=self signed certificate server=127.0.0.1\(127.0.0.1\) 
depth=0",
+    r"WARNING: Core server certificate verification failed for \(random.com\). 
Action=Continue Error=self.signed certificate server=127.0.0.1\(127.0.0.1\) 
depth=0",
     "Warning for self signed certificate")
 # permissive failure for bar.com
 ts.Disk.diags_log.Content += Testers.ContainsExpression(

Reply via email to