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(