diff --git a/integration/test_hurl.py b/integration/test_hurl.py index ee20623a7..c4ca7b590 100755 --- a/integration/test_hurl.py +++ b/integration/test_hurl.py @@ -7,7 +7,7 @@ import subprocess import os import platform import check_json_output -import tempfile +import re def decode_string(encoded): @@ -93,11 +93,35 @@ def test(hurl_file): if os.path.exists(f): expected = open(f, "rb").read() actual = result.stdout - if expected != actual: + if actual != expected: print(">>> error in stdout") print(f"actual: <{actual}>\nexpected: <{expected}>") sys.exit(1) + # stdout with textual pattern / line per line + f = hurl_file.replace(".hurl", ".out.pattern") + if os.path.exists(f): + expected = open(f, "r").read() + actual = decode_string(result.stdout) + expected_lines = expected.split("\n") + expected_pattern_lines = [parse_pattern(line) for line in expected_lines] + actual_lines = actual.split("\n") + if len(actual_lines) != len(expected_pattern_lines): + print(">>> error in stderr / mismatch in number of lines") + print( + "actual: %d lines\nexpected: %d lines" + % (len(actual_lines), len(expected_lines)) + ) + sys.exit(1) + for i in range(len(expected_pattern_lines)): + if not re.match(expected_pattern_lines[i], actual_lines[i]): + print(f">>> error in stdout in line {i+1}") + print(f"actual: <{actual_lines[i]}>") + print( + f"expected: <{expected_lines[i]}> (translated to regex <{expected_pattern_lines[i]}>)" + ) + sys.exit(1) + # stdout (json) if os.path.exists(json_output_file): expected = open(json_output_file).read() @@ -109,7 +133,7 @@ def test(hurl_file): if os.path.exists(f): expected = open(f).read().strip() actual = decode_string(result.stderr).strip() - if expected != actual: + if actual != expected: print(">>> error in stderr") print(f"actual: <{actual}>\nexpected: <{expected}>") sys.exit(1) @@ -123,6 +147,30 @@ def test(hurl_file): print(f"actual: <{actual}>\nexpected: <{expected}>") sys.exit(1) + # stderr with textual pattern / line per line + f = hurl_file.replace(".hurl", ".err.pattern") + if os.path.exists(f): + expected = open(f, "r").read() + actual = decode_string(result.stderr) + expected_lines = expected.split("\n") + expected_pattern_lines = [parse_pattern(line) for line in expected_lines] + actual_lines = re.split(r"\r?\n", actual) + if len(actual_lines) != len(expected_pattern_lines): + print(">>> error in stderr / mismatch in number of lines") + print( + "actual: %d lines\nexpected: %d lines" + % (len(actual_lines), len(expected_lines)) + ) + sys.exit(1) + for i in range(len(expected_pattern_lines)): + if not re.match(expected_pattern_lines[i], actual_lines[i]): + print(f">>> error in stderr in line {i+1}") + print(f"actual: <{actual_lines[i]}>") + print( + f"expected: <{expected_lines[i]}> (translated to regex <{expected_pattern_lines[i]}>)" + ) + sys.exit(1) + # curl output if os.path.exists(curl_file): expected_commands = [] @@ -151,6 +199,16 @@ def test(hurl_file): sys.exit(1) +def parse_pattern(s): + # Escape regex metacharacters + for c in [".", "(", ")", "[", "]", "^", "$", "*", "+", "?"]: + s = s.replace(c, "\\" + c) + + s = re.sub("~+", ".*", s) + s = "^" + s + "$" + return s + + def main(): for hurl_file in sys.argv[1:]: test(hurl_file) diff --git a/integration/tests_ok/include.out b/integration/tests_ok/include.out.pattern similarity index 89% rename from integration/tests_ok/include.out rename to integration/tests_ok/include.out.pattern index 361a0bcf2..bee67ba8e 100644 --- a/integration/tests_ok/include.out +++ b/integration/tests_ok/include.out.pattern @@ -1,7 +1,7 @@ HTTP/1.0 200 -Date: DATE Content-Type: text/html; charset=utf-8 Content-Length: 5 Server: Flask Server +Date: ~~~ Hello \ No newline at end of file diff --git a/integration/tests_ok/include.py b/integration/tests_ok/include.py index 582d5fca9..435c7ec2a 100644 --- a/integration/tests_ok/include.py +++ b/integration/tests_ok/include.py @@ -4,5 +4,4 @@ from flask import Response @app.route("/include") def include(): - headers = {"Date": "DATE"} - return Response("Hello", headers=headers) + return Response("Hello")