Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Unified Diff: LayoutTests/http/tests/resources/testharness.js

Issue 1209033011: Pull in the latest upstream testharness.js changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@bluetooth-temp
Patch Set: Rebase Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | LayoutTests/http/tests/w3c/resources/idlharness.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: LayoutTests/http/tests/resources/testharness.js
diff --git a/LayoutTests/http/tests/resources/testharness.js b/LayoutTests/http/tests/resources/testharness.js
index 67b0f406c08fd9f634892eec50fb1f918d17e57c..9ad4f9aa5c1acdfd6be2c6903f53d7013e92fee2 100644
--- a/LayoutTests/http/tests/resources/testharness.js
+++ b/LayoutTests/http/tests/resources/testharness.js
@@ -22,7 +22,8 @@ policies and contribution forms [3].
"normal":10000,
"long":60000
},
- test_timeout:null
+ test_timeout:null,
+ message_events: ["start", "test_state", "result", "completion"]
};
var xhtml_ns = "http://www.w3.org/1999/xhtml";
@@ -64,6 +65,40 @@ policies and contribution forms [3].
this.output_handler = null;
this.all_loaded = false;
var this_obj = this;
+ this.message_events = [];
+
+ this.message_functions = {
+ start: [add_start_callback, remove_start_callback,
+ function (properties) {
+ this_obj._dispatch("start_callback", [properties],
+ {type: "start", properties: properties});
+ }],
+
+ test_state: [add_test_state_callback, remove_test_state_callback,
+ function(test) {
+ this_obj._dispatch("test_state_callback", [test],
+ {type: "test_state",
+ test: test.structured_clone()});
+ }],
+ result: [add_result_callback, remove_result_callback,
+ function (test) {
+ this_obj.output_handler.show_status();
+ this_obj._dispatch("result_callback", [test],
+ {type: "result",
+ test: test.structured_clone()});
+ }],
+ completion: [add_completion_callback, remove_completion_callback,
+ function (tests, harness_status) {
+ var cloned_tests = map(tests, function(test) {
+ return test.structured_clone();
+ });
+ this_obj._dispatch("completion_callback", [tests, harness_status],
+ {type: "complete",
+ tests: cloned_tests,
+ status: harness_status.structured_clone()});
+ }]
+ }
+
on_event(window, 'load', function() {
this_obj.all_loaded = true;
});
@@ -150,30 +185,39 @@ policies and contribution forms [3].
this.output_handler = output;
var this_obj = this;
+
add_start_callback(function (properties) {
this_obj.output_handler.init(properties);
- this_obj._dispatch("start_callback", [properties],
- { type: "start", properties: properties });
});
+
add_test_state_callback(function(test) {
this_obj.output_handler.show_status();
- this_obj._dispatch("test_state_callback", [test],
- { type: "test_state", test: test.structured_clone() });
});
+
add_result_callback(function (test) {
this_obj.output_handler.show_status();
- this_obj._dispatch("result_callback", [test],
- { type: "result", test: test.structured_clone() });
});
+
add_completion_callback(function (tests, harness_status) {
this_obj.output_handler.show_results(tests, harness_status);
- var cloned_tests = map(tests, function(test) { return test.structured_clone(); });
- this_obj._dispatch("completion_callback", [tests, harness_status],
- { type: "complete", tests: cloned_tests,
- status: harness_status.structured_clone() });
});
+ this.setup_messages(settings.message_events);
};
+ WindowTestEnvironment.prototype.setup_messages = function(new_events) {
+ var this_obj = this;
+ forEach(settings.message_events, function(x) {
+ var current_dispatch = this_obj.message_events.indexOf(x) !== -1;
+ var new_dispatch = new_events.indexOf(x) !== -1;
+ if (!current_dispatch && new_dispatch) {
+ this_obj.message_functions[x][0](this_obj.message_functions[x][2]);
+ } else if (current_dispatch && !new_dispatch) {
+ this_obj.message_functions[x][1](this_obj.message_functions[x][2]);
+ }
+ });
+ this.message_events = new_events;
+ }
+
WindowTestEnvironment.prototype.next_default_test_name = function() {
//Don't use document.title to work around an Opera bug in XHTML documents
var title = document.getElementsByTagName("title")[0];
@@ -185,6 +229,9 @@ policies and contribution forms [3].
WindowTestEnvironment.prototype.on_new_harness_properties = function(properties) {
this.output_handler.setup(properties);
+ if (properties.hasOwnProperty("message_events")) {
+ this.setup_messages(properties.message_events);
+ }
};
WindowTestEnvironment.prototype.add_on_loaded_callback = function(callback) {
@@ -368,8 +415,20 @@ policies and contribution forms [3].
self.addEventListener("message",
function(event) {
if (event.data.type && event.data.type === "connect") {
- this_obj._add_message_port(event.ports[0]);
- event.ports[0].start();
+ if (event.ports && event.ports[0]) {
+ // If a MessageChannel was passed, then use it to
+ // send results back to the main window. This
+ // allows the tests to work even if the browser
+ // does not fully support MessageEvent.source in
+ // ServiceWorkers yet.
+ this_obj._add_message_port(event.ports[0]);
+ event.ports[0].start();
+ } else {
+ // If there is no MessageChannel, then attempt to
+ // use the MessageEvent.source to send results
+ // back to the main window.
+ this_obj._add_message_port(event.source);
+ }
}
});
@@ -458,19 +517,27 @@ policies and contribution forms [3].
function promise_test(func, name, properties) {
var test = async_test(name, properties);
- Promise.resolve(test.step(func, test, test))
- .then(
- function() {
- test.done();
- })
- .catch(test.step_func(
- function(value) {
- if (value instanceof AssertionError) {
- throw value;
- }
- assert(false, "promise_test", null,
- "Unhandled rejection with value: ${value}", {value:value});
- }));
+ // If there is no promise tests queue make one.
+ test.step(function() {
+ if (!tests.promise_tests) {
+ tests.promise_tests = Promise.resolve();
+ }
+ });
+ tests.promise_tests = tests.promise_tests.then(function() {
+ return Promise.resolve(test.step(func, test, test))
+ .then(
+ function() {
+ test.done();
+ })
+ .catch(test.step_func(
+ function(value) {
+ if (value instanceof AssertionError) {
+ throw value;
+ }
+ assert(false, "promise_test", null,
+ "Unhandled rejection with value: ${value}", {value:value});
+ }));
+ });
}
function promise_rejects(test, expected, promise) {
@@ -1436,13 +1503,13 @@ policies and contribution forms [3].
RemoteTest.prototype.structured_clone = function() {
var clone = {};
Object.keys(this).forEach(
- function(key) {
+ (function(key) {
if (typeof(this[key]) === "object") {
clone[key] = merge({}, this[key]);
} else {
clone[key] = this[key];
}
- });
+ }).bind(this));
clone.phases = merge({}, this.phases);
return clone;
};
@@ -1476,15 +1543,24 @@ policies and contribution forms [3].
var message_port;
if (is_service_worker(worker)) {
- // The ServiceWorker's implicit MessagePort is currently not
- // reliably accessible from the ServiceWorkerGlobalScope due to
- // Blink setting MessageEvent.source to null for messages sent via
- // ServiceWorker.postMessage(). Until that's resolved, create an
- // explicit MessageChannel and pass one end to the worker.
- var message_channel = new MessageChannel();
- message_port = message_channel.port1;
- message_port.start();
- worker.postMessage({type: "connect"}, [message_channel.port2]);
+ if (window.MessageChannel) {
+ // The ServiceWorker's implicit MessagePort is currently not
+ // reliably accessible from the ServiceWorkerGlobalScope due to
+ // Blink setting MessageEvent.source to null for messages sent
+ // via ServiceWorker.postMessage(). Until that's resolved,
+ // create an explicit MessageChannel and pass one end to the
+ // worker.
+ var message_channel = new MessageChannel();
+ message_port = message_channel.port1;
+ message_port.start();
+ worker.postMessage({type: "connect"}, [message_channel.port2]);
+ } else {
+ // If MessageChannel is not available, then try the
+ // ServiceWorker.postMessage() approach using MessageEvent.source
+ // on the other end.
+ message_port = navigator.serviceWorker;
+ worker.postMessage({type: "connect"});
+ }
} else if (is_shared_worker(worker)) {
message_port = worker.port;
} else {
@@ -1837,14 +1913,12 @@ policies and contribution forms [3].
tests.test_state_callbacks.push(callback);
}
- function add_result_callback(callback)
- {
+ function add_result_callback(callback) {
tests.test_done_callbacks.push(callback);
}
- function add_completion_callback(callback)
- {
- tests.all_done_callbacks.push(callback);
+ function add_completion_callback(callback) {
+ tests.all_done_callbacks.push(callback);
}
expose(add_start_callback, 'add_start_callback');
@@ -1852,6 +1926,29 @@ policies and contribution forms [3].
expose(add_result_callback, 'add_result_callback');
expose(add_completion_callback, 'add_completion_callback');
+ function remove(array, item) {
+ var index = array.indexOf(item);
+ if (index > -1) {
+ array.splice(index, 1);
+ }
+ }
+
+ function remove_start_callback(callback) {
+ remove(tests.start_callbacks, callback);
+ }
+
+ function remove_test_state_callback(callback) {
+ remove(tests.test_state_callbacks, callback);
+ }
+
+ function remove_result_callback(callback) {
+ remove(tests.test_done_callbacks, callback);
+ }
+
+ function remove_completion_callback(callback) {
+ remove(tests.all_done_callbacks, callback);
+ }
+
/*
* Output listener
*/
@@ -1959,28 +2056,11 @@ policies and contribution forms [3].
log.removeChild(log.lastChild);
}
- var script_prefix = null;
- var scripts = document.getElementsByTagName("script");
- for (var i = 0; i < scripts.length; i++) {
- var src;
- if (scripts[i].src) {
- src = scripts[i].src;
- } else if (scripts[i].href) {
- //SVG case
- src = scripts[i].href.baseVal;
- }
-
- var matches = src && src.match(/^(.*\/|)testharness\.js$/);
- if (matches) {
- script_prefix = matches[1];
- break;
- }
- }
-
- if (script_prefix !== null) {
+ var harness_url = get_harness_url();
+ if (harness_url !== null) {
var stylesheet = output_document.createElementNS(xhtml_ns, "link");
stylesheet.setAttribute("rel", "stylesheet");
- stylesheet.setAttribute("href", script_prefix + "testharness.css");
+ stylesheet.setAttribute("href", harness_url + "testharness.css");
var heads = output_document.getElementsByTagName("head");
if (heads.length) {
heads[0].appendChild(stylesheet);
@@ -2335,18 +2415,39 @@ policies and contribution forms [3].
AssertionError.prototype = Object.create(Error.prototype);
AssertionError.prototype.get_stack = function() {
- var lines = new Error().stack.split("\n");
- var rv = [];
- var re = /\/resources\/testharness\.js/;
+ var stack = new Error().stack;
+ // IE11 does not initialize 'Error.stack' until the object is thrown.
+ if (!stack) {
+ try {
+ throw new Error();
+ } catch (e) {
+ stack = e.stack;
+ }
+ }
+
+ var lines = stack.split("\n");
+
+ // Create a pattern to match stack frames originating within testharness.js. These include the
+ // script URL, followed by the line/col (e.g., '/resources/testharness.js:120:21').
+ var re = new RegExp((get_script_url() || "\\btestharness.js") + ":\\d+:\\d+");
+
+ // Some browsers include a preamble that specifies the type of the error object. Skip this by
+ // advancing until we find the first stack frame originating from testharness.js.
var i = 0;
- // Fire remove any preamble that doesn't match the regexp
- while (!re.test(lines[i])) {
- i++
+ while (!re.test(lines[i]) && i < lines.length) {
+ i++;
}
- // Then remove top frames in testharness.js itself
- while (re.test(lines[i])) {
- i++
+
+ // Then skip the top frames originating from testharness.js to begin the stack at the test code.
+ while (re.test(lines[i]) && i < lines.length) {
+ i++;
}
+
+ // Paranoid check that we didn't skip all frames. If so, return the original stack unmodified.
+ if (i >= lines.length) {
+ return stack;
+ }
+
return lines.slice(i).join("\n");
}
@@ -2394,7 +2495,7 @@ policies and contribution forms [3].
Array.prototype.push.apply(array, items);
}
- function forEach (array, callback, thisObj)
+ function forEach(array, callback, thisObj)
{
for (var i = 0; i < array.length; i++) {
if (array.hasOwnProperty(i)) {
@@ -2438,11 +2539,46 @@ policies and contribution forms [3].
}
}
+ /** Returns the 'src' URL of the first <script> tag in the page to include the file 'testharness.js'. */
+ function get_script_url()
+ {
+ if (!('document' in self)) {
+ return undefined;
+ }
+
+ var scripts = document.getElementsByTagName("script");
+ for (var i = 0; i < scripts.length; i++) {
+ var src;
+ if (scripts[i].src) {
+ src = scripts[i].src;
+ } else if (scripts[i].href) {
+ //SVG case
+ src = scripts[i].href.baseVal;
+ }
+
+ var matches = src && src.match(/^(.*\/|)testharness\.js$/);
+ if (matches) {
+ return src;
+ }
+ }
+ return undefined;
+ }
+
+ /** Returns the URL path at which the files for testharness.js are assumed to reside (e.g., '/resources/').
+ The path is derived from inspecting the 'src' of the <script> tag that included 'testharness.js'. */
+ function get_harness_url()
+ {
+ var script_url = get_script_url();
+
+ // Exclude the 'testharness.js' file from the returned path, but '+ 1' to include the trailing slash.
+ return script_url ? script_url.slice(0, script_url.lastIndexOf('/') + 1) : undefined;
+ }
+
function supports_post_message(w)
{
var supports;
var type;
- // Given IE implements postMessage across nested iframes but not across
+ // Given IE implements postMessage across nested iframes but not across
// windows or tabs, you can't infer cross-origin communication from the presence
// of postMessage on the current window object only.
//
« no previous file with comments | « no previous file | LayoutTests/http/tests/w3c/resources/idlharness.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698