Update web-platform-tests to revision 0ed072539aa45d3a5a67c9164b243d27873f257c

This commit is contained in:
WPT Sync Bot 2019-12-13 08:23:34 +00:00
parent 0954871992
commit e613cfd108
76 changed files with 1109 additions and 703 deletions

View file

@ -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

View file

@ -0,0 +1,2 @@
[width-047.xht]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -1,5 +0,0 @@
[response-trailer.html]
type: testharness
[trailer() test]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,4 +0,0 @@
[window-serviceworker-success.https.html]
[Test ServiceWorkerContainer.onmessageerror using SharedArrayBuffer]
expected: FAIL

View file

@ -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

View file

@ -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

View file

@ -1,4 +0,0 @@
[window-serviceworker-success.https.html]
[Test ServiceWorkerContainer.onmessageerror using WebAssembly.Module]
expected: FAIL

View file

@ -3,5 +3,5 @@
expected: FAIL expected: FAIL
[test_element_in_collection] [test_element_in_collection]
expected: expected: FAIL
if os == "mac": FAIL

View file

@ -0,0 +1,5 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -1,5 +0,0 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -0,0 +1,5 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -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:

View file

@ -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>

View 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).

View file

@ -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/)

View file

@ -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.");

View file

@ -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");

View file

@ -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")

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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");

View file

@ -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}`);
}
};

View file

@ -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";

View file

@ -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>

View file

@ -1,2 +0,0 @@
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -0,0 +1,5 @@
onmessage = e => {
e.waitUntil(import("./module.json")
.then(module => e.source.postMessage("LOADED"))
.catch(error => e.source.postMessage("FAILED")));
};

View file

@ -0,0 +1 @@
<p>Test that should not crash

View file

@ -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();
}; };

View file

@ -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 {};

View file

@ -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;

View file

@ -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;
}

View file

@ -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>

View file

@ -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>

View file

@ -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:

View file

@ -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)):

View file

@ -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__ = ()

View file

@ -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,

View file

@ -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

View file

@ -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",

View file

@ -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",

View file

@ -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

View file

@ -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}

View file

@ -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]

View file

@ -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}

View file

@ -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."""

View file

@ -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});

View file

@ -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

View file

@ -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:

View file

@ -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__":

View file

@ -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):

View file

@ -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");

View file

@ -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}`);
}
};

View file

@ -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";

View file

@ -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>