image/test/mochitest/animationPolling.js

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 var currentTest;
michael@0 3 var gIsRefImageLoaded = false;
michael@0 4 const gShouldOutputDebugInfo = false;
michael@0 5
michael@0 6 function pollForSuccess()
michael@0 7 {
michael@0 8 if (!currentTest.isTestFinished) {
michael@0 9 if (!currentTest.reusingReferenceImage || (currentTest.reusingReferenceImage
michael@0 10 && gRefImageLoaded)) {
michael@0 11 currentTest.checkImage();
michael@0 12 }
michael@0 13
michael@0 14 setTimeout(pollForSuccess, currentTest.pollFreq);
michael@0 15 }
michael@0 16 };
michael@0 17
michael@0 18 function referencePoller()
michael@0 19 {
michael@0 20 currentTest.takeReferenceSnapshot();
michael@0 21 }
michael@0 22
michael@0 23 function reuseImageCallback()
michael@0 24 {
michael@0 25 gIsRefImageLoaded = true;
michael@0 26 }
michael@0 27
michael@0 28 function failTest()
michael@0 29 {
michael@0 30 if (currentTest.isTestFinished || currentTest.closeFunc) {
michael@0 31 return;
michael@0 32 }
michael@0 33
michael@0 34 ok(false, "timing out after " + currentTest.timeout + "ms. "
michael@0 35 + "Animated image still doesn't look correct, after poll #"
michael@0 36 + currentTest.pollCounter);
michael@0 37 currentTest.wereFailures = true;
michael@0 38
michael@0 39 if (currentTest.currentSnapshotDataURI) {
michael@0 40 currentTest.outputDebugInfo("Snapshot #" + currentTest.pollCounter,
michael@0 41 "snapNum" + currentTest.pollCounter,
michael@0 42 currentTest.currentSnapshotDataURI);
michael@0 43 }
michael@0 44
michael@0 45 currentTest.enableDisplay(document.getElementById(currentTest.debugElementId));
michael@0 46
michael@0 47 currentTest.cleanUpAndFinish();
michael@0 48 };
michael@0 49
michael@0 50 /**
michael@0 51 * Create a new AnimationTest object.
michael@0 52 *
michael@0 53 * @param pollFreq The amount of time (in ms) to wait between consecutive
michael@0 54 * snapshots if the reference image and the test image don't match.
michael@0 55 * @param timeout The total amount of time (in ms) to wait before declaring the
michael@0 56 * test as failed.
michael@0 57 * @param referenceElementId The id attribute of the reference image element, or
michael@0 58 * the source of the image to change to, once the reference snapshot has
michael@0 59 * been successfully taken. This latter option could be used if you don't
michael@0 60 * want the image to become invisible at any time during the test.
michael@0 61 * @param imageElementId The id attribute of the test image element.
michael@0 62 * @param debugElementId The id attribute of the div where links should be
michael@0 63 * appended if the test fails.
michael@0 64 * @param cleanId The id attribute of the div or element to use as the 'clean'
michael@0 65 * test. This element is only enabled when we are testing to verify that
michael@0 66 * the reference image has been loaded. It can be undefined.
michael@0 67 * @param srcAttr The location of the source of the image, for preloading. This
michael@0 68 * is usually not required, but it useful for preloading reference
michael@0 69 * images.
michael@0 70 * @param xulTest A boolean value indicating whether or not this is a XUL test
michael@0 71 * (uses hidden=true/false rather than display: none to hide/show
michael@0 72 * elements).
michael@0 73 * @param closeFunc A function that should be called when this test is finished.
michael@0 74 * If null, then cleanUpAndFinish() will be called. This can be used to
michael@0 75 * chain tests together, so they are all finished exactly once.
michael@0 76 * @returns {AnimationTest}
michael@0 77 */
michael@0 78 function AnimationTest(pollFreq, timeout, referenceElementId, imageElementId,
michael@0 79 debugElementId, cleanId, srcAttr, xulTest, closeFunc)
michael@0 80 {
michael@0 81 // We want to test the cold loading behavior, so clear cache in case an
michael@0 82 // earlier test got our image in there already.
michael@0 83 clearImageCache();
michael@0 84
michael@0 85 this.wereFailures = false;
michael@0 86 this.pollFreq = pollFreq;
michael@0 87 this.timeout = timeout;
michael@0 88 this.imageElementId = imageElementId;
michael@0 89 this.referenceElementId = referenceElementId;
michael@0 90
michael@0 91 if (!document.getElementById(referenceElementId)) {
michael@0 92 // In this case, we're assuming the user passed in a string that
michael@0 93 // indicates the source of the image they want to change to,
michael@0 94 // after the reference image has been taken.
michael@0 95 this.reusingImageAsReference = true;
michael@0 96 }
michael@0 97
michael@0 98 this.srcAttr = srcAttr;
michael@0 99 this.debugElementId = debugElementId;
michael@0 100 this.referenceSnapshot = ""; // value will be set in takeReferenceSnapshot()
michael@0 101 this.pollCounter = 0;
michael@0 102 this.isTestFinished = false;
michael@0 103 this.numRefsTaken = 0;
michael@0 104 this.blankWaitTime = 0;
michael@0 105
michael@0 106 this.cleanId = cleanId ? cleanId : '';
michael@0 107 this.xulTest = xulTest ? xulTest : '';
michael@0 108 this.closeFunc = closeFunc ? closeFunc : '';
michael@0 109 };
michael@0 110
michael@0 111 AnimationTest.prototype.preloadImage = function()
michael@0 112 {
michael@0 113 if (this.srcAttr) {
michael@0 114 this.myImage = new Image();
michael@0 115 this.myImage.onload = function() { currentTest.continueTest(); };
michael@0 116 this.myImage.src = this.srcAttr;
michael@0 117 } else {
michael@0 118 this.continueTest();
michael@0 119 }
michael@0 120 };
michael@0 121
michael@0 122 AnimationTest.prototype.outputDebugInfo = function(message, id, dataUri)
michael@0 123 {
michael@0 124 if (!gShouldOutputDebugInfo) {
michael@0 125 return;
michael@0 126 }
michael@0 127 var debugElement = document.getElementById(this.debugElementId);
michael@0 128 var newDataUriElement = document.createElement("a");
michael@0 129 newDataUriElement.setAttribute("id", id);
michael@0 130 newDataUriElement.setAttribute("href", dataUri);
michael@0 131 newDataUriElement.appendChild(document.createTextNode(message));
michael@0 132 debugElement.appendChild(newDataUriElement);
michael@0 133 var brElement = document.createElement("br");
michael@0 134 debugElement.appendChild(brElement);
michael@0 135 todo(false, "Debug (" + id + "): " + message + " " + dataUri);
michael@0 136 };
michael@0 137
michael@0 138 AnimationTest.prototype.isFinished = function()
michael@0 139 {
michael@0 140 return this.isTestFinished;
michael@0 141 };
michael@0 142
michael@0 143 AnimationTest.prototype.takeCleanSnapshot = function()
michael@0 144 {
michael@0 145 var cleanElement;
michael@0 146 if (this.cleanId) {
michael@0 147 cleanElement = document.getElementById(this.cleanId);
michael@0 148 }
michael@0 149
michael@0 150 // Enable clean page comparison element
michael@0 151 if (cleanElement) {
michael@0 152 this.enableDisplay(cleanElement);
michael@0 153 }
michael@0 154
michael@0 155 // Take a snapshot of the initial (clean) page
michael@0 156 this.cleanSnapshot = snapshotWindow(window, false);
michael@0 157
michael@0 158 // Disable the clean page comparison element
michael@0 159 if (cleanElement) {
michael@0 160 this.disableDisplay(cleanElement);
michael@0 161 }
michael@0 162
michael@0 163 var dataString1 = "Clean Snapshot";
michael@0 164 this.outputDebugInfo(dataString1, 'cleanSnap',
michael@0 165 this.cleanSnapshot.toDataURL());
michael@0 166 };
michael@0 167
michael@0 168 AnimationTest.prototype.takeBlankSnapshot = function()
michael@0 169 {
michael@0 170 // Take a snapshot of the initial (essentially blank) page
michael@0 171 this.blankSnapshot = snapshotWindow(window, false);
michael@0 172
michael@0 173 var dataString1 = "Initial Blank Snapshot";
michael@0 174 this.outputDebugInfo(dataString1, 'blank1Snap',
michael@0 175 this.blankSnapshot.toDataURL());
michael@0 176 };
michael@0 177
michael@0 178 /**
michael@0 179 * Begin the AnimationTest. This will utilize the information provided in the
michael@0 180 * constructor to invoke a mochitest on animated images. It will automatically
michael@0 181 * fail if allowed to run past the timeout. This will attempt to preload an
michael@0 182 * image, if applicable, and then asynchronously call continueTest(), or if not
michael@0 183 * applicable, synchronously trigger a call to continueTest().
michael@0 184 */
michael@0 185 AnimationTest.prototype.beginTest = function()
michael@0 186 {
michael@0 187 SimpleTest.waitForExplicitFinish();
michael@0 188
michael@0 189 currentTest = this;
michael@0 190 this.preloadImage();
michael@0 191 };
michael@0 192
michael@0 193 /**
michael@0 194 * This is the second part of the test. It is triggered (eventually) from
michael@0 195 * beginTest() either synchronously or asynchronously, as an image load
michael@0 196 * callback.
michael@0 197 */
michael@0 198 AnimationTest.prototype.continueTest = function()
michael@0 199 {
michael@0 200 // In case something goes wrong, fail earlier than mochitest timeout,
michael@0 201 // and with more information.
michael@0 202 setTimeout(failTest, this.timeout);
michael@0 203
michael@0 204 if (!this.reusingImageAsReference) {
michael@0 205 this.disableDisplay(document.getElementById(this.imageElementId));
michael@0 206 }
michael@0 207
michael@0 208 this.takeReferenceSnapshot();
michael@0 209 this.setupPolledImage();
michael@0 210 SimpleTest.executeSoon(pollForSuccess);
michael@0 211 };
michael@0 212
michael@0 213 AnimationTest.prototype.setupPolledImage = function ()
michael@0 214 {
michael@0 215 // Make sure the image is visible
michael@0 216 if (!this.reusingImageAsReference) {
michael@0 217 this.enableDisplay(document.getElementById(this.imageElementId));
michael@0 218 var currentSnapshot = snapshotWindow(window, false);
michael@0 219 var result = compareSnapshots(currentSnapshot,
michael@0 220 this.referenceSnapshot, true);
michael@0 221
michael@0 222 this.currentSnapshotDataURI = currentSnapshot.toDataURL();
michael@0 223
michael@0 224 if (result[0]) {
michael@0 225 // SUCCESS!
michael@0 226 ok(true, "Animated image looks correct, at poll #"
michael@0 227 + this.pollCounter);
michael@0 228
michael@0 229 this.cleanUpAndFinish();
michael@0 230 }
michael@0 231 } else {
michael@0 232 if (!gIsRefImageLoaded) {
michael@0 233 this.myImage = new Image();
michael@0 234 this.myImage.onload = reuseImageCallback;
michael@0 235 document.getElementById(this.imageElementId).setAttribute('src',
michael@0 236 this.referenceElementId);
michael@0 237 }
michael@0 238 }
michael@0 239 }
michael@0 240
michael@0 241 AnimationTest.prototype.checkImage = function ()
michael@0 242 {
michael@0 243 if (this.isTestFinished) {
michael@0 244 return;
michael@0 245 }
michael@0 246
michael@0 247 this.pollCounter++;
michael@0 248
michael@0 249 // We need this for some tests, because we need to force the
michael@0 250 // test image to be visible.
michael@0 251 if (!this.reusingImageAsReference) {
michael@0 252 this.enableDisplay(document.getElementById(this.imageElementId));
michael@0 253 }
michael@0 254
michael@0 255 var currentSnapshot = snapshotWindow(window, false);
michael@0 256 var result = compareSnapshots(currentSnapshot, this.referenceSnapshot, true);
michael@0 257
michael@0 258 this.currentSnapshotDataURI = currentSnapshot.toDataURL();
michael@0 259
michael@0 260 if (result[0]) {
michael@0 261 // SUCCESS!
michael@0 262 ok(true, "Animated image looks correct, at poll #"
michael@0 263 + this.pollCounter);
michael@0 264
michael@0 265 this.cleanUpAndFinish();
michael@0 266 }
michael@0 267 };
michael@0 268
michael@0 269 AnimationTest.prototype.takeReferenceSnapshot = function ()
michael@0 270 {
michael@0 271 this.numRefsTaken++;
michael@0 272
michael@0 273 // Test to make sure the reference image doesn't match a clean snapshot
michael@0 274 if (!this.cleanSnapshot) {
michael@0 275 this.takeCleanSnapshot();
michael@0 276 }
michael@0 277
michael@0 278 // Used later to verify that the reference div disappeared
michael@0 279 if (!this.blankSnapshot) {
michael@0 280 this.takeBlankSnapshot();
michael@0 281 }
michael@0 282
michael@0 283 if (this.reusingImageAsReference) {
michael@0 284 // Show reference elem (which is actually our image), & take a snapshot
michael@0 285 var referenceElem = document.getElementById(this.imageElementId);
michael@0 286 this.enableDisplay(referenceElem);
michael@0 287
michael@0 288 this.referenceSnapshot = snapshotWindow(window, false);
michael@0 289
michael@0 290 var snapResult = compareSnapshots(this.cleanSnapshot,
michael@0 291 this.referenceSnapshot, false);
michael@0 292 if (!snapResult[0]) {
michael@0 293 if (this.blankWaitTime > 2000) {
michael@0 294 // if it took longer than two seconds to load the image, we probably
michael@0 295 // have a problem.
michael@0 296 this.wereFailures = true;
michael@0 297 ok(snapResult[0],
michael@0 298 "Reference snapshot shouldn't match clean (non-image) snapshot");
michael@0 299 } else {
michael@0 300 this.blankWaitTime += currentTest.pollFreq;
michael@0 301 // let's wait a bit and see if it clears up
michael@0 302 setTimeout(referencePoller, currentTest.pollFreq);
michael@0 303 return;
michael@0 304 }
michael@0 305 }
michael@0 306
michael@0 307 ok(snapResult[0],
michael@0 308 "Reference snapshot shouldn't match clean (non-image) snapshot");
michael@0 309
michael@0 310 var dataString = "Reference Snapshot #" + this.numRefsTaken;
michael@0 311 this.outputDebugInfo(dataString, 'refSnapId',
michael@0 312 this.referenceSnapshot.toDataURL());
michael@0 313 } else {
michael@0 314 // Make sure the animation section is hidden
michael@0 315 this.disableDisplay(document.getElementById(this.imageElementId));
michael@0 316
michael@0 317 // Show reference div, & take a snapshot
michael@0 318 var referenceDiv = document.getElementById(this.referenceElementId);
michael@0 319 this.enableDisplay(referenceDiv);
michael@0 320
michael@0 321 this.referenceSnapshot = snapshotWindow(window, false);
michael@0 322 var snapResult = compareSnapshots(this.cleanSnapshot,
michael@0 323 this.referenceSnapshot, false);
michael@0 324 if (!snapResult[0]) {
michael@0 325 if (this.blankWaitTime > 2000) {
michael@0 326 // if it took longer than two seconds to load the image, we probably
michael@0 327 // have a problem.
michael@0 328 this.wereFailures = true;
michael@0 329 ok(snapResult[0],
michael@0 330 "Reference snapshot shouldn't match clean (non-image) snapshot");
michael@0 331 } else {
michael@0 332 this.blankWaitTime += 20;
michael@0 333 // let's wait a bit and see if it clears up
michael@0 334 setTimeout(referencePoller, 20);
michael@0 335 return;
michael@0 336 }
michael@0 337 }
michael@0 338
michael@0 339 ok(snapResult[0],
michael@0 340 "Reference snapshot shouldn't match clean (non-image) snapshot");
michael@0 341
michael@0 342 var dataString = "Reference Snapshot #" + this.numRefsTaken;
michael@0 343 this.outputDebugInfo(dataString, 'refSnapId',
michael@0 344 this.referenceSnapshot.toDataURL());
michael@0 345
michael@0 346 // Re-hide reference div, and take another snapshot to be sure it's gone
michael@0 347 this.disableDisplay(referenceDiv);
michael@0 348 this.testBlankCameBack();
michael@0 349 }
michael@0 350 };
michael@0 351
michael@0 352 AnimationTest.prototype.enableDisplay = function(element)
michael@0 353 {
michael@0 354 if (!element) {
michael@0 355 return;
michael@0 356 }
michael@0 357
michael@0 358 if (!this.xulTest) {
michael@0 359 element.style.display = '';
michael@0 360 } else {
michael@0 361 element.setAttribute('hidden', 'false');
michael@0 362 }
michael@0 363 };
michael@0 364
michael@0 365 AnimationTest.prototype.disableDisplay = function(element)
michael@0 366 {
michael@0 367 if (!element) {
michael@0 368 return;
michael@0 369 }
michael@0 370
michael@0 371 if (!this.xulTest) {
michael@0 372 element.style.display = 'none';
michael@0 373 } else {
michael@0 374 element.setAttribute('hidden', 'true');
michael@0 375 }
michael@0 376 };
michael@0 377
michael@0 378 AnimationTest.prototype.testBlankCameBack = function()
michael@0 379 {
michael@0 380 var blankSnapshot2 = snapshotWindow(window, false);
michael@0 381 var result = compareSnapshots(this.blankSnapshot, blankSnapshot2, true);
michael@0 382 ok(result[0], "Reference image should disappear when it becomes display:none");
michael@0 383
michael@0 384 if (!result[0]) {
michael@0 385 this.wereFailures = true;
michael@0 386 var dataString = "Second Blank Snapshot";
michael@0 387 this.outputDebugInfo(dataString, 'blank2SnapId', result[2]);
michael@0 388 }
michael@0 389 };
michael@0 390
michael@0 391 AnimationTest.prototype.cleanUpAndFinish = function ()
michael@0 392 {
michael@0 393 // On the off chance that failTest and checkImage are triggered
michael@0 394 // back-to-back, use a flag to prevent multiple calls to SimpleTest.finish.
michael@0 395 if (this.isTestFinished) {
michael@0 396 return;
michael@0 397 }
michael@0 398
michael@0 399 this.isTestFinished = true;
michael@0 400
michael@0 401 // Call our closing function, if one exists
michael@0 402 if (this.closeFunc) {
michael@0 403 this.closeFunc();
michael@0 404 return;
michael@0 405 }
michael@0 406
michael@0 407 if (this.wereFailures) {
michael@0 408 document.getElementById(this.debugElementId).style.display = 'block';
michael@0 409 }
michael@0 410
michael@0 411 SimpleTest.finish();
michael@0 412 document.getElementById(this.debugElementId).style.display = "";
michael@0 413 };

mercurial