diff options
Diffstat (limited to 'components/net/tests/cookie_http_state_utils.py')
-rw-r--r-- | components/net/tests/cookie_http_state_utils.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/components/net/tests/cookie_http_state_utils.py b/components/net/tests/cookie_http_state_utils.py new file mode 100644 index 00000000000..b8820c312da --- /dev/null +++ b/components/net/tests/cookie_http_state_utils.py @@ -0,0 +1,174 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +import subprocess +import tempfile + +REPO = "https://github.com/abarth/http-state.git" +TEST_FILE = "cookie_http_state.rs" +DOMAIN = "http://home.example.org:8888" +RUST_FN = """ +#[test]{should_panic} +fn test_{name}() {{ + let r = run("{set_location}", + {set_cookies}, + "{location}"); + assert_eq!(&r, "{expect}"); +}} +""" +SET_COOKIES_INDENT = 18 +SHOULD_PANIC = "\n#[should_panic] // Look at cookie_http_state_utils.py if this test fails" + +# Those tests should PASS. But until fixes land in servo, keep them failing +FAILING_TESTS = [ + "0003", # Waiting for a way to clean expired cookies + "0006", # Waiting for a way to clean expired cookies + "mozilla0001", # Waiting for a way to clean expired cookies + "mozilla0002", # Waiting for a way to clean expired cookies + "mozilla0003", # Waiting for a way to clean expired cookies + "mozilla0005", # Waiting for a way to clean expired cookies + "mozilla0007", # Waiting for a way to clean expired cookies + "mozilla0009", # Waiting for a way to clean expired cookies + "mozilla0010", # Waiting for a way to clean expired cookies + "mozilla0013", # Waiting for a way to clean expired cookies +] + + +def list_tests(dir): + suffix = "-test" + + def keep(name): + return name.endswith(suffix) and not name.startswith("disabled") + + tests = [name[:-len(suffix)] for name in os.listdir(dir) if keep(name)] + tests.sort() + return tests + + +def escape(s): + """ Escape the string `s` so that it can be parsed by rust as a valid + UTF-8 string. + We can't use only `encode("unicode_escape")` as it produces things that + rust does not accept ("\\xbf", "\\u6265" for example). So we manually + convert all character whose code point is greater than 128 to + \\u{code_point}. + All other characters are encoded with "unicode_escape" to get escape + sequences ("\\r" for example) except for `"` that we specifically escape + because our string will be quoted by double-quotes. + Lines are also limited in size, so split the string every 70 characters + (gives room for indentation). + """ + res = "" + last_split = 0 + for c in s: + if len(res) - last_split > 70: + res += "\\\n" + last_split = len(res) + o = ord(c) + if o == 34: + res += "\\\"" + continue + if o >= 128: + res += "\\u{" + hex(o)[2:] + "}" + else: + res += c.encode("unicode_escape") + return res + + +def format_slice_cookies(cookies): + esc_cookies = ['"%s"' % escape(c) for c in cookies] + if sum(len(s) for s in esc_cookies) < 80: + sep = ", " + else: + sep = ",\n" + " " * SET_COOKIES_INDENT + return "&[" + sep.join(esc_cookies) + "]" + + +def generate_code_for_test(test_dir, name): + if name in FAILING_TESTS: + should_panic = SHOULD_PANIC + else: + should_panic = "" + + test_file = os.path.join(test_dir, name + "-test") + expect_file = os.path.join(test_dir, name + "-expected") + + set_cookies = [] + set_location = DOMAIN + "/cookie-parser?" + name + expect = "" + location = DOMAIN + "/cookie-parser-result?" + name + + with open(test_file) as fo: + for line in fo: + line = line.decode("utf-8").rstrip() + prefix = "Set-Cookie: " + if line.startswith(prefix): + set_cookies.append(line[len(prefix):]) + prefix = "Location: " + if line.startswith(prefix): + location = line[len(prefix):] + if location.startswith("/"): + location = DOMAIN + location + + with open(expect_file) as fo: + for line in fo: + line = line.decode("utf-8").rstrip() + prefix = "Cookie: " + if line.startswith(prefix): + expect = line[len(prefix):] + + return RUST_FN.format(name=name.replace('-', '_'), + set_location=escape(set_location), + set_cookies=format_slice_cookies(set_cookies), + should_panic=should_panic, + location=escape(location), + expect=escape(expect)) + + +def update_test_file(cachedir): + workdir = os.path.dirname(os.path.realpath(__file__)) + test_file = os.path.join(workdir, TEST_FILE) + + # Create the cache dir + if not os.path.isdir(cachedir): + os.makedirs(cachedir) + + # Clone or update the repo + repo_dir = os.path.join(cachedir, "http-state") + if os.path.isdir(repo_dir): + args = ["git", "pull", "-f"] + process = subprocess.Popen(args, cwd=repo_dir) + if process.wait() != 0: + print("failed to update the http-state git repo") + return 1 + else: + args = ["git", "clone", REPO, repo_dir] + process = subprocess.Popen(args) + if process.wait() != 0: + print("failed to clone the http-state git repo") + return 1 + + # Truncate the unit test file to remove all existing tests + with open(test_file, "r+") as fo: + while True: + line = fo.readline() + if line.strip() == "// Test listing": + fo.truncate() + fo.flush() + break + if line == "": + print("Failed to find listing delimiter on unit test file") + return 1 + + # Append all tests to unit test file + tests_dir = os.path.join(repo_dir, "tests", "data", "parser") + with open(test_file, "a") as fo: + for test in list_tests(tests_dir): + fo.write(generate_code_for_test(tests_dir, test).encode("utf-8")) + + return 0 + +if __name__ == "__main__": + update_test_file(tempfile.gettempdir()) |