Update web-platform-tests to revision 5084587f6b05bf99ad09e7844be66dcc61070cdf

This commit is contained in:
WPT Sync Bot 2018-04-25 21:10:30 -04:00 committed by Anthony Ramine
parent 6d42d2f1e8
commit 7d1071a6a4
408 changed files with 8968 additions and 2608 deletions

View file

@ -0,0 +1,7 @@
#!/bin/bash
if [ $1 == "firefox" ]; then
./wpt run firefox --log-tbpl=- --log-tbpl-level=debug --log-wptreport=../artifacts/wpt_report.json --this-chunk=$3 --total-chunks=$4 --test-type=$2 -y --install-browser --no-pause --no-restart-on-unexpected
elif [ $1 == "chrome" ]; then
./wpt run chrome --log-tbpl=- --log-tbpl-level=debug --log-wptreport=../artifacts/wpt_report.json --this-chunk=$3 --total-chunks=$4 --test-type=$2 -y --no-pause --no-restart-on-unexpected
fi

View file

@ -3,5 +3,7 @@
"virtualenv": false},
"check-stability": {"path": "check_stability.py", "script": "run", "parser": "get_parser", "parse_known": true, "help": "Check test stability",
"virtualenv": true, "install": ["requests"], "requirements": ["../wptrunner/requirements.txt"]},
"make-hosts-file": {"path": "make_hosts_file.py", "script": "run", "parser": "create_parser", "help": "Output a hosts file to stdout", "virtualenv": false}
"make-hosts-file": {"path": "make_hosts_file.py", "script": "run", "parser": "create_parser", "help": "Output a hosts file to stdout", "virtualenv": false},
"make-tasks": {"path": "taskgraph.py", "script": "run", "parser": "get_parser", "parse_known": true, "help": "Generate taskcluster.yml file containing the run tasks",
"virtualenv": true, "install": ["pyyaml"]}
}

View file

@ -0,0 +1,123 @@
import argparse
import copy
import os
import six
import yaml
here = os.path.dirname(__file__)
wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))
task_template = {
"provisionerId": "{{ taskcluster.docker.provisionerId }}",
"workerType": "{{ taskcluster.docker.workerType }}",
"extra": {
"github": {
"events": ["push"],
"branches": ["master"],
},
},
"payload": {
"maxRunTime": 5400,
"image": "harjgam/web-platform-tests:0.6",
"command":[
"/bin/bash",
"--login",
"-c",
""">-
~/start.sh &&
cd /home/test/web-platform-tests &&
git fetch {{event.head.repo.url}} &&
git config advice.detachedHead false &&
git checkout {{event.head.sha}} &&
%(command)s"""],
"artifacts": {
"public/results": {
"path": "/home/test/artifacts",
"type": "directory"
}
}
},
"metadata": {
"name": "wpt-%(browser_name)s-%(suite)s-%(chunk)s",
"description": "",
"owner": "{{ event.head.user.email }}",
"source": "{{ event.head.repo.url }}",
}
}
file_template = {
"version": 0,
"tasks": [],
"allowPullRequests": "collaborators"
}
suites = {
"testharness": {"chunks": 12},
"reftest": {"chunks": 6},
"wdspec": {"chunks": 1}
}
browsers = {
"firefox": {"name": "firefox-nightly"},
"chrome": {"name": "chrome-dev"}
}
def get_parser():
parser = argparse.ArgumentParser()
parser.add_argument("--dest",
action="store",
default=wpt_root,
help="Directory to write the .taskcluster.yml file to")
return parser
def fill(template, data):
rv = {}
for key, value in template.iteritems():
rv[key] = fill_inner(value, data)
return rv
def fill_inner(value, data):
if isinstance(value, six.string_types):
return value % data
elif isinstance(value, dict):
return fill(value, data)
elif isinstance(value, list):
return [fill_inner(item, data) for item in value]
elif isinstance(value, (float,) + six.integer_types):
return value
else:
raise ValueError
def run(venv, *args, **kwargs):
if not os.path.isdir(kwargs["dest"]):
raise ValueError("Invalid directory %s" % kwargs["dest"])
task_config = copy.deepcopy(file_template)
for browser, browser_props in browsers.iteritems():
for suite, suite_props in suites.iteritems():
total_chunks = suite_props.get("chunks", 1)
for chunk in six.moves.xrange(1, total_chunks + 1):
data = {
"suite": suite,
"chunk": chunk,
"browser_name": browser_props["name"],
"command": ("./tools/ci/ci_taskcluster.sh %s %s %s %s" %
(browser, suite, chunk, total_chunks))
}
task_data = fill(task_template, data)
task_config["tasks"].append(task_data)
with open(os.path.join(kwargs["dest"], ".taskcluster.yml"), "w") as f:
f.write("""# GENERATED FILE DO NOT EDIT
# To regenerate this file run ./wpt make-tasks
""")
yaml.dump(task_config, f)

