diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:14:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:14:29 +0000 |
commit | fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 (patch) | |
tree | 4c1ccaf5486d4f2009f9a338a98a83e886e29c97 /testing/web-platform/tests/tools/wptserve | |
parent | Releasing progress-linux version 124.0.1-1~progress7.99u1. (diff) | |
download | firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.tar.xz firefox-fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8.zip |
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/tools/wptserve')
9 files changed, 146 insertions, 4 deletions
diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.py b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.py new file mode 100644 index 0000000000..c235aeb58a --- /dev/null +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.py @@ -0,0 +1,3 @@ +def main(request, response): + response.headers.set("Content-Type", "text/plain") + return "default" diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.sub.py b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.sub.py new file mode 100644 index 0000000000..32a10d8535 --- /dev/null +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultpy/default.sub.py @@ -0,0 +1,3 @@ +def main(request, response): + response.headers.set("Content-Type", "text/plain") + return "default.sub" diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultsubpy/default.sub.py b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultsubpy/default.sub.py new file mode 100644 index 0000000000..c549100066 --- /dev/null +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/defaultsubpy/default.sub.py @@ -0,0 +1,3 @@ +def main(request, response): + response.headers.set("Content-Type", "text/plain") + return "{{host}}" diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/foo.any.window-module.html b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/foo.any.window-module.html new file mode 100644 index 0000000000..59646e6abd --- /dev/null +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/docroot/foo.any.window-module.html @@ -0,0 +1,8 @@ +<!doctype html> +<meta charset=utf-8> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id=log></div> +<script type=module src="/foo.any.js"></script> diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py index 623a0e5b6a..91b05f4fe4 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_handlers.py @@ -275,6 +275,17 @@ class TestPythonHandler(TestUsingServer): self.assertEqual("text/plain", resp.info()["Content-Type"]) self.assertEqual(b"PASS", resp.read()) + def test_directory(self): + route = ("GET", "/defaultpy", wptserve.handlers.python_script_handler) + self.server.router.register(*route) + resp = self.request("/defaultpy") + self.assertEqual(200, resp.getcode()) + self.assertEqual("text/plain", resp.info()["Content-Type"]) + # default.py returns "default", default.sub.py returns "default.sub". + # Because this should find the first matching default*.py file + # lexicographically sorted, this should have gotten "default". + self.assertEqual(b"default", resp.read()) + def test_no_main(self): with pytest.raises(HTTPError) as cm: self.request("/no_main.py") @@ -325,6 +336,15 @@ class TestAsIsHandler(TestUsingServer): self.assertEqual(b"Content", resp.read()) #Add a check that the response is actually sane + def test_directory_fails(self): + route = ("GET", "/subdir", wptserve.handlers.as_is_handler) + self.server.router.register(*route) + with pytest.raises(HTTPError) as cm: + self.request("/subdir") + + assert cm.value.code == 500 + del cm + class TestH2Handler(TestUsingH2Server): def test_handle_headers(self): @@ -410,6 +430,12 @@ class TestWindowHandler(TestWrapperHandlerUsingServer): self.run_wrapper_test('foo.window.html', 'text/html', serve.WindowHandler) +class TestWindowModulesHandler(TestWrapperHandlerUsingServer): + dummy_files = {'foo.any.js': b'// META: global=window-module\n'} + + def test_any_window_module_html(self): + self.run_wrapper_test('foo.any.window-module.html', + 'text/html', serve.WindowModulesHandler) class TestAnyHtmlHandler(TestWrapperHandlerUsingServer): dummy_files = {'foo.any.js': b'', diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py index beb124d1db..c11577acb5 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_pipes.py @@ -232,6 +232,12 @@ class TestPipesWithVariousHandlers(TestUsingServer): resp = self.request("/document.txt", query="pipe=gzip") self.assertEqual(resp.getcode(), 200) + def test_sub_default_py(self): + route = ("GET", "/defaultsubpy", wptserve.handlers.python_script_handler) + self.server.router.register(*route) + resp = self.request("/defaultsubpy") + self.assertEqual(b"localhost", resp.read()) + if __name__ == '__main__': unittest.main() diff --git a/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py b/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py index 939396ddee..39ef5889be 100644 --- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py +++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_server.py @@ -1,10 +1,15 @@ +import os +import socket +import ssl import unittest +from urllib.error import HTTPError import pytest -from urllib.error import HTTPError + +from localpaths import repo_root wptserve = pytest.importorskip("wptserve") -from .base import TestUsingServer, TestUsingH2Server +from .base import TestUsingH2Server, TestUsingServer, doc_root class TestFileHandler(TestUsingServer): @@ -60,6 +65,65 @@ class TestRequestHandler(TestUsingServer): self.assertEqual(200, resp.getcode()) +class TestH1TLSHandshake(TestUsingServer): + def setUp(self): + self.server = wptserve.server.WebTestHttpd( + host="localhost", + port=0, + use_ssl=True, + key_file=os.path.join(repo_root, "tools", "certs", "web-platform.test.key"), + certificate=os.path.join( + repo_root, "tools", "certs", "web-platform.test.pem" + ), + doc_root=doc_root, + ) + self.server.start() + + def test_no_handshake(self): + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.load_verify_locations( + os.path.join(repo_root, "tools", "certs", "cacert.pem") + ) + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s_no_handshake: + s_no_handshake.connect(("localhost", self.server.port)) + # Note: this socket is left open, notably not sending the TLS handshake. + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + sock.settimeout(10) + with context.wrap_socket( + sock, + do_handshake_on_connect=False, + server_hostname="web-platform.test", + ) as ssock: + ssock.connect(("localhost", self.server.port)) + ssock.do_handshake() + # The pass condition here is essentially "don't raise TimeoutError". + + +class TestH2TLSHandshake(TestUsingH2Server): + def test_no_handshake(self): + context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + context.load_verify_locations( + os.path.join(repo_root, "tools", "certs", "cacert.pem") + ) + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s_no_handshake: + s_no_handshake.connect(("localhost", self.server.port)) + # Note: this socket is left open, notably not sending the TLS handshake. + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0) as sock: + sock.settimeout(10) + with context.wrap_socket( + sock, + do_handshake_on_connect=False, + server_hostname="web-platform.test", + ) as ssock: + ssock.connect(("localhost", self.server.port)) + ssock.do_handshake() + # The pass condition here is essentially "don't raise TimeoutError". + + class TestH2Version(TestUsingH2Server): # The purpose of this test is to ensure that all TestUsingH2Server tests # actually end up using HTTP/2, in case there's any protocol negotiation. diff --git a/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py b/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py index 6d79230a32..62faf47d64 100644 --- a/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py +++ b/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py @@ -2,6 +2,7 @@ import json import os +import pathlib from collections import defaultdict from urllib.parse import quote, unquote, urljoin @@ -289,6 +290,10 @@ class PythonScriptHandler: """ This loads the requested python file as an environ variable. + If the requested file is a directory, this instead loads the first + lexicographically sorted file found in that directory that matches + "default*.py". + Once the environ is loaded, the passed `func` is run with this loaded environ. :param request: The request object @@ -298,6 +303,14 @@ class PythonScriptHandler: """ path = filesystem_path(self.base_path, request, self.url_base) + # Find a default Python file if the specified path is a directory + if os.path.isdir(path): + default_py_files = sorted(list(filter( + pathlib.Path.is_file, + pathlib.Path(path).glob("default*.py")))) + if default_py_files: + path = str(default_py_files[0]) + try: environ = {"__file__": path} with open(path, 'rb') as f: @@ -416,6 +429,9 @@ class AsIsHandler: def __call__(self, request, response): path = filesystem_path(self.base_path, request, self.url_base) + if os.path.isdir(path): + raise HTTPException( + 500, "AsIsHandler cannot process directory, %s" % path) try: with open(path, 'rb') as f: diff --git a/testing/web-platform/tests/tools/wptserve/wptserve/server.py b/testing/web-platform/tests/tools/wptserve/wptserve/server.py index e1772d00b1..8ce36201ee 100644 --- a/testing/web-platform/tests/tools/wptserve/wptserve/server.py +++ b/testing/web-platform/tests/tools/wptserve/wptserve/server.py @@ -130,7 +130,9 @@ class RequestRewriter: class WebTestServer(http.server.ThreadingHTTPServer): allow_reuse_address = True - acceptable_errors = (errno.EPIPE, errno.ECONNABORTED) + # Older versions of Python might throw `OSError: [Errno 0] Error` + # instead of `SSLEOFError`. + acceptable_errors = (errno.EPIPE, errno.ECONNABORTED, 0) request_queue_size = 2000 # Ensure that we don't hang on shutdown waiting for requests @@ -214,14 +216,21 @@ class WebTestServer(http.server.ThreadingHTTPServer): ssl_context.load_cert_chain(keyfile=self.key_file, certfile=self.certificate) ssl_context.set_alpn_protocols(['h2']) self.socket = ssl_context.wrap_socket(self.socket, + do_handshake_on_connect=False, server_side=True) else: ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) ssl_context.load_cert_chain(keyfile=self.key_file, certfile=self.certificate) self.socket = ssl_context.wrap_socket(self.socket, + do_handshake_on_connect=False, server_side=True) + def finish_request(self, request, client_address): + if isinstance(self.socket, ssl.SSLSocket): + request.do_handshake() + super().finish_request(request, client_address) + def handle_error(self, request, client_address): error = sys.exc_info()[1] @@ -229,7 +238,11 @@ class WebTestServer(http.server.ThreadingHTTPServer): isinstance(error.args, tuple) and error.args[0] in self.acceptable_errors) or (isinstance(error, IOError) and - error.errno in self.acceptable_errors)): + error.errno in self.acceptable_errors) or + # `SSLEOFError` and `SSLError` may occur when a client + # (e.g., wptrunner's `TestEnvironment`) tests for connectivity + # but doesn't perform the handshake. + isinstance(error, ssl.SSLEOFError) or isinstance(error, ssl.SSLError)): pass # remote hang up before the result is sent else: msg = traceback.format_exc() |