mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Update web-platform-tests to revision 0ed072539aa45d3a5a67c9164b243d27873f257c
This commit is contained in:
parent
0954871992
commit
e613cfd108
76 changed files with 1109 additions and 703 deletions
|
@ -7,7 +7,7 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Opening a blob URL in a new window immediately before revoking it works.]
|
[Opening a blob URL in a new window immediately before revoking it works.]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
|
[Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,2 @@
|
||||||
|
[width-047.xht]
|
||||||
|
expected: FAIL
|
|
@ -2,3 +2,6 @@
|
||||||
[listeners are called in order they were added, ignoring capture parameter]
|
[listeners are called in order they were added, ignoring capture parameter]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[capturing event listener fires before non-capturing listener at target]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[remove-and-adopt-crash.html]
|
[remove-and-adopt-thcrash.html]
|
||||||
[Check that removing a node and then adopting its parent into a different window/document doesn't crash.]
|
[Check that removing a node and then adopting its parent into a different window/document doesn't crash.]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[response-trailer.html]
|
|
||||||
type: testharness
|
|
||||||
[trailer() test]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -309,12 +309,6 @@
|
||||||
[<iframe>: separate response Content-Type: */* text/html]
|
[<iframe>: separate response Content-Type: */* text/html]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<iframe>: combined response Content-Type: */* text/html]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<iframe>: separate response Content-Type: text/html;" text/plain]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
|
[<iframe>: separate response Content-Type: text/html */*;charset=gbk]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -327,6 +321,9 @@
|
||||||
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
|
[<iframe>: combined response Content-Type: text/html;" text/plain]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[<iframe>: separate response Content-Type: text/plain */*]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,6 @@
|
||||||
[X-Content-Type-Options%3A%20nosniff%0C]
|
[X-Content-Type-Options%3A%20nosniff%0C]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[X-Content-Type-Options%3A%20'NosniFF']
|
[X-Content-Type-Options%3A%20%2Cnosniff]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.]
|
[Embedded credentials matching the top-level are treated as network errors for cross-origin URLs.]
|
||||||
expected: FAIL
|
expected: TIMEOUT
|
||||||
|
|
||||||
[Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.]
|
[Embedded credentials matching the top-level are not treated as network errors for same-origin URLs.]
|
||||||
expected: TIMEOUT
|
expected: TIMEOUT
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[window-serviceworker-success.https.html]
|
|
||||||
[Test ServiceWorkerContainer.onmessageerror using SharedArrayBuffer]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
[supported-elements.html]
|
[supported-elements.html]
|
||||||
expected: TIMEOUT
|
|
||||||
[Contenteditable element should support autofocus]
|
[Contenteditable element should support autofocus]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -10,7 +9,7 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[Area element should support autofocus]
|
[Area element should support autofocus]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[Host element with delegatesFocus should support autofocus]
|
[Host element with delegatesFocus should support autofocus]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[form-double-submit-3.html]
|
[form-double-submit-3.html]
|
||||||
expected: ERROR
|
expected: ERROR
|
||||||
[<button> should have the same double-submit protection as <input type=submit>]
|
[<button> should have the same double-submit protection as <input type=submit>]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
[window-serviceworker-success.https.html]
|
|
||||||
[Test ServiceWorkerContainer.onmessageerror using WebAssembly.Module]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[test_element_in_collection]
|
[test_element_in_collection]
|
||||||
expected:
|
expected: FAIL
|
||||||
if os == "mac": FAIL
|
|
||||||
|
|
5
tests/wpt/metadata/webmessaging/with-ports/018.html.ini
Normal file
5
tests/wpt/metadata/webmessaging/with-ports/018.html.ini
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
[018.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[origin of the script that invoked the method, javascript:]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
[017.html]
|
|
||||||
expected: TIMEOUT
|
|
||||||
[origin of the script that invoked the method, about:blank]
|
|
||||||
expected: TIMEOUT
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
[018.html]
|
||||||
|
expected: TIMEOUT
|
||||||
|
[origin of the script that invoked the method, javascript:]
|
||||||
|
expected: TIMEOUT
|
||||||
|
|
|
@ -321,13 +321,12 @@ jobs:
|
||||||
parallel: 5 # chosen to make runtime ~2h
|
parallel: 5 # chosen to make runtime ~2h
|
||||||
timeoutInMinutes: 180
|
timeoutInMinutes: 180
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'macOS-10.13'
|
vmImage: 'macOS-10.14'
|
||||||
steps:
|
steps:
|
||||||
- template: tools/ci/azure/checkout.yml
|
- template: tools/ci/azure/checkout.yml
|
||||||
- template: tools/ci/azure/pip_install.yml
|
- template: tools/ci/azure/pip_install.yml
|
||||||
parameters:
|
parameters:
|
||||||
packages: virtualenv
|
packages: virtualenv
|
||||||
- template: tools/ci/azure/install_fonts.yml
|
|
||||||
- template: tools/ci/azure/install_certs.yml
|
- template: tools/ci/azure/install_certs.yml
|
||||||
- template: tools/ci/azure/install_safari.yml
|
- template: tools/ci/azure/install_safari.yml
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -144,6 +144,10 @@ promise_test(async t => {
|
||||||
assert_equals(calls, 2, "dispatchEvent");
|
assert_equals(calls, 2, "dispatchEvent");
|
||||||
}, "removeListener doesn't remove listener added with addEventListener (capture)");
|
}, "removeListener doesn't remove listener added with addEventListener (capture)");
|
||||||
|
|
||||||
|
// See:
|
||||||
|
// * https://github.com/whatwg/dom/issues/746
|
||||||
|
// * https://bugzilla.mozilla.org/show_bug.cgi?id=1492446
|
||||||
|
// * https://bugs.chromium.org/p/chromium/issues/detail?id=949432
|
||||||
promise_test(async t => {
|
promise_test(async t => {
|
||||||
const mql = await createMQL(t);
|
const mql = await createMQL(t);
|
||||||
|
|
||||||
|
@ -164,5 +168,5 @@ promise_test(async t => {
|
||||||
calls = [];
|
calls = [];
|
||||||
mql.dispatchEvent(new Event("change"));
|
mql.dispatchEvent(new Event("change"));
|
||||||
assert_array_equals(calls, ["addEventListener", "addListener"], "dispatchEvent");
|
assert_array_equals(calls, ["addEventListener", "addListener"], "dispatchEvent");
|
||||||
}, "listeners are called in order they were added, ignoring capture parameter");
|
}, "capturing event listener fires before non-capturing listener at target");
|
||||||
</script>
|
</script>
|
||||||
|
|
22
tests/wpt/web-platform-tests/docs/writing-tests/crashtest.md
Normal file
22
tests/wpt/web-platform-tests/docs/writing-tests/crashtest.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
# crashtest tests
|
||||||
|
|
||||||
|
Crash tests are used to ensure that a document can be loaded without
|
||||||
|
crashing or experiencing other low-level issues that may be checked by
|
||||||
|
implementation-specific tooling (e.g. leaks, asserts, or sanitizer
|
||||||
|
failures).
|
||||||
|
|
||||||
|
Crashtests are identified by the string `-crash` in the filename, or
|
||||||
|
by being in a directory called `crashtests`.
|
||||||
|
|
||||||
|
The simplest crashtest is a single HTML file with any content. The
|
||||||
|
test passes if the load event is reached, and the browser finishes
|
||||||
|
painting, without terminating.
|
||||||
|
|
||||||
|
In some cases crashtests may need to perform work after the initial
|
||||||
|
page load. In this case the test may specify a `class=wait` attribute
|
||||||
|
on the root element. The test will not complete until that attribute
|
||||||
|
is removed from the root. At the time when the test would otherwise
|
||||||
|
have ended a `TestRendered` event is emitted; test authors can use
|
||||||
|
this event to perform modifications that are guaranteed not to be
|
||||||
|
batched with the initial paint. This matches the behaviour of
|
||||||
|
[reftests](reftests).
|
|
@ -15,6 +15,7 @@ There's also a load of [general guidelines](general-guidelines) that apply to al
|
||||||
general-guidelines
|
general-guidelines
|
||||||
ahem
|
ahem
|
||||||
assumptions
|
assumptions
|
||||||
|
crashtest
|
||||||
css-metadata
|
css-metadata
|
||||||
css-user-styles
|
css-user-styles
|
||||||
file-names
|
file-names
|
||||||
|
@ -63,6 +64,11 @@ expectations:
|
||||||
testing everything else. They are built with the testharness.js unit testing
|
testing everything else. They are built with the testharness.js unit testing
|
||||||
framework, and consist of assertions written in JavaScript.
|
framework, and consist of assertions written in JavaScript.
|
||||||
|
|
||||||
|
* [Crashtests](crashtest) tests are used to check that the browser is
|
||||||
|
able to load a given document without crashing or experiencing other
|
||||||
|
low-level issues (asserts, leaks, etc.). They pass if the load
|
||||||
|
completes without error.
|
||||||
|
|
||||||
* [wdspec](wdspec) tests are written in Python using
|
* [wdspec](wdspec) tests are written in Python using
|
||||||
[pytest](https://docs.pytest.org/en/latest/) and test [the WebDriver browser
|
[pytest](https://docs.pytest.org/en/latest/) and test [the WebDriver browser
|
||||||
automation protocol](https://w3c.github.io/webdriver/)
|
automation protocol](https://w3c.github.io/webdriver/)
|
||||||
|
|
|
@ -278,6 +278,12 @@
|
||||||
|
|
||||||
input1.removeAttribute("aria-labelledby");
|
input1.removeAttribute("aria-labelledby");
|
||||||
assert_equals(input1.ariaLabelledByElements, null);
|
assert_equals(input1.ariaLabelledByElements, null);
|
||||||
|
|
||||||
|
input1.setAttribute("aria-labelledby", "nameElement addressElement");
|
||||||
|
assert_array_equals(input1.ariaLabelledByElements, [nameElement, addressElement]);
|
||||||
|
|
||||||
|
input1.ariaLabelledByElements = null;
|
||||||
|
assert_false(input1.hasAttribute("aria-labelledby", "Nullifying the IDL attribute should remove the content attribute."));
|
||||||
}, "aria-labelledby.");
|
}, "aria-labelledby.");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -305,6 +311,12 @@
|
||||||
|
|
||||||
link2.removeAttribute("aria-controls");
|
link2.removeAttribute("aria-controls");
|
||||||
assert_equals(link2.ariaControlsElements, null);
|
assert_equals(link2.ariaControlsElements, null);
|
||||||
|
|
||||||
|
link2.ariaControlsElements = [panel1, panel2];
|
||||||
|
assert_equals(link2.getAttribute("aria-controls"), "panel1 panel2");
|
||||||
|
|
||||||
|
link2.ariaControlsElements = null;
|
||||||
|
assert_false(link2.hasAttribute("aria-controls", "Nullifying the IDL attribute should remove the content attribute."));
|
||||||
}, "aria-controls.");
|
}, "aria-controls.");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -327,6 +339,12 @@
|
||||||
|
|
||||||
describedLink.removeAttribute("aria-describedby");
|
describedLink.removeAttribute("aria-describedby");
|
||||||
assert_equals(describedLink.ariaDescribedByElements, null);
|
assert_equals(describedLink.ariaDescribedByElements, null);
|
||||||
|
|
||||||
|
describedLink.ariaDescribedByElements = [description1, description2];
|
||||||
|
assert_equals(describedLink.getAttribute("aria-describedby"), "description1 description2");
|
||||||
|
|
||||||
|
describedLink.ariaDescribedByElements = null;
|
||||||
|
assert_false(describedLink.hasAttribute("aria-describedby", "Nullifying the IDL attribute should remove the content attribute."));
|
||||||
}, "aria-describedby.");
|
}, "aria-describedby.");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -353,6 +371,12 @@
|
||||||
|
|
||||||
titleHeading.removeAttribute("aria-flowto");
|
titleHeading.removeAttribute("aria-flowto");
|
||||||
assert_equals(titleHeading.ariaFlowToElements, null);
|
assert_equals(titleHeading.ariaFlowToElements, null);
|
||||||
|
|
||||||
|
titleHeading.ariaFlowToElements = [article1, article2];
|
||||||
|
assert_equals(titleHeading.getAttribute("aria-flowto"), "article1 article2");
|
||||||
|
|
||||||
|
titleHeading.ariaFlowToElements = null;
|
||||||
|
assert_false(titleHeading.hasAttribute("aria-flowto", "Nullifying the IDL attribute should remove the content attribute."));
|
||||||
}, "aria-flowto.");
|
}, "aria-flowto.");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -378,6 +402,12 @@
|
||||||
|
|
||||||
listItemOwner.setAttribute("aria-owns", "child1");
|
listItemOwner.setAttribute("aria-owns", "child1");
|
||||||
assert_array_equals(listItemOwner.ariaOwnsElements, [child1]);
|
assert_array_equals(listItemOwner.ariaOwnsElements, [child1]);
|
||||||
|
|
||||||
|
listItemOwner.ariaOwnsElements = [child1, child2];
|
||||||
|
assert_equals(listItemOwner.getAttribute("aria-owns"), "child1 child2");
|
||||||
|
|
||||||
|
listItemOwner.ariaOwnsElements = null;
|
||||||
|
assert_false(listItemOwner.hasAttribute("aria-owns", "Nullifying the IDL attribute should remove the content attribute."));
|
||||||
}, "aria-owns.");
|
}, "aria-owns.");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -477,6 +507,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="sameScopeContainer">
|
<div id="sameScopeContainer">
|
||||||
|
<div id="labeledby" aria-labeledby="headingLabel1 headingLabel2">Misspelling</div>
|
||||||
<div id="headingLabel1">Wonderful</div>
|
<div id="headingLabel1">Wonderful</div>
|
||||||
<div id="headingLabel2">Fantastic</div>
|
<div id="headingLabel2">Fantastic</div>
|
||||||
|
|
||||||
|
@ -491,6 +522,8 @@
|
||||||
const headingLabel2 = document.getElementById("headingLabel2")
|
const headingLabel2 = document.getElementById("headingLabel2")
|
||||||
shadowRoot.appendChild(headingElement);
|
shadowRoot.appendChild(headingElement);
|
||||||
|
|
||||||
|
assert_array_equals(labeledby.ariaLabelledByElements, [headingLabel1, headingLabel2], "aria-labeled by is supported by IDL getter.");
|
||||||
|
|
||||||
// Explicitly set elements are in a lighter shadow DOM, so that's ok.
|
// Explicitly set elements are in a lighter shadow DOM, so that's ok.
|
||||||
headingElement.ariaLabelledByElements = [headingLabel1, headingLabel2];
|
headingElement.ariaLabelledByElements = [headingLabel1, headingLabel2];
|
||||||
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2], "Lighter elements are gettable when explicitly set.");
|
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2], "Lighter elements are gettable when explicitly set.");
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
test(() => {
|
||||||
|
assert_false("getAll" in new Headers());
|
||||||
|
assert_false("getAll" in Headers.prototype);
|
||||||
|
}, "Headers object no longer has a getAll() method");
|
||||||
|
|
||||||
|
test(() => {
|
||||||
|
assert_false("type" in new Request("about:blank"));
|
||||||
|
assert_false("type" in Request.prototype);
|
||||||
|
}, "'type' getter should not exist on Request objects");
|
||||||
|
|
||||||
|
// See https://github.com/whatwg/fetch/pull/979 for the removal
|
||||||
|
test(() => {
|
||||||
|
assert_false("trailer" in new Response());
|
||||||
|
assert_false("trailer" in Response.prototype);
|
||||||
|
}, "Response object no longer has a trailer getter");
|
|
@ -1,4 +0,0 @@
|
||||||
test(() => {
|
|
||||||
assert_false("getAll" in new Headers)
|
|
||||||
assert_false("getAll" in Headers.prototype)
|
|
||||||
}, "Headers object no longer has a getAll() method")
|
|
|
@ -1,11 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<title>Request.type attribute should not exist</title>
|
|
||||||
<script src="/resources/testharness.js"></script>
|
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
|
||||||
<div id=log></div>
|
|
||||||
<script>
|
|
||||||
var request = new Request("https://domfarolino.com");
|
|
||||||
test(() => {
|
|
||||||
assert_equals(request.type, undefined, "request.type should be undefined");
|
|
||||||
}, "'type' getter should not exist on Request objects");
|
|
||||||
</script>
|
|
|
@ -1,24 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<title>trailer() test</title>
|
|
||||||
<script src=/resources/testharness.js></script>
|
|
||||||
<script src=/resources/testharnessreport.js></script>
|
|
||||||
<div id=log></div>
|
|
||||||
<!-- based on /xhr/getresponseheader-chunked-trailer.htm -->
|
|
||||||
<script>
|
|
||||||
promise_test(() => {
|
|
||||||
return fetch("/xhr/resources/chunked.py").then(res => {
|
|
||||||
assert_equals(res.headers.get("Trailer"), "X-Test-Me")
|
|
||||||
assert_equals(res.headers.get("X-Test-Me"), null)
|
|
||||||
assert_equals(res.headers.get("Content-Type"), "text/plain")
|
|
||||||
return Promise.all([
|
|
||||||
res.text().then(text => {
|
|
||||||
assert_equals(text, "First chunk\r\nSecond chunk\r\nYet another (third) chunk\r\nYet another (fourth) chunk\r\n")
|
|
||||||
}),
|
|
||||||
res.trailer.then(trailers => {
|
|
||||||
assert_equals(trailers.get("X-Test-Me"), "Trailer header value")
|
|
||||||
assert_throws(new TypeError, () => trailers.append("Immutable-My-Ass", "Hi!"))
|
|
||||||
})
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
</script>
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<script src=/resources/testharness.js></script>
|
||||||
|
<script src=/resources/testharnessreport.js></script>
|
||||||
|
<script src=/resources/testdriver.js></script>
|
||||||
|
<script src=/resources/testdriver-vendor.js></script>
|
||||||
|
<script src=/fetch/metadata/resources/helper.js></script>
|
||||||
|
<script src=/common/utils.js></script>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
const USER = true;
|
||||||
|
const FORCED = false;
|
||||||
|
|
||||||
|
function create_test(host, user_activated, expectations) {
|
||||||
|
async_test(t => {
|
||||||
|
let nonce = token();
|
||||||
|
let w = window.open("", nonce);
|
||||||
|
let f = document.createElement('form');
|
||||||
|
|
||||||
|
window.addEventListener('message', t.step_func(e => {
|
||||||
|
if (e.source != w)
|
||||||
|
return;
|
||||||
|
assert_header_equals(e.data, expectations,
|
||||||
|
`{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
|
||||||
|
t.done();
|
||||||
|
}));
|
||||||
|
|
||||||
|
let url = `https://${host}/fetch/metadata/resources/post-to-owner.py`;
|
||||||
|
f.action = url;
|
||||||
|
f.target = nonce;
|
||||||
|
document.body.appendChild(f);
|
||||||
|
|
||||||
|
if (user_activated == FORCED) {
|
||||||
|
f.submit();
|
||||||
|
} else if (user_activated == USER) {
|
||||||
|
let s = document.createElement('input');
|
||||||
|
s.type = "submit";
|
||||||
|
f.appendChild(s);
|
||||||
|
|
||||||
|
test_driver.click(s);
|
||||||
|
}
|
||||||
|
}, `{{host}} -> ${host} iframe: ${user_activated ? "user-activated" : "forced"}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_test("{{host}}:{{ports[https][0]}}", FORCED, {
|
||||||
|
"site": "same-origin",
|
||||||
|
"user": "",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
|
||||||
|
create_test("{{hosts[][www]}}:{{ports[https][0]}}", FORCED, {
|
||||||
|
"site": "same-site",
|
||||||
|
"user": "",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
|
||||||
|
create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", FORCED, {
|
||||||
|
"site": "cross-site",
|
||||||
|
"user": "",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
|
||||||
|
create_test("{{host}}:{{ports[https][0]}}", USER, {
|
||||||
|
"site": "same-origin",
|
||||||
|
"user": "?1",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
|
||||||
|
create_test("{{hosts[][www]}}:{{ports[https][0]}}", USER, {
|
||||||
|
"site": "same-site",
|
||||||
|
"user": "?1",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
|
||||||
|
create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", USER, {
|
||||||
|
"site": "cross-site",
|
||||||
|
"user": "?1",
|
||||||
|
"mode": "navigate",
|
||||||
|
"dest": "document"
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -19,6 +19,7 @@ self.onmessage = e => {
|
||||||
|
|
||||||
self.onmessageerror = e => {
|
self.onmessageerror = e => {
|
||||||
if (state === "we are expecting a messageerror due to the window sending us a SAB") {
|
if (state === "we are expecting a messageerror due to the window sending us a SAB") {
|
||||||
|
assert_equals(e.constructor.name, "ExtendableMessageEvent", "type");
|
||||||
assert_equals(e.data, null, "data");
|
assert_equals(e.data, null, "data");
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
assert_equals(e.origin, self.origin, "origin");
|
||||||
assert_not_equals(e.source, null, "source");
|
assert_not_equals(e.source, null, "source");
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
"use strict";
|
|
||||||
self.importScripts("/resources/testharness.js");
|
|
||||||
|
|
||||||
let state = "start in worker";
|
|
||||||
|
|
||||||
self.onmessage = e => {
|
|
||||||
if (e.data === "start in window") {
|
|
||||||
assert_equals(state, "start in worker");
|
|
||||||
e.source.postMessage(state);
|
|
||||||
state = "waiting for message from the window";
|
|
||||||
} else if (e.data === "we are expecting a messageerror due to the worker sending us a SAB") {
|
|
||||||
assert_equals(state, "waiting for message from the window");
|
|
||||||
e.source.postMessage(new SharedArrayBuffer());
|
|
||||||
state = "done in worker";
|
|
||||||
} else {
|
|
||||||
e.source.postMessage(`worker onmessage was reached when in state "${state}" and data ${e.data}`);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1 +0,0 @@
|
||||||
Cross-Origin-Embedder-Policy: require-corp
|
|
|
@ -11,12 +11,14 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
promise_test(t => {
|
promise_test(t => {
|
||||||
const scope = "resources/blank.html";
|
const scope = "resources/blank.html";
|
||||||
return service_worker_unregister_and_register(t, "resources/serviceworker-failure.js", scope).then(reg => {
|
return service_worker_unregister_and_register(t, "resources/serviceworker-failure.js", scope)
|
||||||
|
.then(reg => {
|
||||||
|
t.add_cleanup(() => service_worker_unregister(t, scope));
|
||||||
return wait_for_state(t, reg.installing, "activated");
|
return wait_for_state(t, reg.installing, "activated");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => with_iframe(scope))
|
||||||
return with_iframe(scope);
|
.then(iframe => {
|
||||||
}).then(iframe => {
|
t.add_cleanup(() => iframe.remove());
|
||||||
const sw = iframe.contentWindow.navigator.serviceWorker;
|
const sw = iframe.contentWindow.navigator.serviceWorker;
|
||||||
let state = "start in window";
|
let state = "start in window";
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ promise_test(t => {
|
||||||
|
|
||||||
assert_equals(e.data, null, "data");
|
assert_equals(e.data, null, "data");
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
assert_equals(e.origin, self.origin, "origin");
|
||||||
assert_equals(e.source, null, "source");
|
assert_not_equals(e.source, null, "source");
|
||||||
assert_equals(e.ports.length, 0, "ports length");
|
assert_equals(e.ports.length, 0, "ports length");
|
||||||
|
|
||||||
state = "done in window";
|
state = "done in window";
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Test ServiceWorkerContainer.onmessageerror using SharedArrayBuffer</title>
|
|
||||||
<script src="/resources/testharness.js"></script>
|
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
|
||||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
"use strict";
|
|
||||||
promise_test(t => {
|
|
||||||
const scope = "resources/blank.html";
|
|
||||||
return service_worker_unregister_and_register(t, "resources/serviceworker-success.js", scope)
|
|
||||||
.then(reg => {
|
|
||||||
t.add_cleanup(() => service_worker_unregister(t, scope));
|
|
||||||
return wait_for_state(t, reg.installing, "activated");
|
|
||||||
})
|
|
||||||
.then(() => with_iframe(scope))
|
|
||||||
.then(iframe => {
|
|
||||||
t.add_cleanup(() => iframe.remove());
|
|
||||||
const sw = iframe.contentWindow.navigator.serviceWorker;
|
|
||||||
let state = "start in window";
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
sw.onmessage = t.step_func(e => {
|
|
||||||
if (e.data === "start in worker") {
|
|
||||||
assert_equals(state, "start in window");
|
|
||||||
state = "we are expecting a messageerror due to the worker sending us a SAB";
|
|
||||||
sw.controller.postMessage(state);
|
|
||||||
} else {
|
|
||||||
assert_unreached("Got an unexpected message from the service worker: " + e.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sw.onmessageerror = t.step_func(e => {
|
|
||||||
assert_equals(state, "we are expecting a messageerror due to the worker sending us a SAB");
|
|
||||||
assert_equals(e.data, null, "data");
|
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
|
||||||
assert_not_equals(e.source, null, "source");
|
|
||||||
assert_equals(e.ports.length, 0, "ports length");
|
|
||||||
state = "done in window";
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
sw.controller.postMessage(state);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,2 +0,0 @@
|
||||||
Cross-Origin-Opener-Policy: same-origin
|
|
||||||
Cross-Origin-Embedder-Policy: require-corp
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>link element rel is ASCII case-insensitive (mismatch reference)</title>
|
||||||
|
<link rel="stylesheet" href="stylesheet.css">
|
||||||
|
<p>Test passes if background is not red.</p>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>link element rel is ASCII case-insensitive</title>
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#the-link-element">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#attr-link-rel">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/#linkTypes">
|
||||||
|
<meta name="assert" content="link element's rel attribute is ASCII case-insensitive.">
|
||||||
|
<link rel="mismatch" href="link-rel-attribute-ascii-case-insensitive-notref.html">
|
||||||
|
|
||||||
|
<!-- Load sheet with a red background (rel attribute value is case-sensitive
|
||||||
|
equal to "stylesheet") -->
|
||||||
|
<link rel="stylesheet" href="stylesheet.css">
|
||||||
|
|
||||||
|
<!-- Load sheet with white background (rel attribute value is ASCII
|
||||||
|
case-insensitive equal to "stylesheet") -->
|
||||||
|
<link rel="StyLeShEeT" href="style.css">
|
||||||
|
|
||||||
|
<!-- Do not load sheet with a red background (rel attribute value is
|
||||||
|
case-insensitive equal to "stylesheet") -->
|
||||||
|
<link rel="ſtyleſheet" href="stylesheet.css">
|
||||||
|
|
||||||
|
<p>Test passes if background is not red.</p>
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!doctype html>
|
||||||
|
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
promise_test(async (test) => {
|
||||||
|
const reg = await navigator.serviceWorker.register('./serviceworker.js', { type: 'module' });
|
||||||
|
test.add_cleanup(() => reg.unregister());
|
||||||
|
assert_not_equals(reg.installing, undefined);
|
||||||
|
}, "Javascript importing JSON Module should load within the context of a service worker");
|
||||||
|
|
||||||
|
promise_test(async (test) => {
|
||||||
|
const reg = await navigator.serviceWorker.register('./module.json', { type: 'module' });
|
||||||
|
test.add_cleanup(() => reg.unregister());
|
||||||
|
assert_not_equals(reg.installing, undefined);
|
||||||
|
}, "JSON Modules should load within the context of a service worker");
|
||||||
|
|
||||||
|
promise_test(async (test) => {
|
||||||
|
const reg = await navigator.serviceWorker.register('./serviceworker-dynamic-import.js', { type: 'module' });
|
||||||
|
test.add_cleanup(() => reg.unregister());
|
||||||
|
assert_not_equals(reg.installing, undefined);
|
||||||
|
reg.installing.postMessage("PING");
|
||||||
|
const msgEvent = await new Promise(resolve => {
|
||||||
|
navigator.serviceWorker.onmessage = resolve;
|
||||||
|
});
|
||||||
|
assert_equals(msgEvent.data, "FAILED");
|
||||||
|
}, "JSON Module dynamic import should not load within the context of a service worker");
|
||||||
|
</script>
|
|
@ -0,0 +1,5 @@
|
||||||
|
onmessage = e => {
|
||||||
|
e.waitUntil(import("./module.json")
|
||||||
|
.then(module => e.source.postMessage("LOADED"))
|
||||||
|
.catch(error => e.source.postMessage("FAILED")));
|
||||||
|
};
|
|
@ -0,0 +1 @@
|
||||||
|
import './module.json';
|
|
@ -0,0 +1 @@
|
||||||
|
<p>Test that should not crash
|
|
@ -90,7 +90,6 @@ enum RequestRedirect { "follow", "error", "manual" };
|
||||||
readonly attribute boolean ok;
|
readonly attribute boolean ok;
|
||||||
readonly attribute ByteString statusText;
|
readonly attribute ByteString statusText;
|
||||||
[SameObject] readonly attribute Headers headers;
|
[SameObject] readonly attribute Headers headers;
|
||||||
readonly attribute Promise<Headers> trailer;
|
|
||||||
|
|
||||||
[NewObject] Response clone();
|
[NewObject] Response clone();
|
||||||
};
|
};
|
||||||
|
|
|
@ -220,11 +220,6 @@ dictionary RTCPeerConnectionStats : RTCStats {
|
||||||
unsigned long dataChannelsAccepted;
|
unsigned long dataChannelsAccepted;
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary RTCMediaStreamStats : RTCStats {
|
|
||||||
DOMString streamIdentifier;
|
|
||||||
sequence<DOMString> trackIds;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary RTCRtpTransceiverStats {
|
dictionary RTCRtpTransceiverStats {
|
||||||
DOMString senderId;
|
DOMString senderId;
|
||||||
DOMString receiverId;
|
DOMString receiverId;
|
||||||
|
@ -301,7 +296,6 @@ dictionary RTCSctpTransportStats : RTCStats {
|
||||||
|
|
||||||
dictionary RTCIceCandidateStats : RTCStats {
|
dictionary RTCIceCandidateStats : RTCStats {
|
||||||
DOMString transportId;
|
DOMString transportId;
|
||||||
RTCNetworkType networkType;
|
|
||||||
DOMString? address;
|
DOMString? address;
|
||||||
long port;
|
long port;
|
||||||
DOMString protocol;
|
DOMString protocol;
|
||||||
|
@ -311,16 +305,6 @@ dictionary RTCIceCandidateStats : RTCStats {
|
||||||
DOMString relayProtocol;
|
DOMString relayProtocol;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RTCNetworkType {
|
|
||||||
"bluetooth",
|
|
||||||
"cellular",
|
|
||||||
"ethernet",
|
|
||||||
"wifi",
|
|
||||||
"wimax",
|
|
||||||
"vpn",
|
|
||||||
"unknown"
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary RTCIceCandidatePairStats : RTCStats {
|
dictionary RTCIceCandidatePairStats : RTCStats {
|
||||||
DOMString transportId;
|
DOMString transportId;
|
||||||
DOMString localCandidateId;
|
DOMString localCandidateId;
|
||||||
|
@ -372,12 +356,16 @@ dictionary RTCIceServerStats : RTCStats {
|
||||||
DOMString url;
|
DOMString url;
|
||||||
long port;
|
long port;
|
||||||
DOMString protocol;
|
DOMString protocol;
|
||||||
RTCNetworkType networkType;
|
|
||||||
unsigned long totalRequestsSent;
|
unsigned long totalRequestsSent;
|
||||||
unsigned long totalResponsesReceived;
|
unsigned long totalResponsesReceived;
|
||||||
double totalRoundTripTime;
|
double totalRoundTripTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dictionary RTCMediaStreamStats : RTCStats {
|
||||||
|
DOMString streamIdentifier;
|
||||||
|
sequence<DOMString> trackIds;
|
||||||
|
};
|
||||||
|
|
||||||
dictionary RTCReceiverVideoTrackAttachmentStats : RTCVideoReceiverStats {};
|
dictionary RTCReceiverVideoTrackAttachmentStats : RTCVideoReceiverStats {};
|
||||||
|
|
||||||
dictionary RTCReceiverAudioTrackAttachmentStats : RTCAudioReceiverStats {};
|
dictionary RTCReceiverAudioTrackAttachmentStats : RTCAudioReceiverStats {};
|
||||||
|
|
|
@ -100,7 +100,7 @@ interface RTCPeerConnection : EventTarget {
|
||||||
readonly attribute boolean? canTrickleIceCandidates;
|
readonly attribute boolean? canTrickleIceCandidates;
|
||||||
void restartIce();
|
void restartIce();
|
||||||
RTCConfiguration getConfiguration();
|
RTCConfiguration getConfiguration();
|
||||||
void setConfiguration(RTCConfiguration configuration);
|
void setConfiguration(optional RTCConfiguration configuration = {});
|
||||||
void close();
|
void close();
|
||||||
attribute EventHandler onnegotiationneeded;
|
attribute EventHandler onnegotiationneeded;
|
||||||
attribute EventHandler onicecandidate;
|
attribute EventHandler onicecandidate;
|
||||||
|
|
|
@ -12,3 +12,34 @@ class ElementLoadPromise {
|
||||||
return document.getElementById(this.element_id);
|
return document.getElementById(this.element_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns if the image is complete and the lazily loaded image matches the expected image.
|
||||||
|
function is_image_fully_loaded(image, expected_image) {
|
||||||
|
if (!image.complete || !expected_image.complete) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image.width != expected_image.width ||
|
||||||
|
image.height != expected_image.height) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let canvas = document.createElement('canvas');
|
||||||
|
canvas.width = image.width;
|
||||||
|
canvas.height = image.height;
|
||||||
|
let canvasContext = canvas.getContext("2d");
|
||||||
|
canvasContext.save();
|
||||||
|
canvasContext.drawImage(image, 0, 0);
|
||||||
|
let data = canvasContext.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||||
|
|
||||||
|
canvasContext.restore();
|
||||||
|
canvasContext.drawImage(expected_image, 0, 0);
|
||||||
|
let expected_data = canvasContext.getImageData(0, 0, canvas.width, canvas.height).data;
|
||||||
|
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i] != expected_data[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Test that below-viewport invisible images that are not marked
|
||||||
|
loading=lazy still load, and block the window load event</title>
|
||||||
|
<link rel="author" title="Rob Buis" href="mailto:rbuis@igalia.com">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script src="common.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<img id="expected" src='resources/image.png?1'>
|
||||||
|
<div style="height:10000px;"></div>
|
||||||
|
<img id="visibility_hidden" style="visibility:hidden;" src='resources/image.png?2'>
|
||||||
|
<img id="display_none" style="display:none;" src='resources/image.png?3'>
|
||||||
|
<img id="attribute_hidden" hidden src='resources/image.png?4'>
|
||||||
|
<img id="js_hidden" src='resources/image.png?5'>.
|
||||||
|
<script>
|
||||||
|
document.getElementById("js_hidden").style = 'display:none;';
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const expected = document.getElementById("expected");
|
||||||
|
const visibility_hidden_element = document.getElementById("visibility_hidden");
|
||||||
|
const display_none_element = document.getElementById("display_none");
|
||||||
|
const attribute_hidden_element = document.getElementById("attribute_hidden");
|
||||||
|
const js_hidden_element = document.getElementById("js_hidden");
|
||||||
|
|
||||||
|
let has_window_loaded = false;
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
window.addEventListener("load", t.step_func(function() {
|
||||||
|
has_window_loaded = true;
|
||||||
|
}));
|
||||||
|
|
||||||
|
let image_fully_loaded_promise = (element) => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
element.addEventListener("load",
|
||||||
|
t.step_func(() => {
|
||||||
|
assert_true(is_image_fully_loaded(element, expected));
|
||||||
|
assert_false(has_window_loaded);
|
||||||
|
resolve();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Promise.all([image_fully_loaded_promise(visibility_hidden_element),
|
||||||
|
image_fully_loaded_promise(display_none_element),
|
||||||
|
image_fully_loaded_promise(attribute_hidden_element),
|
||||||
|
image_fully_loaded_promise(js_hidden_element)]).then(() => {
|
||||||
|
t.done();
|
||||||
|
});
|
||||||
|
}, "Test that below-viewport invisible images that are not marked " +
|
||||||
|
"loading=lazy still load, and block the window load event");
|
||||||
|
</script>
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<head>
|
||||||
|
<title>Test that lazily loaded below the viewport invisible
|
||||||
|
images are not loaded</title>
|
||||||
|
<link rel="author" title="Rob Buis" href="mailto:rbuis@igalia.com">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div style="height:10000px;"></div>
|
||||||
|
<img id="visibility_hidden" style="visibility:hidden;" src='resources/image.png?1' loading="lazy">
|
||||||
|
<img id="display_none" style="display:none;" src='resources/image.png?2' loading="lazy">
|
||||||
|
<img id="attribute_hidden" hidden src='resources/image.png?3' loading="lazy">
|
||||||
|
<img id="js_hidden" src='resources/image.png?4' loading="lazy">
|
||||||
|
<script>
|
||||||
|
document.getElementById("js_hidden").style = 'display:none;';
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Marked as tentative until https://github.com/whatwg/html/pull/3752 is landed.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const visibility_hidden_element = document.getElementById("visibility_hidden");
|
||||||
|
const display_none_element = document.getElementById("display_none");
|
||||||
|
const attribute_hidden_element = document.getElementById("attribute_hidden");
|
||||||
|
const js_hidden_element = document.getElementById("js_hidden");
|
||||||
|
|
||||||
|
async_test(function(t) {
|
||||||
|
visibility_hidden_element.onload = e => {
|
||||||
|
t.step(function() {
|
||||||
|
t.unreached_func("Invisible image with loading=lazy should be loaded lazily.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
display_none_element.onload = e => {
|
||||||
|
t.step(function() {
|
||||||
|
t.unreached_func("Invisible image with loading=lazy should be loaded lazily.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
attribute_hidden_element.onload = e => {
|
||||||
|
t.step(function() {
|
||||||
|
t.unreached_func("Invisible image with loading=lazy should be loaded lazily.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
js_hidden_element.onload = e => {
|
||||||
|
t.step(function() {
|
||||||
|
t.unreached_func("Invisible image with loading=lazy should be loaded lazily.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
window.addEventListener("load", t.step_func(function() {
|
||||||
|
visibility_hidden_element.scrollIntoView();
|
||||||
|
display_none_element.scrollIntoView();
|
||||||
|
attribute_hidden_element.scrollIntoView();
|
||||||
|
js_hidden_element.scrollIntoView();
|
||||||
|
}));
|
||||||
|
|
||||||
|
t.step_timeout(function() { t.done(); }, 2000);
|
||||||
|
}, "Test that lazily loaded below the viewport invisible images " +
|
||||||
|
"are not loaded");
|
||||||
|
</script>
|
||||||
|
|
|
@ -26,6 +26,11 @@ components:
|
||||||
vars:
|
vars:
|
||||||
test-type: wdspec
|
test-type: wdspec
|
||||||
|
|
||||||
|
wpt-crashtest:
|
||||||
|
chunks: 1
|
||||||
|
vars:
|
||||||
|
test-type: crashtest
|
||||||
|
|
||||||
run-options:
|
run-options:
|
||||||
options:
|
options:
|
||||||
xvfb: true
|
xvfb: true
|
||||||
|
@ -115,6 +120,8 @@ tasks:
|
||||||
suite: reftest
|
suite: reftest
|
||||||
- vars:
|
- vars:
|
||||||
suite: wdspec
|
suite: wdspec
|
||||||
|
- vars:
|
||||||
|
suite: crashtest
|
||||||
do:
|
do:
|
||||||
$map:
|
$map:
|
||||||
for:
|
for:
|
||||||
|
|
|
@ -123,6 +123,8 @@ def test_verify_payload():
|
||||||
'wpt-chrome-dev-reftest-5',
|
'wpt-chrome-dev-reftest-5',
|
||||||
'wpt-firefox-nightly-wdspec-1',
|
'wpt-firefox-nightly-wdspec-1',
|
||||||
'wpt-chrome-dev-wdspec-1',
|
'wpt-chrome-dev-wdspec-1',
|
||||||
|
'wpt-firefox-nightly-crashtest-1',
|
||||||
|
'wpt-chrome-dev-crashtest-1',
|
||||||
'lint'}),
|
'lint'}),
|
||||||
("pr_event.json", True, {".taskcluster.yml",".travis.yml","tools/ci/start.sh"},
|
("pr_event.json", True, {".taskcluster.yml",".travis.yml","tools/ci/start.sh"},
|
||||||
{'lint',
|
{'lint',
|
||||||
|
@ -166,6 +168,7 @@ def test_verify_payload():
|
||||||
'wpt-chrome-stable-testharness-8',
|
'wpt-chrome-stable-testharness-8',
|
||||||
'wpt-chrome-stable-testharness-9',
|
'wpt-chrome-stable-testharness-9',
|
||||||
'wpt-chrome-stable-wdspec-1',
|
'wpt-chrome-stable-wdspec-1',
|
||||||
|
'wpt-chrome-stable-crashtest-1',
|
||||||
'wpt-firefox-stable-reftest-1',
|
'wpt-firefox-stable-reftest-1',
|
||||||
'wpt-firefox-stable-reftest-2',
|
'wpt-firefox-stable-reftest-2',
|
||||||
'wpt-firefox-stable-reftest-3',
|
'wpt-firefox-stable-reftest-3',
|
||||||
|
@ -188,6 +191,7 @@ def test_verify_payload():
|
||||||
'wpt-firefox-stable-testharness-8',
|
'wpt-firefox-stable-testharness-8',
|
||||||
'wpt-firefox-stable-testharness-9',
|
'wpt-firefox-stable-testharness-9',
|
||||||
'wpt-firefox-stable-wdspec-1',
|
'wpt-firefox-stable-wdspec-1',
|
||||||
|
'wpt-firefox-stable-crashtest-1',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-reftest-1',
|
'wpt-webkitgtk_minibrowser-nightly-reftest-1',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-reftest-2',
|
'wpt-webkitgtk_minibrowser-nightly-reftest-2',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-reftest-3',
|
'wpt-webkitgtk_minibrowser-nightly-reftest-3',
|
||||||
|
@ -209,7 +213,8 @@ def test_verify_payload():
|
||||||
'wpt-webkitgtk_minibrowser-nightly-testharness-7',
|
'wpt-webkitgtk_minibrowser-nightly-testharness-7',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-testharness-8',
|
'wpt-webkitgtk_minibrowser-nightly-testharness-8',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-testharness-9',
|
'wpt-webkitgtk_minibrowser-nightly-testharness-9',
|
||||||
'wpt-webkitgtk_minibrowser-nightly-wdspec-1'})
|
'wpt-webkitgtk_minibrowser-nightly-wdspec-1',
|
||||||
|
'wpt-webkitgtk_minibrowser-nightly-crashtest-1'})
|
||||||
])
|
])
|
||||||
def test_schedule_tasks(event_path, is_pr, files_changed, expected):
|
def test_schedule_tasks(event_path, is_pr, files_changed, expected):
|
||||||
with mock.patch("tools.ci.tc.decision.get_fetch_rev", return_value=(None, None, None)):
|
with mock.patch("tools.ci.tc.decision.get_fetch_rev", return_value=(None, None, None)):
|
||||||
|
|
|
@ -329,6 +329,17 @@ class VisualTest(URLManifestItem):
|
||||||
item_type = "visual"
|
item_type = "visual"
|
||||||
|
|
||||||
|
|
||||||
|
class CrashTest(URLManifestItem):
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
item_type = "crashtest"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timeout(self):
|
||||||
|
# type: () -> Optional[Text]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class WebDriverSpecTest(URLManifestItem):
|
class WebDriverSpecTest(URLManifestItem):
|
||||||
__slots__ = ()
|
__slots__ = ()
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ from six import iteritems, iterkeys, itervalues, string_types, binary_type, text
|
||||||
|
|
||||||
from . import vcs
|
from . import vcs
|
||||||
from .item import (ConformanceCheckerTest, ManifestItem, ManualTest, RefTest, RefTestNode,
|
from .item import (ConformanceCheckerTest, ManifestItem, ManualTest, RefTest, RefTestNode,
|
||||||
SupportFile, TestharnessTest, VisualTest, WebDriverSpecTest)
|
SupportFile, TestharnessTest, VisualTest, WebDriverSpecTest, CrashTest)
|
||||||
from .log import get_logger
|
from .log import get_logger
|
||||||
from .sourcefile import SourceFile
|
from .sourcefile import SourceFile
|
||||||
from .utils import from_os_path, to_os_path
|
from .utils import from_os_path, to_os_path
|
||||||
|
@ -50,6 +50,7 @@ class ManifestVersionMismatch(ManifestError):
|
||||||
item_classes = {"testharness": TestharnessTest,
|
item_classes = {"testharness": TestharnessTest,
|
||||||
"reftest": RefTest,
|
"reftest": RefTest,
|
||||||
"reftest_node": RefTestNode,
|
"reftest_node": RefTestNode,
|
||||||
|
"crashtest": CrashTest,
|
||||||
"manual": ManualTest,
|
"manual": ManualTest,
|
||||||
"wdspec": WebDriverSpecTest,
|
"wdspec": WebDriverSpecTest,
|
||||||
"conformancechecker": ConformanceCheckerTest,
|
"conformancechecker": ConformanceCheckerTest,
|
||||||
|
|
|
@ -34,7 +34,7 @@ import html5lib
|
||||||
|
|
||||||
from . import XMLParser
|
from . import XMLParser
|
||||||
from .item import (ManifestItem, ManualTest, WebDriverSpecTest, RefTestNode, TestharnessTest,
|
from .item import (ManifestItem, ManualTest, WebDriverSpecTest, RefTestNode, TestharnessTest,
|
||||||
SupportFile, ConformanceCheckerTest, VisualTest)
|
SupportFile, CrashTest, ConformanceCheckerTest, VisualTest)
|
||||||
from .utils import ContextManagerBytesIO, cached_property
|
from .utils import ContextManagerBytesIO, cached_property
|
||||||
|
|
||||||
wd_pattern = "*.py"
|
wd_pattern = "*.py"
|
||||||
|
@ -408,6 +408,11 @@ class SourceFile(object):
|
||||||
be a reference file (not a reftest)"""
|
be a reference file (not a reftest)"""
|
||||||
return "/reference/" in self.url or bool(reference_file_re.search(self.name))
|
return "/reference/" in self.url or bool(reference_file_re.search(self.name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name_is_crashtest(self):
|
||||||
|
# type: () -> bool
|
||||||
|
return self.type_flag == "crash" or "crashtests" in self.dir_path.split(os.path.sep)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def markup_type(self):
|
def markup_type(self):
|
||||||
# type: () -> Optional[Text]
|
# type: () -> Optional[Text]
|
||||||
|
@ -820,6 +825,15 @@ class SourceFile(object):
|
||||||
self.rel_url
|
self.rel_url
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
elif self.name_is_crashtest:
|
||||||
|
rv = CrashTest.item_type, [
|
||||||
|
CrashTest(
|
||||||
|
self.tests_root,
|
||||||
|
self.rel_path,
|
||||||
|
self.url_base,
|
||||||
|
self.rel_url
|
||||||
|
)]
|
||||||
|
|
||||||
elif self.name_is_multi_global:
|
elif self.name_is_multi_global:
|
||||||
globals = b""
|
globals = b""
|
||||||
script_metadata = self.script_metadata
|
script_metadata = self.script_metadata
|
||||||
|
|
|
@ -3,7 +3,8 @@ from .base import get_timeout_multiplier # noqa: F401
|
||||||
from ..webdriver_server import ChromeDriverServer
|
from ..webdriver_server import ChromeDriverServer
|
||||||
from ..executors import executor_kwargs as base_executor_kwargs
|
from ..executors import executor_kwargs as base_executor_kwargs
|
||||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||||
WebDriverRefTestExecutor) # noqa: F401
|
WebDriverRefTestExecutor, # noqa: F401
|
||||||
|
WebDriverCrashtestExecutor) # noqa: F401
|
||||||
from ..executors.executorchrome import ChromeDriverWdspecExecutor # noqa: F401
|
from ..executors.executorchrome import ChromeDriverWdspecExecutor # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,7 +13,8 @@ __wptrunner__ = {"product": "chrome",
|
||||||
"browser": "ChromeBrowser",
|
"browser": "ChromeBrowser",
|
||||||
"executor": {"testharness": "WebDriverTestharnessExecutor",
|
"executor": {"testharness": "WebDriverTestharnessExecutor",
|
||||||
"reftest": "WebDriverRefTestExecutor",
|
"reftest": "WebDriverRefTestExecutor",
|
||||||
"wdspec": "ChromeDriverWdspecExecutor"},
|
"wdspec": "ChromeDriverWdspecExecutor",
|
||||||
|
"crashtest": "WebDriverCrashtestExecutor"},
|
||||||
"browser_kwargs": "browser_kwargs",
|
"browser_kwargs": "browser_kwargs",
|
||||||
"executor_kwargs": "executor_kwargs",
|
"executor_kwargs": "executor_kwargs",
|
||||||
"env_extras": "env_extras",
|
"env_extras": "env_extras",
|
||||||
|
|
|
@ -23,7 +23,8 @@ from .base import (get_free_port,
|
||||||
from ..executors import executor_kwargs as base_executor_kwargs
|
from ..executors import executor_kwargs as base_executor_kwargs
|
||||||
from ..executors.executormarionette import (MarionetteTestharnessExecutor, # noqa: F401
|
from ..executors.executormarionette import (MarionetteTestharnessExecutor, # noqa: F401
|
||||||
MarionetteRefTestExecutor, # noqa: F401
|
MarionetteRefTestExecutor, # noqa: F401
|
||||||
MarionetteWdspecExecutor) # noqa: F401
|
MarionetteWdspecExecutor, # noqa: F401
|
||||||
|
MarionetteCrashtestExecutor) # noqa: F401
|
||||||
|
|
||||||
|
|
||||||
here = os.path.join(os.path.split(__file__)[0])
|
here = os.path.join(os.path.split(__file__)[0])
|
||||||
|
@ -31,7 +32,8 @@ here = os.path.join(os.path.split(__file__)[0])
|
||||||
__wptrunner__ = {"product": "firefox",
|
__wptrunner__ = {"product": "firefox",
|
||||||
"check_args": "check_args",
|
"check_args": "check_args",
|
||||||
"browser": "FirefoxBrowser",
|
"browser": "FirefoxBrowser",
|
||||||
"executor": {"testharness": "MarionetteTestharnessExecutor",
|
"executor": {"crashtest": "MarionetteCrashtestExecutor",
|
||||||
|
"testharness": "MarionetteTestharnessExecutor",
|
||||||
"reftest": "MarionetteRefTestExecutor",
|
"reftest": "MarionetteRefTestExecutor",
|
||||||
"wdspec": "MarionetteWdspecExecutor"},
|
"wdspec": "MarionetteWdspecExecutor"},
|
||||||
"browser_kwargs": "browser_kwargs",
|
"browser_kwargs": "browser_kwargs",
|
||||||
|
|
|
@ -121,6 +121,9 @@ def pytest_result_converter(self, test, data):
|
||||||
return (harness_result, subtest_results)
|
return (harness_result, subtest_results)
|
||||||
|
|
||||||
|
|
||||||
|
def crashtest_result_converter(self, test, result):
|
||||||
|
return test.result_cls(**result), []
|
||||||
|
|
||||||
class ExecutorException(Exception):
|
class ExecutorException(Exception):
|
||||||
def __init__(self, status, message):
|
def __init__(self, status, message):
|
||||||
self.status = status
|
self.status = status
|
||||||
|
@ -316,6 +319,10 @@ class RefTestExecutor(TestExecutor):
|
||||||
self.screenshot_cache = screenshot_cache
|
self.screenshot_cache = screenshot_cache
|
||||||
|
|
||||||
|
|
||||||
|
class CrashtestExecutor(TestExecutor):
|
||||||
|
convert_result = crashtest_result_converter
|
||||||
|
|
||||||
|
|
||||||
class RefTestImplementation(object):
|
class RefTestImplementation(object):
|
||||||
def __init__(self, executor):
|
def __init__(self, executor):
|
||||||
self.timeout_multiplier = executor.timeout_multiplier
|
self.timeout_multiplier = executor.timeout_multiplier
|
||||||
|
@ -573,6 +580,9 @@ class WdspecRun(object):
|
||||||
|
|
||||||
|
|
||||||
class ConnectionlessBaseProtocolPart(BaseProtocolPart):
|
class ConnectionlessBaseProtocolPart(BaseProtocolPart):
|
||||||
|
def load(self, url):
|
||||||
|
pass
|
||||||
|
|
||||||
def execute_script(self, script, asynchronous=False):
|
def execute_script(self, script, asynchronous=False):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ pytestrunner = None
|
||||||
here = os.path.join(os.path.split(__file__)[0])
|
here = os.path.join(os.path.split(__file__)[0])
|
||||||
|
|
||||||
from .base import (CallbackHandler,
|
from .base import (CallbackHandler,
|
||||||
|
CrashtestExecutor,
|
||||||
RefTestExecutor,
|
RefTestExecutor,
|
||||||
RefTestImplementation,
|
RefTestImplementation,
|
||||||
TestharnessExecutor,
|
TestharnessExecutor,
|
||||||
|
@ -80,6 +81,9 @@ class MarionetteBaseProtocolPart(BaseProtocolPart):
|
||||||
def set_window(self, handle):
|
def set_window(self, handle):
|
||||||
self.marionette.switch_to_window(handle)
|
self.marionette.switch_to_window(handle)
|
||||||
|
|
||||||
|
def load(self, url):
|
||||||
|
self.marionette.navigate(url)
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
try:
|
try:
|
||||||
socket_timeout = self.marionette.client.socket_timeout
|
socket_timeout = self.marionette.client.socket_timeout
|
||||||
|
@ -790,8 +794,8 @@ class MarionetteRefTestExecutor(RefTestExecutor):
|
||||||
|
|
||||||
with open(os.path.join(here, "reftest.js")) as f:
|
with open(os.path.join(here, "reftest.js")) as f:
|
||||||
self.script = f.read()
|
self.script = f.read()
|
||||||
with open(os.path.join(here, "reftest-wait_webdriver.js")) as f:
|
with open(os.path.join(here, "test-wait.js")) as f:
|
||||||
self.wait_script = f.read()
|
self.wait_script = f.read() % {"classname": "reftest-wait"}
|
||||||
|
|
||||||
def setup(self, runner):
|
def setup(self, runner):
|
||||||
super(self.__class__, self).setup(runner)
|
super(self.__class__, self).setup(runner)
|
||||||
|
@ -935,10 +939,77 @@ class InternalRefTestImplementation(RefTestImplementation):
|
||||||
self.logger.warning(traceback.format_exc(e))
|
self.logger.warning(traceback.format_exc(e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GeckoDriverProtocol(WebDriverProtocol):
|
class GeckoDriverProtocol(WebDriverProtocol):
|
||||||
server_cls = GeckoDriverServer
|
server_cls = GeckoDriverServer
|
||||||
|
|
||||||
|
|
||||||
class MarionetteWdspecExecutor(WdspecExecutor):
|
class MarionetteWdspecExecutor(WdspecExecutor):
|
||||||
protocol_cls = GeckoDriverProtocol
|
protocol_cls = GeckoDriverProtocol
|
||||||
|
|
||||||
|
|
||||||
|
class MarionetteCrashtestExecutor(CrashtestExecutor):
|
||||||
|
def __init__(self, browser, server_config, timeout_multiplier=1,
|
||||||
|
debug_info=None, capabilities=None, debug=False,
|
||||||
|
ccov=False, **kwargs):
|
||||||
|
"""Marionette-based executor for testharness.js tests"""
|
||||||
|
CrashtestExecutor.__init__(self, browser, server_config,
|
||||||
|
timeout_multiplier=timeout_multiplier,
|
||||||
|
debug_info=debug_info)
|
||||||
|
self.protocol = MarionetteProtocol(self,
|
||||||
|
browser,
|
||||||
|
capabilities,
|
||||||
|
timeout_multiplier,
|
||||||
|
kwargs["e10s"],
|
||||||
|
ccov)
|
||||||
|
|
||||||
|
self.original_pref_values = {}
|
||||||
|
self.debug = debug
|
||||||
|
|
||||||
|
with open(os.path.join(here, "test-wait.js")) as f:
|
||||||
|
self.wait_script = f.read() % {"classname": "test-wait"}
|
||||||
|
|
||||||
|
if marionette is None:
|
||||||
|
do_delayed_imports()
|
||||||
|
|
||||||
|
def is_alive(self):
|
||||||
|
return self.protocol.is_alive
|
||||||
|
|
||||||
|
def on_environment_change(self, new_environment):
|
||||||
|
self.protocol.on_environment_change(self.last_environment, new_environment)
|
||||||
|
|
||||||
|
def do_test(self, test):
|
||||||
|
timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
|
||||||
|
else None)
|
||||||
|
|
||||||
|
success, data = ExecuteAsyncScriptRun(self.logger,
|
||||||
|
self.do_crashtest,
|
||||||
|
self.protocol,
|
||||||
|
self.test_url(test),
|
||||||
|
timeout,
|
||||||
|
self.extra_timeout).run()
|
||||||
|
status = None
|
||||||
|
if not success:
|
||||||
|
status = data[0]
|
||||||
|
|
||||||
|
if self.debug and (success or status not in ("CRASH", "INTERNAL-ERROR")):
|
||||||
|
assertion_count = self.protocol.asserts.get()
|
||||||
|
if assertion_count is not None:
|
||||||
|
data["extra"] = {"assertion_count": assertion_count}
|
||||||
|
|
||||||
|
if success:
|
||||||
|
return self.convert_result(test, data)
|
||||||
|
|
||||||
|
return (test.result_cls(**data), [])
|
||||||
|
|
||||||
|
def do_crashtest(self, protocol, url, timeout):
|
||||||
|
if self.protocol.coverage.is_enabled:
|
||||||
|
self.protocol.coverage.reset()
|
||||||
|
|
||||||
|
protocol.base.load(url)
|
||||||
|
protocol.base.execute_script(self.wait_script, asynchronous=True)
|
||||||
|
|
||||||
|
if self.protocol.coverage.is_enabled:
|
||||||
|
self.protocol.coverage.dump()
|
||||||
|
|
||||||
|
return {"status": "PASS",
|
||||||
|
"message": None}
|
||||||
|
|
|
@ -76,6 +76,9 @@ class ServoBaseProtocolPart(BaseProtocolPart):
|
||||||
def set_window(self, handle):
|
def set_window(self, handle):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def load(self, url):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ServoWebDriverProtocol(Protocol):
|
class ServoWebDriverProtocol(Protocol):
|
||||||
implements = [ServoBaseProtocolPart]
|
implements = [ServoBaseProtocolPart]
|
||||||
|
|
|
@ -8,6 +8,7 @@ import urlparse
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from .base import (CallbackHandler,
|
from .base import (CallbackHandler,
|
||||||
|
CrashtestExecutor,
|
||||||
RefTestExecutor,
|
RefTestExecutor,
|
||||||
RefTestImplementation,
|
RefTestImplementation,
|
||||||
TestharnessExecutor,
|
TestharnessExecutor,
|
||||||
|
@ -58,6 +59,9 @@ class WebDriverBaseProtocolPart(BaseProtocolPart):
|
||||||
def set_window(self, handle):
|
def set_window(self, handle):
|
||||||
self.webdriver.window_handle = handle
|
self.webdriver.window_handle = handle
|
||||||
|
|
||||||
|
def load(self, url):
|
||||||
|
self.webdriver.url = url
|
||||||
|
|
||||||
def wait(self):
|
def wait(self):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
|
@ -449,8 +453,8 @@ class WebDriverRefTestExecutor(RefTestExecutor):
|
||||||
self.close_after_done = close_after_done
|
self.close_after_done = close_after_done
|
||||||
self.has_window = False
|
self.has_window = False
|
||||||
|
|
||||||
with open(os.path.join(here, "reftest-wait_webdriver.js")) as f:
|
with open(os.path.join(here, "test-wait.js")) as f:
|
||||||
self.wait_script = f.read()
|
self.wait_script = f.read() % {"classname": "reftest-wait"}
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.implementation.reset()
|
self.implementation.reset()
|
||||||
|
@ -487,15 +491,55 @@ class WebDriverRefTestExecutor(RefTestExecutor):
|
||||||
self.extra_timeout).run()
|
self.extra_timeout).run()
|
||||||
|
|
||||||
def _screenshot(self, protocol, url, timeout):
|
def _screenshot(self, protocol, url, timeout):
|
||||||
webdriver = protocol.webdriver
|
self.protocol.base.load(url)
|
||||||
webdriver.url = url
|
|
||||||
|
|
||||||
webdriver.execute_async_script(self.wait_script)
|
self.protocol.base.execute_script(self.wait_script, True)
|
||||||
|
|
||||||
screenshot = webdriver.screenshot()
|
screenshot = self.protocol.webdriver.screenshot()
|
||||||
|
|
||||||
# strip off the data:img/png, part of the url
|
# strip off the data:img/png, part of the url
|
||||||
if screenshot.startswith("data:image/png;base64,"):
|
if screenshot.startswith("data:image/png;base64,"):
|
||||||
screenshot = screenshot.split(",", 1)[1]
|
screenshot = screenshot.split(",", 1)[1]
|
||||||
|
|
||||||
return screenshot
|
return screenshot
|
||||||
|
|
||||||
|
|
||||||
|
class WebDriverCrashtestExecutor(CrashtestExecutor):
|
||||||
|
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"""
|
||||||
|
CrashtestExecutor.__init__(self,
|
||||||
|
browser,
|
||||||
|
server_config,
|
||||||
|
screenshot_cache=screenshot_cache,
|
||||||
|
timeout_multiplier=timeout_multiplier,
|
||||||
|
debug_info=debug_info)
|
||||||
|
self.protocol = WebDriverProtocol(self, browser,
|
||||||
|
capabilities=capabilities)
|
||||||
|
|
||||||
|
with open(os.path.join(here, "test-wait.js")) as f:
|
||||||
|
self.wait_script = f.read() % {"classname": "test-wait"}
|
||||||
|
|
||||||
|
def do_test(self, test):
|
||||||
|
timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
|
||||||
|
else None)
|
||||||
|
|
||||||
|
success, data = WebDriverRun(self.logger,
|
||||||
|
self.do_crashtest,
|
||||||
|
self.protocol,
|
||||||
|
self.test_url(test),
|
||||||
|
timeout,
|
||||||
|
self.extra_timeout).run()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
return self.convert_result(test, data)
|
||||||
|
|
||||||
|
return (test.result_cls(**data), [])
|
||||||
|
|
||||||
|
def do_crashtest(self, protocol, url, timeout):
|
||||||
|
protocol.base.load(url)
|
||||||
|
protocol.base.execute_script(self.wait_script, asynchronous=True)
|
||||||
|
|
||||||
|
return {"status": "PASS",
|
||||||
|
"message": None}
|
||||||
|
|
|
@ -147,6 +147,13 @@ class BaseProtocolPart(ProtocolPart):
|
||||||
context."""
|
context."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def load(self, url):
|
||||||
|
"""Load a url in the current browsing context
|
||||||
|
|
||||||
|
:param url: The url to load"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class TestharnessProtocolPart(ProtocolPart):
|
class TestharnessProtocolPart(ProtocolPart):
|
||||||
"""Protocol part required to run testharness tests."""
|
"""Protocol part required to run testharness tests."""
|
||||||
|
|
|
@ -32,7 +32,7 @@ function wait_paints() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function screenshot_if_ready() {
|
function screenshot_if_ready() {
|
||||||
if (root.classList.contains("reftest-wait") &&
|
if (root.classList.contains("%(classname)s") &&
|
||||||
observer === null) {
|
observer === null) {
|
||||||
observer = new MutationObserver(wait_paints);
|
observer = new MutationObserver(wait_paints);
|
||||||
observer.observe(root, {attributes: true});
|
observer.observe(root, {attributes: true});
|
|
@ -1,3 +1,5 @@
|
||||||
|
from six.moves import xrange
|
||||||
|
|
||||||
class NodeVisitor(object):
|
class NodeVisitor(object):
|
||||||
def visit(self, node):
|
def visit(self, node):
|
||||||
# This is ugly as hell, but we don't have multimethods and
|
# This is ugly as hell, but we don't have multimethods and
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from six import binary_type, text_type, BytesIO
|
from six import binary_type, text_type, BytesIO
|
||||||
|
from six.moves import xrange
|
||||||
|
|
||||||
from .node import (Node, AtomNode, BinaryExpressionNode, BinaryOperatorNode,
|
from .node import (Node, AtomNode, BinaryExpressionNode, BinaryOperatorNode,
|
||||||
ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode,
|
ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode,
|
||||||
|
@ -541,7 +542,7 @@ class Parser(object):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def consume(self):
|
def consume(self):
|
||||||
self.token = self.token_generator.next()
|
self.token = next(self.token_generator)
|
||||||
|
|
||||||
def expect(self, type, value=None):
|
def expect(self, type, value=None):
|
||||||
if self.token[0] != type:
|
if self.token[0] != type:
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
import pytest
|
|
||||||
import sys
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from six.moves import cStringIO as StringIO
|
|
||||||
|
|
||||||
from .. import parser
|
from .. import parser
|
||||||
|
|
||||||
# There aren't many tests here because it turns out to be way more convenient to
|
# There aren't many tests here because it turns out to be way more convenient to
|
||||||
# use test_serializer for the majority of cases
|
# use test_serializer for the majority of cases
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail(sys.version[0] == "3",
|
|
||||||
reason="wptmanifest.parser doesn't support py3")
|
|
||||||
class TestExpression(unittest.TestCase):
|
class TestExpression(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.parser = parser.Parser()
|
self.parser = parser.Parser()
|
||||||
|
|
||||||
def parse(self, input_str):
|
def parse(self, input_str):
|
||||||
return self.parser.parse(StringIO(input_str))
|
return self.parser.parse(input_str)
|
||||||
|
|
||||||
def compare(self, input_text, expected):
|
def compare(self, input_text, expected):
|
||||||
actual = self.parse(input_text)
|
actual = self.parse(input_text)
|
||||||
|
@ -32,7 +26,7 @@ class TestExpression(unittest.TestCase):
|
||||||
|
|
||||||
def test_expr_0(self):
|
def test_expr_0(self):
|
||||||
self.compare(
|
self.compare(
|
||||||
"""
|
b"""
|
||||||
key:
|
key:
|
||||||
if x == 1 : value""",
|
if x == 1 : value""",
|
||||||
["DataNode", None,
|
["DataNode", None,
|
||||||
|
@ -49,7 +43,7 @@ key:
|
||||||
|
|
||||||
def test_expr_1(self):
|
def test_expr_1(self):
|
||||||
self.compare(
|
self.compare(
|
||||||
"""
|
b"""
|
||||||
key:
|
key:
|
||||||
if not x and y : value""",
|
if not x and y : value""",
|
||||||
["DataNode", None,
|
["DataNode", None,
|
||||||
|
@ -69,7 +63,7 @@ key:
|
||||||
|
|
||||||
def test_expr_2(self):
|
def test_expr_2(self):
|
||||||
self.compare(
|
self.compare(
|
||||||
"""
|
b"""
|
||||||
key:
|
key:
|
||||||
if x == 1 : [value1, value2]""",
|
if x == 1 : [value1, value2]""",
|
||||||
["DataNode", None,
|
["DataNode", None,
|
||||||
|
@ -88,7 +82,7 @@ key:
|
||||||
|
|
||||||
def test_expr_3(self):
|
def test_expr_3(self):
|
||||||
self.compare(
|
self.compare(
|
||||||
"""
|
b"""
|
||||||
key:
|
key:
|
||||||
if x == 1: 'if b: value'""",
|
if x == 1: 'if b: value'""",
|
||||||
["DataNode", None,
|
["DataNode", None,
|
||||||
|
@ -105,15 +99,15 @@ key:
|
||||||
|
|
||||||
def test_atom_0(self):
|
def test_atom_0(self):
|
||||||
with self.assertRaises(parser.ParseError):
|
with self.assertRaises(parser.ParseError):
|
||||||
self.parse("key: @Unknown")
|
self.parse(b"key: @Unknown")
|
||||||
|
|
||||||
def test_atom_1(self):
|
def test_atom_1(self):
|
||||||
with self.assertRaises(parser.ParseError):
|
with self.assertRaises(parser.ParseError):
|
||||||
self.parse("key: @true")
|
self.parse(b"key: @true")
|
||||||
|
|
||||||
def test_if_1(self):
|
def test_if_1(self):
|
||||||
with self.assertRaises(parser.ParseError):
|
with self.assertRaises(parser.ParseError):
|
||||||
self.parse("key: if foo")
|
self.parse(b"key: if foo")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -6,7 +6,7 @@ from collections import defaultdict
|
||||||
from .wptmanifest.parser import atoms
|
from .wptmanifest.parser import atoms
|
||||||
|
|
||||||
atom_reset = atoms["Reset"]
|
atom_reset = atoms["Reset"]
|
||||||
enabled_tests = {"testharness", "reftest", "wdspec"}
|
enabled_tests = {"testharness", "reftest", "wdspec", "crashtest"}
|
||||||
|
|
||||||
|
|
||||||
class Result(object):
|
class Result(object):
|
||||||
|
@ -71,6 +71,12 @@ class WdspecSubtestResult(SubtestResult):
|
||||||
statuses = {"PASS", "FAIL", "ERROR"}
|
statuses = {"PASS", "FAIL", "ERROR"}
|
||||||
|
|
||||||
|
|
||||||
|
class CrashtestResult(Result):
|
||||||
|
default_expected = "PASS"
|
||||||
|
statuses = {"PASS", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT",
|
||||||
|
"CRASH"}
|
||||||
|
|
||||||
|
|
||||||
def get_run_info(metadata_root, product, **kwargs):
|
def get_run_info(metadata_root, product, **kwargs):
|
||||||
return RunInfo(metadata_root, product, **kwargs)
|
return RunInfo(metadata_root, product, **kwargs)
|
||||||
|
|
||||||
|
@ -546,7 +552,6 @@ class ReftestTest(Test):
|
||||||
|
|
||||||
|
|
||||||
class WdspecTest(Test):
|
class WdspecTest(Test):
|
||||||
|
|
||||||
result_cls = WdspecResult
|
result_cls = WdspecResult
|
||||||
subtest_result_cls = WdspecSubtestResult
|
subtest_result_cls = WdspecSubtestResult
|
||||||
test_type = "wdspec"
|
test_type = "wdspec"
|
||||||
|
@ -555,10 +560,16 @@ class WdspecTest(Test):
|
||||||
long_timeout = 180 # 3 minutes
|
long_timeout = 180 # 3 minutes
|
||||||
|
|
||||||
|
|
||||||
|
class CrashTest(Test):
|
||||||
|
result_cls = CrashtestResult
|
||||||
|
test_type = "crashtest"
|
||||||
|
|
||||||
|
|
||||||
manifest_test_cls = {"reftest": ReftestTest,
|
manifest_test_cls = {"reftest": ReftestTest,
|
||||||
"testharness": TestharnessTest,
|
"testharness": TestharnessTest,
|
||||||
"manual": ManualTest,
|
"manual": ManualTest,
|
||||||
"wdspec": WdspecTest}
|
"wdspec": WdspecTest,
|
||||||
|
"crashtest": CrashTest}
|
||||||
|
|
||||||
|
|
||||||
def from_manifest(manifest_file, manifest_test, inherit_metadata, test_metadata):
|
def from_manifest(manifest_file, manifest_test, inherit_metadata, test_metadata):
|
||||||
|
|
|
@ -21,6 +21,7 @@ self.onmessage = e => {
|
||||||
|
|
||||||
self.onmessageerror = e => {
|
self.onmessageerror = e => {
|
||||||
if (state === "we are expecting a messageerror due to the window sending us a WebAssembly.Module") {
|
if (state === "we are expecting a messageerror due to the window sending us a WebAssembly.Module") {
|
||||||
|
assert_equals(e.constructor.name, "ExtendableMessageEvent", "type");
|
||||||
assert_equals(e.data, null, "data");
|
assert_equals(e.data, null, "data");
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
assert_equals(e.origin, self.origin, "origin");
|
||||||
assert_not_equals(e.source, null, "source");
|
assert_not_equals(e.source, null, "source");
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
"use strict";
|
|
||||||
self.importScripts("/resources/testharness.js");
|
|
||||||
self.importScripts("./create-empty-wasm-module.js");
|
|
||||||
|
|
||||||
let state = "start in worker";
|
|
||||||
|
|
||||||
self.onmessage = e => {
|
|
||||||
if (e.data === "start in window") {
|
|
||||||
assert_equals(state, "start in worker");
|
|
||||||
e.source.postMessage(state);
|
|
||||||
state = "waiting for message from the window";
|
|
||||||
} else if (e.data === "we are expecting a messageerror due to the worker sending us a WebAssembly.Module") {
|
|
||||||
assert_equals(state, "waiting for message from the window");
|
|
||||||
e.source.postMessage(createEmptyWasmModule());
|
|
||||||
state = "done in worker";
|
|
||||||
} else {
|
|
||||||
e.source.postMessage(`worker onmessage was reached when in state "${state}" and data ${e.data}`);
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -11,12 +11,14 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
promise_test(t => {
|
promise_test(t => {
|
||||||
const scope = "resources/blank.html";
|
const scope = "resources/blank.html";
|
||||||
return service_worker_unregister_and_register(t, "resources/serviceworker-failure.js", scope).then(reg => {
|
return service_worker_unregister_and_register(t, "resources/serviceworker-failure.js", scope)
|
||||||
|
.then(reg => {
|
||||||
|
t.add_cleanup(() => service_worker_unregister(t, scope));
|
||||||
return wait_for_state(t, reg.installing, "activated");
|
return wait_for_state(t, reg.installing, "activated");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => with_iframe(scope))
|
||||||
return with_iframe(scope);
|
.then(iframe => {
|
||||||
}).then(iframe => {
|
t.add_cleanup(() => iframe.remove());
|
||||||
const sw = iframe.contentWindow.navigator.serviceWorker;
|
const sw = iframe.contentWindow.navigator.serviceWorker;
|
||||||
let state = "start in window";
|
let state = "start in window";
|
||||||
|
|
||||||
|
@ -40,7 +42,7 @@ promise_test(t => {
|
||||||
|
|
||||||
assert_equals(e.data, null, "data");
|
assert_equals(e.data, null, "data");
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
assert_equals(e.origin, self.origin, "origin");
|
||||||
assert_equals(e.source, null, "source");
|
assert_not_equals(e.source, null, "source");
|
||||||
assert_equals(e.ports.length, 0, "ports length");
|
assert_equals(e.ports.length, 0, "ports length");
|
||||||
|
|
||||||
state = "done in window";
|
state = "done in window";
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Test ServiceWorkerContainer.onmessageerror using WebAssembly.Module</title>
|
|
||||||
<script src="/resources/testharness.js"></script>
|
|
||||||
<script src="/resources/testharnessreport.js"></script>
|
|
||||||
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
|
|
||||||
<script src="./resources/create-empty-wasm-module.js"></script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
"use strict";
|
|
||||||
promise_test(t => {
|
|
||||||
const scope = "resources/blank.html";
|
|
||||||
return service_worker_unregister_and_register(t, "resources/serviceworker-success.js", scope)
|
|
||||||
.then(reg => {
|
|
||||||
t.add_cleanup(() => service_worker_unregister(t, scope));
|
|
||||||
return wait_for_state(t, reg.installing, "activated");
|
|
||||||
})
|
|
||||||
.then(() => with_iframe(scope))
|
|
||||||
.then(iframe => {
|
|
||||||
t.add_cleanup(() => iframe.remove());
|
|
||||||
const sw = iframe.contentWindow.navigator.serviceWorker;
|
|
||||||
let state = "start in window";
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
|
||||||
sw.onmessage = t.step_func(e => {
|
|
||||||
if (e.data === "start in worker") {
|
|
||||||
assert_equals(state, "start in window");
|
|
||||||
state = "we are expecting a messageerror due to the worker sending us a WebAssembly.Module";
|
|
||||||
sw.controller.postMessage(state);
|
|
||||||
} else {
|
|
||||||
assert_unreached("Got an unexpected message from the service worker: " + e.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
sw.onmessageerror = t.step_func(e => {
|
|
||||||
assert_equals(state, "we are expecting a messageerror due to the worker sending us a WebAssembly.Module");
|
|
||||||
assert_equals(e.data, null, "data");
|
|
||||||
assert_equals(e.origin, self.origin, "origin");
|
|
||||||
assert_not_equals(e.source, null, "source");
|
|
||||||
assert_equals(e.ports.length, 0, "ports length");
|
|
||||||
state = "done in window";
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
sw.controller.postMessage(state);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
Loading…
Add table
Add a link
Reference in a new issue