View file

@ -0,0 +1,4 @@
function xvfb_start() {
GEOMETRY="$SCREEN_WIDTH""x""$SCREEN_HEIGHT""x""$SCREEN_DEPTH"
xvfb-run --server-args="-screen 0 $GEOMETRY -ac +extension RANDR" $@
}

View file

@ -0,0 +1,76 @@
FROM ubuntu:16.04
# No interactive frontend during docker build
ENV DEBIAN_FRONTEND=noninteractive \
DEBCONF_NONINTERACTIVE_SEEN=true
# General requirements not in the base image
RUN apt-get -qqy update \
&& apt-get -qqy install \
bzip2 \
ca-certificates \
dbus-x11 \
gdebi \
git \
locales \
pulseaudio \
python \
python-pip \
tzdata \
sudo \
unzip \
wget \
xvfb
# Installing just the deps of firefox and chrome is moderately tricky, so
# just install the default versions of them, and some extra deps we happen
# to know that chrome requires
RUN apt-get -qqy install \
firefox \
libnss3-tools \
fonts-liberation \
indicator-application \
libappindicator1 \
libappindicator3-1 \
libdbusmenu-gtk3-4 \
libindicator3-7 \
libindicator7
RUN pip install --upgrade pip
RUN pip install virtualenv
ENV TZ "UTC"
RUN echo "${TZ}" > /etc/timezone \
&& dpkg-reconfigure --frontend noninteractive tzdata
RUN useradd test \
--shell /bin/bash \
--create-home \
&& usermod -a -G sudo test \
&& echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \
&& echo 'test:secret' | chpasswd
ENV SCREEN_WIDTH 1280
ENV SCREEN_HEIGHT 1024
ENV SCREEN_DEPTH 24
ENV DISPLAY :99.0
USER test
WORKDIR /home/test
COPY .bashrc /home/test/.bashrc
COPY start.sh /home/test/start.sh
# Remove information on how to use sudo on login
RUN sudo echo ""
RUN git clone --depth=1 https://github.com/w3c/web-platform-tests.git
RUN mkdir -p /home/test/.fonts && \
cp web-platform-tests/fonts/Ahem.ttf ~/.fonts && \
fc-cache -f -v
RUN mkdir -p /home/test/artifacts

View file

@ -0,0 +1,14 @@
#!/bin/bash
cd web-platform-tests
git pull --depth=1
sudo sh -c './wpt make-hosts-file >> /etc/hosts'
# Install Chome dev
deb_archive=google-chrome-unstable_current_amd64.deb
wget https://dl.google.com/linux/direct/$deb_archive
sudo gdebi -n $deb_archive
sudo Xvfb $DISPLAY -screen 0 ${SCREEN_WIDTH}x${SCREEN_HEIGHT}x${SCREEN_DEPTH} &

View file

