Commit 44093a32 authored by Luke Zielinski's avatar Luke Zielinski Committed by Commit Bot

Roll internal WPT tools

This rolls up to 4b8a64638b4c06fb38eb562b754eae389b381ec0

Assorted changes, including webkitgtk_minobrowser support and mojojs
improvements

Change-Id: I2a806f1a0040394541fbe52f749f3ab69d3820a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2453794Reviewed-by: default avatarRobert Ma <robertma@chromium.org>
Commit-Queue: Luke Z <lpz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814352}
parent 3d03da81
......@@ -22,7 +22,7 @@ Local Modifications: None
Name: web-platform-tests - Test Suites for Web Platform specifications
Short Name: wpt
URL: https://github.com/web-platform-tests/wpt/
Version: 9f6a7e3cfdae54795a0ca58e194b828537f9659e
Version: 4b8a64638b4c06fb38eb562b754eae389b381ec0
License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html)
License File: wpt/wpt/LICENSE.md
Security Critical: no
......
......@@ -9,7 +9,7 @@ cd $DIR
TARGET_DIR=$DIR/wpt
REMOTE_REPO="https://github.com/web-platform-tests/wpt.git"
WPT_HEAD=9f6a7e3cfdae54795a0ca58e194b828537f9659e
WPT_HEAD=4b8a64638b4c06fb38eb562b754eae389b381ec0
function clone {
# Remove existing repo if already exists.
......
......@@ -581,7 +581,7 @@ class Session(object):
return self.send_session_command("GET", "source")
@command
def new_window(self, type_hint=None):
def new_window(self, type_hint="tab"):
body = {"type": type_hint}
value = self.send_session_command("POST", "window/new", body)
......
......@@ -2,6 +2,7 @@ import json
import select
from six import text_type, PY3
from six.moves.collections_abc import Mapping
from six.moves.http_client import HTTPConnection
from six.moves.urllib import parse as urlparse
......@@ -10,6 +11,56 @@ from . import error
"""Implements HTTP transport for the WebDriver wire protocol."""
missing = object()
class ResponseHeaders(Mapping):
"""Read-only dictionary-like API for accessing response headers.
This class:
* Normalizes the header keys it is built with to lowercase (such that
iterating the items will return lowercase header keys).
* Has case-insensitive header lookup.
* Always returns all header values that have the same name, separated by
commas.
It does not ensure header types (e.g. binary vs string).
"""
def __init__(self, items):
self.headers_dict = {}
for key, value in items:
key = key.lower()
if key not in self.headers_dict:
self.headers_dict[key] = []
self.headers_dict[key].append(value)
def __getitem__(self, key):
"""Get all headers of a certain (case-insensitive) name. If there is
more than one, the values are returned comma separated"""
values = self.headers_dict[key.lower()]
if len(values) == 1:
return values[0]
else:
return ", ".join(values)
def get_list(self, key, default=missing):
"""Get all the header values for a particular field name as a list"""
try:
return self.headers_dict[key.lower()]
except KeyError:
if default is not missing:
return default
else:
raise
def __iter__(self):
for item in self.headers_dict:
yield item
def __len__(self):
return len(self.headers_dict)
class Response(object):
"""
Describes an HTTP response received from a remote end whose
......@@ -40,7 +91,7 @@ class Response(object):
def from_http(cls, http_response, decoder=json.JSONDecoder, **kwargs):
try:
body = json.load(http_response, cls=decoder, **kwargs)
headers = dict(http_response.getheaders())
headers = ResponseHeaders(http_response.getheaders())
except ValueError:
raise ValueError("Failed to decode response body as JSON:\n" +
http_response.read())
......
......@@ -7,7 +7,8 @@ latest_channels = {
'chrome_android': 'dev',
'edgechromium': 'dev',
'safari': 'preview',
'servo': 'nightly'
'servo': 'nightly',
'webkitgtk_minibrowser': 'nightly'
}
channel_by_name = {
......
......@@ -322,16 +322,21 @@ class Chrome(BrowserSetup):
kwargs["binary"] = binary
else:
raise WptrunError("Unable to locate Chrome binary")
if kwargs["mojojs_path"]:
kwargs["enable_mojojs"] = True
logger.info("--mojojs-path is provided, enabling MojoJS")
# TODO(Hexcles): Enable this everywhere when Chrome 86 becomes stable.
if browser_channel in self.experimental_channels:
elif browser_channel in self.experimental_channels:
try:
self.browser.install_mojojs(
path = self.browser.install_mojojs(
dest=self.venv.path,
channel=browser_channel,
browser_binary=kwargs["binary"],
)
kwargs["mojojs_path"] = path
kwargs["enable_mojojs"] = True
logger.info("MojoJS enabled")
logger.info("MojoJS enabled automatically (mojojs_path: %s)" % path)
except Exception as e:
logger.error("Cannot enable MojoJS: %s" % e)
......@@ -662,18 +667,19 @@ class WebKitGTKMiniBrowser(BrowserSetup):
browser_cls = browser.WebKitGTKMiniBrowser
def install(self, channel=None):
raise NotImplementedError
if self.prompt_install(self.name):
return self.browser.install(self.venv.path, channel, self.prompt)
def setup_kwargs(self, kwargs):
if kwargs["binary"] is None:
binary = self.browser.find_binary(channel=kwargs["browser_channel"])
binary = self.browser.find_binary(venv_path=self.venv.path, channel=kwargs["browser_channel"])
if binary is None:
raise WptrunError("Unable to find MiniBrowser binary")
kwargs["binary"] = binary
if kwargs["webdriver_binary"] is None:
webdriver_binary = self.browser.find_webdriver(channel=kwargs["browser_channel"])
webdriver_binary = self.browser.find_webdriver(venv_path=self.venv.path, channel=kwargs["browser_channel"])
if webdriver_binary is None:
raise WptrunError("Unable to find WebKitWebDriver in PATH")
......
......@@ -5,8 +5,11 @@ import shutil
import stat
import subprocess
import tarfile
import time
import zipfile
from io import BytesIO
from socket import error as SocketError # NOQA: N812
from six.moves.urllib.request import urlopen
MYPY = False
if MYPY:
......@@ -100,6 +103,41 @@ def get(url):
return resp
def get_download_to_descriptor(fd, url, max_retries=5):
"""Download an URL in chunks and saves it to a file descriptor (truncating it)
It doesn't close the descriptor, but flushes it on success.
It retries the download in case of ECONNRESET up to max_retries.
This function is meant to download big files directly to the disk without
caching the whole file in memory.
"""
if max_retries < 1:
max_retries = 1
wait = 2
for current_retry in range(1, max_retries+1):
try:
logger.info("Downloading %s Try %d/%d" % (url, current_retry, max_retries))
resp = urlopen(url)
# We may come here in a retry, ensure to truncate fd before start writing.
fd.seek(0)
fd.truncate(0)
while True:
chunk = resp.read(16*1024)
if not chunk:
break # Download finished
fd.write(chunk)
fd.flush()
# Success
return
except SocketError as e:
if current_retry < max_retries and e.errno == errno.ECONNRESET:
# Retry
logger.error("Connection reset by peer. Retrying after %ds..." % wait)
time.sleep(wait)
wait *= 2
else:
# Maximum retries or unknown error
raise
def rmtree(path):
# This works around two issues:
# 1. Cannot delete read-only files owned by us (e.g. files extracted from tarballs)
......@@ -114,3 +152,13 @@ def rmtree(path):
raise
return shutil.rmtree(path, onerror=handle_remove_readonly)
def sha256sum(file_path):
"""Computes the SHA256 hash sum of a file"""
from hashlib import sha256
hash = sha256()
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b''):
hash.update(chunk)
return hash.hexdigest()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment