layout/tools/reftest/reftest.js

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

michael@0 1 /* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- /
michael@0 2 /* vim: set shiftwidth=4 tabstop=8 autoindent cindent expandtab: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #if BOOTSTRAP
michael@0 8 this.EXPORTED_SYMBOLS = ["OnRefTestLoad"];
michael@0 9 #endif
michael@0 10
michael@0 11
michael@0 12 const CC = Components.classes;
michael@0 13 const CI = Components.interfaces;
michael@0 14 const CR = Components.results;
michael@0 15
michael@0 16 const XHTML_NS = "http://www.w3.org/1999/xhtml";
michael@0 17 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 18
michael@0 19 const NS_LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
michael@0 20 const NS_GFXINFO_CONTRACTID = "@mozilla.org/gfx/info;1";
michael@0 21 const IO_SERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
michael@0 22 const DEBUG_CONTRACTID = "@mozilla.org/xpcom/debug;1";
michael@0 23 const NS_LOCALFILEINPUTSTREAM_CONTRACTID =
michael@0 24 "@mozilla.org/network/file-input-stream;1";
michael@0 25 const NS_SCRIPTSECURITYMANAGER_CONTRACTID =
michael@0 26 "@mozilla.org/scriptsecuritymanager;1";
michael@0 27 const NS_REFTESTHELPER_CONTRACTID =
michael@0 28 "@mozilla.org/reftest-helper;1";
michael@0 29 const NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX =
michael@0 30 "@mozilla.org/network/protocol;1?name=";
michael@0 31 const NS_XREAPPINFO_CONTRACTID =
michael@0 32 "@mozilla.org/xre/app-info;1";
michael@0 33 const NS_DIRECTORY_SERVICE_CONTRACTID =
michael@0 34 "@mozilla.org/file/directory_service;1";
michael@0 35 const NS_OBSERVER_SERVICE_CONTRACTID =
michael@0 36 "@mozilla.org/observer-service;1";
michael@0 37
michael@0 38 Components.utils.import("resource://gre/modules/FileUtils.jsm");
michael@0 39
michael@0 40 var gLoadTimeout = 0;
michael@0 41 var gTimeoutHook = null;
michael@0 42 var gRemote = false;
michael@0 43 var gIgnoreWindowSize = false;
michael@0 44 var gShuffle = false;
michael@0 45 var gTotalChunks = 0;
michael@0 46 var gThisChunk = 0;
michael@0 47 var gContainingWindow = null;
michael@0 48 var gURLFilterRegex = null;
michael@0 49 const FOCUS_FILTER_ALL_TESTS = "all";
michael@0 50 const FOCUS_FILTER_NEEDS_FOCUS_TESTS = "needs-focus";
michael@0 51 const FOCUS_FILTER_NON_NEEDS_FOCUS_TESTS = "non-needs-focus";
michael@0 52 var gFocusFilterMode = FOCUS_FILTER_ALL_TESTS;
michael@0 53
michael@0 54 // "<!--CLEAR-->"
michael@0 55 const BLANK_URL_FOR_CLEARING = "data:text/html;charset=UTF-8,%3C%21%2D%2DCLEAR%2D%2D%3E";
michael@0 56
michael@0 57 var gBrowser;
michael@0 58 // Are we testing web content loaded in a separate process?
michael@0 59 var gBrowserIsRemote; // bool
michael@0 60 // Are we using <iframe mozbrowser>?
michael@0 61 var gBrowserIsIframe; // bool
michael@0 62 var gBrowserMessageManager;
michael@0 63 var gCanvas1, gCanvas2;
michael@0 64 // gCurrentCanvas is non-null between InitCurrentCanvasWithSnapshot and the next
michael@0 65 // RecordResult.
michael@0 66 var gCurrentCanvas = null;
michael@0 67 var gURLs;
michael@0 68 // Map from URI spec to the number of times it remains to be used
michael@0 69 var gURIUseCounts;
michael@0 70 // Map from URI spec to the canvas rendered for that URI
michael@0 71 var gURICanvases;
michael@0 72 var gTestResults = {
michael@0 73 // Successful...
michael@0 74 Pass: 0,
michael@0 75 LoadOnly: 0,
michael@0 76 // Unexpected...
michael@0 77 Exception: 0,
michael@0 78 FailedLoad: 0,
michael@0 79 UnexpectedFail: 0,
michael@0 80 UnexpectedPass: 0,
michael@0 81 AssertionUnexpected: 0,
michael@0 82 AssertionUnexpectedFixed: 0,
michael@0 83 // Known problems...
michael@0 84 KnownFail : 0,
michael@0 85 AssertionKnown: 0,
michael@0 86 Random : 0,
michael@0 87 Skip: 0,
michael@0 88 Slow: 0,
michael@0 89 };
michael@0 90 var gTotalTests = 0;
michael@0 91 var gState;
michael@0 92 var gCurrentURL;
michael@0 93 var gTestLog = [];
michael@0 94 var gServer;
michael@0 95 var gCount = 0;
michael@0 96 var gAssertionCount = 0;
michael@0 97
michael@0 98 var gIOService;
michael@0 99 var gDebug;
michael@0 100 var gWindowUtils;
michael@0 101
michael@0 102 var gSlowestTestTime = 0;
michael@0 103 var gSlowestTestURL;
michael@0 104
michael@0 105 var gDrawWindowFlags;
michael@0 106
michael@0 107 var gExpectingProcessCrash = false;
michael@0 108 var gExpectedCrashDumpFiles = [];
michael@0 109 var gUnexpectedCrashDumpFiles = { };
michael@0 110 var gCrashDumpDir;
michael@0 111 var gFailedNoPaint = false;
michael@0 112
michael@0 113 // The enabled-state of the test-plugins, stored so they can be reset later
michael@0 114 var gTestPluginEnabledStates = null;
michael@0 115
michael@0 116 const TYPE_REFTEST_EQUAL = '==';
michael@0 117 const TYPE_REFTEST_NOTEQUAL = '!=';
michael@0 118 const TYPE_LOAD = 'load'; // test without a reference (just test that it does
michael@0 119 // not assert, crash, hang, or leak)
michael@0 120 const TYPE_SCRIPT = 'script'; // test contains individual test results
michael@0 121
michael@0 122 // The order of these constants matters, since when we have a status
michael@0 123 // listed for a *manifest*, we combine the status with the status for
michael@0 124 // the test by using the *larger*.
michael@0 125 // FIXME: In the future, we may also want to use this rule for combining
michael@0 126 // statuses that are on the same line (rather than making the last one
michael@0 127 // win).
michael@0 128 const EXPECTED_PASS = 0;
michael@0 129 const EXPECTED_FAIL = 1;
michael@0 130 const EXPECTED_RANDOM = 2;
michael@0 131 const EXPECTED_DEATH = 3; // test must be skipped to avoid e.g. crash/hang
michael@0 132 const EXPECTED_FUZZY = 4;
michael@0 133
michael@0 134 // types of preference value we might want to set for a specific test
michael@0 135 const PREF_BOOLEAN = 0;
michael@0 136 const PREF_STRING = 1;
michael@0 137 const PREF_INTEGER = 2;
michael@0 138
michael@0 139 var gPrefsToRestore = [];
michael@0 140
michael@0 141 const gProtocolRE = /^\w+:/;
michael@0 142 const gPrefItemRE = /^(|test-|ref-)pref\((.+?),(.*)\)$/;
michael@0 143
michael@0 144 var gHttpServerPort = -1;
michael@0 145
michael@0 146 // whether to run slow tests or not
michael@0 147 var gRunSlowTests = true;
michael@0 148
michael@0 149 // whether we should skip caching canvases
michael@0 150 var gNoCanvasCache = false;
michael@0 151
michael@0 152 var gRecycledCanvases = new Array();
michael@0 153
michael@0 154 // By default we just log to stdout
michael@0 155 var gDumpLog = dump;
michael@0 156 var gVerbose = false;
michael@0 157
michael@0 158 // Only dump the sandbox once, because it doesn't depend on the
michael@0 159 // manifest URL (yet!).
michael@0 160 var gDumpedConditionSandbox = false;
michael@0 161
michael@0 162 function LogWarning(str)
michael@0 163 {
michael@0 164 gDumpLog("REFTEST INFO | " + str + "\n");
michael@0 165 gTestLog.push(str);
michael@0 166 }
michael@0 167
michael@0 168 function LogInfo(str)
michael@0 169 {
michael@0 170 if (gVerbose)
michael@0 171 gDumpLog("REFTEST INFO | " + str + "\n");
michael@0 172 gTestLog.push(str);
michael@0 173 }
michael@0 174
michael@0 175 function FlushTestLog()
michael@0 176 {
michael@0 177 if (!gVerbose) {
michael@0 178 // In verbose mode, we've dumped all these messages already.
michael@0 179 for (var i = 0; i < gTestLog.length; ++i) {
michael@0 180 gDumpLog("REFTEST INFO | Saved log: " + gTestLog[i] + "\n");
michael@0 181 }
michael@0 182 }
michael@0 183 gTestLog = [];
michael@0 184 }
michael@0 185
michael@0 186 function AllocateCanvas()
michael@0 187 {
michael@0 188 if (gRecycledCanvases.length > 0)
michael@0 189 return gRecycledCanvases.shift();
michael@0 190
michael@0 191 var canvas = gContainingWindow.document.createElementNS(XHTML_NS, "canvas");
michael@0 192 var r = gBrowser.getBoundingClientRect();
michael@0 193 canvas.setAttribute("width", Math.ceil(r.width));
michael@0 194 canvas.setAttribute("height", Math.ceil(r.height));
michael@0 195
michael@0 196 return canvas;
michael@0 197 }
michael@0 198
michael@0 199 function ReleaseCanvas(canvas)
michael@0 200 {
michael@0 201 // store a maximum of 2 canvases, if we're not caching
michael@0 202 if (!gNoCanvasCache || gRecycledCanvases.length < 2)
michael@0 203 gRecycledCanvases.push(canvas);
michael@0 204 }
michael@0 205
michael@0 206 function IDForEventTarget(event)
michael@0 207 {
michael@0 208 try {
michael@0 209 return "'" + event.target.getAttribute('id') + "'";
michael@0 210 } catch (ex) {
michael@0 211 return "<unknown>";
michael@0 212 }
michael@0 213 }
michael@0 214
michael@0 215 function getTestPlugin(aName) {
michael@0 216 var ph = CC["@mozilla.org/plugin/host;1"].getService(CI.nsIPluginHost);
michael@0 217 var tags = ph.getPluginTags();
michael@0 218
michael@0 219 // Find the test plugin
michael@0 220 for (var i = 0; i < tags.length; i++) {
michael@0 221 if (tags[i].name == aName)
michael@0 222 return tags[i];
michael@0 223 }
michael@0 224
michael@0 225 LogWarning("Failed to find the test-plugin.");
michael@0 226 return null;
michael@0 227 }
michael@0 228
michael@0 229 this.OnRefTestLoad = function OnRefTestLoad(win)
michael@0 230 {
michael@0 231 gCrashDumpDir = CC[NS_DIRECTORY_SERVICE_CONTRACTID]
michael@0 232 .getService(CI.nsIProperties)
michael@0 233 .get("ProfD", CI.nsIFile);
michael@0 234 gCrashDumpDir.append("minidumps");
michael@0 235
michael@0 236 var env = CC["@mozilla.org/process/environment;1"].
michael@0 237 getService(CI.nsIEnvironment);
michael@0 238 gVerbose = !!env.get("MOZ_REFTEST_VERBOSE");
michael@0 239
michael@0 240 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 241 getService(Components.interfaces.nsIPrefBranch);
michael@0 242 try {
michael@0 243 gBrowserIsRemote = prefs.getBoolPref("browser.tabs.remote.autostart");
michael@0 244 } catch (e) {
michael@0 245 gBrowserIsRemote = false;
michael@0 246 }
michael@0 247
michael@0 248 try {
michael@0 249 gBrowserIsIframe = prefs.getBoolPref("reftest.browser.iframe.enabled");
michael@0 250 } catch (e) {
michael@0 251 gBrowserIsIframe = false;
michael@0 252 }
michael@0 253
michael@0 254 if (win === undefined || win == null) {
michael@0 255 win = window;
michael@0 256 }
michael@0 257 if (gContainingWindow == null && win != null) {
michael@0 258 gContainingWindow = win;
michael@0 259 }
michael@0 260
michael@0 261 if (gBrowserIsIframe) {
michael@0 262 gBrowser = gContainingWindow.document.createElementNS(XHTML_NS, "iframe");
michael@0 263 gBrowser.setAttribute("mozbrowser", "");
michael@0 264 gBrowser.setAttribute("mozapp", prefs.getCharPref("browser.manifestURL"));
michael@0 265 } else {
michael@0 266 gBrowser = gContainingWindow.document.createElementNS(XUL_NS, "xul:browser");
michael@0 267 }
michael@0 268 gBrowser.setAttribute("id", "browser");
michael@0 269 gBrowser.setAttribute("type", "content-primary");
michael@0 270 gBrowser.setAttribute("remote", gBrowserIsRemote ? "true" : "false");
michael@0 271 gBrowser.setAttribute("mozasyncpanzoom", "true");
michael@0 272 // Make sure the browser element is exactly 800x1000, no matter
michael@0 273 // what size our window is
michael@0 274 gBrowser.setAttribute("style", "min-width: 800px; min-height: 1000px; max-width: 800px; max-height: 1000px");
michael@0 275
michael@0 276 #ifdef BOOTSTRAP
michael@0 277 #ifdef REFTEST_B2G
michael@0 278 var doc = gContainingWindow.document.getElementsByTagName("html")[0];
michael@0 279 #else
michael@0 280 var doc = gContainingWindow.document.getElementById('main-window');
michael@0 281 #endif
michael@0 282 while (doc.hasChildNodes()) {
michael@0 283 doc.removeChild(doc.firstChild);
michael@0 284 }
michael@0 285 doc.appendChild(gBrowser);
michael@0 286 #else
michael@0 287 document.getElementById("reftest-window").appendChild(gBrowser);
michael@0 288 #endif
michael@0 289
michael@0 290 // reftests should have the test plugins enabled, not click-to-play
michael@0 291 let plugin1 = getTestPlugin("Test Plug-in");
michael@0 292 let plugin2 = getTestPlugin("Second Test Plug-in");
michael@0 293 if (plugin1 && plugin2) {
michael@0 294 gTestPluginEnabledStates = [plugin1.enabledState, plugin2.enabledState];
michael@0 295 plugin1.enabledState = CI.nsIPluginTag.STATE_ENABLED;
michael@0 296 plugin2.enabledState = CI.nsIPluginTag.STATE_ENABLED;
michael@0 297 } else {
michael@0 298 LogWarning("Could not get test plugin tags.");
michael@0 299 }
michael@0 300
michael@0 301 gBrowserMessageManager = gBrowser.QueryInterface(CI.nsIFrameLoaderOwner)
michael@0 302 .frameLoader.messageManager;
michael@0 303 // The content script waits for the initial onload, then notifies
michael@0 304 // us.
michael@0 305 RegisterMessageListenersAndLoadContentScript();
michael@0 306 }
michael@0 307
michael@0 308 function InitAndStartRefTests()
michael@0 309 {
michael@0 310 /* These prefs are optional, so we don't need to spit an error to the log */
michael@0 311 try {
michael@0 312 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 313 getService(Components.interfaces.nsIPrefBranch);
michael@0 314 } catch(e) {
michael@0 315 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + e + "\n");
michael@0 316 }
michael@0 317
michael@0 318 try {
michael@0 319 prefs.setBoolPref("android.widget_paints_background", false);
michael@0 320 } catch (e) {}
michael@0 321
michael@0 322 /* set the gLoadTimeout */
michael@0 323 try {
michael@0 324 gLoadTimeout = prefs.getIntPref("reftest.timeout");
michael@0 325 } catch(e) {
michael@0 326 gLoadTimeout = 5 * 60 * 1000; //5 minutes as per bug 479518
michael@0 327 }
michael@0 328
michael@0 329 /* Get the logfile for android tests */
michael@0 330 try {
michael@0 331 var logFile = prefs.getCharPref("reftest.logFile");
michael@0 332 if (logFile) {
michael@0 333 try {
michael@0 334 var f = FileUtils.File(logFile);
michael@0 335 var mfl = FileUtils.openFileOutputStream(f, FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE);
michael@0 336 // Set to mirror to stdout as well as the file
michael@0 337 gDumpLog = function (msg) {
michael@0 338 #ifdef BOOTSTRAP
michael@0 339 #ifdef REFTEST_B2G
michael@0 340 dump(msg);
michael@0 341 #else
michael@0 342 //NOTE: on android-xul, we have a libc crash if we do a dump with %7s in the string
michael@0 343 #endif
michael@0 344 #else
michael@0 345 dump(msg);
michael@0 346 #endif
michael@0 347 mfl.write(msg, msg.length);
michael@0 348 };
michael@0 349 }
michael@0 350 catch(e) {
michael@0 351 // If there is a problem, just use stdout
michael@0 352 gDumpLog = dump;
michael@0 353 }
michael@0 354 }
michael@0 355 } catch(e) {}
michael@0 356
michael@0 357 try {
michael@0 358 gRemote = prefs.getBoolPref("reftest.remote");
michael@0 359 } catch(e) {
michael@0 360 gRemote = false;
michael@0 361 }
michael@0 362
michael@0 363 try {
michael@0 364 gIgnoreWindowSize = prefs.getBoolPref("reftest.ignoreWindowSize");
michael@0 365 } catch(e) {
michael@0 366 gIgnoreWindowSize = false;
michael@0 367 }
michael@0 368
michael@0 369 /* Support for running a chunk (subset) of tests. In separate try as this is optional */
michael@0 370 try {
michael@0 371 gTotalChunks = prefs.getIntPref("reftest.totalChunks");
michael@0 372 gThisChunk = prefs.getIntPref("reftest.thisChunk");
michael@0 373 }
michael@0 374 catch(e) {
michael@0 375 gTotalChunks = 0;
michael@0 376 gThisChunk = 0;
michael@0 377 }
michael@0 378
michael@0 379 try {
michael@0 380 gURLFilterRegex = new RegExp(prefs.getCharPref("reftest.filter"));
michael@0 381 } catch(e) {}
michael@0 382
michael@0 383 try {
michael@0 384 gFocusFilterMode = prefs.getCharPref("reftest.focusFilterMode");
michael@0 385 } catch(e) {}
michael@0 386
michael@0 387 gWindowUtils = gContainingWindow.QueryInterface(CI.nsIInterfaceRequestor).getInterface(CI.nsIDOMWindowUtils);
michael@0 388 if (!gWindowUtils || !gWindowUtils.compareCanvases)
michael@0 389 throw "nsIDOMWindowUtils inteface missing";
michael@0 390
michael@0 391 gIOService = CC[IO_SERVICE_CONTRACTID].getService(CI.nsIIOService);
michael@0 392 gDebug = CC[DEBUG_CONTRACTID].getService(CI.nsIDebug2);
michael@0 393
michael@0 394 RegisterProcessCrashObservers();
michael@0 395
michael@0 396 if (gRemote) {
michael@0 397 gServer = null;
michael@0 398 } else {
michael@0 399 // not all gecko applications autoregister xpcom components
michael@0 400 if (CC["@mozilla.org/server/jshttp;1"] === undefined) {
michael@0 401 var file = CC["@mozilla.org/file/directory_service;1"].
michael@0 402 getService(CI.nsIProperties).get("ProfD", CI.nsIFile);
michael@0 403 file.appendRelativePath("extensions/reftest@mozilla.org/chrome.manifest");
michael@0 404
michael@0 405 registrar = Components.manager.QueryInterface(CI.nsIComponentRegistrar);
michael@0 406 registrar.autoRegister(file);
michael@0 407 }
michael@0 408 gServer = CC["@mozilla.org/server/jshttp;1"].
michael@0 409 createInstance(CI.nsIHttpServer);
michael@0 410 }
michael@0 411 try {
michael@0 412 if (gServer)
michael@0 413 StartHTTPServer();
michael@0 414 } catch (ex) {
michael@0 415 //gBrowser.loadURI('data:text/plain,' + ex);
michael@0 416 ++gTestResults.Exception;
michael@0 417 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + ex + "\n");
michael@0 418 DoneTests();
michael@0 419 }
michael@0 420
michael@0 421 // Focus the content browser.
michael@0 422 if (gFocusFilterMode != FOCUS_FILTER_NON_NEEDS_FOCUS_TESTS) {
michael@0 423 gBrowser.focus();
michael@0 424 }
michael@0 425
michael@0 426 StartTests();
michael@0 427 }
michael@0 428
michael@0 429 function StartHTTPServer()
michael@0 430 {
michael@0 431 gServer.registerContentType("sjs", "sjs");
michael@0 432 gServer.start(-1);
michael@0 433 gHttpServerPort = gServer.identity.primaryPort;
michael@0 434 }
michael@0 435
michael@0 436 // Perform a Fisher-Yates shuffle of the array.
michael@0 437 function Shuffle(array)
michael@0 438 {
michael@0 439 for (var i = array.length - 1; i > 0; i--) {
michael@0 440 var j = Math.floor(Math.random() * (i + 1));
michael@0 441 var temp = array[i];
michael@0 442 array[i] = array[j];
michael@0 443 array[j] = temp;
michael@0 444 }
michael@0 445 }
michael@0 446
michael@0 447 function StartTests()
michael@0 448 {
michael@0 449 var uri;
michael@0 450 #if BOOTSTRAP
michael@0 451 /* These prefs are optional, so we don't need to spit an error to the log */
michael@0 452 try {
michael@0 453 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 454 getService(Components.interfaces.nsIPrefBranch);
michael@0 455 } catch(e) {
michael@0 456 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + e + "\n");
michael@0 457 }
michael@0 458
michael@0 459 try {
michael@0 460 gNoCanvasCache = prefs.getIntPref("reftest.nocache");
michael@0 461 } catch(e) {
michael@0 462 gNoCanvasCache = false;
michael@0 463 }
michael@0 464
michael@0 465 try {
michael@0 466 gShuffle = prefs.getBoolPref("reftest.shuffle");
michael@0 467 } catch (e) {
michael@0 468 gShuffle = false;
michael@0 469 }
michael@0 470
michael@0 471 try {
michael@0 472 gRunSlowTests = prefs.getIntPref("reftest.skipslowtests");
michael@0 473 } catch(e) {
michael@0 474 gRunSlowTests = false;
michael@0 475 }
michael@0 476
michael@0 477 try {
michael@0 478 uri = prefs.getCharPref("reftest.uri");
michael@0 479 } catch(e) {
michael@0 480 uri = "";
michael@0 481 }
michael@0 482
michael@0 483 if (uri == "") {
michael@0 484 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | Unable to find reftest.uri pref. Please ensure your profile is setup properly\n");
michael@0 485 DoneTests();
michael@0 486 }
michael@0 487 #else
michael@0 488 try {
michael@0 489 // Need to read the manifest once we have gHttpServerPort..
michael@0 490 var args = window.arguments[0].wrappedJSObject;
michael@0 491
michael@0 492 if ("nocache" in args && args["nocache"])
michael@0 493 gNoCanvasCache = true;
michael@0 494
michael@0 495 if ("skipslowtests" in args && args.skipslowtests)
michael@0 496 gRunSlowTests = false;
michael@0 497
michael@0 498 uri = args.uri;
michael@0 499 } catch (e) {
michael@0 500 ++gTestResults.Exception;
michael@0 501 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + ex + "\n");
michael@0 502 DoneTests();
michael@0 503 }
michael@0 504 #endif
michael@0 505
michael@0 506 if (gShuffle) {
michael@0 507 gNoCanvasCache = true;
michael@0 508 }
michael@0 509
michael@0 510 try {
michael@0 511 ReadTopManifest(uri);
michael@0 512 BuildUseCounts();
michael@0 513
michael@0 514 // Filter tests which will be skipped to get a more even distribution when chunking
michael@0 515 // tURLs is a temporary array containing all active tests
michael@0 516 var tURLs = new Array();
michael@0 517 for (var i = 0; i < gURLs.length; ++i) {
michael@0 518 if (gURLs[i].expected == EXPECTED_DEATH)
michael@0 519 continue;
michael@0 520
michael@0 521 if (gURLs[i].needsFocus && !Focus())
michael@0 522 continue;
michael@0 523
michael@0 524 if (gURLs[i].slow && !gRunSlowTests)
michael@0 525 continue;
michael@0 526
michael@0 527 tURLs.push(gURLs[i]);
michael@0 528 }
michael@0 529
michael@0 530 gDumpLog("REFTEST INFO | Discovered " + gURLs.length + " tests, after filtering SKIP tests, we have " + tURLs.length + "\n");
michael@0 531
michael@0 532 if (gTotalChunks > 0 && gThisChunk > 0) {
michael@0 533 // Calculate start and end indices of this chunk if tURLs array were
michael@0 534 // divided evenly
michael@0 535 var testsPerChunk = tURLs.length / gTotalChunks;
michael@0 536 var start = Math.round((gThisChunk-1) * testsPerChunk);
michael@0 537 var end = Math.round(gThisChunk * testsPerChunk);
michael@0 538
michael@0 539 // Map these indices onto the gURLs array. This avoids modifying the
michael@0 540 // gURLs array which prevents skipped tests from showing up in the log
michael@0 541 start = gThisChunk == 1 ? 0 : gURLs.indexOf(tURLs[start]);
michael@0 542 end = gThisChunk == gTotalChunks ? gURLs.length : gURLs.indexOf(tURLs[end + 1]) - 1;
michael@0 543 gURLs = gURLs.slice(start, end);
michael@0 544
michael@0 545 gDumpLog("REFTEST INFO | Running chunk " + gThisChunk + " out of " + gTotalChunks + " chunks. ");
michael@0 546 gDumpLog("tests " + (start+1) + "-" + end + "/" + gURLs.length + "\n");
michael@0 547 }
michael@0 548
michael@0 549 if (gShuffle) {
michael@0 550 Shuffle(gURLs);
michael@0 551 }
michael@0 552
michael@0 553 gTotalTests = gURLs.length;
michael@0 554
michael@0 555 if (!gTotalTests)
michael@0 556 throw "No tests to run";
michael@0 557
michael@0 558 gURICanvases = {};
michael@0 559 StartCurrentTest();
michael@0 560 } catch (ex) {
michael@0 561 //gBrowser.loadURI('data:text/plain,' + ex);
michael@0 562 ++gTestResults.Exception;
michael@0 563 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | EXCEPTION: " + ex + "\n");
michael@0 564 DoneTests();
michael@0 565 }
michael@0 566 }
michael@0 567
michael@0 568 function OnRefTestUnload()
michael@0 569 {
michael@0 570 let plugin1 = getTestPlugin("Test Plug-in");
michael@0 571 let plugin2 = getTestPlugin("Second Test Plug-in");
michael@0 572 if (plugin1 && plugin2) {
michael@0 573 plugin1.enabledState = gTestPluginEnabledStates[0];
michael@0 574 plugin2.enabledState = gTestPluginEnabledStates[1];
michael@0 575 } else {
michael@0 576 LogWarning("Failed to get test plugin tags.");
michael@0 577 }
michael@0 578 }
michael@0 579
michael@0 580 // Read all available data from an input stream and return it
michael@0 581 // as a string.
michael@0 582 function getStreamContent(inputStream)
michael@0 583 {
michael@0 584 var streamBuf = "";
michael@0 585 var sis = CC["@mozilla.org/scriptableinputstream;1"].
michael@0 586 createInstance(CI.nsIScriptableInputStream);
michael@0 587 sis.init(inputStream);
michael@0 588
michael@0 589 var available;
michael@0 590 while ((available = sis.available()) != 0) {
michael@0 591 streamBuf += sis.read(available);
michael@0 592 }
michael@0 593
michael@0 594 return streamBuf;
michael@0 595 }
michael@0 596
michael@0 597 // Build the sandbox for fails-if(), etc., condition evaluation.
michael@0 598 function BuildConditionSandbox(aURL) {
michael@0 599 var sandbox = new Components.utils.Sandbox(aURL.spec);
michael@0 600 var xr = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULRuntime);
michael@0 601 var appInfo = CC[NS_XREAPPINFO_CONTRACTID].getService(CI.nsIXULAppInfo);
michael@0 602 sandbox.isDebugBuild = gDebug.isDebugBuild;
michael@0 603 sandbox.xulRuntime = {widgetToolkit: xr.widgetToolkit, OS: xr.OS, __exposedProps__: { widgetToolkit: "r", OS: "r", XPCOMABI: "r", shell: "r" } };
michael@0 604
michael@0 605 // xr.XPCOMABI throws exception for configurations without full ABI
michael@0 606 // support (mobile builds on ARM)
michael@0 607 try {
michael@0 608 sandbox.xulRuntime.XPCOMABI = xr.XPCOMABI;
michael@0 609 } catch(e) {
michael@0 610 sandbox.xulRuntime.XPCOMABI = "";
michael@0 611 }
michael@0 612
michael@0 613 var testRect = gBrowser.getBoundingClientRect();
michael@0 614 sandbox.smallScreen = false;
michael@0 615 if (gContainingWindow.innerWidth < 800 || gContainingWindow.innerHeight < 1000) {
michael@0 616 sandbox.smallScreen = true;
michael@0 617 }
michael@0 618
michael@0 619 var gfxInfo = (NS_GFXINFO_CONTRACTID in CC) && CC[NS_GFXINFO_CONTRACTID].getService(CI.nsIGfxInfo);
michael@0 620 try {
michael@0 621 sandbox.d2d = gfxInfo.D2DEnabled;
michael@0 622 } catch (e) {
michael@0 623 sandbox.d2d = false;
michael@0 624 }
michael@0 625 var info = gfxInfo.getInfo();
michael@0 626 sandbox.azureQuartz = info.AzureCanvasBackend == "quartz";
michael@0 627 sandbox.azureSkia = info.AzureCanvasBackend == "skia";
michael@0 628 sandbox.azureSkiaGL = info.AzureSkiaAccelerated; // FIXME: assumes GL right now
michael@0 629 // true if we are using the same Azure backend for rendering canvas and content
michael@0 630 sandbox.contentSameGfxBackendAsCanvas = info.AzureContentBackend == info.AzureCanvasBackend
michael@0 631 || (info.AzureContentBackend == "none" && info.AzureCanvasBackend == "cairo");
michael@0 632
michael@0 633 sandbox.layersGPUAccelerated =
michael@0 634 gWindowUtils.layerManagerType != "Basic";
michael@0 635 sandbox.layersOpenGL =
michael@0 636 gWindowUtils.layerManagerType == "OpenGL";
michael@0 637 sandbox.layersOMTC =
michael@0 638 gWindowUtils.layerManagerRemote == true;
michael@0 639
michael@0 640 // Shortcuts for widget toolkits.
michael@0 641 sandbox.B2G = xr.widgetToolkit == "gonk";
michael@0 642 sandbox.B2GDT = appInfo.name.toLowerCase() == "b2g" && !sandbox.B2G;
michael@0 643 sandbox.Android = xr.OS == "Android" && !sandbox.B2G;
michael@0 644 sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
michael@0 645 sandbox.gtk2Widget = xr.widgetToolkit == "gtk2";
michael@0 646 sandbox.qtWidget = xr.widgetToolkit == "qt";
michael@0 647 sandbox.winWidget = xr.widgetToolkit == "windows";
michael@0 648
michael@0 649 if (sandbox.Android) {
michael@0 650 var sysInfo = CC["@mozilla.org/system-info;1"].getService(CI.nsIPropertyBag2);
michael@0 651
michael@0 652 // This is currently used to distinguish Android 4.0.3 (SDK version 15)
michael@0 653 // and later from Android 2.x
michael@0 654 sandbox.AndroidVersion = sysInfo.getPropertyAsInt32("version");
michael@0 655 }
michael@0 656
michael@0 657 #if MOZ_ASAN
michael@0 658 sandbox.AddressSanitizer = true;
michael@0 659 #else
michael@0 660 sandbox.AddressSanitizer = false;
michael@0 661 #endif
michael@0 662
michael@0 663 #if MOZ_WEBRTC
michael@0 664 sandbox.webrtc = true;
michael@0 665 #else
michael@0 666 sandbox.webrtc = false;
michael@0 667 #endif
michael@0 668
michael@0 669 var hh = CC[NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX + "http"].
michael@0 670 getService(CI.nsIHttpProtocolHandler);
michael@0 671 sandbox.http = { __exposedProps__: {} };
michael@0 672 for each (var prop in [ "userAgent", "appName", "appVersion",
michael@0 673 "vendor", "vendorSub",
michael@0 674 "product", "productSub",
michael@0 675 "platform", "oscpu", "language", "misc" ]) {
michael@0 676 sandbox.http[prop] = hh[prop];
michael@0 677 sandbox.http.__exposedProps__[prop] = "r";
michael@0 678 }
michael@0 679
michael@0 680 // Set OSX to the Mac OS X version for Mac, and 0 otherwise.
michael@0 681 var osxmatch = /Mac OS X (\d+.\d+)$/.exec(hh.oscpu);
michael@0 682 sandbox.OSX = osxmatch ? parseFloat(osxmatch[1]) : 0;
michael@0 683
michael@0 684 // see if we have the test plugin available,
michael@0 685 // and set a sandox prop accordingly
michael@0 686 var navigator = gContainingWindow.navigator;
michael@0 687 var testPlugin = navigator.plugins["Test Plug-in"];
michael@0 688 sandbox.haveTestPlugin = !!testPlugin;
michael@0 689
michael@0 690 // Set a flag on sandbox if the windows default theme is active
michael@0 691 var box = gContainingWindow.document.createElement("box");
michael@0 692 box.setAttribute("id", "_box_windowsDefaultTheme");
michael@0 693 gContainingWindow.document.documentElement.appendChild(box);
michael@0 694 sandbox.windowsDefaultTheme = (gContainingWindow.getComputedStyle(box, null).display == "none");
michael@0 695 gContainingWindow.document.documentElement.removeChild(box);
michael@0 696
michael@0 697 var prefs = CC["@mozilla.org/preferences-service;1"].
michael@0 698 getService(CI.nsIPrefBranch);
michael@0 699 try {
michael@0 700 sandbox.nativeThemePref = !prefs.getBoolPref("mozilla.widget.disable-native-theme");
michael@0 701 } catch (e) {
michael@0 702 sandbox.nativeThemePref = true;
michael@0 703 }
michael@0 704
michael@0 705 sandbox.prefs = {
michael@0 706 __exposedProps__: {
michael@0 707 getBoolPref: 'r',
michael@0 708 getIntPref: 'r',
michael@0 709 },
michael@0 710 _prefs: prefs,
michael@0 711 getBoolPref: function(p) { return this._prefs.getBoolPref(p); },
michael@0 712 getIntPref: function(p) { return this._prefs.getIntPref(p); }
michael@0 713 }
michael@0 714
michael@0 715 sandbox.testPluginIsOOP = function () {
michael@0 716 try {
michael@0 717 netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
michael@0 718 } catch (ex) {}
michael@0 719
michael@0 720 var prefservice = Components.classes["@mozilla.org/preferences-service;1"]
michael@0 721 .getService(CI.nsIPrefBranch);
michael@0 722
michael@0 723 var testPluginIsOOP = false;
michael@0 724 if (navigator.platform.indexOf("Mac") == 0) {
michael@0 725 var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
michael@0 726 .getService(CI.nsIXULAppInfo)
michael@0 727 .QueryInterface(CI.nsIXULRuntime);
michael@0 728 if (xulRuntime.XPCOMABI.match(/x86-/)) {
michael@0 729 try {
michael@0 730 testPluginIsOOP = prefservice.getBoolPref("dom.ipc.plugins.enabled.i386.test.plugin");
michael@0 731 } catch (e) {
michael@0 732 testPluginIsOOP = prefservice.getBoolPref("dom.ipc.plugins.enabled.i386");
michael@0 733 }
michael@0 734 }
michael@0 735 else if (xulRuntime.XPCOMABI.match(/x86_64-/)) {
michael@0 736 try {
michael@0 737 testPluginIsOOP = prefservice.getBoolPref("dom.ipc.plugins.enabled.x86_64.test.plugin");
michael@0 738 } catch (e) {
michael@0 739 testPluginIsOOP = prefservice.getBoolPref("dom.ipc.plugins.enabled.x86_64");
michael@0 740 }
michael@0 741 }
michael@0 742 }
michael@0 743 else {
michael@0 744 testPluginIsOOP = prefservice.getBoolPref("dom.ipc.plugins.enabled");
michael@0 745 }
michael@0 746
michael@0 747 return testPluginIsOOP;
michael@0 748 };
michael@0 749
michael@0 750 // Tests shouldn't care about this except for when they need to
michael@0 751 // crash the content process
michael@0 752 sandbox.browserIsRemote = gBrowserIsRemote;
michael@0 753
michael@0 754 // Distinguish the Fennecs:
michael@0 755 sandbox.xulFennec = sandbox.Android && sandbox.browserIsRemote;
michael@0 756 sandbox.nativeFennec = sandbox.Android && !sandbox.browserIsRemote;
michael@0 757
michael@0 758 if (!gDumpedConditionSandbox) {
michael@0 759 dump("REFTEST INFO | Dumping JSON representation of sandbox \n");
michael@0 760 dump("REFTEST INFO | " + JSON.stringify(sandbox) + " \n");
michael@0 761 gDumpedConditionSandbox = true;
michael@0 762 }
michael@0 763 return sandbox;
michael@0 764 }
michael@0 765
michael@0 766 function AddPrefSettings(aWhere, aPrefName, aPrefValExpression, aSandbox, aTestPrefSettings, aRefPrefSettings)
michael@0 767 {
michael@0 768 var prefVal = Components.utils.evalInSandbox("(" + aPrefValExpression + ")", aSandbox);
michael@0 769 var prefType;
michael@0 770 var valType = typeof(prefVal);
michael@0 771 if (valType == "boolean") {
michael@0 772 prefType = PREF_BOOLEAN;
michael@0 773 } else if (valType == "string") {
michael@0 774 prefType = PREF_STRING;
michael@0 775 } else if (valType == "number" && (parseInt(prefVal) == prefVal)) {
michael@0 776 prefType = PREF_INTEGER;
michael@0 777 } else {
michael@0 778 return false;
michael@0 779 }
michael@0 780 var setting = { name: aPrefName,
michael@0 781 type: prefType,
michael@0 782 value: prefVal };
michael@0 783 if (aWhere != "ref-") {
michael@0 784 aTestPrefSettings.push(setting);
michael@0 785 }
michael@0 786 if (aWhere != "test-") {
michael@0 787 aRefPrefSettings.push(setting);
michael@0 788 }
michael@0 789 return true;
michael@0 790 }
michael@0 791
michael@0 792 function ReadTopManifest(aFileURL)
michael@0 793 {
michael@0 794 gURLs = new Array();
michael@0 795 var url = gIOService.newURI(aFileURL, null, null);
michael@0 796 if (!url)
michael@0 797 throw "Expected a file or http URL for the manifest.";
michael@0 798 ReadManifest(url, EXPECTED_PASS);
michael@0 799 }
michael@0 800
michael@0 801 function AddTestItem(aTest)
michael@0 802 {
michael@0 803 if (gURLFilterRegex && !gURLFilterRegex.test(aTest.url1.spec))
michael@0 804 return;
michael@0 805 if (gFocusFilterMode == FOCUS_FILTER_NEEDS_FOCUS_TESTS &&
michael@0 806 !aTest.needsFocus)
michael@0 807 return;
michael@0 808 if (gFocusFilterMode == FOCUS_FILTER_NON_NEEDS_FOCUS_TESTS &&
michael@0 809 aTest.needsFocus)
michael@0 810 return;
michael@0 811 gURLs.push(aTest);
michael@0 812 }
michael@0 813
michael@0 814 // Note: If you materially change the reftest manifest parsing,
michael@0 815 // please keep the parser in print-manifest-dirs.py in sync.
michael@0 816 function ReadManifest(aURL, inherited_status)
michael@0 817 {
michael@0 818 var secMan = CC[NS_SCRIPTSECURITYMANAGER_CONTRACTID]
michael@0 819 .getService(CI.nsIScriptSecurityManager);
michael@0 820
michael@0 821 var listURL = aURL;
michael@0 822 var channel = gIOService.newChannelFromURI(aURL);
michael@0 823 var inputStream = channel.open();
michael@0 824 if (channel instanceof Components.interfaces.nsIHttpChannel
michael@0 825 && channel.responseStatus != 200) {
michael@0 826 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | | HTTP ERROR : " +
michael@0 827 channel.responseStatus + "\n");
michael@0 828 }
michael@0 829 var streamBuf = getStreamContent(inputStream);
michael@0 830 inputStream.close();
michael@0 831 var lines = streamBuf.split(/\n|\r|\r\n/);
michael@0 832
michael@0 833 // Build the sandbox for fails-if(), etc., condition evaluation.
michael@0 834 var sandbox = BuildConditionSandbox(aURL);
michael@0 835 var lineNo = 0;
michael@0 836 var urlprefix = "";
michael@0 837 var defaultTestPrefSettings = [], defaultRefPrefSettings = [];
michael@0 838 for each (var str in lines) {
michael@0 839 ++lineNo;
michael@0 840 if (str.charAt(0) == "#")
michael@0 841 continue; // entire line was a comment
michael@0 842 var i = str.search(/\s+#/);
michael@0 843 if (i >= 0)
michael@0 844 str = str.substring(0, i);
michael@0 845 // strip leading and trailing whitespace
michael@0 846 str = str.replace(/^\s*/, '').replace(/\s*$/, '');
michael@0 847 if (!str || str == "")
michael@0 848 continue;
michael@0 849 var items = str.split(/\s+/); // split on whitespace
michael@0 850
michael@0 851 if (items[0] == "url-prefix") {
michael@0 852 if (items.length != 2)
michael@0 853 throw "url-prefix requires one url in manifest file " + aURL.spec + " line " + lineNo;
michael@0 854 urlprefix = items[1];
michael@0 855 continue;
michael@0 856 }
michael@0 857
michael@0 858 if (items[0] == "default-preferences") {
michael@0 859 var m;
michael@0 860 var item;
michael@0 861 defaultTestPrefSettings = [];
michael@0 862 defaultRefPrefSettings = [];
michael@0 863 items.shift();
michael@0 864 while ((item = items.shift())) {
michael@0 865 if (!(m = item.match(gPrefItemRE))) {
michael@0 866 throw "Unexpected item in default-preferences list in manifest file " + aURL.spec + " line " + lineNo;
michael@0 867 }
michael@0 868 if (!AddPrefSettings(m[1], m[2], m[3], sandbox, defaultTestPrefSettings, defaultRefPrefSettings)) {
michael@0 869 throw "Error in pref value in manifest file " + aURL.spec + " line " + lineNo;
michael@0 870 }
michael@0 871 }
michael@0 872 continue;
michael@0 873 }
michael@0 874
michael@0 875 var expected_status = EXPECTED_PASS;
michael@0 876 var allow_silent_fail = false;
michael@0 877 var minAsserts = 0;
michael@0 878 var maxAsserts = 0;
michael@0 879 var needs_focus = false;
michael@0 880 var slow = false;
michael@0 881 var testPrefSettings = defaultTestPrefSettings.concat();
michael@0 882 var refPrefSettings = defaultRefPrefSettings.concat();
michael@0 883 var fuzzy_max_delta = 2;
michael@0 884 var fuzzy_max_pixels = 1;
michael@0 885
michael@0 886 while (items[0].match(/^(fails|needs-focus|random|skip|asserts|slow|require-or|silentfail|pref|test-pref|ref-pref|fuzzy)/)) {
michael@0 887 var item = items.shift();
michael@0 888 var stat;
michael@0 889 var cond;
michael@0 890 var m = item.match(/^(fails|random|skip|silentfail)-if(\(.*\))$/);
michael@0 891 if (m) {
michael@0 892 stat = m[1];
michael@0 893 // Note: m[2] contains the parentheses, and we want them.
michael@0 894 cond = Components.utils.evalInSandbox(m[2], sandbox);
michael@0 895 } else if (item.match(/^(fails|random|skip)$/)) {
michael@0 896 stat = item;
michael@0 897 cond = true;
michael@0 898 } else if (item == "needs-focus") {
michael@0 899 needs_focus = true;
michael@0 900 cond = false;
michael@0 901 } else if ((m = item.match(/^asserts\((\d+)(-\d+)?\)$/))) {
michael@0 902 cond = false;
michael@0 903 minAsserts = Number(m[1]);
michael@0 904 maxAsserts = (m[2] == undefined) ? minAsserts
michael@0 905 : Number(m[2].substring(1));
michael@0 906 } else if ((m = item.match(/^asserts-if\((.*?),(\d+)(-\d+)?\)$/))) {
michael@0 907 cond = false;
michael@0 908 if (Components.utils.evalInSandbox("(" + m[1] + ")", sandbox)) {
michael@0 909 minAsserts = Number(m[2]);
michael@0 910 maxAsserts =
michael@0 911 (m[3] == undefined) ? minAsserts
michael@0 912 : Number(m[3].substring(1));
michael@0 913 }
michael@0 914 } else if (item == "slow") {
michael@0 915 cond = false;
michael@0 916 slow = true;
michael@0 917 } else if ((m = item.match(/^require-or\((.*?)\)$/))) {
michael@0 918 var args = m[1].split(/,/);
michael@0 919 if (args.length != 2) {
michael@0 920 throw "Error 7 in manifest file " + aURL.spec + " line " + lineNo + ": wrong number of args to require-or";
michael@0 921 }
michael@0 922 var [precondition_str, fallback_action] = args;
michael@0 923 var preconditions = precondition_str.split(/&&/);
michael@0 924 cond = false;
michael@0 925 for each (var precondition in preconditions) {
michael@0 926 if (precondition === "debugMode") {
michael@0 927 // Currently unimplemented. Requires asynchronous
michael@0 928 // JSD call + getting an event while no JS is running
michael@0 929 stat = fallback_action;
michael@0 930 cond = true;
michael@0 931 break;
michael@0 932 } else if (precondition === "true") {
michael@0 933 // For testing
michael@0 934 } else {
michael@0 935 // Unknown precondition. Assume it is unimplemented.
michael@0 936 stat = fallback_action;
michael@0 937 cond = true;
michael@0 938 break;
michael@0 939 }
michael@0 940 }
michael@0 941 } else if ((m = item.match(/^slow-if\((.*?)\)$/))) {
michael@0 942 cond = false;
michael@0 943 if (Components.utils.evalInSandbox("(" + m[1] + ")", sandbox))
michael@0 944 slow = true;
michael@0 945 } else if (item == "silentfail") {
michael@0 946 cond = false;
michael@0 947 allow_silent_fail = true;
michael@0 948 } else if ((m = item.match(gPrefItemRE))) {
michael@0 949 cond = false;
michael@0 950 if (!AddPrefSettings(m[1], m[2], m[3], sandbox, testPrefSettings, refPrefSettings)) {
michael@0 951 throw "Error in pref value in manifest file " + aURL.spec + " line " + lineNo;
michael@0 952 }
michael@0 953 } else if ((m = item.match(/^fuzzy\((\d+),(\d+)\)$/))) {
michael@0 954 cond = false;
michael@0 955 expected_status = EXPECTED_FUZZY;
michael@0 956 fuzzy_max_delta = Number(m[1]);
michael@0 957 fuzzy_max_pixels = Number(m[2]);
michael@0 958 } else if ((m = item.match(/^fuzzy-if\((.*?),(\d+),(\d+)\)$/))) {
michael@0 959 cond = false;
michael@0 960 if (Components.utils.evalInSandbox("(" + m[1] + ")", sandbox)) {
michael@0 961 expected_status = EXPECTED_FUZZY;
michael@0 962 fuzzy_max_delta = Number(m[2]);
michael@0 963 fuzzy_max_pixels = Number(m[3]);
michael@0 964 }
michael@0 965 } else {
michael@0 966 throw "Error 1 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 967 }
michael@0 968
michael@0 969 if (cond) {
michael@0 970 if (stat == "fails") {
michael@0 971 expected_status = EXPECTED_FAIL;
michael@0 972 } else if (stat == "random") {
michael@0 973 expected_status = EXPECTED_RANDOM;
michael@0 974 } else if (stat == "skip") {
michael@0 975 expected_status = EXPECTED_DEATH;
michael@0 976 } else if (stat == "silentfail") {
michael@0 977 allow_silent_fail = true;
michael@0 978 }
michael@0 979 }
michael@0 980 }
michael@0 981
michael@0 982 expected_status = Math.max(expected_status, inherited_status);
michael@0 983
michael@0 984 if (minAsserts > maxAsserts) {
michael@0 985 throw "Bad range in manifest file " + aURL.spec + " line " + lineNo;
michael@0 986 }
michael@0 987
michael@0 988 var runHttp = false;
michael@0 989 var httpDepth;
michael@0 990 if (items[0] == "HTTP") {
michael@0 991 runHttp = (aURL.scheme == "file"); // We can't yet run the local HTTP server
michael@0 992 // for non-local reftests.
michael@0 993 httpDepth = 0;
michael@0 994 items.shift();
michael@0 995 } else if (items[0].match(/HTTP\(\.\.(\/\.\.)*\)/)) {
michael@0 996 // Accept HTTP(..), HTTP(../..), HTTP(../../..), etc.
michael@0 997 runHttp = (aURL.scheme == "file"); // We can't yet run the local HTTP server
michael@0 998 // for non-local reftests.
michael@0 999 httpDepth = (items[0].length - 5) / 3;
michael@0 1000 items.shift();
michael@0 1001 }
michael@0 1002
michael@0 1003 // do not prefix the url for include commands or urls specifying
michael@0 1004 // a protocol
michael@0 1005 if (urlprefix && items[0] != "include") {
michael@0 1006 if (items.length > 1 && !items[1].match(gProtocolRE)) {
michael@0 1007 items[1] = urlprefix + items[1];
michael@0 1008 }
michael@0 1009 if (items.length > 2 && !items[2].match(gProtocolRE)) {
michael@0 1010 items[2] = urlprefix + items[2];
michael@0 1011 }
michael@0 1012 }
michael@0 1013
michael@0 1014 var principal = secMan.getSimpleCodebasePrincipal(aURL);
michael@0 1015
michael@0 1016 if (items[0] == "include") {
michael@0 1017 if (items.length != 2 || runHttp)
michael@0 1018 throw "Error 2 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 1019 var incURI = gIOService.newURI(items[1], null, listURL);
michael@0 1020 secMan.checkLoadURIWithPrincipal(principal, incURI,
michael@0 1021 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1022 ReadManifest(incURI, expected_status);
michael@0 1023 } else if (items[0] == TYPE_LOAD) {
michael@0 1024 if (items.length != 2 ||
michael@0 1025 (expected_status != EXPECTED_PASS &&
michael@0 1026 expected_status != EXPECTED_DEATH))
michael@0 1027 throw "Error 3 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 1028 var [testURI] = runHttp
michael@0 1029 ? ServeFiles(principal, httpDepth,
michael@0 1030 listURL, [items[1]])
michael@0 1031 : [gIOService.newURI(items[1], null, listURL)];
michael@0 1032 var prettyPath = runHttp
michael@0 1033 ? gIOService.newURI(items[1], null, listURL).spec
michael@0 1034 : testURI.spec;
michael@0 1035 secMan.checkLoadURIWithPrincipal(principal, testURI,
michael@0 1036 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1037 AddTestItem({ type: TYPE_LOAD,
michael@0 1038 expected: expected_status,
michael@0 1039 allowSilentFail: allow_silent_fail,
michael@0 1040 prettyPath: prettyPath,
michael@0 1041 minAsserts: minAsserts,
michael@0 1042 maxAsserts: maxAsserts,
michael@0 1043 needsFocus: needs_focus,
michael@0 1044 slow: slow,
michael@0 1045 prefSettings1: testPrefSettings,
michael@0 1046 prefSettings2: refPrefSettings,
michael@0 1047 fuzzyMaxDelta: fuzzy_max_delta,
michael@0 1048 fuzzyMaxPixels: fuzzy_max_pixels,
michael@0 1049 url1: testURI,
michael@0 1050 url2: null });
michael@0 1051 } else if (items[0] == TYPE_SCRIPT) {
michael@0 1052 if (items.length != 2)
michael@0 1053 throw "Error 4 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 1054 var [testURI] = runHttp
michael@0 1055 ? ServeFiles(principal, httpDepth,
michael@0 1056 listURL, [items[1]])
michael@0 1057 : [gIOService.newURI(items[1], null, listURL)];
michael@0 1058 var prettyPath = runHttp
michael@0 1059 ? gIOService.newURI(items[1], null, listURL).spec
michael@0 1060 : testURI.spec;
michael@0 1061 secMan.checkLoadURIWithPrincipal(principal, testURI,
michael@0 1062 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1063 AddTestItem({ type: TYPE_SCRIPT,
michael@0 1064 expected: expected_status,
michael@0 1065 allowSilentFail: allow_silent_fail,
michael@0 1066 prettyPath: prettyPath,
michael@0 1067 minAsserts: minAsserts,
michael@0 1068 maxAsserts: maxAsserts,
michael@0 1069 needsFocus: needs_focus,
michael@0 1070 slow: slow,
michael@0 1071 prefSettings1: testPrefSettings,
michael@0 1072 prefSettings2: refPrefSettings,
michael@0 1073 fuzzyMaxDelta: fuzzy_max_delta,
michael@0 1074 fuzzyMaxPixels: fuzzy_max_pixels,
michael@0 1075 url1: testURI,
michael@0 1076 url2: null });
michael@0 1077 } else if (items[0] == TYPE_REFTEST_EQUAL || items[0] == TYPE_REFTEST_NOTEQUAL) {
michael@0 1078 if (items.length != 3)
michael@0 1079 throw "Error 5 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 1080 var [testURI, refURI] = runHttp
michael@0 1081 ? ServeFiles(principal, httpDepth,
michael@0 1082 listURL, [items[1], items[2]])
michael@0 1083 : [gIOService.newURI(items[1], null, listURL),
michael@0 1084 gIOService.newURI(items[2], null, listURL)];
michael@0 1085 var prettyPath = runHttp
michael@0 1086 ? gIOService.newURI(items[1], null, listURL).spec
michael@0 1087 : testURI.spec;
michael@0 1088 secMan.checkLoadURIWithPrincipal(principal, testURI,
michael@0 1089 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1090 secMan.checkLoadURIWithPrincipal(principal, refURI,
michael@0 1091 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1092 AddTestItem({ type: items[0],
michael@0 1093 expected: expected_status,
michael@0 1094 allowSilentFail: allow_silent_fail,
michael@0 1095 prettyPath: prettyPath,
michael@0 1096 minAsserts: minAsserts,
michael@0 1097 maxAsserts: maxAsserts,
michael@0 1098 needsFocus: needs_focus,
michael@0 1099 slow: slow,
michael@0 1100 prefSettings1: testPrefSettings,
michael@0 1101 prefSettings2: refPrefSettings,
michael@0 1102 fuzzyMaxDelta: fuzzy_max_delta,
michael@0 1103 fuzzyMaxPixels: fuzzy_max_pixels,
michael@0 1104 url1: testURI,
michael@0 1105 url2: refURI });
michael@0 1106 } else {
michael@0 1107 throw "Error 6 in manifest file " + aURL.spec + " line " + lineNo;
michael@0 1108 }
michael@0 1109 }
michael@0 1110 }
michael@0 1111
michael@0 1112 function AddURIUseCount(uri)
michael@0 1113 {
michael@0 1114 if (uri == null)
michael@0 1115 return;
michael@0 1116
michael@0 1117 var spec = uri.spec;
michael@0 1118 if (spec in gURIUseCounts) {
michael@0 1119 gURIUseCounts[spec]++;
michael@0 1120 } else {
michael@0 1121 gURIUseCounts[spec] = 1;
michael@0 1122 }
michael@0 1123 }
michael@0 1124
michael@0 1125 function BuildUseCounts()
michael@0 1126 {
michael@0 1127 gURIUseCounts = {};
michael@0 1128 for (var i = 0; i < gURLs.length; ++i) {
michael@0 1129 var url = gURLs[i];
michael@0 1130 if (url.expected != EXPECTED_DEATH &&
michael@0 1131 (url.type == TYPE_REFTEST_EQUAL ||
michael@0 1132 url.type == TYPE_REFTEST_NOTEQUAL)) {
michael@0 1133 if (url.prefSettings1.length == 0) {
michael@0 1134 AddURIUseCount(gURLs[i].url1);
michael@0 1135 }
michael@0 1136 if (url.prefSettings2.length == 0) {
michael@0 1137 AddURIUseCount(gURLs[i].url2);
michael@0 1138 }
michael@0 1139 }
michael@0 1140 }
michael@0 1141 }
michael@0 1142
michael@0 1143 function ServeFiles(manifestPrincipal, depth, aURL, files)
michael@0 1144 {
michael@0 1145 var listURL = aURL.QueryInterface(CI.nsIFileURL);
michael@0 1146 var directory = listURL.file.parent;
michael@0 1147
michael@0 1148 // Allow serving a tree that's an ancestor of the directory containing
michael@0 1149 // the files so that they can use resources in ../ (etc.).
michael@0 1150 var dirPath = "/";
michael@0 1151 while (depth > 0) {
michael@0 1152 dirPath = "/" + directory.leafName + dirPath;
michael@0 1153 directory = directory.parent;
michael@0 1154 --depth;
michael@0 1155 }
michael@0 1156
michael@0 1157 gCount++;
michael@0 1158 var path = "/" + Date.now() + "/" + gCount;
michael@0 1159 gServer.registerDirectory(path + "/", directory);
michael@0 1160
michael@0 1161 var secMan = CC[NS_SCRIPTSECURITYMANAGER_CONTRACTID]
michael@0 1162 .getService(CI.nsIScriptSecurityManager);
michael@0 1163
michael@0 1164 var testbase = gIOService.newURI("http://localhost:" + gHttpServerPort +
michael@0 1165 path + dirPath, null, null);
michael@0 1166
michael@0 1167 function FileToURI(file)
michael@0 1168 {
michael@0 1169 // Only serve relative URIs via the HTTP server, not absolute
michael@0 1170 // ones like about:blank.
michael@0 1171 var testURI = gIOService.newURI(file, null, testbase);
michael@0 1172
michael@0 1173 // XXX necessary? manifestURL guaranteed to be file, others always HTTP
michael@0 1174 secMan.checkLoadURIWithPrincipal(manifestPrincipal, testURI,
michael@0 1175 CI.nsIScriptSecurityManager.DISALLOW_SCRIPT);
michael@0 1176
michael@0 1177 return testURI;
michael@0 1178 }
michael@0 1179
michael@0 1180 return files.map(FileToURI);
michael@0 1181 }
michael@0 1182
michael@0 1183 // Return true iff this window is focused when this function returns.
michael@0 1184 function Focus()
michael@0 1185 {
michael@0 1186 var fm = CC["@mozilla.org/focus-manager;1"].getService(CI.nsIFocusManager);
michael@0 1187 fm.focusedWindow = gContainingWindow;
michael@0 1188 #ifdef XP_MACOSX
michael@0 1189 try {
michael@0 1190 var dock = CC["@mozilla.org/widget/macdocksupport;1"].getService(CI.nsIMacDockSupport);
michael@0 1191 dock.activateApplication(true);
michael@0 1192 } catch(ex) {
michael@0 1193 }
michael@0 1194 #endif // XP_MACOSX
michael@0 1195 return true;
michael@0 1196 }
michael@0 1197
michael@0 1198 function Blur()
michael@0 1199 {
michael@0 1200 // On non-remote reftests, this will transfer focus to the dummy window
michael@0 1201 // we created to hold focus for non-needs-focus tests. Buggy tests
michael@0 1202 // (ones which require focus but don't request needs-focus) will then
michael@0 1203 // fail.
michael@0 1204 gContainingWindow.blur();
michael@0 1205 }
michael@0 1206
michael@0 1207 function StartCurrentTest()
michael@0 1208 {
michael@0 1209 gTestLog = [];
michael@0 1210
michael@0 1211 // make sure we don't run tests that are expected to kill the browser
michael@0 1212 while (gURLs.length > 0) {
michael@0 1213 var test = gURLs[0];
michael@0 1214 if (test.expected == EXPECTED_DEATH) {
michael@0 1215 ++gTestResults.Skip;
michael@0 1216 gDumpLog("REFTEST TEST-KNOWN-FAIL | " + test.url1.spec + " | (SKIP)\n");
michael@0 1217 gURLs.shift();
michael@0 1218 } else if (test.needsFocus && !Focus()) {
michael@0 1219 // FIXME: Marking this as a known fail is dangerous! What
michael@0 1220 // if it starts failing all the time?
michael@0 1221 ++gTestResults.Skip;
michael@0 1222 gDumpLog("REFTEST TEST-KNOWN-FAIL | " + test.url1.spec + " | (SKIPPED; COULDN'T GET FOCUS)\n");
michael@0 1223 gURLs.shift();
michael@0 1224 } else if (test.slow && !gRunSlowTests) {
michael@0 1225 ++gTestResults.Slow;
michael@0 1226 gDumpLog("REFTEST TEST-KNOWN-SLOW | " + test.url1.spec + " | (SLOW)\n");
michael@0 1227 gURLs.shift();
michael@0 1228 } else {
michael@0 1229 break;
michael@0 1230 }
michael@0 1231 }
michael@0 1232
michael@0 1233 if (gURLs.length == 0) {
michael@0 1234 RestoreChangedPreferences();
michael@0 1235 DoneTests();
michael@0 1236 }
michael@0 1237 else {
michael@0 1238 gDumpLog("REFTEST TEST-START | " + gURLs[0].prettyPath + "\n");
michael@0 1239 if (!gURLs[0].needsFocus) {
michael@0 1240 Blur();
michael@0 1241 }
michael@0 1242 var currentTest = gTotalTests - gURLs.length;
michael@0 1243 gContainingWindow.document.title = "reftest: " + currentTest + " / " + gTotalTests +
michael@0 1244 " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)";
michael@0 1245 StartCurrentURI(1);
michael@0 1246 }
michael@0 1247 }
michael@0 1248
michael@0 1249 function StartCurrentURI(aState)
michael@0 1250 {
michael@0 1251 gState = aState;
michael@0 1252 gCurrentURL = gURLs[0]["url" + aState].spec;
michael@0 1253
michael@0 1254 RestoreChangedPreferences();
michael@0 1255
michael@0 1256 var prefSettings = gURLs[0]["prefSettings" + aState];
michael@0 1257 if (prefSettings.length > 0) {
michael@0 1258 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 1259 getService(Components.interfaces.nsIPrefBranch);
michael@0 1260 var badPref = undefined;
michael@0 1261 try {
michael@0 1262 prefSettings.forEach(function(ps) {
michael@0 1263 var oldVal;
michael@0 1264 if (ps.type == PREF_BOOLEAN) {
michael@0 1265 try {
michael@0 1266 oldVal = prefs.getBoolPref(ps.name);
michael@0 1267 } catch (e) {
michael@0 1268 badPref = "boolean preference '" + ps.name + "'";
michael@0 1269 throw "bad pref";
michael@0 1270 }
michael@0 1271 } else if (ps.type == PREF_STRING) {
michael@0 1272 try {
michael@0 1273 oldVal = prefs.getCharPref(ps.name);
michael@0 1274 } catch (e) {
michael@0 1275 badPref = "string preference '" + ps.name + "'";
michael@0 1276 throw "bad pref";
michael@0 1277 }
michael@0 1278 } else if (ps.type == PREF_INTEGER) {
michael@0 1279 try {
michael@0 1280 oldVal = prefs.getIntPref(ps.name);
michael@0 1281 } catch (e) {
michael@0 1282 badPref = "integer preference '" + ps.name + "'";
michael@0 1283 throw "bad pref";
michael@0 1284 }
michael@0 1285 } else {
michael@0 1286 throw "internal error - unknown preference type";
michael@0 1287 }
michael@0 1288 if (oldVal != ps.value) {
michael@0 1289 gPrefsToRestore.push( { name: ps.name,
michael@0 1290 type: ps.type,
michael@0 1291 value: oldVal } );
michael@0 1292 var value = ps.value;
michael@0 1293 if (ps.type == PREF_BOOLEAN) {
michael@0 1294 prefs.setBoolPref(ps.name, value);
michael@0 1295 } else if (ps.type == PREF_STRING) {
michael@0 1296 prefs.setCharPref(ps.name, value);
michael@0 1297 value = '"' + value + '"';
michael@0 1298 } else if (ps.type == PREF_INTEGER) {
michael@0 1299 prefs.setIntPref(ps.name, value);
michael@0 1300 }
michael@0 1301 gDumpLog("SET PREFERENCE pref(" + ps.name + "," + value + ")\n");
michael@0 1302 }
michael@0 1303 });
michael@0 1304 } catch (e) {
michael@0 1305 if (e == "bad pref") {
michael@0 1306 var test = gURLs[0];
michael@0 1307 if (test.expected == EXPECTED_FAIL) {
michael@0 1308 gDumpLog("REFTEST TEST-KNOWN-FAIL | " + test.url1.spec +
michael@0 1309 " | (SKIPPED; " + badPref + " not known or wrong type)\n");
michael@0 1310 ++gTestResults.Skip;
michael@0 1311 } else {
michael@0 1312 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + test.url1.spec +
michael@0 1313 " | " + badPref + " not known or wrong type\n");
michael@0 1314 ++gTestResults.UnexpectedFail;
michael@0 1315 }
michael@0 1316 } else {
michael@0 1317 throw e;
michael@0 1318 }
michael@0 1319 }
michael@0 1320 if (badPref != undefined) {
michael@0 1321 // skip the test that had a bad preference
michael@0 1322 gURLs.shift();
michael@0 1323
michael@0 1324 StartCurrentTest();
michael@0 1325 return;
michael@0 1326 }
michael@0 1327 }
michael@0 1328
michael@0 1329 if (prefSettings.length == 0 &&
michael@0 1330 gURICanvases[gCurrentURL] &&
michael@0 1331 (gURLs[0].type == TYPE_REFTEST_EQUAL ||
michael@0 1332 gURLs[0].type == TYPE_REFTEST_NOTEQUAL) &&
michael@0 1333 gURLs[0].maxAsserts == 0) {
michael@0 1334 // Pretend the document loaded --- RecordResult will notice
michael@0 1335 // there's already a canvas for this URL
michael@0 1336 gContainingWindow.setTimeout(RecordResult, 0);
michael@0 1337 } else {
michael@0 1338 var currentTest = gTotalTests - gURLs.length;
michael@0 1339 gDumpLog("REFTEST TEST-LOAD | " + gCurrentURL + " | " + currentTest + " / " + gTotalTests +
michael@0 1340 " (" + Math.floor(100 * (currentTest / gTotalTests)) + "%)\n");
michael@0 1341 LogInfo("START " + gCurrentURL);
michael@0 1342 var type = gURLs[0].type
michael@0 1343 if (TYPE_SCRIPT == type) {
michael@0 1344 SendLoadScriptTest(gCurrentURL, gLoadTimeout);
michael@0 1345 } else {
michael@0 1346 SendLoadTest(type, gCurrentURL, gLoadTimeout);
michael@0 1347 }
michael@0 1348 }
michael@0 1349 }
michael@0 1350
michael@0 1351 function DoneTests()
michael@0 1352 {
michael@0 1353 gDumpLog("REFTEST FINISHED: Slowest test took " + gSlowestTestTime +
michael@0 1354 "ms (" + gSlowestTestURL + ")\n");
michael@0 1355
michael@0 1356 gDumpLog("REFTEST INFO | Result summary:\n");
michael@0 1357 var count = gTestResults.Pass + gTestResults.LoadOnly;
michael@0 1358 gDumpLog("REFTEST INFO | Successful: " + count + " (" +
michael@0 1359 gTestResults.Pass + " pass, " +
michael@0 1360 gTestResults.LoadOnly + " load only)\n");
michael@0 1361 count = gTestResults.Exception + gTestResults.FailedLoad +
michael@0 1362 gTestResults.UnexpectedFail + gTestResults.UnexpectedPass +
michael@0 1363 gTestResults.AssertionUnexpected +
michael@0 1364 gTestResults.AssertionUnexpectedFixed;
michael@0 1365 gDumpLog("REFTEST INFO | Unexpected: " + count + " (" +
michael@0 1366 gTestResults.UnexpectedFail + " unexpected fail, " +
michael@0 1367 gTestResults.UnexpectedPass + " unexpected pass, " +
michael@0 1368 gTestResults.AssertionUnexpected + " unexpected asserts, " +
michael@0 1369 gTestResults.AssertionUnexpectedFixed + " unexpected fixed asserts, " +
michael@0 1370 gTestResults.FailedLoad + " failed load, " +
michael@0 1371 gTestResults.Exception + " exception)\n");
michael@0 1372 count = gTestResults.KnownFail + gTestResults.AssertionKnown +
michael@0 1373 gTestResults.Random + gTestResults.Skip + gTestResults.Slow;
michael@0 1374 gDumpLog("REFTEST INFO | Known problems: " + count + " (" +
michael@0 1375 gTestResults.KnownFail + " known fail, " +
michael@0 1376 gTestResults.AssertionKnown + " known asserts, " +
michael@0 1377 gTestResults.Random + " random, " +
michael@0 1378 gTestResults.Skip + " skipped, " +
michael@0 1379 gTestResults.Slow + " slow)\n");
michael@0 1380
michael@0 1381 gDumpLog("REFTEST INFO | Total canvas count = " + gRecycledCanvases.length + "\n");
michael@0 1382
michael@0 1383 gDumpLog("REFTEST TEST-START | Shutdown\n");
michael@0 1384 function onStopped() {
michael@0 1385 let appStartup = CC["@mozilla.org/toolkit/app-startup;1"].getService(CI.nsIAppStartup);
michael@0 1386 appStartup.quit(CI.nsIAppStartup.eForceQuit);
michael@0 1387 }
michael@0 1388 if (gServer) {
michael@0 1389 gServer.stop(onStopped);
michael@0 1390 }
michael@0 1391 else {
michael@0 1392 onStopped();
michael@0 1393 }
michael@0 1394 }
michael@0 1395
michael@0 1396 function UpdateCanvasCache(url, canvas)
michael@0 1397 {
michael@0 1398 var spec = url.spec;
michael@0 1399
michael@0 1400 --gURIUseCounts[spec];
michael@0 1401
michael@0 1402 if (gNoCanvasCache || gURIUseCounts[spec] == 0) {
michael@0 1403 ReleaseCanvas(canvas);
michael@0 1404 delete gURICanvases[spec];
michael@0 1405 } else if (gURIUseCounts[spec] > 0) {
michael@0 1406 gURICanvases[spec] = canvas;
michael@0 1407 } else {
michael@0 1408 throw "Use counts were computed incorrectly";
michael@0 1409 }
michael@0 1410 }
michael@0 1411
michael@0 1412 // Recompute drawWindow flags for every drawWindow operation.
michael@0 1413 // We have to do this every time since our window can be
michael@0 1414 // asynchronously resized (e.g. by the window manager, to make
michael@0 1415 // it fit on screen) at unpredictable times.
michael@0 1416 // Fortunately this is pretty cheap.
michael@0 1417 function DoDrawWindow(ctx, x, y, w, h)
michael@0 1418 {
michael@0 1419 var flags = ctx.DRAWWINDOW_DRAW_CARET | ctx.DRAWWINDOW_DRAW_VIEW;
michael@0 1420 var testRect = gBrowser.getBoundingClientRect();
michael@0 1421 if (gIgnoreWindowSize ||
michael@0 1422 (0 <= testRect.left &&
michael@0 1423 0 <= testRect.top &&
michael@0 1424 gContainingWindow.innerWidth >= testRect.right &&
michael@0 1425 gContainingWindow.innerHeight >= testRect.bottom)) {
michael@0 1426 // We can use the window's retained layer manager
michael@0 1427 // because the window is big enough to display the entire
michael@0 1428 // browser element
michael@0 1429 flags |= ctx.DRAWWINDOW_USE_WIDGET_LAYERS;
michael@0 1430 } else if (gBrowserIsRemote) {
michael@0 1431 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gCurrentURL + " | can't drawWindow remote content\n");
michael@0 1432 ++gTestResults.Exception;
michael@0 1433 }
michael@0 1434
michael@0 1435 if (gDrawWindowFlags != flags) {
michael@0 1436 // Every time the flags change, dump the new state.
michael@0 1437 gDrawWindowFlags = flags;
michael@0 1438 var flagsStr = "DRAWWINDOW_DRAW_CARET | DRAWWINDOW_DRAW_VIEW";
michael@0 1439 if (flags & ctx.DRAWWINDOW_USE_WIDGET_LAYERS) {
michael@0 1440 flagsStr += " | DRAWWINDOW_USE_WIDGET_LAYERS";
michael@0 1441 } else {
michael@0 1442 // Output a special warning because we need to be able to detect
michael@0 1443 // this whenever it happens.
michael@0 1444 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | WARNING: USE_WIDGET_LAYERS disabled\n");
michael@0 1445 }
michael@0 1446 gDumpLog("REFTEST INFO | drawWindow flags = " + flagsStr +
michael@0 1447 "; window size = " + gContainingWindow.innerWidth + "," + gContainingWindow.innerHeight +
michael@0 1448 "; test browser size = " + testRect.width + "," + testRect.height +
michael@0 1449 "\n");
michael@0 1450 }
michael@0 1451
michael@0 1452 LogInfo("DoDrawWindow " + x + "," + y + "," + w + "," + h);
michael@0 1453 ctx.drawWindow(gContainingWindow, x, y, w, h, "rgb(255,255,255)",
michael@0 1454 gDrawWindowFlags);
michael@0 1455 }
michael@0 1456
michael@0 1457 function InitCurrentCanvasWithSnapshot()
michael@0 1458 {
michael@0 1459 LogInfo("Initializing canvas snapshot");
michael@0 1460
michael@0 1461 if (gURLs[0].type == TYPE_LOAD || gURLs[0].type == TYPE_SCRIPT) {
michael@0 1462 // We don't want to snapshot this kind of test
michael@0 1463 return false;
michael@0 1464 }
michael@0 1465
michael@0 1466 if (!gCurrentCanvas) {
michael@0 1467 gCurrentCanvas = AllocateCanvas();
michael@0 1468 }
michael@0 1469
michael@0 1470 var ctx = gCurrentCanvas.getContext("2d");
michael@0 1471 DoDrawWindow(ctx, 0, 0, gCurrentCanvas.width, gCurrentCanvas.height);
michael@0 1472 return true;
michael@0 1473 }
michael@0 1474
michael@0 1475 function UpdateCurrentCanvasForInvalidation(rects)
michael@0 1476 {
michael@0 1477 LogInfo("Updating canvas for invalidation");
michael@0 1478
michael@0 1479 if (!gCurrentCanvas) {
michael@0 1480 return;
michael@0 1481 }
michael@0 1482
michael@0 1483 var ctx = gCurrentCanvas.getContext("2d");
michael@0 1484 for (var i = 0; i < rects.length; ++i) {
michael@0 1485 var r = rects[i];
michael@0 1486 // Set left/top/right/bottom to pixel boundaries
michael@0 1487 var left = Math.floor(r.left);
michael@0 1488 var top = Math.floor(r.top);
michael@0 1489 var right = Math.ceil(r.right);
michael@0 1490 var bottom = Math.ceil(r.bottom);
michael@0 1491
michael@0 1492 ctx.save();
michael@0 1493 ctx.translate(left, top);
michael@0 1494 DoDrawWindow(ctx, left, top, right - left, bottom - top);
michael@0 1495 ctx.restore();
michael@0 1496 }
michael@0 1497 }
michael@0 1498
michael@0 1499 function UpdateWholeCurrentCanvasForInvalidation()
michael@0 1500 {
michael@0 1501 LogInfo("Updating entire canvas for invalidation");
michael@0 1502
michael@0 1503 if (!gCurrentCanvas) {
michael@0 1504 return;
michael@0 1505 }
michael@0 1506
michael@0 1507 var ctx = gCurrentCanvas.getContext("2d");
michael@0 1508 DoDrawWindow(ctx, 0, 0, gCurrentCanvas.width, gCurrentCanvas.height);
michael@0 1509 }
michael@0 1510
michael@0 1511 function RecordResult(testRunTime, errorMsg, scriptResults)
michael@0 1512 {
michael@0 1513 LogInfo("RecordResult fired");
michael@0 1514
michael@0 1515 // Keep track of which test was slowest, and how long it took.
michael@0 1516 if (testRunTime > gSlowestTestTime) {
michael@0 1517 gSlowestTestTime = testRunTime;
michael@0 1518 gSlowestTestURL = gCurrentURL;
michael@0 1519 }
michael@0 1520
michael@0 1521 // Not 'const ...' because of 'EXPECTED_*' value dependency.
michael@0 1522 var outputs = {};
michael@0 1523 const randomMsg = "(EXPECTED RANDOM)";
michael@0 1524 outputs[EXPECTED_PASS] = {
michael@0 1525 true: {s: "TEST-PASS" , n: "Pass"},
michael@0 1526 false: {s: "TEST-UNEXPECTED-FAIL" , n: "UnexpectedFail"}
michael@0 1527 };
michael@0 1528 outputs[EXPECTED_FAIL] = {
michael@0 1529 true: {s: "TEST-UNEXPECTED-PASS" , n: "UnexpectedPass"},
michael@0 1530 false: {s: "TEST-KNOWN-FAIL" , n: "KnownFail"}
michael@0 1531 };
michael@0 1532 outputs[EXPECTED_RANDOM] = {
michael@0 1533 true: {s: "TEST-PASS" + randomMsg , n: "Random"},
michael@0 1534 false: {s: "TEST-KNOWN-FAIL" + randomMsg, n: "Random"}
michael@0 1535 };
michael@0 1536 outputs[EXPECTED_FUZZY] = outputs[EXPECTED_PASS];
michael@0 1537
michael@0 1538 var output;
michael@0 1539
michael@0 1540 if (gURLs[0].type == TYPE_LOAD) {
michael@0 1541 ++gTestResults.LoadOnly;
michael@0 1542 gDumpLog("REFTEST TEST-PASS | " + gURLs[0].prettyPath + " | (LOAD ONLY)\n");
michael@0 1543 gCurrentCanvas = null;
michael@0 1544 FinishTestItem();
michael@0 1545 return;
michael@0 1546 }
michael@0 1547 if (gURLs[0].type == TYPE_SCRIPT) {
michael@0 1548 var expected = gURLs[0].expected;
michael@0 1549
michael@0 1550 if (errorMsg) {
michael@0 1551 // Force an unexpected failure to alert the test author to fix the test.
michael@0 1552 expected = EXPECTED_PASS;
michael@0 1553 } else if (scriptResults.length == 0) {
michael@0 1554 // This failure may be due to a JavaScript Engine bug causing
michael@0 1555 // early termination of the test. If we do not allow silent
michael@0 1556 // failure, report an error.
michael@0 1557 if (!gURLs[0].allowSilentFail)
michael@0 1558 errorMsg = "No test results reported. (SCRIPT)\n";
michael@0 1559 else
michael@0 1560 gDumpLog("REFTEST INFO | An expected silent failure occurred \n");
michael@0 1561 }
michael@0 1562
michael@0 1563 if (errorMsg) {
michael@0 1564 output = outputs[expected][false];
michael@0 1565 ++gTestResults[output.n];
michael@0 1566 var result = "REFTEST " + output.s + " | " +
michael@0 1567 gURLs[0].prettyPath + " | " + // the URL being tested
michael@0 1568 errorMsg;
michael@0 1569
michael@0 1570 gDumpLog(result);
michael@0 1571 FinishTestItem();
michael@0 1572 return;
michael@0 1573 }
michael@0 1574
michael@0 1575 var anyFailed = scriptResults.some(function(result) { return !result.passed; });
michael@0 1576 var outputPair;
michael@0 1577 if (anyFailed && expected == EXPECTED_FAIL) {
michael@0 1578 // If we're marked as expected to fail, and some (but not all) tests
michael@0 1579 // passed, treat those tests as though they were marked random
michael@0 1580 // (since we can't tell whether they were really intended to be
michael@0 1581 // marked failing or not).
michael@0 1582 outputPair = { true: outputs[EXPECTED_RANDOM][true],
michael@0 1583 false: outputs[expected][false] };
michael@0 1584 } else {
michael@0 1585 outputPair = outputs[expected];
michael@0 1586 }
michael@0 1587 var index = 0;
michael@0 1588 scriptResults.forEach(function(result) {
michael@0 1589 var output = outputPair[result.passed];
michael@0 1590
michael@0 1591 ++gTestResults[output.n];
michael@0 1592 result = "REFTEST " + output.s + " | " +
michael@0 1593 gURLs[0].prettyPath + " | " + // the URL being tested
michael@0 1594 result.description + " item " + (++index) + "\n";
michael@0 1595 gDumpLog(result);
michael@0 1596 });
michael@0 1597
michael@0 1598 if (anyFailed && expected == EXPECTED_PASS) {
michael@0 1599 FlushTestLog();
michael@0 1600 }
michael@0 1601
michael@0 1602 FinishTestItem();
michael@0 1603 return;
michael@0 1604 }
michael@0 1605
michael@0 1606 if (gURLs[0]["prefSettings" + gState].length == 0 &&
michael@0 1607 gURICanvases[gCurrentURL]) {
michael@0 1608 gCurrentCanvas = gURICanvases[gCurrentURL];
michael@0 1609 }
michael@0 1610 if (gCurrentCanvas == null) {
michael@0 1611 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gCurrentURL + " | program error managing snapshots\n");
michael@0 1612 ++gTestResults.Exception;
michael@0 1613 }
michael@0 1614 if (gState == 1) {
michael@0 1615 gCanvas1 = gCurrentCanvas;
michael@0 1616 } else {
michael@0 1617 gCanvas2 = gCurrentCanvas;
michael@0 1618 }
michael@0 1619 gCurrentCanvas = null;
michael@0 1620
michael@0 1621 ResetRenderingState();
michael@0 1622
michael@0 1623 switch (gState) {
michael@0 1624 case 1:
michael@0 1625 // First document has been loaded.
michael@0 1626 // Proceed to load the second document.
michael@0 1627
michael@0 1628 CleanUpCrashDumpFiles();
michael@0 1629 StartCurrentURI(2);
michael@0 1630 break;
michael@0 1631 case 2:
michael@0 1632 // Both documents have been loaded. Compare the renderings and see
michael@0 1633 // if the comparison result matches the expected result specified
michael@0 1634 // in the manifest.
michael@0 1635
michael@0 1636 // number of different pixels
michael@0 1637 var differences;
michael@0 1638 // whether the two renderings match:
michael@0 1639 var equal;
michael@0 1640 var maxDifference = {};
michael@0 1641
michael@0 1642 differences = gWindowUtils.compareCanvases(gCanvas1, gCanvas2, maxDifference);
michael@0 1643 equal = (differences == 0);
michael@0 1644
michael@0 1645 // what is expected on this platform (PASS, FAIL, or RANDOM)
michael@0 1646 var expected = gURLs[0].expected;
michael@0 1647
michael@0 1648 if (maxDifference.value > 0 && maxDifference.value <= gURLs[0].fuzzyMaxDelta &&
michael@0 1649 differences <= gURLs[0].fuzzyMaxPixels) {
michael@0 1650 if (equal) {
michael@0 1651 throw "Inconsistent result from compareCanvases.";
michael@0 1652 }
michael@0 1653 equal = expected == EXPECTED_FUZZY;
michael@0 1654 gDumpLog("REFTEST fuzzy match\n");
michael@0 1655 }
michael@0 1656
michael@0 1657 // whether the comparison result matches what is in the manifest
michael@0 1658 var test_passed = (equal == (gURLs[0].type == TYPE_REFTEST_EQUAL)) && !gFailedNoPaint;
michael@0 1659
michael@0 1660 output = outputs[expected][test_passed];
michael@0 1661
michael@0 1662 ++gTestResults[output.n];
michael@0 1663
michael@0 1664 // It's possible that we failed both reftest-no-paint and the normal comparison, but we don't
michael@0 1665 // have a way to annotate these separately, so just print an error for the no-paint failure.
michael@0 1666 if (gFailedNoPaint) {
michael@0 1667 if (expected == EXPECTED_FAIL) {
michael@0 1668 gDumpLog("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath + " | failed reftest-no-paint\n");
michael@0 1669 } else {
michael@0 1670 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath + " | failed reftest-no-paint\n");
michael@0 1671 }
michael@0 1672 } else {
michael@0 1673 var result = "REFTEST " + output.s + " | " +
michael@0 1674 gURLs[0].prettyPath + " | "; // the URL being tested
michael@0 1675 switch (gURLs[0].type) {
michael@0 1676 case TYPE_REFTEST_NOTEQUAL:
michael@0 1677 result += "image comparison (!=)";
michael@0 1678 break;
michael@0 1679 case TYPE_REFTEST_EQUAL:
michael@0 1680 result += "image comparison (==)";
michael@0 1681 break;
michael@0 1682 }
michael@0 1683
michael@0 1684 if (!test_passed && expected == EXPECTED_PASS ||
michael@0 1685 !test_passed && expected == EXPECTED_FUZZY ||
michael@0 1686 test_passed && expected == EXPECTED_FAIL) {
michael@0 1687 if (!equal) {
michael@0 1688 result += ", max difference: " + maxDifference.value + ", number of differing pixels: " + differences + "\n";
michael@0 1689 result += "REFTEST IMAGE 1 (TEST): " + gCanvas1.toDataURL() + "\n";
michael@0 1690 result += "REFTEST IMAGE 2 (REFERENCE): " + gCanvas2.toDataURL() + "\n";
michael@0 1691 } else {
michael@0 1692 result += "\n";
michael@0 1693 result += "REFTEST IMAGE: " + gCanvas1.toDataURL() + "\n";
michael@0 1694 }
michael@0 1695 } else {
michael@0 1696 result += "\n";
michael@0 1697 }
michael@0 1698
michael@0 1699 gDumpLog(result);
michael@0 1700 }
michael@0 1701
michael@0 1702 if (!test_passed && expected == EXPECTED_PASS) {
michael@0 1703 FlushTestLog();
michael@0 1704 }
michael@0 1705
michael@0 1706 if (gURLs[0].prefSettings1.length == 0) {
michael@0 1707 UpdateCanvasCache(gURLs[0].url1, gCanvas1);
michael@0 1708 }
michael@0 1709 if (gURLs[0].prefSettings2.length == 0) {
michael@0 1710 UpdateCanvasCache(gURLs[0].url2, gCanvas2);
michael@0 1711 }
michael@0 1712
michael@0 1713 CleanUpCrashDumpFiles();
michael@0 1714 FinishTestItem();
michael@0 1715 break;
michael@0 1716 default:
michael@0 1717 throw "Unexpected state.";
michael@0 1718 }
michael@0 1719 }
michael@0 1720
michael@0 1721 function LoadFailed(why)
michael@0 1722 {
michael@0 1723 ++gTestResults.FailedLoad;
michael@0 1724 // Once bug 896840 is fixed, this can go away, but for now it will give log
michael@0 1725 // output that is TBPL starable for bug 789751 and bug 720452.
michael@0 1726 if (!why) {
michael@0 1727 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | load failed with unknown reason\n");
michael@0 1728 }
michael@0 1729 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " +
michael@0 1730 gURLs[0]["url" + gState].spec + " | load failed: " + why + "\n");
michael@0 1731 FlushTestLog();
michael@0 1732 FinishTestItem();
michael@0 1733 }
michael@0 1734
michael@0 1735 function RemoveExpectedCrashDumpFiles()
michael@0 1736 {
michael@0 1737 if (gExpectingProcessCrash) {
michael@0 1738 for each (let crashFilename in gExpectedCrashDumpFiles) {
michael@0 1739 let file = gCrashDumpDir.clone();
michael@0 1740 file.append(crashFilename);
michael@0 1741 if (file.exists()) {
michael@0 1742 file.remove(false);
michael@0 1743 }
michael@0 1744 }
michael@0 1745 }
michael@0 1746 gExpectedCrashDumpFiles.length = 0;
michael@0 1747 }
michael@0 1748
michael@0 1749 function FindUnexpectedCrashDumpFiles()
michael@0 1750 {
michael@0 1751 if (!gCrashDumpDir.exists()) {
michael@0 1752 return;
michael@0 1753 }
michael@0 1754
michael@0 1755 let entries = gCrashDumpDir.directoryEntries;
michael@0 1756 if (!entries) {
michael@0 1757 return;
michael@0 1758 }
michael@0 1759
michael@0 1760 let foundCrashDumpFile = false;
michael@0 1761 while (entries.hasMoreElements()) {
michael@0 1762 let file = entries.getNext().QueryInterface(CI.nsIFile);
michael@0 1763 let path = String(file.path);
michael@0 1764 if (path.match(/\.(dmp|extra)$/) && !gUnexpectedCrashDumpFiles[path]) {
michael@0 1765 if (!foundCrashDumpFile) {
michael@0 1766 ++gTestResults.UnexpectedFail;
michael@0 1767 foundCrashDumpFile = true;
michael@0 1768 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gCurrentURL +
michael@0 1769 " | This test left crash dumps behind, but we weren't expecting it to!\n");
michael@0 1770 }
michael@0 1771 gDumpLog("REFTEST INFO | Found unexpected crash dump file " + path +
michael@0 1772 ".\n");
michael@0 1773 gUnexpectedCrashDumpFiles[path] = true;
michael@0 1774 }
michael@0 1775 }
michael@0 1776 }
michael@0 1777
michael@0 1778 function CleanUpCrashDumpFiles()
michael@0 1779 {
michael@0 1780 RemoveExpectedCrashDumpFiles();
michael@0 1781 FindUnexpectedCrashDumpFiles();
michael@0 1782 gExpectingProcessCrash = false;
michael@0 1783 }
michael@0 1784
michael@0 1785 function FinishTestItem()
michael@0 1786 {
michael@0 1787 // Replace document with BLANK_URL_FOR_CLEARING in case there are
michael@0 1788 // assertions when unloading.
michael@0 1789 gDumpLog("REFTEST INFO | Loading a blank page\n");
michael@0 1790 // After clearing, content will notify us of the assertion count
michael@0 1791 // and tests will continue.
michael@0 1792 SetAsyncScroll(false);
michael@0 1793 SendClear();
michael@0 1794 gFailedNoPaint = false;
michael@0 1795 }
michael@0 1796
michael@0 1797 function DoAssertionCheck(numAsserts)
michael@0 1798 {
michael@0 1799 if (gDebug.isDebugBuild) {
michael@0 1800 if (gBrowserIsRemote) {
michael@0 1801 // Count chrome-process asserts too when content is out of
michael@0 1802 // process.
michael@0 1803 var newAssertionCount = gDebug.assertionCount;
michael@0 1804 var numLocalAsserts = newAssertionCount - gAssertionCount;
michael@0 1805 gAssertionCount = newAssertionCount;
michael@0 1806
michael@0 1807 numAsserts += numLocalAsserts;
michael@0 1808 }
michael@0 1809
michael@0 1810 var minAsserts = gURLs[0].minAsserts;
michael@0 1811 var maxAsserts = gURLs[0].maxAsserts;
michael@0 1812
michael@0 1813 var expectedAssertions = "expected " + minAsserts;
michael@0 1814 if (minAsserts != maxAsserts) {
michael@0 1815 expectedAssertions += " to " + maxAsserts;
michael@0 1816 }
michael@0 1817 expectedAssertions += " assertions";
michael@0 1818
michael@0 1819 if (numAsserts < minAsserts) {
michael@0 1820 ++gTestResults.AssertionUnexpectedFixed;
michael@0 1821 gDumpLog("REFTEST TEST-UNEXPECTED-PASS | " + gURLs[0].prettyPath +
michael@0 1822 " | assertion count " + numAsserts + " is less than " +
michael@0 1823 expectedAssertions + "\n");
michael@0 1824 } else if (numAsserts > maxAsserts) {
michael@0 1825 ++gTestResults.AssertionUnexpected;
michael@0 1826 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gURLs[0].prettyPath +
michael@0 1827 " | assertion count " + numAsserts + " is more than " +
michael@0 1828 expectedAssertions + "\n");
michael@0 1829 } else if (numAsserts != 0) {
michael@0 1830 ++gTestResults.AssertionKnown;
michael@0 1831 gDumpLog("REFTEST TEST-KNOWN-FAIL | " + gURLs[0].prettyPath +
michael@0 1832 " | assertion count " + numAsserts + " matches " +
michael@0 1833 expectedAssertions + "\n");
michael@0 1834 }
michael@0 1835 }
michael@0 1836
michael@0 1837 gDumpLog("REFTEST TEST-END | " + gURLs[0].prettyPath + "\n");
michael@0 1838
michael@0 1839 // And start the next test.
michael@0 1840 gURLs.shift();
michael@0 1841 StartCurrentTest();
michael@0 1842 }
michael@0 1843
michael@0 1844 function ResetRenderingState()
michael@0 1845 {
michael@0 1846 SendResetRenderingState();
michael@0 1847 // We would want to clear any viewconfig here, if we add support for it
michael@0 1848 }
michael@0 1849
michael@0 1850 function RestoreChangedPreferences()
michael@0 1851 {
michael@0 1852 if (gPrefsToRestore.length > 0) {
michael@0 1853 var prefs = Components.classes["@mozilla.org/preferences-service;1"].
michael@0 1854 getService(Components.interfaces.nsIPrefBranch);
michael@0 1855 gPrefsToRestore.reverse();
michael@0 1856 gPrefsToRestore.forEach(function(ps) {
michael@0 1857 var value = ps.value;
michael@0 1858 if (ps.type == PREF_BOOLEAN) {
michael@0 1859 prefs.setBoolPref(ps.name, value);
michael@0 1860 } else if (ps.type == PREF_STRING) {
michael@0 1861 prefs.setCharPref(ps.name, value);
michael@0 1862 value = '"' + value + '"';
michael@0 1863 } else if (ps.type == PREF_INTEGER) {
michael@0 1864 prefs.setIntPref(ps.name, value);
michael@0 1865 }
michael@0 1866 gDumpLog("RESTORE PREFERENCE pref(" + ps.name + "," + value + ")\n");
michael@0 1867 });
michael@0 1868 gPrefsToRestore = [];
michael@0 1869 }
michael@0 1870 }
michael@0 1871
michael@0 1872 function RegisterMessageListenersAndLoadContentScript()
michael@0 1873 {
michael@0 1874 gBrowserMessageManager.addMessageListener(
michael@0 1875 "reftest:AssertionCount",
michael@0 1876 function (m) { RecvAssertionCount(m.json.count); }
michael@0 1877 );
michael@0 1878 gBrowserMessageManager.addMessageListener(
michael@0 1879 "reftest:ContentReady",
michael@0 1880 function (m) { return RecvContentReady() }
michael@0 1881 );
michael@0 1882 gBrowserMessageManager.addMessageListener(
michael@0 1883 "reftest:Exception",
michael@0 1884 function (m) { RecvException(m.json.what) }
michael@0 1885 );
michael@0 1886 gBrowserMessageManager.addMessageListener(
michael@0 1887 "reftest:FailedLoad",
michael@0 1888 function (m) { RecvFailedLoad(m.json.why); }
michael@0 1889 );
michael@0 1890 gBrowserMessageManager.addMessageListener(
michael@0 1891 "reftest:FailedNoPaint",
michael@0 1892 function (m) { RecvFailedNoPaint(); }
michael@0 1893 );
michael@0 1894 gBrowserMessageManager.addMessageListener(
michael@0 1895 "reftest:InitCanvasWithSnapshot",
michael@0 1896 function (m) { return RecvInitCanvasWithSnapshot(); }
michael@0 1897 );
michael@0 1898 gBrowserMessageManager.addMessageListener(
michael@0 1899 "reftest:Log",
michael@0 1900 function (m) { RecvLog(m.json.type, m.json.msg); }
michael@0 1901 );
michael@0 1902 gBrowserMessageManager.addMessageListener(
michael@0 1903 "reftest:ScriptResults",
michael@0 1904 function (m) { RecvScriptResults(m.json.runtimeMs, m.json.error, m.json.results); }
michael@0 1905 );
michael@0 1906 gBrowserMessageManager.addMessageListener(
michael@0 1907 "reftest:TestDone",
michael@0 1908 function (m) { RecvTestDone(m.json.runtimeMs); }
michael@0 1909 );
michael@0 1910 gBrowserMessageManager.addMessageListener(
michael@0 1911 "reftest:UpdateCanvasForInvalidation",
michael@0 1912 function (m) { RecvUpdateCanvasForInvalidation(m.json.rects); }
michael@0 1913 );
michael@0 1914 gBrowserMessageManager.addMessageListener(
michael@0 1915 "reftest:UpdateWholeCanvasForInvalidation",
michael@0 1916 function (m) { RecvUpdateWholeCanvasForInvalidation(); }
michael@0 1917 );
michael@0 1918 gBrowserMessageManager.addMessageListener(
michael@0 1919 "reftest:ExpectProcessCrash",
michael@0 1920 function (m) { RecvExpectProcessCrash(); }
michael@0 1921 );
michael@0 1922 gBrowserMessageManager.addMessageListener(
michael@0 1923 "reftest:EnableAsyncScroll",
michael@0 1924 function (m) { SetAsyncScroll(true); }
michael@0 1925 );
michael@0 1926
michael@0 1927 gBrowserMessageManager.loadFrameScript("chrome://reftest/content/reftest-content.js", true, true);
michael@0 1928 }
michael@0 1929
michael@0 1930 function SetAsyncScroll(enabled)
michael@0 1931 {
michael@0 1932 gBrowser.QueryInterface(CI.nsIFrameLoaderOwner).frameLoader.renderMode =
michael@0 1933 enabled ? CI.nsIFrameLoader.RENDER_MODE_ASYNC_SCROLL :
michael@0 1934 CI.nsIFrameLoader.RENDER_MODE_DEFAULT;
michael@0 1935 }
michael@0 1936
michael@0 1937 function RecvAssertionCount(count)
michael@0 1938 {
michael@0 1939 DoAssertionCheck(count);
michael@0 1940 }
michael@0 1941
michael@0 1942 function RecvContentReady()
michael@0 1943 {
michael@0 1944 InitAndStartRefTests();
michael@0 1945 return { remote: gBrowserIsRemote };
michael@0 1946 }
michael@0 1947
michael@0 1948 function RecvException(what)
michael@0 1949 {
michael@0 1950 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gCurrentURL + " | " + what + "\n");
michael@0 1951 ++gTestResults.Exception;
michael@0 1952 }
michael@0 1953
michael@0 1954 function RecvFailedLoad(why)
michael@0 1955 {
michael@0 1956 LoadFailed(why);
michael@0 1957 }
michael@0 1958
michael@0 1959 function RecvFailedNoPaint()
michael@0 1960 {
michael@0 1961 gFailedNoPaint = true;
michael@0 1962 }
michael@0 1963
michael@0 1964 function RecvInitCanvasWithSnapshot()
michael@0 1965 {
michael@0 1966 var painted = InitCurrentCanvasWithSnapshot();
michael@0 1967 return { painted: painted };
michael@0 1968 }
michael@0 1969
michael@0 1970 function RecvLog(type, msg)
michael@0 1971 {
michael@0 1972 msg = "[CONTENT] "+ msg;
michael@0 1973 if (type == "info") {
michael@0 1974 LogInfo(msg);
michael@0 1975 } else if (type == "warning") {
michael@0 1976 LogWarning(msg);
michael@0 1977 } else {
michael@0 1978 gDumpLog("REFTEST TEST-UNEXPECTED-FAIL | " + gCurrentURL + " | unknown log type " + type + "\n");
michael@0 1979 ++gTestResults.Exception;
michael@0 1980 }
michael@0 1981 }
michael@0 1982
michael@0 1983 function RecvScriptResults(runtimeMs, error, results)
michael@0 1984 {
michael@0 1985 RecordResult(runtimeMs, error, results);
michael@0 1986 }
michael@0 1987
michael@0 1988 function RecvTestDone(runtimeMs)
michael@0 1989 {
michael@0 1990 RecordResult(runtimeMs, '', [ ]);
michael@0 1991 }
michael@0 1992
michael@0 1993 function RecvUpdateCanvasForInvalidation(rects)
michael@0 1994 {
michael@0 1995 UpdateCurrentCanvasForInvalidation(rects);
michael@0 1996 }
michael@0 1997
michael@0 1998 function RecvUpdateWholeCanvasForInvalidation()
michael@0 1999 {
michael@0 2000 UpdateWholeCurrentCanvasForInvalidation();
michael@0 2001 }
michael@0 2002
michael@0 2003 function OnProcessCrashed(subject, topic, data)
michael@0 2004 {
michael@0 2005 var id;
michael@0 2006 subject = subject.QueryInterface(CI.nsIPropertyBag2);
michael@0 2007 if (topic == "plugin-crashed") {
michael@0 2008 id = subject.getPropertyAsAString("pluginDumpID");
michael@0 2009 } else if (topic == "ipc:content-shutdown") {
michael@0 2010 id = subject.getPropertyAsAString("dumpID");
michael@0 2011 }
michael@0 2012 if (id) {
michael@0 2013 gExpectedCrashDumpFiles.push(id + ".dmp");
michael@0 2014 gExpectedCrashDumpFiles.push(id + ".extra");
michael@0 2015 }
michael@0 2016 }
michael@0 2017
michael@0 2018 function RegisterProcessCrashObservers()
michael@0 2019 {
michael@0 2020 var os = CC[NS_OBSERVER_SERVICE_CONTRACTID]
michael@0 2021 .getService(CI.nsIObserverService);
michael@0 2022 os.addObserver(OnProcessCrashed, "plugin-crashed", false);
michael@0 2023 os.addObserver(OnProcessCrashed, "ipc:content-shutdown", false);
michael@0 2024 }
michael@0 2025
michael@0 2026 function RecvExpectProcessCrash()
michael@0 2027 {
michael@0 2028 gExpectingProcessCrash = true;
michael@0 2029 }
michael@0 2030
michael@0 2031 function SendClear()
michael@0 2032 {
michael@0 2033 gBrowserMessageManager.sendAsyncMessage("reftest:Clear");
michael@0 2034 }
michael@0 2035
michael@0 2036 function SendLoadScriptTest(uri, timeout)
michael@0 2037 {
michael@0 2038 gBrowserMessageManager.sendAsyncMessage("reftest:LoadScriptTest",
michael@0 2039 { uri: uri, timeout: timeout });
michael@0 2040 }
michael@0 2041
michael@0 2042 function SendLoadTest(type, uri, timeout)
michael@0 2043 {
michael@0 2044 gBrowserMessageManager.sendAsyncMessage("reftest:LoadTest",
michael@0 2045 { type: type, uri: uri, timeout: timeout }
michael@0 2046 );
michael@0 2047 }
michael@0 2048
michael@0 2049 function SendResetRenderingState()
michael@0 2050 {
michael@0 2051 gBrowserMessageManager.sendAsyncMessage("reftest:ResetRenderingState");
michael@0 2052 }

mercurial