@ -18,7 +18,7 @@ from .. import localpaths
from ..gitignore.gitignore import PathFilter
from ..wpt import testfiles
from manifest.sourcefile import SourceFile, js_meta_re, python_meta_re, space_chars
from manifest.sourcefile import SourceFile, js_meta_re, python_meta_re, space_chars, get_any_variants, get_default_any_variants
from six import binary_type, iteritems, itervalues
from six.moves import range
from six.moves.urllib.parse import urlsplit, urljoin
@ -616,6 +616,31 @@ broken_js_metadata = re.compile(b"//\s*META:")
broken_python_metadata = re.compile(b"#\s*META:")
def check_global_metadata(value):
global_values = {item.strip() for item in value.split(b",") if item.strip()}
included_variants = set.union(get_default_any_variants(),
*(get_any_variants(v) for v in global_values if not v.startswith(b"!")))
for global_value in global_values:
if global_value.startswith(b"!"):
excluded_value = global_value[1:]
if not get_any_variants(excluded_value):
yield ("UNKNOWN-GLOBAL-METADATA", "Unexpected value for global metadata")
elif excluded_value in global_values:
yield ("BROKEN-GLOBAL-METADATA", "Cannot specify both %s and %s" % (global_value, excluded_value))
else:
excluded_variants = get_any_variants(excluded_value)
if not (excluded_variants & included_variants):
yield ("BROKEN-GLOBAL-METADATA", "Cannot exclude %s if it is not included" % (excluded_value,))
else:
if not get_any_variants(global_value):
yield ("UNKNOWN-GLOBAL-METADATA", "Unexpected value for global metadata")
def check_script_metadata(repo_root, path, f):
if path.endswith((".worker.js", ".any.js")):
meta_re = js_meta_re
@ -634,7 +659,9 @@ def check_script_metadata(repo_root, path, f):
m = meta_re.match(line)
if m:
key, value = m.groups()
if key == b"timeout":
if key == b"global":
errors.extend((kind, message, path, idx + 1) for (kind, message) in check_global_metadata(value))
elif key == b"timeout":
if value != b"long":
errors.append(("UNKNOWN-TIMEOUT-METADATA", "Unexpected value for timeout metadata", path, idx + 1))
elif key == b"script":

View file

