tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d183fbe1b44b05702ea0bb4795ab600f0c0d775a
parent 17f2e2a68ec680ecf71ff3ae7177392ad8e1899b
Author: Mukilan Thiyagarajan <mukilan@igalia.com>
Date:   Thu,  6 Nov 2025 21:35:20 +0000

Bug 1997735 [wpt PR 55812] - wpt: Have `ServoRefTestExecutor` inherit from `RefTestExecutor`, a=testonly

Automatic update from web-platform-tests
wpt: Have `ServoRefTestExecutor` inherit from `RefTestExecutor`

Since `ProcessTestExecutor` is only used by Servo and doesn't add much
on top of `ServoExecutor`, merge the former into the latter.

Also make `ServoExecutor` a mixin so that the derived classes can
inherit from upstream `wptrunner`'s classes and avoid the diamond
inheritance of `TestExecutor` base class.

Another issue is that new changes in the
`RefTestImplementation.get_screenshot_list` method upstream conflicts
with the assumptions in Servo's executor:
  - The `dpi` argument is used as an `int` although it is a string
  - The `viewport_size` argument is treated as a tuple of ints but it is
    in fact a string of the format `WxH`. It also treats the viewport
    dimensions as being specified in device pixel coordinates while
    Servo treats it as logical coordinates and will scale it by `dpi`.

These issues need to discussed with upstream and patched in
`RefTestImplementation`.

Finally, add back `**kwargs` argument to `ServoCrashtestExecutor`'s
constructor to fix #40322.

Fixes #40288, #40322

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

--

wpt-commits: bd278f4c26d874da5bbe10188693f6be3b6fb0e2
wpt-pr: 55812

Diffstat:
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py | 95+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Dtesting/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py | 22----------------------
2 files changed, 54 insertions(+), 63 deletions(-)

diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/executorservo.py @@ -13,12 +13,11 @@ from mozprocess import ProcessHandler from tools.serve.serve import make_hosts_file -from .base import (RefTestImplementation, +from .base import (RefTestExecutor, RefTestImplementation, TestExecutor, crashtest_result_converter, testharness_result_converter, reftest_result_converter, TimedRunner) -from .process import ProcessTestExecutor from .protocol import ConnectionlessProtocol from ..browsers.base import browser_command @@ -27,14 +26,22 @@ pytestrunner = None webdriver = None -class ServoExecutor(ProcessTestExecutor): +# A mixin class that includes functionality common to all Servo +# executors that work by spawing a new process. This is intended to +# be used along with either the `TestExecutor` class or its children +# and must be the first in the inheritance list to allow `super` +# to forward the calls to correct base class. +class ServoExecutorMixin: def __init__(self, logger, browser, server_config, headless, - timeout_multiplier, debug_info, + timeout_multiplier, debug_info, pause_after_test, reftest_screenshot="unexpected"): - ProcessTestExecutor.__init__(self, logger, browser, server_config, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info, - reftest_screenshot=reftest_screenshot) + super().__init__(logger, browser, server_config, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info, + reftest_screenshot=reftest_screenshot) + self.binary = self.browser.binary + self.interactive = (False if self.debug_info is None + else self.debug_info.interactive) self.pause_after_test = pause_after_test self.environment = {} self.protocol = ConnectionlessProtocol(self, browser) @@ -44,18 +51,23 @@ class ServoExecutor(ProcessTestExecutor): hosts_fd, self.hosts_path = tempfile.mkstemp() with os.fdopen(hosts_fd, "w") as f: - f.write(make_hosts_file(server_config, "127.0.0.1")) + f.write(make_hosts_file(self.server_config, "127.0.0.1")) self.env_for_tests = os.environ.copy() self.env_for_tests["HOST_FILE"] = self.hosts_path self.env_for_tests["RUST_BACKTRACE"] = "1" + def setup(self, runner, protocol=None): + self.runner = runner + self.runner.send_message("init_succeeded") + return True + def teardown(self): try: os.unlink(self.hosts_path) except OSError: pass - ProcessTestExecutor.teardown(self) + super().teardown() def on_environment_change(self, new_environment): self.environment = new_environment @@ -107,16 +119,17 @@ class ServoExecutor(ProcessTestExecutor): return debug_args + command -class ServoTestharnessExecutor(ServoExecutor): +class ServoTestharnessExecutor(ServoExecutorMixin, TestExecutor): convert_result = testharness_result_converter def __init__(self, logger, browser, server_config, headless, timeout_multiplier=1, debug_info=None, pause_after_test=False, **kwargs): - ServoExecutor.__init__(self, logger, browser, server_config, headless, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info, - pause_after_test=pause_after_test) + super().__init__(logger, browser, server_config, + headless, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info, + pause_after_test=pause_after_test) self.result_data = None self.result_flag = None @@ -182,7 +195,7 @@ class ServoTestharnessExecutor(ServoExecutor): self.logger.error(f"Could not process test output JSON: {error}") self.result_flag.set() else: - ServoExecutor.on_output(self, line) + super().on_output(line) def on_finish(self): self.result_flag.set() @@ -204,21 +217,20 @@ class TempFilename: pass -class ServoRefTestExecutor(ServoExecutor): +class ServoRefTestExecutor(ServoExecutorMixin, RefTestExecutor): convert_result = reftest_result_converter def __init__(self, logger, browser, server_config, binary=None, timeout_multiplier=1, screenshot_cache=None, debug_info=None, pause_after_test=False, reftest_screenshot="unexpected", **kwargs): - ServoExecutor.__init__(self, - logger, - browser, - server_config, - headless=True, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info, - reftest_screenshot=reftest_screenshot, - pause_after_test=pause_after_test) + super().__init__(logger, + browser, + server_config, + headless=True, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info, + reftest_screenshot=reftest_screenshot, + pause_after_test=pause_after_test) self.screenshot_cache = screenshot_cache self.reftest_screenshot = reftest_screenshot @@ -230,7 +242,7 @@ class ServoRefTestExecutor(ServoExecutor): def teardown(self): os.rmdir(self.tempdir) - ServoExecutor.teardown(self) + super().teardown() def screenshot(self, test, viewport_size, dpi, page_ranges): with TempFilename(self.tempdir) as output_path: @@ -239,7 +251,7 @@ class ServoRefTestExecutor(ServoExecutor): "--window-size", viewport_size or "800x600"] if dpi: - extra_args += ["--device-pixel-ratio", dpi] + extra_args += ["--device-pixel-ratio", str(dpi)] self.command = self.build_servo_command(test, extra_args) @@ -278,6 +290,11 @@ class ServoRefTestExecutor(ServoExecutor): return True, [base64.b64encode(data).decode()] def do_test(self, test): + # FIXME: This is a temporary fix until Servo syncs with upstream WPT. + # Once that happens, we can patch the `RefTestImplementation.get_screenshot_list` + # method to cast dpi to integer when using it in arithmetic expressions. + if test.dpi is not None: + test.dpi = int(test.dpi) self.test = test result = self.implementation.run_test(test) @@ -301,23 +318,19 @@ class ServoTimedRunner(TimedRunner): pass -class ServoCrashtestExecutor(ServoExecutor): +class ServoCrashtestExecutor(ServoExecutorMixin, TestExecutor): convert_result = crashtest_result_converter def __init__(self, logger, browser, server_config, headless, binary=None, timeout_multiplier=1, screenshot_cache=None, - debug_info=None, pause_after_test=False): - ServoExecutor.__init__(self, - logger, - browser, - server_config, - headless, - timeout_multiplier=timeout_multiplier, - debug_info=debug_info, - pause_after_test=pause_after_test) - - self.pause_after_test = pause_after_test - self.protocol = ConnectionlessProtocol(self, browser) + debug_info=None, pause_after_test=False, **kwargs): + super().__init__(logger, + browser, + server_config, + headless, + timeout_multiplier=timeout_multiplier, + debug_info=debug_info, + pause_after_test=pause_after_test) def do_test(self, test): timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/executors/process.py @@ -1,22 +0,0 @@ -# mypy: allow-untyped-defs - -from .base import TestExecutor - - -class ProcessTestExecutor(TestExecutor): - def __init__(self, *args, **kwargs): - TestExecutor.__init__(self, *args, **kwargs) - self.binary = self.browser.binary - self.interactive = (False if self.debug_info is None - else self.debug_info.interactive) - - def setup(self, runner, protocol=None): - self.runner = runner - self.runner.send_message("init_succeeded") - return True - - def is_alive(self): - return True - - def do_test(self, test): - raise NotImplementedError