Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wptrunner] Transmit test results via postMessage #13881

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 38 additions & 32 deletions tools/wptrunner/wptrunner/executors/runner.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,44 @@
document.title = '%(title)s';

window.addEventListener(
"message",
function(event) {
window.message_queue.push(event);
window.process_next_event();
},
false
);


window.process_next_event = function() {
/* This function handles the next testdriver event. The presence of
window.testdriver_callback is used as a switch; when that function
is present we are able to handle the next event and when is is not
present we must wait. Therefore to drive the event processing, this
function must be called in two circumstances:
* Every time there is a new event that we may be able to handle
* Every time we set the callback function
This function unsets the callback, so no further testdriver actions
will be run until it is reset, which wptrunner does after it has
completed handling the current action.
*/
if (!window.testdriver_callback) {
var message_queue = [];
var source = null;

/**
* In preparation to execute a test, testdriver issues a number of messages
* which should be queued until execution time. During execution, testdriver
* consumes the queued messages by repeatedly "resuming" via `do_testharness`.
* The sequence of these events is variable, so the handler must account for
* cases where "resume" requests arrive before any messages are available (by
* caching the request's source) and where messages arrive before "resume"
* requests (by queuing the messages).
*/
window.addEventListener("message", function(event) {
if (!event.data) {
return;
}
var event = window.message_queue.shift();
if (!event) {

if (event.data.type === "testdriver-resume") {
source = event.source;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really understand the point of this; it seems like the identity of the test window is statically known here; it's window.win. Why do we need to keep updating it?

} else {
message_queue.push(event.data);
}

if (!source || !message_queue.length) {
return;
}
var data = event.data;

reply(source, message_queue[0]);
source = null;
message_queue.shift();
}, false);

function reply(source, data) {
var payload = undefined;

switch(data.type) {
case "complete":
var tests = event.data.tests;
var status = event.data.status;
var tests = data.tests;
var status = data.status;

var subtest_results = tests.map(function(x) {
return [x.name, x.status, x.message, x.stack];
Expand All @@ -53,7 +55,11 @@ window.process_next_event = function() {
default:
return;
}
var callback = window.testdriver_callback;
window.testdriver_callback = null;
callback([window.url, data.type, payload]);
};

source.postMessage({
type: "testdriver-next message",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type string doesn't match anything else.

message: [window.url, data.type, payload]
},
"*"
);
}
4 changes: 0 additions & 4 deletions tools/wptrunner/wptrunner/executors/testharness_webdriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ window.win.addEventListener('DOMContentLoaded', (e) => {
callback();
});


window.message_queue = [];
window.testdriver_callback = null;

if (%(timeout)s != null) {
window.timer = setTimeout(function() {
window.win.timeout();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
var callback = arguments[arguments.length - 1];
window.opener.testdriver_callback = callback;
window.opener.process_next_event();

window.addEventListener("message", function handle(event) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the pattern where we keep adding and removing message listeners; we've had bags with such code before. Ideally we define the message handler once in testharnessreport.js and just have this script update the current callback and resume the test.

if (!event.data || event.data.type !== "testdriver-next message") {
return;
}

window.removeEventListener("message", handle);

callback(event.data.message);
});

/**
* The current window and its opener belong to the same domain, making it
* technically possible for data structures to be shared directly. Some
* browser/WebDriver implementations [1] do not correctly serialize Arrays from
* a foreign realm. Transmitting data structures via the `postMessage` API
* avoids this issue because doing so involves de-serializing values in the
* local realm.
*
* [1] This has been observed in Edge version 17 and/or the corresponding
* release of Edgedriver
*/
window.opener.postMessage({ type: "testdriver-resume" }, "*");