diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:43:14 +0000 |
commit | 8dd16259287f58f9273002717ec4d27e97127719 (patch) | |
tree | 3863e62a53829a84037444beab3abd4ed9dfc7d0 /testing/web-platform/tests/tools/wptrunner | |
parent | Releasing progress-linux version 126.0.1-1~progress7.99u1. (diff) | |
download | firefox-8dd16259287f58f9273002717ec4d27e97127719.tar.xz firefox-8dd16259287f58f9273002717ec4d27e97127719.zip |
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/tools/wptrunner')
22 files changed, 204 insertions, 175 deletions
diff --git a/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst b/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst index fea676565b..76f088dd8f 100644 --- a/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst +++ b/testing/web-platform/tests/tools/wptrunner/docs/expectation.rst @@ -153,7 +153,7 @@ When used for expectation data, metadata files have the following format: :implementation-status: One of the values ``implementing``, - ``not-implementing`` or ``default``. This is used in conjunction + ``not-implementing`` or ``backlog``. This is used in conjunction with the ``--skip-implementation-status`` command line argument to ``wptrunner`` to ignore certain features where running the test is low value. diff --git a/testing/web-platform/tests/tools/wptrunner/requirements.txt b/testing/web-platform/tests/tools/wptrunner/requirements.txt index a7face3bd0..bb9b4ac77c 100644 --- a/testing/web-platform/tests/tools/wptrunner/requirements.txt +++ b/testing/web-platform/tests/tools/wptrunner/requirements.txt @@ -1,11 +1,11 @@ html5lib==1.1 -mozdebug==0.3.0 +mozdebug==0.3.1 mozinfo==1.2.3 # https://bugzilla.mozilla.org/show_bug.cgi?id=1621226 mozlog==8.0.0 mozprocess==1.3.1 -packaging==23.1 -pillow==9.5.0 +packaging==24.0 +pillow==10.3.0 requests==2.31.0 six==1.16.0 -urllib3==2.0.7 -aioquic==0.9.19 +urllib3==2.2.1 +aioquic==0.9.21 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt b/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt index 3ba4731494..ed377b9c95 100644 --- a/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt +++ b/testing/web-platform/tests/tools/wptrunner/requirements_firefox.txt @@ -1,10 +1,10 @@ marionette_driver==3.4.0 mozcrash==2.2.0 -mozdevice==4.1.1 +mozdevice==4.1.2 mozinstall==2.1.0 mozleak==0.2 -mozprofile==2.6.1 -mozrunner==8.3.0 +mozprofile==3.0.0 +mozrunner==8.3.1 mozversion==2.4.0 -psutil==5.9.5 +psutil==5.9.8 redo==2.0.4 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_opera.txt b/testing/web-platform/tests/tools/wptrunner/requirements_opera.txt index db0c5dd992..6c2425f337 100644 --- a/testing/web-platform/tests/tools/wptrunner/requirements_opera.txt +++ b/testing/web-platform/tests/tools/wptrunner/requirements_opera.txt @@ -1,2 +1,2 @@ mozprocess==1.3.1 -selenium==4.18.1 +selenium==4.20.0 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_safari.txt b/testing/web-platform/tests/tools/wptrunner/requirements_safari.txt index bcce11aed8..0704b2dbf6 100644 --- a/testing/web-platform/tests/tools/wptrunner/requirements_safari.txt +++ b/testing/web-platform/tests/tools/wptrunner/requirements_safari.txt @@ -1 +1 @@ -psutil==5.9.5 +psutil==5.9.8 diff --git a/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt b/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt index c9e42346ce..806352e87e 100644 --- a/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt +++ b/testing/web-platform/tests/tools/wptrunner/requirements_sauce.txt @@ -1,2 +1,2 @@ -selenium==4.18.1 +selenium==4.20.0 requests==2.31.0 diff --git a/testing/web-platform/tests/tools/wptrunner/tox.ini b/testing/web-platform/tests/tools/wptrunner/tox.ini index 82d3ac6f55..c380be1252 100644 --- a/testing/web-platform/tests/tools/wptrunner/tox.ini +++ b/testing/web-platform/tests/tools/wptrunner/tox.ini @@ -2,7 +2,7 @@ xfail_strict=true [tox] -envlist = py311-{base,chrome,firefox,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py37,py38,py39,py310}-base +envlist = py312-{base,chrome,firefox,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py38,py39,py310,py311}-base skip_missing_interpreters = False [testenv] diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py index 81dc549d73..d54a9be943 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/__init__.py @@ -22,14 +22,13 @@ All classes and functions named in the above dict must be imported into the module global scope. """ -product_list = ["android_weblayer", - "android_webview", +product_list = ["android_webview", "chrome", "chrome_android", "chrome_ios", "chromium", "content_shell", - "edgechromium", + "edge", "firefox", "firefox_android", "safari", diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/android_weblayer.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/android_weblayer.py deleted file mode 100644 index db23b64793..0000000000 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/android_weblayer.py +++ /dev/null @@ -1,105 +0,0 @@ -# mypy: allow-untyped-defs - -from .base import NullBrowser # noqa: F401 -from .base import require_arg -from .base import get_timeout_multiplier # noqa: F401 -from .chrome import executor_kwargs as chrome_executor_kwargs -from .chrome_android import ChromeAndroidBrowserBase -from ..executors.base import WdspecExecutor # noqa: F401 -from ..executors.executorchrome import ChromeDriverPrintRefTestExecutor # noqa: F401 -from ..executors.executorwebdriver import (WebDriverCrashtestExecutor, # noqa: F401 - WebDriverTestharnessExecutor, # noqa: F401 - WebDriverRefTestExecutor) # noqa: F401 - - -__wptrunner__ = {"product": "android_weblayer", - "check_args": "check_args", - "browser": {None: "WeblayerShell", - "wdspec": "NullBrowser"}, - "executor": {"testharness": "WebDriverTestharnessExecutor", - "reftest": "WebDriverRefTestExecutor", - "print-reftest": "ChromeDriverPrintRefTestExecutor", - "wdspec": "WdspecExecutor", - "crashtest": "WebDriverCrashtestExecutor"}, - "browser_kwargs": "browser_kwargs", - "executor_kwargs": "executor_kwargs", - "env_extras": "env_extras", - "env_options": "env_options", - "timeout_multiplier": "get_timeout_multiplier"} - -_wptserve_ports = set() - - -def check_args(**kwargs): - require_arg(kwargs, "webdriver_binary") - - -def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): - return {"binary": kwargs["binary"], - "adb_binary": kwargs["adb_binary"], - "device_serial": kwargs["device_serial"], - "webdriver_binary": kwargs["webdriver_binary"], - "webdriver_args": kwargs.get("webdriver_args"), - "stackwalk_binary": kwargs.get("stackwalk_binary"), - "symbols_path": kwargs.get("symbols_path")} - - -def executor_kwargs(logger, test_type, test_environment, run_info_data, - **kwargs): - # Use update() to modify the global list in place. - _wptserve_ports.update(set( - test_environment.config['ports']['http'] + test_environment.config['ports']['https'] + - test_environment.config['ports']['ws'] + test_environment.config['ports']['wss'] - )) - - executor_kwargs = chrome_executor_kwargs(logger, test_type, test_environment, run_info_data, - **kwargs) - del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"] - capabilities = executor_kwargs["capabilities"] - # Note that for WebLayer, we launch a test shell and have the test shell use - # WebLayer. - # https://cs.chromium.org/chromium/src/weblayer/shell/android/shell_apk/ - capabilities["goog:chromeOptions"]["androidPackage"] = \ - "org.chromium.weblayer.shell" - capabilities["goog:chromeOptions"]["androidActivity"] = ".WebLayerShellActivity" - capabilities["goog:chromeOptions"]["androidKeepAppDataDir"] = \ - kwargs.get("keep_app_data_directory") - - # Workaround: driver.quit() cannot quit WeblayerShell. - executor_kwargs["pause_after_test"] = False - # Workaround: driver.close() is not supported. - executor_kwargs["restart_after_test"] = True - executor_kwargs["close_after_done"] = False - return executor_kwargs - - -def env_extras(**kwargs): - return [] - - -def env_options(): - # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file - return {"server_host": "127.0.0.1"} - - -class WeblayerShell(ChromeAndroidBrowserBase): - """Chrome is backed by chromedriver, which is supplied through - ``wptrunner.webdriver.ChromeDriverServer``. - """ - - def __init__(self, logger, binary, - webdriver_binary="chromedriver", - adb_binary=None, - remote_queue=None, - device_serial=None, - webdriver_args=None, - stackwalk_binary=None, - symbols_path=None): - """Creates a new representation of Chrome. The `binary` argument gives - the browser binary to use for testing.""" - super().__init__(logger, - webdriver_binary, adb_binary, remote_queue, - device_serial, webdriver_args, stackwalk_binary, - symbols_path) - self.binary = binary - self.wptserver_ports = _wptserve_ports diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py index 8198bfe11d..c0a176743d 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/chrome.py @@ -53,13 +53,13 @@ def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(logger, test_type, test_environment, run_info_data, +def executor_kwargs(logger, test_type, test_environment, run_info_data, subsuite, **kwargs): sanitizer_enabled = kwargs.get("sanitizer_enabled") if sanitizer_enabled: test_type = "crashtest" executor_kwargs = base_executor_kwargs(test_type, test_environment, run_info_data, - **kwargs) + subsuite, **kwargs) executor_kwargs["close_after_done"] = True executor_kwargs["sanitizer_enabled"] = sanitizer_enabled executor_kwargs["reuse_window"] = kwargs.get("reuse_window", False) @@ -115,6 +115,10 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, # The GenericSensorExtraClasses flag enables the browser-side # implementation of sensors such as Ambient Light Sensor. chrome_options["args"].append("--enable-features=GenericSensorExtraClasses") + # Do not show Chrome for Testing infobar. For other Chromium build this + # flag is no-op. Required to avoid flakiness in tests, as the infobar + # changes the viewport, which can happen during the test run. + chrome_options["args"].append("--disable-infobars") # Classify `http-private`, `http-public` and https variants in the # appropriate IP address spaces. @@ -134,8 +138,14 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, chrome_options["args"].append( "--ip-address-space-overrides=" + address_space_overrides_arg) + # Always disable antialiasing on the Ahem font. + blink_features = ['DisableAhemAntialias'] + if kwargs["enable_mojojs"]: - chrome_options["args"].append("--enable-blink-features=MojoJS,MojoJSTest") + blink_features.append('MojoJS') + blink_features.append('MojoJSTest') + + chrome_options["args"].append("--enable-blink-features=" + ','.join(blink_features)) if kwargs["enable_swiftshader"]: # https://chromium.googlesource.com/chromium/src/+/HEAD/docs/gpu/swiftshader.md @@ -149,6 +159,10 @@ def executor_kwargs(logger, test_type, test_environment, run_info_data, if arg not in chrome_options["args"]: chrome_options["args"].append(arg) + for arg in subsuite.config.get("binary_args", []): + if arg not in chrome_options["args"]: + chrome_options["args"].append(arg) + # Pass the --headless=new flag to Chrome if WPT's own --headless flag was # set. '--headless' should always mean the new headless mode, as the old # headless mode is not used anyway. diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edgechromium.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edge.py index 4f5bffa06c..82597c9312 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edgechromium.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/edge.py @@ -6,18 +6,18 @@ from .chrome import executor_kwargs as chrome_executor_kwargs from ..executors.executorwebdriver import WebDriverCrashtestExecutor # noqa: F401 from ..executors.base import WdspecExecutor # noqa: F401 from ..executors.executoredge import ( # noqa: F401 - EdgeChromiumDriverPrintRefTestExecutor, - EdgeChromiumDriverRefTestExecutor, - EdgeChromiumDriverTestharnessExecutor, + EdgeDriverPrintRefTestExecutor, + EdgeDriverRefTestExecutor, + EdgeDriverTestharnessExecutor, ) -__wptrunner__ = {"product": "edgechromium", +__wptrunner__ = {"product": "edge", "check_args": "check_args", - "browser": "EdgeChromiumBrowser", - "executor": {"testharness": "EdgeChromiumDriverTestharnessExecutor", - "reftest": "EdgeChromiumDriverRefTestExecutor", - "print-reftest": "EdgeChromiumDriverPrintRefTestExecutor", + "browser": "EdgeBrowser", + "executor": {"testharness": "EdgeDriverTestharnessExecutor", + "reftest": "EdgeDriverRefTestExecutor", + "print-reftest": "EdgeDriverPrintRefTestExecutor", "wdspec": "WdspecExecutor", "crashtest": "WebDriverCrashtestExecutor"}, "browser_kwargs": "browser_kwargs", @@ -58,9 +58,9 @@ def update_properties(): return (["debug", "os", "processor"], {"os": ["version"], "processor": ["bits"]}) -class EdgeChromiumBrowser(WebDriverBrowser): +class EdgeBrowser(WebDriverBrowser): """MicrosoftEdge is backed by MSEdgeDriver, which is supplied through - ``wptrunner.webdriver.EdgeChromiumDriverServer``. + ``wptrunner.webdriver.EdgeDriverServer``. """ def make_command(self): diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py index 814b8b8d75..d977930a28 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox.py @@ -132,6 +132,7 @@ def browser_kwargs(logger, test_type, run_info_data, config, subsuite, **kwargs) "headless": kwargs["headless"], "preload_browser": kwargs["preload_browser"] and not kwargs["pause_after_test"] and not kwargs["num_test_groups"] == 1, "specialpowers_path": kwargs["specialpowers_path"], + "allow_list_paths": kwargs["allow_list_paths"], "debug_test": kwargs["debug_test"]} if test_type == "wdspec" and kwargs["binary"]: browser_kwargs["webdriver_args"].extend(["--binary", kwargs["binary"]]) @@ -644,7 +645,8 @@ class GeckodriverOutputHandler(FirefoxOutputHandler): class ProfileCreator: def __init__(self, logger, prefs_root, config, test_type, extra_prefs, disable_fission, debug_test, browser_channel, binary, - package_name, certutil_binary, ca_certificate_path): + package_name, certutil_binary, ca_certificate_path, + allow_list_paths): self.logger = logger self.prefs_root = prefs_root self.config = config @@ -658,6 +660,7 @@ class ProfileCreator: self.package_name = package_name self.certutil_binary = certutil_binary self.ca_certificate_path = ca_certificate_path + self.allow_list_paths = allow_list_paths def create(self, **kwargs): """Create a Firefox profile and return the mozprofile Profile object pointing at that @@ -669,6 +672,7 @@ class ProfileCreator: profile = FirefoxProfile(preferences=preferences, restore=False, + allowlistpaths=self.allow_list_paths, **kwargs) self._set_required_prefs(profile) if self.ca_certificate_path is not None: @@ -795,7 +799,7 @@ class FirefoxBrowser(Browser): stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False, asan=False, chaos_mode_flags=None, config=None, browser_channel="nightly", headless=None, preload_browser=False, - specialpowers_path=None, debug_test=False, **kwargs): + specialpowers_path=None, debug_test=False, allow_list_paths=None, **kwargs): Browser.__init__(self, logger) self.logger = logger @@ -826,7 +830,8 @@ class FirefoxBrowser(Browser): binary, package_name, certutil_binary, - ca_certificate_path) + ca_certificate_path, + allow_list_paths) if preload_browser: instance_manager_cls = PreloadInstanceManager @@ -899,7 +904,7 @@ class FirefoxWdSpecBrowser(WebDriverBrowser): disable_fission=False, stackfix_dir=None, leak_check=False, asan=False, chaos_mode_flags=None, config=None, browser_channel="nightly", headless=None, debug_test=False, profile_creator_cls=ProfileCreator, - **kwargs): + allow_list_paths=None, **kwargs): super().__init__(logger, binary, webdriver_binary, webdriver_args) self.binary = binary @@ -927,7 +932,8 @@ class FirefoxWdSpecBrowser(WebDriverBrowser): binary, package_name, certutil_binary, - ca_certificate_path) + ca_certificate_path, + allow_list_paths) self.profile = profile_creator.create() self.marionette_port = None diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py index 7c158902e1..526f83d595 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/firefox_android.py @@ -148,11 +148,13 @@ def get_environ(chaos_mode_flags, env_extras=None): class ProfileCreator(FirefoxProfileCreator): def __init__(self, logger, prefs_root, config, test_type, extra_prefs, disable_fission, debug_test, browser_channel, binary, - package_name, certutil_binary, ca_certificate_path): + package_name, certutil_binary, ca_certificate_path, + allow_list_paths=None): super().__init__(logger, prefs_root, config, test_type, extra_prefs, disable_fission, debug_test, browser_channel, None, - package_name, certutil_binary, ca_certificate_path) + package_name, certutil_binary, ca_certificate_path, + allow_list_paths) def _set_required_prefs(self, profile): profile.set_preferences({ diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/actions.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/actions.py index cb9c1a1508..6e0c081b48 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/actions.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/actions.py @@ -443,6 +443,26 @@ class GetVirtualSensorInformationAction: self.logger.debug("Requesting information from %s sensor" % sensor_type) return self.protocol.virtual_sensor.get_virtual_sensor_information(sensor_type) +class SetDevicePostureAction: + name = "set_device_posture" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + posture = payload["posture"] + return self.protocol.device_posture.set_device_posture(posture) + +class ClearDevicePostureAction: + name = "clear_device_posture" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + return self.protocol.device_posture.clear_device_posture() actions = [ClickAction, DeleteAllCookiesAction, @@ -477,4 +497,6 @@ actions = [ClickAction, CreateVirtualSensorAction, UpdateVirtualSensorAction, RemoveVirtualSensorAction, - GetVirtualSensorInformationAction] + GetVirtualSensorInformationAction, + SetDevicePostureAction, + ClearDevicePostureAction] diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py index 763b6fcb19..92a782e835 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/base.py @@ -313,7 +313,7 @@ class TestExecutor: result = self.do_test(test) except Exception as e: exception_string = traceback.format_exc() - message = f"Exception in TextExecutor.run:\n{exception_string}" + message = f"Exception in TestExecutor.run:\n{exception_string}" self.logger.warning(message) result = self.result_from_exception(test, e, exception_string) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executoredge.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executoredge.py index cbe5eadf9a..3b62cb7477 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executoredge.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executoredge.py @@ -20,42 +20,42 @@ here = os.path.dirname(__file__) _SanitizerMixin = make_sanitizer_mixin(WebDriverCrashtestExecutor)
-class EdgeChromiumDriverTestharnessProtocolPart(ChromeDriverTestharnessProtocolPart):
+class EdgeDriverTestharnessProtocolPart(ChromeDriverTestharnessProtocolPart):
def setup(self):
super().setup()
self.cdp_company_prefix = "ms"
-class EdgeChromiumDriverPrintProtocolPart(ChromeDriverPrintProtocolPart):
+class EdgeDriverPrintProtocolPart(ChromeDriverPrintProtocolPart):
def setup(self):
super().setup()
self.cdp_company_prefix = "ms"
-class EdgeChromiumDriverProtocol(WebDriverProtocol):
+class EdgeDriverProtocol(WebDriverProtocol):
implements = [
- EdgeChromiumDriverPrintProtocolPart,
- EdgeChromiumDriverTestharnessProtocolPart,
+ EdgeDriverPrintProtocolPart,
+ EdgeDriverTestharnessProtocolPart,
*(part for part in WebDriverProtocol.implements
- if part.name != EdgeChromiumDriverTestharnessProtocolPart.name)
+ if part.name != EdgeDriverTestharnessProtocolPart.name)
]
reuse_window = False
-class EdgeChromiumDriverRefTestExecutor(WebDriverRefTestExecutor, _SanitizerMixin): # type: ignore
- protocol_cls = EdgeChromiumDriverProtocol
+class EdgeDriverRefTestExecutor(WebDriverRefTestExecutor, _SanitizerMixin): # type: ignore
+ protocol_cls = EdgeDriverProtocol
-class EdgeChromiumDriverTestharnessExecutor(WebDriverTestharnessExecutor, _SanitizerMixin): # type: ignore
- protocol_cls = EdgeChromiumDriverProtocol
+class EdgeDriverTestharnessExecutor(WebDriverTestharnessExecutor, _SanitizerMixin): # type: ignore
+ protocol_cls = EdgeDriverProtocol
def __init__(self, *args, reuse_window=False, **kwargs):
super().__init__(*args, **kwargs)
self.protocol.reuse_window = reuse_window
-class EdgeChromiumDriverPrintRefTestExecutor(EdgeChromiumDriverRefTestExecutor):
- protocol_cls = EdgeChromiumDriverProtocol
+class EdgeDriverPrintRefTestExecutor(EdgeDriverRefTestExecutor):
+ protocol_cls = EdgeDriverProtocol
def setup(self, runner):
super().setup(runner)
diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py index 0f640d7741..05a9fc1ae4 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executormarionette.py @@ -45,6 +45,7 @@ from .protocol import (AccessibilityProtocolPart, PrintProtocolPart, DebugProtocolPart, VirtualSensorProtocolPart, + DevicePostureProtocolPart, merge_dicts) @@ -749,6 +750,17 @@ class MarionetteVirtualSensorProtocolPart(VirtualSensorProtocolPart): raise NotImplementedError("get_virtual_sensor_information not yet implemented") +class MarionetteDevicePostureProtocolPart(DevicePostureProtocolPart): + def setup(self): + self.marionette = self.parent.marionette + + def set_device_posture(self, posture): + raise NotImplementedError("set_device_posture not yet implemented") + + def clear_device_posture(self): + raise NotImplementedError("clear_device_posture not yet implemented") + + class MarionetteProtocol(Protocol): implements = [MarionetteBaseProtocolPart, MarionetteTestharnessProtocolPart, @@ -769,7 +781,8 @@ class MarionetteProtocol(Protocol): MarionettePrintProtocolPart, MarionetteDebugProtocolPart, MarionetteAccessibilityProtocolPart, - MarionetteVirtualSensorProtocolPart] + MarionetteVirtualSensorProtocolPart, + MarionetteDevicePostureProtocolPart] def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False): do_delayed_imports() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py index 6df2d96461..69013e5e79 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorwebdriver.py @@ -35,6 +35,7 @@ from .protocol import (BaseProtocolPart, RPHRegistrationsProtocolPart, FedCMProtocolPart, VirtualSensorProtocolPart, + DevicePostureProtocolPart, merge_dicts) from webdriver.client import Session @@ -431,6 +432,16 @@ class WebDriverVirtualSensorPart(VirtualSensorProtocolPart): def get_virtual_sensor_information(self, sensor_type): return self.webdriver.send_session_command("GET", "sensor/%s" % sensor_type) +class WebDriverDevicePostureProtocolPart(DevicePostureProtocolPart): + def setup(self): + self.webdriver = self.parent.webdriver + + def set_device_posture(self, posture): + body = {"posture": posture} + return self.webdriver.send_session_command("POST", "deviceposture", body) + + def clear_device_posture(self): + return self.webdriver.send_session_command("DELETE", "deviceposture") class WebDriverProtocol(Protocol): implements = [WebDriverBaseProtocolPart, @@ -450,7 +461,8 @@ class WebDriverProtocol(Protocol): WebDriverRPHRegistrationsProtocolPart, WebDriverFedCMProtocolPart, WebDriverDebugProtocolPart, - WebDriverVirtualSensorPart] + WebDriverVirtualSensorPart, + WebDriverDevicePostureProtocolPart] def __init__(self, executor, browser, capabilities, **kwargs): super().__init__(executor, browser) @@ -527,7 +539,9 @@ class WebDriverRun(TimedRunner): self.result = True, self.func(self.protocol, self.url, self.timeout) except (error.TimeoutException, error.ScriptTimeoutException): self.result = False, ("EXTERNAL-TIMEOUT", None) - except (socket.timeout, error.UnknownErrorException): + except socket.timeout: + # Checking if the browser is alive below is likely to hang, so mark + # this case as a CRASH unconditionally. self.result = False, ("CRASH", None) except Exception as e: if (isinstance(e, error.WebDriverException) and @@ -536,11 +550,12 @@ class WebDriverRun(TimedRunner): # workaround for https://bugs.chromium.org/p/chromedriver/issues/detail?id=2001 self.result = False, ("EXTERNAL-TIMEOUT", None) else: + status = "INTERNAL-ERROR" if self.protocol.is_alive() else "CRASH" message = str(getattr(e, "message", "")) if message: message += "\n" message += traceback.format_exc() - self.result = False, ("INTERNAL-ERROR", message) + self.result = False, (status, message) finally: self.result_flag.set() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py index e44d1a7666..3d588738b6 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/protocol.py @@ -802,3 +802,17 @@ class VirtualSensorProtocolPart(ProtocolPart): @abstractmethod def get_virtual_sensor_information(self, sensor_type): pass + +class DevicePostureProtocolPart(ProtocolPart): + """Protocol part for Device Posture""" + __metaclass__ = ABCMeta + + name = "device_posture" + + @abstractmethod + def set_device_posture(self, posture): + pass + + @abstractmethod + def clear_device_posture(self): + pass diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testdriver-extra.js b/testing/web-platform/tests/tools/wptrunner/wptrunner/testdriver-extra.js index af25bf4111..87d3826bfc 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/testdriver-extra.js +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testdriver-extra.js @@ -327,4 +327,12 @@ window.test_driver_internal.get_virtual_sensor_information = function(sensor_type, context=null) { return create_action("get_virtual_sensor_information", {sensor_type, context}); }; + + window.test_driver_internal.set_device_posture = function(posture, context=null) { + return create_action("set_device_posture", {posture, context}); + }; + + window.test_driver_internal.clear_device_posture = function(context=null) { + return create_action("clear_device_posture", {context}); + }; })(); diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py index 70da22f5b7..93e19fa47b 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/testrunner.py @@ -1,7 +1,6 @@ # mypy: allow-untyped-defs import threading -import time import traceback from queue import Empty from collections import namedtuple, defaultdict @@ -31,6 +30,30 @@ TestImplementation = namedtuple('TestImplementation', 'browser_cls', 'browser_kwargs']) +class StopFlag: + """Synchronization for coordinating a graceful exit.""" + + def __init__(self, size: int): + # Flag that is polled by threads so that they can gracefully exit in the + # face of SIGINT. + self._should_stop = threading.Event() + # A barrier that each `TestRunnerManager` thread waits on when exiting + # its run loop. This provides a reliable way for the `ManagerGroup` to + # tell when all threads have cleaned up their resources. + # + # The barrier's extra waiter is the main thread (`ManagerGroup`). + self._all_managers_done = threading.Barrier(1 + size) + + def stop(self) -> None: + self._should_stop.set() + + def should_stop(self) -> bool: + return self._should_stop.is_set() + + def wait_for_all_managers_done(self, timeout: Optional[float] = None) -> None: + self._all_managers_done.wait(timeout) + + class LogMessageHandler: def __init__(self, send_message): self.send_message = send_message @@ -443,7 +466,8 @@ class TestRunnerManager(threading.Thread): if self.browser is not None: assert self.browser.browser is not None self.browser.browser.cleanup() - self.logger.debug("TestRunnerManager main loop terminated") + self.logger.debug("TestRunnerManager main loop terminated") + self.parent_stop_flag.wait_for_all_managers_done() def wait_event(self): dispatch = { @@ -517,7 +541,7 @@ class TestRunnerManager(threading.Thread): return f(*data) def should_stop(self): - return self.child_stop_flag.is_set() or self.parent_stop_flag.is_set() + return self.child_stop_flag.is_set() or self.parent_stop_flag.should_stop() def start_init(self): subsuite, test_type, test, test_group, group_metadata = self.get_next_test() @@ -977,9 +1001,7 @@ class ManagerGroup: self.max_restarts = max_restarts self.pool = set() - # Event that is polled by threads so that they can gracefully exit in the face - # of sigint - self.stop_flag = threading.Event() + self.stop_flag = None self.logger = structuredlog.StructuredLogger(suite_name) def __enter__(self): @@ -992,6 +1014,7 @@ class ManagerGroup: """Start all managers in the group""" test_queue, size = self.test_queue_builder.make_queue(tests) self.logger.info("Using %i child processes" % size) + self.stop_flag = StopFlag(size) for idx in range(size): manager = TestRunnerManager(self.suite_name, @@ -1020,18 +1043,31 @@ class ManagerGroup: timeout: Overall timeout (in seconds) for all threads to join. The default value indicates an indefinite timeout. """ - deadline = None if timeout is None else time.time() + timeout - for manager in self.pool: - manager_timeout = None - if deadline is not None: - manager_timeout = max(0, deadline - time.time()) - manager.join(manager_timeout) + # Here, the main thread cannot simply `join()` the threads in + # `self.pool` sequentially because a keyboard interrupt raised during a + # `Thread.join()` may incorrectly mark that thread as "stopped" when it + # is not [0, 1]. Subsequent `join()`s for the affected thread won't + # block anymore, so a subsequent `ManagerGroup.wait()` may return with + # that thread still alive. + # + # To the extent the timeout allows, it's important that + # `ManagerGroup.wait()` returns with all `TestRunnerManager` threads + # actually stopped. Otherwise, a live thread may log after `mozlog` + # shutdown (not allowed) or worse, leak browser processes that the + # thread should have stopped when exiting its run loop [2]. + # + # [0]: https://github.com/python/cpython/issues/90882 + # [1]: https://github.com/python/cpython/blob/558b517b/Lib/threading.py#L1146-L1178 + # [2]: https://crbug.com/330236796 + assert self.stop_flag, "ManagerGroup hasn't been started yet" + self.stop_flag.wait_for_all_managers_done(timeout) def stop(self): """Set the stop flag so that all managers in the group stop as soon as possible""" - self.stop_flag.set() - self.logger.debug("Stop flag set in ManagerGroup") + if self.stop_flag: + self.stop_flag.stop() + self.logger.debug("Stop flag set in ManagerGroup") def test_count(self): return sum(manager.test_count for manager in self.pool) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py index d65369b380..d9d85de6a4 100644 --- a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptrunner.py @@ -396,11 +396,16 @@ def run_tests(config, product, test_paths, **kwargs): product.check_args(**kwargs) + kwargs["allow_list_paths"] = [] if kwargs["install_fonts"]: + # Add test font to allow list for sandbox to ensure that the content + # processes will have read access. + ahem_path = os.path.join(test_paths["/"].tests_path, "fonts/Ahem.ttf") + kwargs["allow_list_paths"].append(ahem_path) env_extras.append(FontInstaller( logger, font_dir=kwargs["font_dir"], - ahem=os.path.join(test_paths["/"].tests_path, "fonts/Ahem.ttf") + ahem=ahem_path )) recording.set(["startup", "load_tests"]) |