@ -559,6 +559,39 @@ def test_script_metadata(filename, input, error):
assert errors == []
@pytest.mark.parametrize("globals,error", [
(b"", None),
(b"default", None),
(b"!default", None),
(b"window", None),
(b"!window", None),
(b"!dedicatedworker", None),
(b"window, !window", "BROKEN-GLOBAL-METADATA"),
(b"!serviceworker", "BROKEN-GLOBAL-METADATA"),
(b"serviceworker, !serviceworker", "BROKEN-GLOBAL-METADATA"),
(b"worker, !dedicatedworker", None),
(b"worker, !serviceworker", None),
(b"!worker", None),
(b"foo", "UNKNOWN-GLOBAL-METADATA"),
(b"!foo", "UNKNOWN-GLOBAL-METADATA"),
])
def test_script_globals_metadata(globals, error):
filename = "foo.any.js"
input = b"""// META: global=%s\n""" % globals
errors = check_file_contents("", filename, six.BytesIO(input))
check_errors(errors)
if error is not None:
errors = [(k, f, l) for (k, _, f, l) in errors]
assert errors == [
(error,
filename,
1),
]
else:
assert errors == []
@pytest.mark.parametrize("input,error", [
(b"""#META: timeout=long\n""", None),
(b"""# META: timeout=long\n""", None),

View file

@ -49,6 +49,87 @@ def read_script_metadata(f, regexp):
yield (m.groups()[0], m.groups()[1])
_any_variants = {
b"default": {"longhand": {b"window", b"dedicatedworker"}},
b"window": {"suffix": ".any.html"},
b"serviceworker": {"force_https": True},
b"sharedworker": {},
b"dedicatedworker": {"suffix": ".any.worker.html"},
b"worker": {"longhand": {b"dedicatedworker", b"sharedworker", b"serviceworker"}}
}
def get_any_variants(item):
"""
Returns a set of variants (bytestrings) defined by the given keyword.
"""
assert isinstance(item, binary_type), item
assert not item.startswith(b"!"), item
variant = _any_variants.get(item, None)
if variant is None:
return set()
return variant.get("longhand", {item})
def get_default_any_variants():
"""
Returns a set of variants (bytestrings) that will be used by default.
"""
return set(_any_variants[b"default"]["longhand"])
def parse_variants(value):
"""
Returns a set of variants (bytestrings) defined by a comma-separated value.
"""
assert isinstance(value, binary_type), value
globals = get_default_any_variants()
for item in value.split(b","):
item = item.strip()
if item.startswith(b"!"):
globals -= get_any_variants(item[1:])
else:
globals |= get_any_variants(item)
return globals
def global_suffixes(value):
"""
Yields the relevant filename suffixes (strings) for the variants defined by
the given comma-separated value.
"""
assert isinstance(value, binary_type), value
rv = set()
global_types = parse_variants(value)
for global_type in global_types:
variant = _any_variants[global_type]
suffix = variant.get("suffix", ".any.%s.html" % global_type.decode("utf-8"))
if variant.get("force_https", False):
suffix = ".https" + suffix
rv.add(suffix)
return rv
def global_variant_url(url, suffix):
"""
Returns a url created from the given url and suffix (all strings).
"""
url = url.replace(".any.", ".")
# If the url must be loaded over https, ensure that it will have
# the form .https.any.js
if ".https." in url and suffix.startswith(".https."):
url = url.replace(".https.", ".")
return replace_end(url, ".js", suffix)
class SourceFile(object):
parsers = {"html":lambda x:html5lib.parse(x, treebuilder="etree"),
"xhtml":lambda x:ElementTree.parse(x, XMLParser.XMLParser()),
@ -370,11 +451,18 @@ class SourceFile(object):
@cached_property
def test_variants(self):
rv = []
for element in self.variant_nodes:
if "content" in element.attrib:
variant = element.attrib["content"]
assert variant == "" or variant[0] in ["#", "?"]
rv.append(variant)
if self.ext == ".js":
for (key, value) in self.script_metadata:
if key == b"variant":
rv.append(value.decode("utf-8"))
else:
for element in self.variant_nodes:
if "content" in element.attrib:
variant = element.attrib["content"]
rv.append(variant)
for variant in rv:
assert variant == "" or variant[0] in ["#", "?"], variant
if not rv:
rv = [""]
@ -510,22 +598,34 @@ class SourceFile(object):
rv = VisualTest.item_type, [VisualTest(self, self.url)]
elif self.name_is_multi_global:
rv = TestharnessTest.item_type, [
TestharnessTest(self, replace_end(self.url, ".any.js", ".any.html"),
timeout=self.timeout),
TestharnessTest(self, replace_end(self.url, ".any.js", ".any.worker.html"),
timeout=self.timeout),
globals = b""
for (key, value) in self.script_metadata:
if key == b"global":
globals = value
break
tests = [
TestharnessTest(self, global_variant_url(self.url, suffix) + variant, timeout=self.timeout)
for suffix in sorted(global_suffixes(globals))
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_worker:
rv = (TestharnessTest.item_type,
[TestharnessTest(self, replace_end(self.url, ".worker.js", ".worker.html"),
timeout=self.timeout)])
test_url = replace_end(self.url, ".worker.js", ".worker.html")
tests = [
TestharnessTest(self, test_url + variant, timeout=self.timeout)
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_window:
rv = (TestharnessTest.item_type,
[TestharnessTest(self, replace_end(self.url, ".window.js", ".window.html"),
timeout=self.timeout)])
test_url = replace_end(self.url, ".window.js", ".window.html")
tests = [
TestharnessTest(self, test_url + variant, timeout=self.timeout)
for variant in self.test_variants
]
rv = TestharnessTest.item_type, tests
elif self.name_is_webdriver:
rv = WebdriverSpecTest.item_type, [WebdriverSpecTest(self, self.url,

View file

@ -3,6 +3,7 @@ import os
import pytest
from six import BytesIO
from ...lint.lint import check_global_metadata
from ..sourcefile import SourceFile, read_script_metadata, js_meta_re, python_meta_re
def create(filename, contents=b""):
@ -201,6 +202,66 @@ test()"""
assert item.timeout == "long"
def test_worker_with_variants():
contents = b"""// META: variant=
// META: variant=?wss
test()"""
s = create("html/test.worker.js", contents=contents)
assert not s.name_is_non_test
assert not s.name_is_manual
assert not s.name_is_visual
assert not s.name_is_multi_global
assert s.name_is_worker
assert not s.name_is_window
assert not s.name_is_reference
assert not s.content_is_testharness
item_type, items = s.manifest_items()
assert item_type == "testharness"
expected_urls = [
"/html/test.worker.html" + suffix
for suffix in ["", "?wss"]
]
assert len(items) == len(expected_urls)
for item, url in zip(items, expected_urls):
assert item.url == url
assert item.timeout is None
def test_window_with_variants():
contents = b"""// META: variant=
// META: variant=?wss
test()"""
s = create("html/test.window.js", contents=contents)
assert not s.name_is_non_test
assert not s.name_is_manual
assert not s.name_is_visual
assert not s.name_is_multi_global
assert not s.name_is_worker
assert s.name_is_window
assert not s.name_is_reference
assert not s.content_is_testharness
item_type, items = s.manifest_items()
assert item_type == "testharness"
expected_urls = [
"/html/test.window.html" + suffix
for suffix in ["", "?wss"]
]
assert len(items) == len(expected_urls)
for item, url in zip(items, expected_urls):
assert item.url == url
assert item.timeout is None
def test_python_long_timeout():
contents = b"""# META: timeout=long
@ -263,6 +324,99 @@ test()"""
assert item.timeout == "long"
@pytest.mark.parametrize("input,expected", [
(b"", {"dedicatedworker", "window"}),
(b"default", {"dedicatedworker", "window"}),
(b"!default", {}),
(b"!default,window", {"window"}),
(b"window,!default", {}),
(b"!default,dedicatedworker", {"dedicatedworker"}),
(b"dedicatedworker,!default", {}),
(b"!default,worker", {"dedicatedworker", "serviceworker", "sharedworker"}),
(b"worker,!default", {"serviceworker", "sharedworker"}),
(b"!dedicatedworker", {"window"}),
(b"!worker", {"window"}),
(b"!window", {"dedicatedworker"}),
(b"!window,worker", {"dedicatedworker", "serviceworker", "sharedworker"}),
(b"worker,!dedicatedworker", {"serviceworker", "sharedworker", "window"}),
(b"!dedicatedworker,worker", {"dedicatedworker", "serviceworker", "sharedworker", "window"}),
(b"worker,!sharedworker", {"dedicatedworker", "serviceworker", "window"}),
(b"!sharedworker,worker", {"dedicatedworker", "serviceworker", "sharedworker", "window"}),
(b"sharedworker", {"dedicatedworker", "sharedworker", "window"}),
(b"sharedworker,serviceworker", {"dedicatedworker", "serviceworker", "sharedworker", "window"}),
])
def test_multi_global_with_custom_globals(input, expected):
contents = b"""// META: global=%s
test()""" % input
assert list(check_global_metadata(input)) == []
s = create("html/test.any.js", contents=contents)
assert not s.name_is_non_test
assert not s.name_is_manual
assert not s.name_is_visual
assert s.name_is_multi_global
assert not s.name_is_worker
assert not s.name_is_reference
assert not s.content_is_testharness
item_type, items = s.manifest_items()
assert item_type == "testharness"
urls = {
"dedicatedworker": "/html/test.any.worker.html",
"serviceworker": "/html/test.https.any.serviceworker.html",
"sharedworker": "/html/test.any.sharedworker.html",
"window": "/html/test.any.html",
}
expected_urls = sorted(urls[ty] for ty in expected)
assert len(items) == len(expected_urls)
for item, url in zip(items, expected_urls):
assert item.url == url
assert item.timeout is None
def test_multi_global_with_variants():
contents = b"""// META: global=window,worker
// META: variant=
// META: variant=?wss
test()"""
s = create("html/test.any.js", contents=contents)
assert not s.name_is_non_test
assert not s.name_is_manual
assert not s.name_is_visual
assert s.name_is_multi_global
assert not s.name_is_worker
assert not s.name_is_reference
assert not s.content_is_testharness
item_type, items = s.manifest_items()
assert item_type == "testharness"
urls = {
"dedicatedworker": "/html/test.any.worker.html",
"serviceworker": "/html/test.https.any.serviceworker.html",
"sharedworker": "/html/test.any.sharedworker.html",
"window": "/html/test.any.html",
}
expected_urls = sorted(
urls[ty] + suffix
for ty in ["dedicatedworker", "serviceworker", "sharedworker", "window"]
for suffix in ["", "?wss"]
)
assert len(items) == len(expected_urls)
for item, url in zip(items, expected_urls):
assert item.url == url
assert item.timeout is None
@pytest.mark.parametrize("input,expected", [
(b"""//META: foo=bar\n""", [(b"foo", b"bar")]),
(b"""// META: foo=bar\n""", [(b"foo", b"bar")]),

View file

@ -20,13 +20,13 @@ from multiprocessing import Process, Event
from localpaths import repo_root
import sslutils
from manifest.sourcefile import read_script_metadata, js_meta_re
from manifest.sourcefile import read_script_metadata, js_meta_re, parse_variants
from wptserve import server as wptserve, handlers
from wptserve import stash
from wptserve import config
from wptserve.logger import set_logger
from wptserve.handlers import filesystem_path, wrap_pipeline
from wptserve.utils import get_port
from wptserve.utils import get_port, HTTPException
from mod_pywebsocket import standalone as pywebsocket
def replace_end(s, old, new):
@ -56,9 +56,14 @@ class WrapperHandler(object):
for header_name, header_value in self.headers:
response.headers.set(header_name, header_value)
self.check_exposure(request)
path = self._get_path(request.url_parts.path, True)
query = request.url_parts.query
if query:
query = "?" + query
meta = "\n".join(self._get_meta(request))
response.content = self.wrapper % {"meta": meta, "path": path}
response.content = self.wrapper % {"meta": meta, "path": path, "query": query}
wrap_pipeline(path, request, response)
def _get_path(self, path, resource_path):
@ -85,18 +90,27 @@ class WrapperHandler(object):
path = replace_end(path, src, dest)
return path
def _get_meta(self, request):
"""Get an iterator over strings to inject into the wrapper document
based on //META comments in the associated js file.
def _get_metadata(self, request):
"""Get an iterator over script metadata based on //META comments in the
associated js file.
:param request: The Request being processed.
"""
path = self._get_path(filesystem_path(self.base_path, request, self.url_base), False)
with open(path, "rb") as f:
for key, value in read_script_metadata(f, js_meta_re):
replacement = self._meta_replacement(key, value)
if replacement:
yield replacement
yield key, value
def _get_meta(self, request):
"""Get an iterator over strings to inject into the wrapper document
based on //META comments in the associated js file.
:param request: The Request being processed.
"""
for key, value in self._get_metadata(request):
replacement = self._meta_replacement(key, value)
if replacement:
yield replacement
@abc.abstractproperty
def path_replace(self):
@ -118,8 +132,27 @@ class WrapperHandler(object):
# a specific metadata key: value pair.
pass
@abc.abstractmethod
def check_exposure(self, request):
# Raise an exception if this handler shouldn't be exposed after all.
pass
class HtmlWrapperHandler(WrapperHandler):
global_type = None
def check_exposure(self, request):
if self.global_type:
globals = b""
for (key, value) in self._get_metadata(request):
if key == b"global":
globals = value
break
if self.global_type not in parse_variants(globals):
raise HTTPException(404, "This test cannot be loaded in %s mode" %
self.global_type)
def _meta_replacement(self, key, value):
if key == b"timeout":
if value == b"long":
@ -131,6 +164,7 @@ class HtmlWrapperHandler(WrapperHandler):
class WorkersHandler(HtmlWrapperHandler):
global_type = b"dedicatedworker"
path_replace = [(".any.worker.html", ".any.js", ".any.worker.js"),
(".worker.html", ".worker.js")]
wrapper = """<!doctype html>
@ -140,7 +174,7 @@ class WorkersHandler(HtmlWrapperHandler):
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
fetch_tests_from_worker(new Worker("%(path)s"));
fetch_tests_from_worker(new Worker("%(path)s%(query)s"));
</script>
"""
@ -158,6 +192,7 @@ class WindowHandler(HtmlWrapperHandler):
class AnyHtmlHandler(HtmlWrapperHandler):
global_type = b"window"
path_replace = [(".any.html", ".any.js")]
wrapper = """<!doctype html>
<meta charset=utf-8>
@ -175,6 +210,42 @@ self.GLOBAL = {
"""
class SharedWorkersHandler(HtmlWrapperHandler):
global_type = b"sharedworker"
path_replace = [(".any.sharedworker.html", ".any.js", ".any.worker.js")]
wrapper = """<!doctype html>
<meta charset=utf-8>
%(meta)s
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
fetch_tests_from_worker(new SharedWorker("%(path)s%(query)s"));
</script>
"""
class ServiceWorkersHandler(HtmlWrapperHandler):
global_type = b"serviceworker"
path_replace = [(".https.any.serviceworker.html", ".any.js", ".any.worker.js")]
wrapper = """<!doctype html>
<meta charset=utf-8>
%(meta)s
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
(async function() {
const scope = 'does/not/exist';
let reg = await navigator.serviceWorker.getRegistration(scope);
if (reg) await reg.unregister();
reg = await navigator.serviceWorker.register("%(path)s%(query)s", {scope});
fetch_tests_from_worker(reg.installing);
})();
</script>
"""
class AnyWorkerHandler(WrapperHandler):
headers = [('Content-Type', 'text/javascript')]
path_replace = [(".any.worker.js", ".any.js")]
@ -189,8 +260,6 @@ done();
"""
def _meta_replacement(self, key, value):
if key == b"timeout":
return None
if key == b"script":
attribute = value.decode('utf-8').replace("\\", "\\\\").replace('"', '\\"')
return 'importScripts("%s")' % attribute
@ -243,6 +312,8 @@ class RoutesBuilder(object):
("GET", "*.worker.html", WorkersHandler),
("GET", "*.window.html", WindowHandler),
("GET", "*.any.html", AnyHtmlHandler),
("GET", "*.any.sharedworker.html", SharedWorkersHandler),
("GET", "*.https.any.serviceworker.html", ServiceWorkersHandler),
("GET", "*.any.worker.js", AnyWorkerHandler),
("GET", "*.asis", handlers.AsIsHandler),
("*", "*.py", handlers.PythonScriptHandler),

View file

@ -457,7 +457,8 @@ def run(venv, **kwargs):
def run_single(venv, **kwargs):
from wptrunner import wptrunner
return wptrunner.start(**kwargs)
wptrunner.start(**kwargs)
return
def main():

View file

@ -153,10 +153,10 @@ class TestExecutor(object):
:param test: The test to run"""
if test.environment != self.last_environment:
self.on_environment_change(test.environment)
try:
result = self.do_test(test)
except Exception as e:
self.logger.warning(traceback.format_exc(e))
result = self.result_from_exception(test, e)
if result is Stop:
@ -547,6 +547,7 @@ class CallbackHandler(object):
def _send_message(self, message_type, status, message=None):
self.protocol.testdriver.send_message(message_type, status, message=message)
class ClickAction(object):
def __init__(self, logger, protocol):
self.logger = logger
@ -562,6 +563,7 @@ class ClickAction(object):
self.logger.debug("Clicking element: %s" % selector)
self.protocol.click.element(elements[0])
class SendKeysAction(object):
def __init__(self, logger, protocol):
self.logger = logger

View file

@ -475,7 +475,8 @@ class ExecuteAsyncScriptRun(object):
if message:
message += "\n"
message += traceback.format_exc(e)
self.result = False, ("INTERNAL-ERROR", e)
self.logger.warning(message)
self.result = False, ("INTERNAL-ERROR", None)
finally:
self.result_flag.set()
@ -551,6 +552,9 @@ class MarionetteTestharnessExecutor(TestharnessExecutor):
while True:
result = protocol.base.execute_script(
self.script_resume % format_map, async=True)
if result is None:
# This can happen if we get an content process crash
return None
done, rv = handler(result)
if done:
break

View file

@ -594,7 +594,8 @@ class TestRunnerManager(threading.Thread):
((subtest_unexpected or is_unexpected) and
self.restart_on_unexpected))
if (self.pause_after_test or
if (not file_result.status == "CRASH" and
self.pause_after_test or
(self.pause_on_unexpected and (subtest_unexpected or is_unexpected))):
self.logger.info("Pausing until the browser exits")
self.send_message("wait")