diff --git a/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini b/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini deleted file mode 100644 index f64b45fea6b..00000000000 --- a/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-002.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[hit-test-floats-002.html] - [Hit test float] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-004.html.ini b/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-004.html.ini new file mode 100644 index 00000000000..4bfb0c2053a --- /dev/null +++ b/tests/wpt/metadata-layout-2020/css/CSS2/floats/hit-test-floats-004.html.ini @@ -0,0 +1,4 @@ +[hit-test-floats-004.html] + [Miss float below something else] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/css/css-text-decor/parsing/text-decoration-shorthand.html.ini b/tests/wpt/metadata-layout-2020/css/css-text-decor/parsing/text-decoration-shorthand.html.ini index add13e507a6..5f5d8af5cf8 100644 --- a/tests/wpt/metadata-layout-2020/css/css-text-decor/parsing/text-decoration-shorthand.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-text-decor/parsing/text-decoration-shorthand.html.ini @@ -11,3 +11,18 @@ [e.style['text-decoration'\] = "overline dotted green" should not set unrelated longhands] expected: FAIL + [e.style['text-decoration'\] = "overline from-font dotted green" should set text-decoration-style] + expected: FAIL + + [e.style['text-decoration'\] = "overline from-font dotted green" should set text-decoration-line] + expected: FAIL + + [e.style['text-decoration'\] = "overline from-font dotted green" should set text-decoration-color] + expected: FAIL + + [e.style['text-decoration'\] = "overline from-font dotted green" should not set unrelated longhands] + expected: FAIL + + [e.style['text-decoration'\] = "overline from-font dotted green" should set text-decoration-thickness] + expected: FAIL + diff --git a/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini b/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini index 7e7bd2ce287..ab63c03ee2a 100644 --- a/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini +++ b/tests/wpt/metadata-layout-2020/fetch/content-type/response.window.js.ini @@ -312,27 +312,21 @@ [Response: combined response Content-Type: text/html;" \\" text/plain ";charset=GBK] expected: NOTRUN - [ + diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/stash.py b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/stash.py index 0b8693a9011..231eeb492fc 100644 --- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/stash.py +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/stash.py @@ -4,7 +4,7 @@ def main(request, response): - if request.method == 'POST': - request.server.stash.put(request.GET["id"], request.body) - return '' - return request.server.stash.take(request.GET["id"]) + if request.method == u'POST': + request.server.stash.put(request.GET[b"id"], request.body) + return u'' + return request.server.stash.take(request.GET[b"id"]) diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py index 24e1dfd58f7..95256a2457a 100644 --- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py @@ -1,28 +1,28 @@ import time def main(request, response): - token = request.GET["token"] + token = request.GET[b"token"] response.status = 200 - response.headers.append("Content-Type", "text/html") - if "verify-token" in request.GET: + response.headers.append(b"Content-Type", b"text/html") + if b"verify-token" in request.GET: if request.server.stash.take(token): - return 'TOKEN_SET' - return 'TOKEN_NOT_SET' + return u'TOKEN_SET' + return u'TOKEN_NOT_SET' - if "finish-delay" not in request.GET: + if b"finish-delay" not in request.GET: # request.server.stash.put(token, True) return # navigation to download - response.headers.append("Content-Disposition", "attachment") + response.headers.append(b"Content-Disposition", b"attachment") response.write_status_headers() - finish_delay = float(request.GET["finish-delay"]) / 1E3 + finish_delay = float(request.GET[b"finish-delay"]) / 1E3 count = 10 single_delay = finish_delay / count for i in range(count): # pylint: disable=unused-variable time.sleep(single_delay) - response.writer.write_content("\n") + response.writer.write_content(u"\n") if not response.writer.flush(): return request.server.stash.put(token, True) diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/resources/referrer-checker-img.py b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/resources/referrer-checker-img.py index 0597268d839..bb2071cb976 100644 --- a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/resources/referrer-checker-img.py +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/resources/referrer-checker-img.py @@ -1,12 +1,14 @@ import os +from wptserve.utils import isomorphic_decode + # Returns a valid image response when request's |referrer| matches # |expected_referrer|. def main(request, response): - referrer = request.headers.get("referer", "") - expected_referrer = request.GET.first("expected_referrer", "") - response_headers = [("Content-Type", "image/png")] + referrer = request.headers.get(b"referer", b"") + expected_referrer = request.GET.first(b"expected_referrer", b"") + response_headers = [(b"Content-Type", b"image/png")] if referrer == expected_referrer: - image_path = os.path.join(os.path.dirname(__file__), "image.png") + image_path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), u"image.png") return (200, response_headers, open(image_path, mode='rb').read()) - return (404, response_headers, "Not found") + return (404, response_headers, u"Not found") diff --git a/tests/wpt/web-platform-tests/manifest/META.yml b/tests/wpt/web-platform-tests/manifest/META.yml deleted file mode 100644 index 013fc58a29f..00000000000 --- a/tests/wpt/web-platform-tests/manifest/META.yml +++ /dev/null @@ -1,5 +0,0 @@ -spec: https://w3c.github.io/manifest/ -suggested_reviewers: - - marcoscaceres - - mgiuca - - kenchris diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order-ref.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order-ref.html new file mode 100644 index 00000000000..72694959a86 --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order-ref.html @@ -0,0 +1,83 @@ + + + + + mrow painting order (reference) + + + + +

This test passes if there is no red and content is stacked such that

+ + +
+ + + + + +
+ +
+ + + + p XXÉ + + +
+ +
+ + + + + p X + + +
+ +
+ + + XXÉ + + +
+ +
+ + + + p XXÉ + + +
+ +
+ + + + + p X + + +
+ + diff --git a/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order.html b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order.html new file mode 100644 index 00000000000..b221ec8ffda --- /dev/null +++ b/tests/wpt/web-platform-tests/mathml/presentation-markup/mrow/mrow-painting-order.html @@ -0,0 +1,42 @@ + + + + + mrow painting order + + + + + + + + + +

This test passes if there is no red and content is stacked such that

+ +
+ + + XXÉ + X + p XXÉ + X + p X + + +
+ + diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py index 3a26efc5542..0340294dcaa 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testloader.py @@ -1,4 +1,5 @@ import hashlib +import json import os from six.moves.urllib.parse import urlsplit from abc import ABCMeta, abstractmethod @@ -26,6 +27,45 @@ def do_delayed_imports(): from manifest.download import download_from_github +class TestGroupsFile(object): + """ + Mapping object representing {group name: [test ids]} + """ + + def __init__(self, logger, path): + try: + with open(path) as f: + self._data = json.load(f) + except ValueError: + logger.critical("test groups file %s not valid json" % path) + raise + + self.group_by_test = {} + for group, test_ids in iteritems(self._data): + for test_id in test_ids: + self.group_by_test[test_id] = group + + def __contains__(self, key): + return key in self._data + + def __getitem__(self, key): + return self._data[key] + + +def update_include_for_groups(test_groups, include): + if include is None: + # We're just running everything + return + + new_include = [] + for item in include: + if item in test_groups: + new_include.extend(test_groups[item]) + else: + new_include.append(item) + return new_include + + class TestChunker(object): def __init__(self, total_chunks, chunk_number, **kwargs): self.total_chunks = total_chunks @@ -292,6 +332,23 @@ class TestLoader(object): return groups +def get_test_src(**kwargs): + test_source_kwargs = {"processes": kwargs["processes"], + "logger": kwargs["logger"]} + chunker_kwargs = {} + if kwargs["run_by_dir"] is not False: + # A value of None indicates infinite depth + test_source_cls = PathGroupedSource + test_source_kwargs["depth"] = kwargs["run_by_dir"] + chunker_kwargs["depth"] = kwargs["run_by_dir"] + elif kwargs["test_groups"]: + test_source_cls = GroupFileTestSource + test_source_kwargs["test_groups"] = kwargs["test_groups"] + else: + test_source_cls = SingleTestSource + return test_source_cls, test_source_kwargs, chunker_kwargs + + class TestSource(object): __metaclass__ = ABCMeta @@ -397,3 +454,39 @@ class PathGroupedSource(GroupedSource): @classmethod def group_metadata(cls, state): return {"scope": "/%s" % "/".join(state["prev_path"])} + + +class GroupFileTestSource(TestSource): + @classmethod + def make_queue(cls, tests, **kwargs): + tests_by_group = cls.tests_by_group(tests, **kwargs) + + test_queue = Queue() + + for group_name, tests in iteritems(tests_by_group): + group_metadata = {"scope": group_name} + group = deque() + + for test in tests: + group.append(test) + test.update_metadata(group_metadata) + + test_queue.put((group, group_metadata)) + + return test_queue + + @classmethod + def tests_by_group(cls, tests, **kwargs): + logger = kwargs["logger"] + test_groups = kwargs["test_groups"] + + tests_by_group = defaultdict(list) + for test in tests: + try: + group = test_groups.group_by_test[test.id] + except KeyError: + logger.error("%s is missing from test groups file" % test.id) + raise + tests_by_group[group].append(test) + + return tests_by_group diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py index 49a3525e883..4c9468a0eba 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/testrunner.py @@ -700,8 +700,9 @@ class TestRunnerManager(threading.Thread): test, test_group, group_metadata = self.get_next_test() if test is None: return RunnerManagerState.stop() - if test_group != self.state.test_group: + if test_group is not self.state.test_group: # We are starting a new group of tests, so force a restart + self.logger.info("Restarting browser for new test group") restart = True else: test_group = self.state.test_group diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py index 96227bb4690..80879476704 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptcommandline.py @@ -135,6 +135,8 @@ scheme host and port.""") help="URL prefix to exclude") test_selection_group.add_argument("--include-manifest", type=abs_path, help="Path to manifest listing tests to include") + test_selection_group.add_argument("--test-groups", dest="test_groups_file", type=abs_path, + help="Path to json file containing a mapping {group_name: [test_ids]}") test_selection_group.add_argument("--skip-timeout", action="store_true", help="Skip tests that are expected to time out") test_selection_group.add_argument("--skip-implementation-status", @@ -504,6 +506,14 @@ def check_args(kwargs): else: kwargs["chunk_type"] = "none" + if kwargs["test_groups_file"] is not None: + if kwargs["run_by_dir"] is not False: + print("Can't pass --test-groups and --run-by-dir") + sys.exit(1) + if not os.path.exists(kwargs["test_groups_file"]): + print("--test-groups file %s not found" % kwargs["test_groups_file"]) + sys.exit(1) + if kwargs["processes"] is None: kwargs["processes"] = 1 diff --git a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py index d0cc19481db..86cc36d3af5 100644 --- a/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py +++ b/tests/wpt/web-platform-tests/tools/wptrunner/wptrunner/wptrunner.py @@ -45,7 +45,8 @@ def setup_logging(*args, **kwargs): return logger -def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kwargs=None, **kwargs): +def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kwargs=None, + test_groups=None, **kwargs): if run_info_extras is None: run_info_extras = {} @@ -62,8 +63,12 @@ def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kw manifest_filters = [] - if kwargs["include"] or kwargs["exclude"] or kwargs["include_manifest"] or kwargs["default_exclude"]: - manifest_filters.append(testloader.TestFilter(include=kwargs["include"], + include = kwargs["include"] + if test_groups: + include = testloader.update_include_for_groups(test_groups, include) + + if include or kwargs["exclude"] or kwargs["include_manifest"] or kwargs["default_exclude"]: + manifest_filters.append(testloader.TestFilter(include=include, exclude=kwargs["exclude"], manifest_path=kwargs["include_manifest"], test_manifests=test_manifests, @@ -166,23 +171,21 @@ def run_tests(config, test_paths, product, **kwargs): recording.set(["startup", "load_tests"]) - test_source_kwargs = {"processes": kwargs["processes"]} - chunker_kwargs = {} - if kwargs["run_by_dir"] is False: - test_source_cls = testloader.SingleTestSource - else: - # A value of None indicates infinite depth - test_source_cls = testloader.PathGroupedSource - test_source_kwargs["depth"] = kwargs["run_by_dir"] - chunker_kwargs["depth"] = kwargs["run_by_dir"] + test_groups = (testloader.TestGroupsFile(logger, kwargs["test_groups_file"]) + if kwargs["test_groups_file"] else None) + (test_source_cls, + test_source_kwargs, + chunker_kwargs) = testloader.get_test_src(logger=logger, + test_groups=test_groups, + **kwargs) run_info, test_loader = get_loader(test_paths, product.name, run_info_extras=product.run_info_extras(**kwargs), chunker_kwargs=chunker_kwargs, + test_groups=test_groups, **kwargs) - logger.info("Using %i client processes" % kwargs["processes"]) skipped_tests = 0 @@ -203,7 +206,9 @@ def run_tests(config, test_paths, product, **kwargs): "host_cert_path": kwargs["host_cert_path"], "ca_cert_path": kwargs["ca_cert_path"]}} - testharness_timeout_multipler = product.get_timeout_multiplier("testharness", run_info, **kwargs) + testharness_timeout_multipler = product.get_timeout_multiplier("testharness", + run_info, + **kwargs) recording.set(["startup", "start_environment"]) with env.TestEnvironment(test_paths, @@ -241,7 +246,13 @@ def run_tests(config, test_paths, product, **kwargs): for test_type in test_loader.test_types: tests.extend(test_loader.tests[test_type]) - logger.suite_start(test_source_cls.tests_by_group(tests, **test_source_kwargs), + try: + test_groups = test_source_cls.tests_by_group(tests, **test_source_kwargs) + except Exception: + logger.critical("Loading tests failed") + return False + + logger.suite_start(test_groups, name='web-platform-test', run_info=run_info, extra={"run_by_dir": kwargs["run_by_dir"]}) diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html new file mode 100644 index 00000000000..33627204a6f --- /dev/null +++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/audioworkletprocessor-process-frozen-array.https.html @@ -0,0 +1,53 @@ + + + + + Test given arrays within AudioWorkletProcessor.process() method + + + + + + + + + + diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/processors/array-check-processor.js b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/processors/array-check-processor.js new file mode 100644 index 00000000000..d6eeff3d155 --- /dev/null +++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/processors/array-check-processor.js @@ -0,0 +1,94 @@ +/** + * @class ArrayFrozenProcessor + * @extends AudioWorkletProcessor + */ +class ArrayFrozenProcessor extends AudioWorkletProcessor { + constructor() { + super(); + this._messageSent = false; + } + + process(inputs, outputs, parameters) { + const input = inputs[0]; + const output = outputs[0]; + + if (!this._messageSent) { + this.port.postMessage({ + inputLength: input.length, + isInputFrozen: Object.isFrozen(inputs) && Object.isFrozen(input), + outputLength: output.length, + isOutputFrozen: Object.isFrozen(outputs) && Object.isFrozen(output) + }); + this._messageSent = true; + } + + return false; + } +} + +/** + * @class ArrayTransferProcessor + * @extends AudioWorkletProcessor + */ +class ArrayTransferProcessor extends AudioWorkletProcessor { + constructor() { + super(); + this._messageSent = false; + } + + process(inputs, outputs, parameters) { + const input = inputs[0]; + const output = outputs[0]; + + if (!this._messageSent) { + try { + // Transferring Array objects should NOT work. + this.port.postMessage({ + inputs, input, inputChannel: input[0], + outputs, output, outputChannel: output[0] + }, [inputs, input, inputs[0], outputs, output, output[0]]); + // Hence, the following must NOT be reached. + this.port.postMessage({ + type: 'assertion', + success: false, + message: 'Transferring inputs/outputs, an individual input/output ' + + 'array, or a channel Float32Array MUST fail, but succeeded.' + }); + } catch (error) { + this.port.postMessage({ + type: 'assertion', + success: true, + message: 'Transferring inputs/outputs, an individual input/output ' + + 'array, or a channel Float32Array is not allowed as expected.' + }); + } + + try { + // Transferring ArrayBuffers should work. + this.port.postMessage( + {inputChannel: input[0], outputChannel: output[0]}, + [input[0].buffer, output[0].buffer]); + this.port.postMessage({ + type: 'assertion', + success: true, + message: 'Transferring ArrayBuffers was successful as expected.' + }); + } catch (error) { + // This must NOT be reached. + this.port.postMessage({ + type: 'assertion', + success: false, + message: 'Transferring ArrayBuffers unexpectedly failed.' + }); + } + + this.port.postMessage({done: true}); + this._messageSent = true; + } + + return false; + } +} + +registerProcessor('array-frozen-processor', ArrayFrozenProcessor); +registerProcessor('array-transfer-processor', ArrayTransferProcessor); diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html index 7857cf16aa0..3f8360417dd 100644 --- a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html +++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-delaynode-interface/no-dezippering.html @@ -93,7 +93,8 @@ audit.define( {label: 'test1', description: 'Test value setter and setValueAtTime'}, (task, should) => { - testWithAutomation(should, {prefix: ''}).then(() => task.done()); + testWithAutomation(should, {prefix: '', threshold: 5.9605e-8}) + .then(() => task.done()); }); audit.define( @@ -168,7 +169,8 @@ let expected = renderedBuffer.getChannelData(1); let match = should(actual, prefix + '.value setter output') - .beEqualToArray(expected); + .beCloseToArray( + expected, {absoluteThreshold: options.threshold}); should( match, prefix + '.value setter output matches setValueAtTime output') @@ -177,7 +179,6 @@ } audit.run(); -