mirror of
https://github.com/servo/servo.git
synced 2025-09-07 05:28:21 +01:00
Update web-platform-tests to revision 9a5d71b326166e12784bdd9d161772e20f87c1fd
This commit is contained in:
parent
f7630dad87
commit
4ae3d09ff3
86 changed files with 2739 additions and 640 deletions
|
@ -1,6 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
./wpt manifest-download
|
||||
# This is allowed to fail
|
||||
./wpt manifest-download || echo
|
||||
|
||||
if [ $1 == "firefox" ]; then
|
||||
./wpt run firefox --log-tbpl=../artifacts/log_tbpl.log --log-tbpl-level=info --log-wptreport=../artifacts/wpt_report.json --log-mach=- --this-chunk=$4 --total-chunks=$5 --test-type=$3 -y --install-browser --channel=$2 --no-pause --no-restart-on-unexpected --reftest-internal --install-fonts --no-fail-on-unexpected
|
||||
|
|
|
@ -18,14 +18,14 @@ test_infrastructure() {
|
|||
}
|
||||
|
||||
main() {
|
||||
PRODUCTS=( "firefox" "chrome" )
|
||||
PRODUCTS=( "firefox" "chrome" "chrome_webdriver" )
|
||||
for PRODUCT in "${PRODUCTS[@]}"; do
|
||||
if [ "$PRODUCT" != "firefox" ]; then
|
||||
# Firefox is expected to work using pref settings for DNS
|
||||
# Don't adjust the hostnames in that case to ensure this keeps working
|
||||
hosts_fixup
|
||||
fi
|
||||
if [ "$PRODUCT" == "chrome" ]; then
|
||||
if [[ "$PRODUCT" == "chrome"* ]]; then
|
||||
install_chrome unstable
|
||||
test_infrastructure "--binary=$(which google-chrome-unstable)"
|
||||
else
|
||||
|
|
|
@ -6,8 +6,10 @@ class WebDriverException(Exception):
|
|||
http_status = None
|
||||
status_code = None
|
||||
|
||||
def __init__(self, message=None, stacktrace=None):
|
||||
def __init__(self, http_status=None, status_code=None, message=None, stacktrace=None):
|
||||
super(WebDriverException, self)
|
||||
self.http_status = http_status
|
||||
self.status_code = status_code
|
||||
self.message = message
|
||||
self.stacktrace = stacktrace
|
||||
|
||||
|
@ -171,6 +173,8 @@ def from_response(response):
|
|||
"""
|
||||
if response.status == 200:
|
||||
raise UnknownErrorException(
|
||||
response.status,
|
||||
None,
|
||||
"Response is not an error:\n"
|
||||
"%s" % json.dumps(response.body))
|
||||
|
||||
|
@ -178,6 +182,8 @@ def from_response(response):
|
|||
value = response.body["value"]
|
||||
else:
|
||||
raise UnknownErrorException(
|
||||
response.status,
|
||||
None,
|
||||
"Expected 'value' key in response body:\n"
|
||||
"%s" % json.dumps(response.body))
|
||||
|
||||
|
@ -187,7 +193,7 @@ def from_response(response):
|
|||
stack = value["stacktrace"] or None
|
||||
|
||||
cls = get(code)
|
||||
return cls(message, stacktrace=stack)
|
||||
return cls(response.status, code, message, stacktrace=stack)
|
||||
|
||||
|
||||
def get(error_code):
|
||||
|
|
|
@ -486,6 +486,12 @@ class ChromeAndroid(Browser):
|
|||
def version(self, binary):
|
||||
return None
|
||||
|
||||
class ChromeWebDriver(Chrome):
|
||||
"""Chrome-specific interface for chrome without using selenium.
|
||||
|
||||
Includes webdriver installation.
|
||||
"""
|
||||
product = "chrome_webdriver"
|
||||
|
||||
class Opera(Browser):
|
||||
"""Opera-specific interface.
|
||||
|
@ -582,6 +588,10 @@ class Edge(Browser):
|
|||
return None
|
||||
|
||||
|
||||
class EdgeWebDriver(Edge):
|
||||
product = "edge_webdriver"
|
||||
|
||||
|
||||
class InternetExplorer(Browser):
|
||||
"""Internet Explorer-specific interface."""
|
||||
|
||||
|
@ -629,6 +639,10 @@ class Safari(Browser):
|
|||
return None
|
||||
|
||||
|
||||
class SafariWebDriver(Safari):
|
||||
product = "safari_webdriver"
|
||||
|
||||
|
||||
class Servo(Browser):
|
||||
"""Servo-specific interface."""
|
||||
|
||||
|
|
|
@ -273,6 +273,10 @@ class ChromeAndroid(BrowserSetup):
|
|||
else:
|
||||
raise WptrunError("Unable to locate or install chromedriver binary")
|
||||
|
||||
class ChromeWebDriver(Chrome):
|
||||
name = "chrome_webdriver"
|
||||
browser_cls = browser.ChromeWebDriver
|
||||
|
||||
|
||||
class Opera(BrowserSetup):
|
||||
name = "opera"
|
||||
|
@ -318,6 +322,11 @@ https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
|
|||
kwargs["webdriver_binary"] = webdriver_binary
|
||||
|
||||
|
||||
class EdgeWebDriver(Edge):
|
||||
name = "edge_webdriver"
|
||||
browser_cls = browser.EdgeWebDriver
|
||||
|
||||
|
||||
class InternetExplorer(BrowserSetup):
|
||||
name = "ie"
|
||||
browser_cls = browser.InternetExplorer
|
||||
|
@ -356,6 +365,11 @@ class Safari(BrowserSetup):
|
|||
kwargs["webdriver_binary"] = webdriver_binary
|
||||
|
||||
|
||||
class SafariWebDriver(Safari):
|
||||
name = "safari_webdriver"
|
||||
browser_cls = browser.SafariWebDriver
|
||||
|
||||
|
||||
class Sauce(BrowserSetup):
|
||||
name = "sauce"
|
||||
browser_cls = browser.Sauce
|
||||
|
@ -402,9 +416,12 @@ product_setup = {
|
|||
"firefox": Firefox,
|
||||
"chrome": Chrome,
|
||||
"chrome_android": ChromeAndroid,
|
||||
"chrome_webdriver": ChromeWebDriver,
|
||||
"edge": Edge,
|
||||
"edge_webdriver": EdgeWebDriver,
|
||||
"ie": InternetExplorer,
|
||||
"safari": Safari,
|
||||
"safari_webdriver": SafariWebDriver,
|
||||
"servo": Servo,
|
||||
"sauce": Sauce,
|
||||
"opera": Opera,
|
||||
|
|
|
@ -101,9 +101,6 @@ def main(prog=None, argv=None):
|
|||
|
||||
main_args, command_args = parse_args(argv, commands)
|
||||
|
||||
if not(len(argv) and argv[0] in commands):
|
||||
sys.exit(1)
|
||||
|
||||
command = main_args.command
|
||||
props = commands[command]
|
||||
venv = None
|
||||
|
|
|
@ -24,11 +24,14 @@ module global scope.
|
|||
|
||||
product_list = ["chrome",
|
||||
"chrome_android",
|
||||
"chrome_webdriver",
|
||||
"edge",
|
||||
"edge_webdriver",
|
||||
"fennec",
|
||||
"firefox",
|
||||
"ie",
|
||||
"safari",
|
||||
"safari_webdriver",
|
||||
"sauce",
|
||||
"servo",
|
||||
"servodriver",
|
||||
|
|
|
@ -2,12 +2,32 @@ import os
|
|||
import platform
|
||||
import socket
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from copy import deepcopy
|
||||
|
||||
from ..wptcommandline import require_arg # noqa: F401
|
||||
|
||||
here = os.path.split(__file__)[0]
|
||||
|
||||
|
||||
def inherit(super_module, child_globals, product_name):
|
||||
super_wptrunner = super_module.__wptrunner__
|
||||
child_globals["__wptrunner__"] = child_wptrunner = deepcopy(super_wptrunner)
|
||||
|
||||
child_wptrunner["product"] = product_name
|
||||
|
||||
for k in ("check_args", "browser", "browser_kwargs", "executor_kwargs",
|
||||
"env_extras", "env_options"):
|
||||
attr = super_wptrunner[k]
|
||||
child_globals[attr] = getattr(super_module, attr)
|
||||
|
||||
for v in super_module.__wptrunner__["executor"].values():
|
||||
child_globals[v] = getattr(super_module, v)
|
||||
|
||||
if "run_info_extras" in super_wptrunner:
|
||||
attr = super_wptrunner["run_info_extras"]
|
||||
child_globals[attr] = getattr(super_module, attr)
|
||||
|
||||
|
||||
def cmd_arg(name, value=None):
|
||||
prefix = "-" if platform.system() == "Windows" else "--"
|
||||
rv = prefix + name
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
from .base import inherit
|
||||
from . import chrome
|
||||
|
||||
from ..executors import executor_kwargs as base_executor_kwargs
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(chrome, globals(), "chrome_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor_kwargs"] = "executor_kwargs" # noqa: F821
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
||||
|
||||
|
||||
def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
|
||||
**kwargs):
|
||||
executor_kwargs = base_executor_kwargs(test_type, server_config,
|
||||
cache_manager, run_info_data,
|
||||
**kwargs)
|
||||
executor_kwargs["close_after_done"] = True
|
||||
|
||||
capabilities = {
|
||||
"browserName": "chrome",
|
||||
"platform": "ANY",
|
||||
"version": "",
|
||||
"goog:chromeOptions": {
|
||||
"prefs": {
|
||||
"profile": {
|
||||
"default_content_setting_values": {
|
||||
"popups": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"w3c": True
|
||||
}
|
||||
}
|
||||
|
||||
for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
|
||||
if kwargs[kwarg] is not None:
|
||||
capabilities["goog:chromeOptions"][capability] = kwargs[kwarg]
|
||||
|
||||
if test_type == "testharness":
|
||||
capabilities["goog:chromeOptions"]["useAutomationExtension"] = False
|
||||
capabilities["goog:chromeOptions"]["excludeSwitches"] = ["enable-automation"]
|
||||
|
||||
executor_kwargs["capabilities"] = capabilities
|
||||
|
||||
return executor_kwargs
|
|
@ -0,0 +1,12 @@
|
|||
from .base import inherit
|
||||
from . import edge
|
||||
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(edge, globals(), "edge_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
|
@ -0,0 +1,12 @@
|
|||
from .base import inherit
|
||||
from . import safari
|
||||
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(safari, globals(), "safari_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
|
@ -95,14 +95,14 @@ class SeleniumTestharnessProtocolPart(TestharnessProtocolPart):
|
|||
|
||||
def get_test_window(self, window_id, parent):
|
||||
test_window = None
|
||||
if window_id:
|
||||
try:
|
||||
# Try this, it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % self.window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
# Try using the JSON serialization of the WindowProxy object,
|
||||
# it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if test_window is None:
|
||||
after = self.webdriver.window_handles
|
||||
|
@ -296,7 +296,7 @@ class SeleniumTestharnessExecutor(TestharnessExecutor):
|
|||
parent_window = protocol.testharness.close_old_windows()
|
||||
# Now start the test harness
|
||||
protocol.base.execute_script(self.script % format_map)
|
||||
test_window = protocol.testharness.get_test_window(webdriver, parent_window)
|
||||
test_window = protocol.testharness.get_test_window(self.window_id, parent_window)
|
||||
|
||||
handler = CallbackHandler(self.logger, protocol, test_window)
|
||||
while True:
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
import json
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import traceback
|
||||
import urlparse
|
||||
import uuid
|
||||
|
||||
from .base import (CallbackHandler,
|
||||
RefTestExecutor,
|
||||
RefTestImplementation,
|
||||
TestharnessExecutor,
|
||||
extra_timeout,
|
||||
strip_server)
|
||||
from .protocol import (BaseProtocolPart,
|
||||
TestharnessProtocolPart,
|
||||
Protocol,
|
||||
SelectorProtocolPart,
|
||||
ClickProtocolPart,
|
||||
SendKeysProtocolPart,
|
||||
TestDriverProtocolPart)
|
||||
from ..testrunner import Stop
|
||||
|
||||
import webdriver as client
|
||||
|
||||
here = os.path.join(os.path.split(__file__)[0])
|
||||
|
||||
class WebDriverBaseProtocolPart(BaseProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def execute_script(self, script, async=False):
|
||||
method = self.webdriver.execute_async_script if async else self.webdriver.execute_script
|
||||
return method(script)
|
||||
|
||||
def set_timeout(self, timeout):
|
||||
try:
|
||||
self.webdriver.timeouts.script = timeout
|
||||
except client.WebDriverException:
|
||||
# workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2057
|
||||
body = {"type": "script", "ms": timeout * 1000}
|
||||
self.webdriver.send_session_command("POST", "timeouts", body)
|
||||
|
||||
@property
|
||||
def current_window(self):
|
||||
return self.webdriver.window_handle
|
||||
|
||||
def set_window(self, handle):
|
||||
self.webdriver.window_handle = handle
|
||||
|
||||
def wait(self):
|
||||
while True:
|
||||
try:
|
||||
self.webdriver.execute_async_script("")
|
||||
except client.TimeoutException:
|
||||
pass
|
||||
except (socket.timeout, client.NoSuchWindowException,
|
||||
client.UnknownErrorException, IOError):
|
||||
break
|
||||
except Exception as e:
|
||||
self.logger.error(traceback.format_exc(e))
|
||||
break
|
||||
|
||||
|
||||
class WebDriverTestharnessProtocolPart(TestharnessProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def load_runner(self, url_protocol):
|
||||
url = urlparse.urljoin(self.parent.executor.server_url(url_protocol),
|
||||
"/testharness_runner.html")
|
||||
self.logger.debug("Loading %s" % url)
|
||||
|
||||
self.webdriver.url = url
|
||||
self.webdriver.execute_script("document.title = '%s'" %
|
||||
threading.current_thread().name.replace("'", '"'))
|
||||
|
||||
def close_old_windows(self):
|
||||
exclude = self.webdriver.window_handle
|
||||
handles = [item for item in self.webdriver.handles if item != exclude]
|
||||
for handle in handles:
|
||||
try:
|
||||
self.webdriver.window_handle = handle
|
||||
self.webdriver.close()
|
||||
except client.NoSuchWindowException:
|
||||
pass
|
||||
self.webdriver.window_handle = exclude
|
||||
return exclude
|
||||
|
||||
def get_test_window(self, window_id, parent):
|
||||
test_window = None
|
||||
try:
|
||||
# Try using the JSON serialization of the WindowProxy object,
|
||||
# it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if test_window is None:
|
||||
after = self.webdriver.handles
|
||||
if len(after) == 2:
|
||||
test_window = next(iter(set(after) - set([parent])))
|
||||
elif after[0] == parent and len(after) > 2:
|
||||
# Hope the first one here is the test window
|
||||
test_window = after[1]
|
||||
else:
|
||||
raise Exception("unable to find test window")
|
||||
|
||||
assert test_window != parent
|
||||
return test_window
|
||||
|
||||
|
||||
class WebDriverSelectorProtocolPart(SelectorProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def elements_by_selector(self, selector):
|
||||
return self.webdriver.find.css(selector)
|
||||
|
||||
|
||||
class WebDriverClickProtocolPart(ClickProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def element(self, element):
|
||||
return element.click()
|
||||
|
||||
|
||||
class WebDriverSendKeysProtocolPart(SendKeysProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def send_keys(self, element, keys):
|
||||
try:
|
||||
return element.send_keys(keys)
|
||||
except client.UnknownErrorException as e:
|
||||
# workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=1999
|
||||
if (e.http_status != 500 or
|
||||
e.status_code != "unknown error"):
|
||||
raise
|
||||
return element.send_element_command("POST", "value", {"value": list(keys)})
|
||||
|
||||
|
||||
class WebDriverTestDriverProtocolPart(TestDriverProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def send_message(self, message_type, status, message=None):
|
||||
obj = {
|
||||
"type": "testdriver-%s" % str(message_type),
|
||||
"status": str(status)
|
||||
}
|
||||
if message:
|
||||
obj["message"] = str(message)
|
||||
self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
|
||||
|
||||
|
||||
class WebDriverProtocol(Protocol):
|
||||
implements = [WebDriverBaseProtocolPart,
|
||||
WebDriverTestharnessProtocolPart,
|
||||
WebDriverSelectorProtocolPart,
|
||||
WebDriverClickProtocolPart,
|
||||
WebDriverSendKeysProtocolPart,
|
||||
WebDriverTestDriverProtocolPart]
|
||||
|
||||
def __init__(self, executor, browser, capabilities, **kwargs):
|
||||
super(WebDriverProtocol, self).__init__(executor, browser)
|
||||
self.capabilities = capabilities
|
||||
self.url = browser.webdriver_url
|
||||
self.webdriver = None
|
||||
|
||||
def connect(self):
|
||||
"""Connect to browser via WebDriver."""
|
||||
self.logger.debug("Connecting to WebDriver on URL: %s" % self.url)
|
||||
|
||||
host, port = self.url.split(":")[1].strip("/"), self.url.split(':')[-1].strip("/")
|
||||
|
||||
capabilities = {"alwaysMatch": self.capabilities}
|
||||
self.webdriver = client.Session(host, port, capabilities=capabilities)
|
||||
self.webdriver.start()
|
||||
|
||||
|
||||
def after_conect(self):
|
||||
pass
|
||||
|
||||
def teardown(self):
|
||||
self.logger.debug("Hanging up on WebDriver session")
|
||||
try:
|
||||
self.webdriver.quit()
|
||||
except Exception:
|
||||
pass
|
||||
del self.webdriver
|
||||
|
||||
def is_alive(self):
|
||||
try:
|
||||
# Get a simple property over the connection
|
||||
self.webdriver.window_handle
|
||||
except (socket.timeout, client.UnknownErrorException):
|
||||
return False
|
||||
return True
|
||||
|
||||
def after_connect(self):
|
||||
self.testharness.load_runner(self.executor.last_environment["protocol"])
|
||||
|
||||
|
||||
class WebDriverRun(object):
|
||||
def __init__(self, func, protocol, url, timeout):
|
||||
self.func = func
|
||||
self.result = None
|
||||
self.protocol = protocol
|
||||
self.url = url
|
||||
self.timeout = timeout
|
||||
self.result_flag = threading.Event()
|
||||
|
||||
def run(self):
|
||||
timeout = self.timeout
|
||||
|
||||
try:
|
||||
self.protocol.base.set_timeout((timeout + extra_timeout))
|
||||
except client.UnknownErrorException:
|
||||
self.logger.error("Lost WebDriver connection")
|
||||
return Stop
|
||||
|
||||
executor = threading.Thread(target=self._run)
|
||||
executor.start()
|
||||
|
||||
flag = self.result_flag.wait(timeout + 2 * extra_timeout)
|
||||
if self.result is None:
|
||||
assert not flag
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
|
||||
return self.result
|
||||
|
||||
def _run(self):
|
||||
try:
|
||||
self.result = True, self.func(self.protocol, self.url, self.timeout)
|
||||
except client.TimeoutException:
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
except (socket.timeout, client.UnknownErrorException):
|
||||
self.result = False, ("CRASH", None)
|
||||
except Exception as e:
|
||||
if (isinstance(e, client.WebDriverException) and
|
||||
e.http_status == 408 and
|
||||
e.status_code == "asynchronous script timeout"):
|
||||
# workaround for https://bugs.chromium.org/p/chromedriver/issues/detail?id=2001
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
else:
|
||||
message = getattr(e, "message", "")
|
||||
if message:
|
||||
message += "\n"
|
||||
message += traceback.format_exc(e)
|
||||
self.result = False, ("ERROR", message)
|
||||
finally:
|
||||
self.result_flag.set()
|
||||
|
||||
|
||||
class WebDriverTestharnessExecutor(TestharnessExecutor):
|
||||
supports_testdriver = True
|
||||
|
||||
def __init__(self, browser, server_config, timeout_multiplier=1,
|
||||
close_after_done=True, capabilities=None, debug_info=None,
|
||||
**kwargs):
|
||||
"""WebDriver-based executor for testharness.js tests"""
|
||||
TestharnessExecutor.__init__(self, browser, server_config,
|
||||
timeout_multiplier=timeout_multiplier,
|
||||
debug_info=debug_info)
|
||||
self.protocol = WebDriverProtocol(self, browser, capabilities)
|
||||
with open(os.path.join(here, "testharness_webdriver.js")) as f:
|
||||
self.script = f.read()
|
||||
with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
|
||||
self.script_resume = f.read()
|
||||
self.close_after_done = close_after_done
|
||||
self.window_id = str(uuid.uuid4())
|
||||
|
||||
def is_alive(self):
|
||||
return self.protocol.is_alive()
|
||||
|
||||
def on_environment_change(self, new_environment):
|
||||
if new_environment["protocol"] != self.last_environment["protocol"]:
|
||||
self.protocol.testharness.load_runner(new_environment["protocol"])
|
||||
|
||||
def do_test(self, test):
|
||||
url = self.test_url(test)
|
||||
|
||||
success, data = WebDriverRun(self.do_testharness,
|
||||
self.protocol,
|
||||
url,
|
||||
test.timeout * self.timeout_multiplier).run()
|
||||
|
||||
if success:
|
||||
return self.convert_result(test, data)
|
||||
|
||||
return (test.result_cls(*data), [])
|
||||
|
||||
def do_testharness(self, protocol, url, timeout):
|
||||
format_map = {"abs_url": url,
|
||||
"url": strip_server(url),
|
||||
"window_id": self.window_id,
|
||||
"timeout_multiplier": self.timeout_multiplier,
|
||||
"timeout": timeout * 1000}
|
||||
|
||||
parent_window = protocol.testharness.close_old_windows()
|
||||
# Now start the test harness
|
||||
protocol.base.execute_script(self.script % format_map)
|
||||
test_window = protocol.testharness.get_test_window(self.window_id, parent_window)
|
||||
|
||||
handler = CallbackHandler(self.logger, protocol, test_window)
|
||||
while True:
|
||||
result = protocol.base.execute_script(
|
||||
self.script_resume % format_map, async=True)
|
||||
done, rv = handler(result)
|
||||
if done:
|
||||
break
|
||||
return rv
|
||||
|
||||
|
||||
class WebDriverRefTestExecutor(RefTestExecutor):
|
||||
def __init__(self, browser, server_config, timeout_multiplier=1,
|
||||
screenshot_cache=None, close_after_done=True,
|
||||
debug_info=None, capabilities=None, **kwargs):
|
||||
"""WebDriver-based executor for reftests"""
|
||||
RefTestExecutor.__init__(self,
|
||||
browser,
|
||||
server_config,
|
||||
screenshot_cache=screenshot_cache,
|
||||
timeout_multiplier=timeout_multiplier,
|
||||
debug_info=debug_info)
|
||||
self.protocol = WebDriverProtocol(self, browser,
|
||||
capabilities=capabilities)
|
||||
self.implementation = RefTestImplementation(self)
|
||||
self.close_after_done = close_after_done
|
||||
self.has_window = False
|
||||
|
||||
with open(os.path.join(here, "reftest.js")) as f:
|
||||
self.script = f.read()
|
||||
with open(os.path.join(here, "reftest-wait_webdriver.js")) as f:
|
||||
self.wait_script = f.read()
|
||||
|
||||
def is_alive(self):
|
||||
return self.protocol.is_alive()
|
||||
|
||||
def do_test(self, test):
|
||||
self.protocol.webdriver.window.size = (600, 600)
|
||||
|
||||
result = self.implementation.run_test(test)
|
||||
|
||||
return self.convert_result(test, result)
|
||||
|
||||
def screenshot(self, test, viewport_size, dpi):
|
||||
# https://github.com/w3c/wptrunner/issues/166
|
||||
assert viewport_size is None
|
||||
assert dpi is None
|
||||
|
||||
return WebDriverRun(self._screenshot,
|
||||
self.protocol,
|
||||
self.test_url(test),
|
||||
test.timeout).run()
|
||||
|
||||
def _screenshot(self, protocol, url, timeout):
|
||||
webdriver = protocol.webdriver
|
||||
webdriver.url = url
|
||||
|
||||
webdriver.execute_async_script(self.wait_script)
|
||||
|
||||
screenshot = webdriver.screenshot()
|
||||
|
||||
# strip off the data:img/png, part of the url
|
||||
if screenshot.startswith("data:image/png;base64,"):
|
||||
screenshot = screenshot.split(",", 1)[1]
|
||||
|
||||
return screenshot
|
|
@ -96,8 +96,12 @@ class LogHandler(reader.LogHandler):
|
|||
duration = data["time"] - test.pop("start_time")
|
||||
test["longest_duration"][data["status"]] = max(
|
||||
duration, test["longest_duration"][data["status"]])
|
||||
# test_timeout is in seconds; convert it to ms.
|
||||
test["timeout"] = data["extra"]["test_timeout"] * 1000
|
||||
try:
|
||||
# test_timeout is in seconds; convert it to ms.
|
||||
test["timeout"] = data["extra"]["test_timeout"] * 1000
|
||||
except KeyError:
|
||||
# If a test is skipped, it won't have extra info.
|
||||
pass
|
||||
|
||||
|
||||
def is_inconsistent(results_dict, iterations):
|
||||
|
@ -118,6 +122,8 @@ def find_slow_status(test):
|
|||
A result status produced by a run that almost times out; None, if no
|
||||
runs almost time out.
|
||||
"""
|
||||
if "timeout" not in test:
|
||||
return None
|
||||
threshold = test["timeout"] * FLAKY_THRESHOLD
|
||||
for status in ['PASS', 'FAIL', 'OK', 'ERROR']:
|
||||
if (status in test["longest_duration"] and
|
||||
|
|
|
@ -17,7 +17,9 @@ if "CURRENT_TOX_ENV" in os.environ:
|
|||
current_tox_env_split = os.environ["CURRENT_TOX_ENV"].split("-")
|
||||
|
||||
tox_env_extra_browsers = {
|
||||
"chrome": {"chrome_android"},
|
||||
"chrome": {"chrome_android", "chrome_webdriver"},
|
||||
"edge": {"edge_webdriver"},
|
||||
"safari": {"safari_webdriver"},
|
||||
"servo": {"servodriver"},
|
||||
}
|
||||
|
||||
|
|
|
@ -29,3 +29,5 @@ def test_find_slow_status():
|
|||
assert stability.find_slow_status({
|
||||
"longest_duration": {"TIMEOUT": 10, "FAIL": 81},
|
||||
"timeout": 100}) == "FAIL"
|
||||
assert stability.find_slow_status({
|
||||
"longest_duration": {"SKIP": 0}}) is None
|
||||
|
|
|
@ -96,11 +96,38 @@ class UpdateMetadata(Step):
|
|||
runner.run()
|
||||
|
||||
|
||||
class RemoveObsolete(Step):
|
||||
"""Remove metadata files that don't corespond to an existing test file"""
|
||||
|
||||
def create(self, state):
|
||||
if not state.kwargs["remove_obsolete"]:
|
||||
return
|
||||
|
||||
paths = state.kwargs["test_paths"]
|
||||
state.tests_path = state.paths["/"]["tests_path"]
|
||||
state.metadata_path = state.paths["/"]["metadata_path"]
|
||||
|
||||
for url_paths in paths.itervalues():
|
||||
tests_path = url_paths["tests_path"]
|
||||
metadata_path = url_paths["metadata_path"]
|
||||
for dirpath, dirnames, filenames in os.walk(metadata_path):
|
||||
for filename in filenames:
|
||||
if filename == "__dir__.ini":
|
||||
continue
|
||||
if filename.endswith(".ini"):
|
||||
full_path = os.path.join(dirpath, filename)
|
||||
rel_path = os.path.relpath(full_path, metadata_path)
|
||||
test_path = os.path.join(tests_path, rel_path[:-4])
|
||||
if not os.path.exists(test_path):
|
||||
os.unlink(full_path)
|
||||
|
||||
|
||||
class UpdateRunner(StepRunner):
|
||||
"""Runner for doing an overall update."""
|
||||
steps = [LoadConfig,
|
||||
LoadTrees,
|
||||
SyncFromUpstream,
|
||||
RemoveObsolete,
|
||||
UpdateMetadata]
|
||||
|
||||
|
||||
|
|
|
@ -565,8 +565,14 @@ def create_parser_update(product_choices=None):
|
|||
parser.add_argument("--stability", nargs="?", action="store", const="unstable", default=None,
|
||||
help=("Reason for disabling tests. When updating test results, disable tests that have "
|
||||
"inconsistent results across many runs with the given reason."))
|
||||
parser.add_argument("--continue", action="store_true", help="Continue a previously started run of the update script")
|
||||
parser.add_argument("--abort", action="store_true", help="Clear state from a previous incomplete run of the update script")
|
||||
parser.add_argument("--no-remove-obsolete", action="store_false", dest="remove_obsolete", default=True,
|
||||
help=("Don't remove metadata files that no longer correspond to a test file"))
|
||||
parser.add_argument("--no-store-state", action="store_false", dest="store_state",
|
||||
help="Store state so that steps can be resumed after failure")
|
||||
parser.add_argument("--continue", action="store_true",
|
||||
help="Continue a previously started run of the update script")
|
||||
parser.add_argument("--abort", action="store_true",
|
||||
help="Clear state from a previous incomplete run of the update script")
|
||||
parser.add_argument("--exclude", action="store", nargs="*",
|
||||
help="List of glob-style paths to exclude when syncing tests")
|
||||
parser.add_argument("--include", action="store", nargs="*",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue