dom/imptests/testharnessreport.js

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 var W3CTest = {
michael@0 6 /**
michael@0 7 * Dictionary mapping a test URL to either the string "all", which means that
michael@0 8 * all tests in this file are expected to fail, or a dictionary mapping test
michael@0 9 * names to either the boolean |true|, or the string "debug". The former
michael@0 10 * means that this test is expected to fail in all builds, and the latter
michael@0 11 * that it is only expected to fail in debug builds.
michael@0 12 */
michael@0 13 "expectedFailures": {},
michael@0 14
michael@0 15 /**
michael@0 16 * If set to true, we will dump the test failures to the console.
michael@0 17 */
michael@0 18 "dumpFailures": false,
michael@0 19
michael@0 20 /**
michael@0 21 * If dumpFailures is true, this holds a structure like necessary for
michael@0 22 * expectedFailures, for ease of updating the expectations.
michael@0 23 */
michael@0 24 "failures": {},
michael@0 25
michael@0 26 /**
michael@0 27 * List of test results, needed by TestRunner to update the UI.
michael@0 28 */
michael@0 29 "tests": [],
michael@0 30
michael@0 31 /**
michael@0 32 * Number of unlogged passes, to stop buildbot from truncating the log.
michael@0 33 * We will print a message every MAX_COLLAPSED_MESSAGES passes.
michael@0 34 */
michael@0 35 "collapsedMessages": 0,
michael@0 36 "MAX_COLLAPSED_MESSAGES": 100,
michael@0 37
michael@0 38 /**
michael@0 39 * Reference to the TestRunner object in the parent frame.
michael@0 40 */
michael@0 41 "runner": parent === this ? null : parent.TestRunner || parent.wrappedJSObject.TestRunner,
michael@0 42
michael@0 43 /**
michael@0 44 * Prefixes for the error logging. Indexed first by int(todo) and second by
michael@0 45 * int(result).
michael@0 46 */
michael@0 47 "prefixes": [
michael@0 48 ["TEST-UNEXPECTED-FAIL", "TEST-PASS"],
michael@0 49 ["TEST-KNOWN-FAIL", "TEST-UNEXPECTED-PASS"]
michael@0 50 ],
michael@0 51
michael@0 52 /**
michael@0 53 * Prefix of the path to parent of the the failures directory.
michael@0 54 */
michael@0 55 "pathprefix": "/tests/dom/imptests/",
michael@0 56
michael@0 57 /**
michael@0 58 * Returns the URL of the current test, relative to the root W3C tests
michael@0 59 * directory. Used as a key into the expectedFailures dictionary.
michael@0 60 */
michael@0 61 "getPath": function() {
michael@0 62 var url = this.getURL();
michael@0 63 if (!url.startsWith(this.pathprefix)) {
michael@0 64 return "";
michael@0 65 }
michael@0 66 return url.substring(this.pathprefix.length);
michael@0 67 },
michael@0 68
michael@0 69 /**
michael@0 70 * Returns the root-relative URL of the current test.
michael@0 71 */
michael@0 72 "getURL": function() {
michael@0 73 return this.runner ? this.runner.currentTestURL : location.pathname;
michael@0 74 },
michael@0 75
michael@0 76 /**
michael@0 77 * Report the results in the tests array.
michael@0 78 */
michael@0 79 "reportResults": function() {
michael@0 80 var element = function element(aLocalName) {
michael@0 81 var xhtmlNS = "http://www.w3.org/1999/xhtml";
michael@0 82 return document.createElementNS(xhtmlNS, aLocalName);
michael@0 83 };
michael@0 84
michael@0 85 var stylesheet = element("link");
michael@0 86 stylesheet.setAttribute("rel", "stylesheet");
michael@0 87 stylesheet.setAttribute("href", "/resources/testharness.css");
michael@0 88 var heads = document.getElementsByTagName("head");
michael@0 89 if (heads.length) {
michael@0 90 heads[0].appendChild(stylesheet);
michael@0 91 }
michael@0 92
michael@0 93 var log = document.getElementById("log");
michael@0 94 if (!log) {
michael@0 95 return;
michael@0 96 }
michael@0 97 var section = log.appendChild(element("section"));
michael@0 98 section.id = "summary";
michael@0 99 section.appendChild(element("h2")).textContent = "Details";
michael@0 100
michael@0 101 var table = section.appendChild(element("table"));
michael@0 102 table.id = "results";
michael@0 103
michael@0 104 var tr = table.appendChild(element("thead")).appendChild(element("tr"));
michael@0 105 for (var header of ["Result", "Test Name", "Message"]) {
michael@0 106 tr.appendChild(element("th")).textContent = header;
michael@0 107 }
michael@0 108 var statuses = [
michael@0 109 ["Unexpected Fail", "Pass"],
michael@0 110 ["Known Fail", "Unexpected Pass"]
michael@0 111 ];
michael@0 112 var tbody = table.appendChild(element("tbody"));
michael@0 113 for (var test of this.tests) {
michael@0 114 tr = tbody.appendChild(element("tr"));
michael@0 115 tr.className = (test.result === !test.todo ? "pass" : "fail");
michael@0 116 tr.appendChild(element("td")).textContent =
michael@0 117 statuses[+test.todo][+test.result];
michael@0 118 tr.appendChild(element("td")).textContent = test.name;
michael@0 119 tr.appendChild(element("td")).textContent = test.message;
michael@0 120 }
michael@0 121 },
michael@0 122
michael@0 123 /**
michael@0 124 * Returns a printable message based on aTest's 'name' and 'message'
michael@0 125 * properties.
michael@0 126 */
michael@0 127 "formatTestMessage": function(aTest) {
michael@0 128 return aTest.name + (aTest.message ? ": " + aTest.message : "");
michael@0 129 },
michael@0 130
michael@0 131 /**
michael@0 132 * Lets the test runner know about a test result.
michael@0 133 */
michael@0 134 "_log": function(test) {
michael@0 135 var url = this.getURL();
michael@0 136 var msg = this.prefixes[+test.todo][+test.result] + " | ";
michael@0 137 if (url) {
michael@0 138 msg += url;
michael@0 139 }
michael@0 140 msg += " | " + this.formatTestMessage(test);
michael@0 141 if (this.runner) {
michael@0 142 this.runner[(test.result === !test.todo) ? "log" : "error"](msg);
michael@0 143 } else {
michael@0 144 dump(msg + "\n");
michael@0 145 }
michael@0 146 },
michael@0 147
michael@0 148 /**
michael@0 149 * Logs a message about collapsed messages (if any), and resets the counter.
michael@0 150 */
michael@0 151 "_logCollapsedMessages": function() {
michael@0 152 if (this.collapsedMessages) {
michael@0 153 this._log({
michael@0 154 "name": document.title,
michael@0 155 "result": true,
michael@0 156 "todo": false,
michael@0 157 "message": "Elided " + this.collapsedMessages + " passes or known failures."
michael@0 158 });
michael@0 159 }
michael@0 160 this.collapsedMessages = 0;
michael@0 161 },
michael@0 162
michael@0 163 /**
michael@0 164 * Maybe logs a result, eliding up to MAX_COLLAPSED_MESSAGES consecutive
michael@0 165 * passes.
michael@0 166 */
michael@0 167 "_maybeLog": function(test) {
michael@0 168 var success = (test.result === !test.todo);
michael@0 169 if (success && ++this.collapsedMessages < this.MAX_COLLAPSED_MESSAGES) {
michael@0 170 return;
michael@0 171 }
michael@0 172 this._logCollapsedMessages();
michael@0 173 this._log(test);
michael@0 174 },
michael@0 175
michael@0 176 /**
michael@0 177 * Reports a test result. The argument is an object with the following
michael@0 178 * properties:
michael@0 179 *
michael@0 180 * o message (string): message to be reported
michael@0 181 * o result (boolean): whether this test failed
michael@0 182 * o todo (boolean): whether this test is expected to fail
michael@0 183 */
michael@0 184 "report": function(test) {
michael@0 185 this.tests.push(test);
michael@0 186 this._maybeLog(test);
michael@0 187 },
michael@0 188
michael@0 189 /**
michael@0 190 * Returns true if this test is expected to fail, and false otherwise.
michael@0 191 */
michael@0 192 "_todo": function(test) {
michael@0 193 if (this.expectedFailures === "all") {
michael@0 194 return true;
michael@0 195 }
michael@0 196 var value = this.expectedFailures[test.name];
michael@0 197 return value === true || (value === "debug" && !!SpecialPowers.isDebugBuild);
michael@0 198 },
michael@0 199
michael@0 200 /**
michael@0 201 * Callback function for testharness.js. Called when one test in a file
michael@0 202 * finishes.
michael@0 203 */
michael@0 204 "result": function(test) {
michael@0 205 var url = this.getPath();
michael@0 206 this.report({
michael@0 207 "name": test.name,
michael@0 208 "message": test.message || "",
michael@0 209 "result": test.status === test.PASS,
michael@0 210 "todo": this._todo(test)
michael@0 211 });
michael@0 212 if (this.dumpFailures && test.status !== test.PASS) {
michael@0 213 this.failures[test.name] = true;
michael@0 214 }
michael@0 215 },
michael@0 216
michael@0 217 /**
michael@0 218 * Callback function for testharness.js. Called when the entire test file
michael@0 219 * finishes.
michael@0 220 */
michael@0 221 "finish": function(tests, status) {
michael@0 222 var url = this.getPath();
michael@0 223 this.report({
michael@0 224 "name": "Finished test",
michael@0 225 "message": "Status: " + status.status,
michael@0 226 "result": status.status === status.OK,
michael@0 227 "todo":
michael@0 228 url in this.expectedFailures &&
michael@0 229 this.expectedFailures[url] === "error"
michael@0 230 });
michael@0 231
michael@0 232 this._logCollapsedMessages();
michael@0 233
michael@0 234 if (this.dumpFailures) {
michael@0 235 dump("@@@ @@@ Failures\n");
michael@0 236 dump(url + "@@@" + JSON.stringify(this.failures) + "\n");
michael@0 237 }
michael@0 238 if (this.runner) {
michael@0 239 this.runner.testFinished(this.tests.map(function(aTest) {
michael@0 240 return {
michael@0 241 "message": this.formatTestMessage(aTest),
michael@0 242 "result": aTest.result,
michael@0 243 "todo": aTest.todo
michael@0 244 };
michael@0 245 }, this));
michael@0 246 } else {
michael@0 247 this.reportResults();
michael@0 248 }
michael@0 249 },
michael@0 250
michael@0 251 /**
michael@0 252 * Log an unexpected failure. Intended to be used from harness code, not
michael@0 253 * from tests.
michael@0 254 */
michael@0 255 "logFailure": function(aTestName, aMessage) {
michael@0 256 this.report({
michael@0 257 "name": aTestName,
michael@0 258 "message": aMessage,
michael@0 259 "result": false,
michael@0 260 "todo": false
michael@0 261 });
michael@0 262 },
michael@0 263
michael@0 264 /**
michael@0 265 * Timeout the current test. Intended to be used from harness code, not
michael@0 266 * from tests.
michael@0 267 */
michael@0 268 "timeout": function() {
michael@0 269 this.logFailure("Timeout", "Test runner timed us out.");
michael@0 270 timeout();
michael@0 271 }
michael@0 272 };
michael@0 273 (function() {
michael@0 274 try {
michael@0 275 var path = W3CTest.getPath();
michael@0 276 if (path) {
michael@0 277 // Get expected fails. If there aren't any, there will be a 404, which is
michael@0 278 // fine. Anything else is unexpected.
michael@0 279 var url = W3CTest.pathprefix + "failures/" + path + ".json";
michael@0 280 var request = new XMLHttpRequest();
michael@0 281 request.open("GET", url, false);
michael@0 282 request.send();
michael@0 283 if (request.status === 200) {
michael@0 284 W3CTest.expectedFailures = JSON.parse(request.responseText);
michael@0 285 } else if (request.status !== 404) {
michael@0 286 W3CTest.logFailure("Fetching failures file", "Request status was " + request.status);
michael@0 287 }
michael@0 288 }
michael@0 289
michael@0 290 add_result_callback(W3CTest.result.bind(W3CTest));
michael@0 291 add_completion_callback(W3CTest.finish.bind(W3CTest));
michael@0 292 setup({
michael@0 293 "output": false,
michael@0 294 "explicit_timeout": true
michael@0 295 });
michael@0 296 } catch (e) {
michael@0 297 W3CTest.logFailure("Harness setup", "Unexpected exception: " + e);
michael@0 298 }
michael@0 299 })();

mercurial