layout/generic/test/test_bug507902.html

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 <!DOCTYPE HTML>
     2 <html>
     3 <!--
     4 https://bugzilla.mozilla.org/show_bug.cgi?id=507902
     5 -->
     6 <head>
     7   <title>Test for Bug 507902</title>
     8   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
     9   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
    10 </head>
    11 <body>
    12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=507902">Mozilla Bug 507902</a>
    14 <iframe id="testFrameElem"></iframe>
    16 <pre id="test">
    17 <script class="testbody" type="text/javascript">
    19 //
    20 // Mochitest to test nsImageFrame icons
    21 //
    22 // The 'loading' icon should be displayed up until we have enough image
    23 // data to determine the frame size.
    24 //
    25 // The 'broken' icon should be displayed when the URL is invalid (either
    26 // a bad server or a file that fails to be sniffed to an appropriate
    27 // mimetype).
    28 //
    30 // Boilerplate
    31 gWindowUtils = SpecialPowers.getDOMWindowUtils(window);
    33 // URL + paths
    34 //
    35 // We have a separate copy of the icons in the test directory to
    36 // avoid any firefox caching mechanisms that might affect the
    37 // behavior of the load.
    38 var us = window.location.href;
    39 var baseURL = us.substring(0, us.lastIndexOf('/') + 1);
    40 var loadIconFilename = "file_LoadingImageReference.png";
    41 var imageFilename = "file_Dolske.png";
    42 var brokenIconFilename = "file_BrokenImageReference.png";
    43 var serverFilename = "file_IconTestServer.sjs";
    44 var serverContinueFlag = "?continue=true";
    45 var bogusFilename = "oneuponatimewhendolskewasyoung.png";
    47 // Our test image element, inside a div, inside an iframe
    48 var testFrameElem = document.getElementById("testFrameElem");
    49 var innerDoc = testFrameElem.contentWindow.document;
    50 var divContainer = innerDoc.createElement("div");
    51 divContainer.style.cssFloat = "left";
    52 innerDoc.body.appendChild(divContainer);
    53 var testImageElem = new Image();
    54 divContainer.appendChild(testImageElem);
    55 var pingImage = new Image();
    57 // Set up the canvases
    58 var canvases = {};
    59 var canvasNames = [ "brokenIconTest",  "brokenIconReference",
    60                     "loadingIconTest", "loadingIconReference",
    61                     "loadedTest",      "loadedReference" ];
    62 var windowElem = document.documentElement;
    63 for (var i in canvasNames) {
    64   var can = document.createElement("canvas");
    65   can.setAttribute("width", windowElem.getAttribute("width"));
    66   can.setAttribute("height", windowElem.getAttribute("height"));
    67   canvases[canvasNames[i]] = can;
    69   // When the image frame has no idea how to size itself, it sizes itself
    70   // to dimensions capable of displaying the alt feedback icons. However, if
    71   // the image has been loaded before, something (I don't know what) seems to
    72   // remember the size of the last successful image for that URL. So when we
    73   // create a new image frame for that URL, it uses that size until it hears
    74   // something different. This happens through a refresh (not sure if this is
    75   // desired behavior). This means that if you refresh the test, the "loading"
    76   // icon for the test image will appear with a border that stretches further
    77   // right and down, because that URL previously displayed an image with larger
    78   // dimensions. This causes the verify stage to fail. To allow for
    79   // successful test refreshes (only useful for people, not automated tests),
    80   // we add a clipping region so that we see the left and top borders, along
    81   // with the image, but not the bottom and right borders.
    83   if ((i > 1) && (i < 4)) {
    84     var ctx = can.getContext("2d");
    85     ctx.beginPath();
    86     ctx.rect(0,0, 30, 30);
    87     ctx.clip();
    88    }
    90 }
    92 // Stage 1 - Load the reference image for the broken icon
    93 function loadBrokenIconReference() {
    95   // Debugging - Let's see if setting onload after src is a problem
    96   testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 1 called\n");};
    98   // Debug - Figure out if we're getting an onerror instead of onload
    99   testImageElem.onerror = function(event) {dump("test_bug507902.html DEBUG - Got onerror for testImageElem!\n");};
   101   testImageElem.src = baseURL + brokenIconFilename;
   102   stageTransition();
   103 }
   105 // Stage 2 - Draw the reference image for the broken icon to a canvas
   106 function drawBrokenIconReference() {
   108   enableBorderAndPad();
   109   drawWindowToCanvas("brokenIconReference");
   110   disableBorderAndPad();
   112   stageTransition();
   113 }
   115 // Stage 3 - Load the reference image for the loading icon
   116 function loadLoadingIconReference() {
   118   // Debugging - Let's see if setting onload after src is a problem
   119   testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 3 called\n");};
   121   testImageElem.src = baseURL + loadIconFilename;
   122   stageTransition();
   123 }
   125 // Stage 4 - Draw the reference image for the loading icon to a canvas
   126 function drawLoadingIconReference() {
   128   enableBorderAndPad();
   129   drawWindowToCanvas("loadingIconReference");
   130   disableBorderAndPad();
   132   stageTransition();
   133 }
   135 // Stage 5 - Try to load a broken image
   136 function loadBrokenImage() {
   137   resetImage();
   138   testImageElem.src = baseURL + bogusFilename;
   139   stageTransition();
   140 }
   142 // Stage 6 - Draw the screen to a canvas. This should hopefully
   143 // be the broken icon.
   144 function drawBrokenIcon() {
   145   drawWindowToCanvas("brokenIconTest");
   146   stageTransition();
   147 }
   149 // Stage 7 - Load the reference image for the test image
   150 function loadImageReference() {
   151   resetImage();
   153   // Debugging - Let's see if setting onload after src is a problem
   154   testImageElem.onload = function(event) { dump("test_bug507902.html DEBUG - uh oh, placeholder onload 7 called\n");};
   156   testImageElem.src = baseURL + imageFilename;
   157   stageTransition();
   158 }
   160 // Stage 8 - Draw the reference image for the test image to a canvas
   161 function drawImageReference() {
   162   drawWindowToCanvas("loadedReference");
   163   stageTransition();
   164 }
   166 // Stage 9 - Start a load of the test image from the delay-generating server
   167 function startServerLoad() {
   169   // Reset the image
   170   resetImage();
   172   // Debugging info so we can figure out the hang
   173   dump("test_bug507902.html DEBUG - starting server load\n");
   175   // Load the image
   176   testImageElem.src = baseURL + serverFilename;
   177   stageTransition();
   178 }
   180 // Stage 10 - Draw the screen to a canvas. This should hopefully be the loading
   181 // icon.
   182 function drawLoadingIcon() {
   184   // Debugging info so we can figure out the hang
   185   dump("test_bug507902.html DEBUG - drawing loading icon\n");
   187   drawWindowToCanvas("loadingIconTest");
   188   stageTransition();
   189 }
   191 // Stage 11 - Tell the server to continue.
   192 function signalServerContinue() {
   194   // Debugging info so we can figure out the hang
   195   dump("test_bug507902.html DEBUG - signaling server to continue\n");
   197   pingImage.src = baseURL + serverFilename + serverContinueFlag;
   198   stageTransition();
   199 }
   201 // Stage 12 - Draw the screen to a canvas. This should hopefully be the loaded
   202 // test image.
   203 function drawLoadedImage() {
   204   drawWindowToCanvas("loadedTest");
   205   stageTransition();
   206 }
   209 // Stage 13 - Verify That the appropriate canvases match
   210 function verifyCanvases() {
   212   // Verify the broken icon
   213   ok(canvasesAreEqual("brokenIconTest", "brokenIconReference"),
   214      "Window drawn on broken load should match broken icon reference");
   216   // Verify the loading icon
   217   ok(canvasesAreEqual("loadingIconTest", "loadingIconReference"),
   218      "Window drawn mid-load should match loading icon reference");
   220   // Verify the loaded image
   221   ok(canvasesAreEqual("loadedTest", "loadedReference"),
   222      "Window drawn post-load should match reference image");
   224   stageTransition();
   225 }
   227 // We have a bunch of different things that need to happen in order
   228 // with different transitions. We make a "stage table" here where
   229 // each entry contains the stage function ('fn') and a transition
   230 // ('trans'), which can be one of the following:
   231 // "instant" - Just calls the next stage directly
   232 // "onload" - Sets the next stage as an onload event for the image element
   233 // "onerror" - Sets the next stage as an onerror event for the image element
   234 // integer  - Sets the next stage to be called after the given timeout duration
   235 // "finish" - Finish the test
   236 var testStages = [
   237   { "fn" : loadBrokenIconReference,  "trans" : "onload"},
   238   { "fn" : drawBrokenIconReference,  "trans" : "instant"},
   239   { "fn" : loadLoadingIconReference, "trans" : "onload" },
   240   { "fn" : drawLoadingIconReference, "trans" : "instant" },
   241   { "fn" : loadBrokenImage,          "trans" : "onerror" },
   242   { "fn" : drawBrokenIcon,           "trans" : "instant" },
   243   { "fn" : loadImageReference,       "trans" : "onload" },
   244   { "fn" : drawImageReference,       "trans" : "instant" },
   245   // XXXbholley - We use a timeout here because resetting the
   246   // image doesn't seem to be quite synchronous. If we make
   247   // this transition "instant", then the drawImage call draws
   248   // an empty (0,0,0,0) rect to the canvas and we're left with
   249   // whatever was there before. I don't know of any good event
   250   // mechanism to figure out when the image frame is bootstrapped
   251   // enough to display the loading image, so I did trial-and-error
   252   // with timeouts. 50ms seems to be enough time for things to work
   253   // reliably, so *= 6 for good measure.
   254   { "fn" : startServerLoad,          "trans" : 300 },
   255   { "fn" : drawLoadingIcon,          "trans" : "instant" },
   256   { "fn" : signalServerContinue,     "trans" : "onload" },
   257   { "fn" : drawLoadedImage,          "trans" : "instant" },
   258   { "fn" : verifyCanvases,           "trans" : "finish" } ];
   259 var currentStage = 0;
   261 // Transition function called at the end of each stage
   262 function stageTransition() {
   264   // Debugging info so we can figure out the hang
   265   dump("test_bug507902.html DEBUG - Current Stage: " + currentStage + "\n");
   267   // What's our transition?
   268   var trans = testStages[currentStage++].trans;
   270   // If the transition is finish, stop now before we access out of bounds
   271   if (trans == "finish") {
   272     makeCanvasesVisible(); // Useful for debugging
   273     SimpleTest.finish();
   274     return;
   275   }
   277   // Otherwise, get the next function
   278   var nextfn = testStages[currentStage].fn;
   280   // Switch based on transition
   281   switch (trans) {
   283     // Continue right away
   284     case "instant":
   285       nextfn();
   286       break;
   288     // Continue after we get an onload event on the test image
   289     case "onload":
   290       testImageElem.onload = function(event) {testImageElem.onload = undefined; nextfn();};
   291       break;
   293     // Continue after we get an onerror event on the test image
   294     case "onerror":
   295       testImageElem.onerror = function(event) {testImageElem.onerror = undefined; nextfn();};
   296       break;
   298     // Timeout
   299     default:
   300       setTimeout(nextfn, trans);
   301       break
   302   }
   303 }
   305 // Lots if asynchronous behavior here
   306 SimpleTest.waitForExplicitFinish();
   308 // Catch somebody's eye
   309 dump("This test is failing intermittently, see bug 510001 - If you see orange here, please paste the following debugging output on the bug!\n");
   311 // Kick off the test by invoking the first stage. The stages call each other
   312 testStages[0].fn();
   315 // We need to get rid of the old image element and make a new one. If we
   316 // don't, the "current/pending" machinery will display the old image until
   317 // the new one is loaded, so we won't see the loading icon.
   318 function resetImage() {
   319   divContainer.removeChild(testImageElem);
   320   testImageElem = null;
   321   testImageElem = new Image();
   322   divContainer.appendChild(testImageElem);
   323 }
   325 //
   326 // Makes the canvases visible. Called before the tests finish. This is useful for
   327 // debugging.
   328 //
   329 function makeCanvasesVisible() {
   330   for (var i = 0; i < canvasNames.length - 1; i += 2) {
   331     var title = document.createElement("h3");
   332     title.innerHTML = canvasNames[i] + ", " + canvasNames[i+1] + ":";
   333     document.body.appendChild(title);
   334     var myDiv = document.createElement("div");
   335     myDiv.appendChild(canvases[canvasNames[i]]);
   336     myDiv.appendChild(canvases[canvasNames[i+1]]);
   337     document.body.appendChild(myDiv);
   338   }
   339 }
   341 //
   342 // Enables and disables bordering/padding to mimic the look of alt feedback icons
   343 //
   344 function enableBorderAndPad() {
   345   divContainer.style.border = "1px";
   346   divContainer.style.borderStyle = "inset";
   347   testImageElem.style.padding = "3px";
   348 }
   350 function disableBorderAndPad() {
   351   testImageElem.style.padding = 0;
   352   divContainer.style.border = "0px";
   353   divContainer.style.borderStyle = "";
   354 }
   356 //
   357 // Helper canvas methods. This is mostly copped directly from the reftest framework
   358 //
   360 function drawWindowToCanvas(canvasName) {
   361   var win = testFrameElem.contentWindow;
   362   var ctx = canvases[canvasName].getContext("2d");
   363   // drawWindow always draws one canvas pixel for each CSS pixel in the source
   364   // window, so scale the drawing to show the zoom (making each canvas pixel be one
   365   // device pixel instead)
   366   ctx.drawWindow(win, win.scrollX, win.scrollY,
   367                  Math.ceil(canvases[canvasName].width),
   368                  Math.ceil(canvases[canvasName].height),
   369                  "rgb(255,255,255)");
   370 }
   372 function canvasesAreEqual(canvas1Name, canvas2Name) {
   373   var c1 = canvases[canvas1Name];
   374   var c2 = canvases[canvas2Name];
   375   var differences = gWindowUtils.compareCanvases(c1, c2, {});
   376   return (differences == 0);
   377 }
   379 </script>
   380 </pre>
   381 </body>
   382 </html>

mercurial