diff --git a/tests/Pipfile b/tests/Pipfile index da0c5dd3aac..87e44ba9103 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 144eeb32032..dcd1787f5b4 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 5be9047289b..45d529f9f25 100644 --- a/tests/gold_tests/cache/background_fill.test.py +++ b/tests/gold_tests/cache/background_fill.test.py @@ -92,7 +92,7 @@ def __testCase0(self): 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 @@ def __testCase1(self): 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 @@ def __testCase2(self): 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 33b04218a98..c114dc4cf45 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 5fd92155bec..55e3daaa870 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 836d51a2884..c09ab52a60f 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 3ed2777919c..4bf3431d7a0 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 8c6bc6cb77e..677e8eeea48 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 e69de29bb2d..cf637de5885 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 c53bba6a7b1..5bd16ccf95e 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 9345ad17fce..d24de922216 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 610580810ce..0a1227adb2a 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 5f7e6ecd5f7..5275ee8321c 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 01659d36c5a..c19d00fcbbd 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 ab73da24e03..00000000000 --- 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 975276115f5..00000000000 --- 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 b3599cf6d41..412a2e546de 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 38476191d61..6f33d4cd530 100644 --- a/tests/gold_tests/h2/http2.test.py +++ b/tests/gold_tests/h2/http2.test.py @@ -135,8 +135,6 @@ }) 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 @@ # 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 @@ # 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 @@ # 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 147b6551f32..ef9066c7be0 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.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 go-httpbin@v2.6.0 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 3a9558b1cd3..635506f6c96 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/`` - - -
- -Error code: 501
Message: Unsupported method ('gET').
-Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.
+`` 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 a3aad5b45df..447d344428f 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 b992609e391..3ccfe84165e 100644 --- a/tests/gold_tests/pluginTest/tsapi/tsapi.test.py +++ b/tests/gold_tests/pluginTest/tsapi/tsapi.test.py @@ -73,6 +73,13 @@ "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 82fc8f731de..d6d74859a83 100644 --- a/tests/gold_tests/post/post-continue.test.py +++ b/tests/gold_tests/post/post-continue.test.py @@ -33,7 +33,8 @@ # ---- # 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 @@ 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 @@ }) 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.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/post/replay/post-continue.replay.yaml b/tests/gold_tests/post/replay/post-continue.replay.yaml new file mode 100644 index 00000000000..884e25ff4f2 --- /dev/null +++ b/tests/gold_tests/post/replay/post-continue.replay.yaml @@ -0,0 +1,43 @@ +# 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. + +# +# 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 f7ae4307911..d613cd8957f 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 10392950339..d9314bdabea 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 f7ae4307911..d613cd8957f 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 b219208c794..3fc45653cc4 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 8aaf1192987..f08574e045e 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 cd46ec0d8cf..62e66eca8ff 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.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 d3bd6a8b5fb..7b96d71ace2 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 @@ 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 8e906d38567..3f4a895f536 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 @@ '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 @@ # 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 0495ec54b78..7d78971fbe8 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 @@ # 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(