Bug 1062821 - fix browser_parsable_css.js to actually catch errors, r=florian
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 17 Sep 2015 14:17:43 +0100
changeset 295594 7dc9037bae6b68f77c58430c6e078cf332fb3caa
parent 295593 cd8101de67b6df0f9332cf5b15b2ff9bca0a77d0
child 295595 c4fc1b25416c12d215f9a530c41cf87923575d95
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersflorian
bugs1062821
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1062821 - fix browser_parsable_css.js to actually catch errors, r=florian
browser/base/content/test/general/browser_parsable_css.js
browser/base/content/test/general/parsingTestHelpers.jsm
browser/themes/shared/devtools/floating-scrollbars-light.css
--- a/browser/base/content/test/general/browser_parsable_css.js
+++ b/browser/base/content/test/general/browser_parsable_css.js
@@ -5,30 +5,35 @@
  * detect newly occurring issues in shipping CSS. It is a list of objects
  * specifying conditions under which an error should be ignored.
  *
  * Every property of the objects in it needs to consist of a regular expression
  * matching the offending error. If an object has multiple regex criteria, they
  * ALL need to match an error in order for that error not to cause a test
  * failure. */
 const kWhitelist = [
-  // Cleopatra is imported as-is, see bug 1004421.
-  {sourceName: /cleopatra.*(tree|ui)\.css/i},
   // CodeMirror is imported as-is, see bug 1004423.
   {sourceName: /codemirror\.css/i},
   // PDFjs is futureproofing its pseudoselectors, and those rules are dropped.
   {sourceName: /web\/viewer\.css/i,
    errorMessage: /Unknown pseudo-class.*(fullscreen|selection)/i},
   // Tracked in bug 1004428.
   {sourceName: /aboutaccounts\/(main|normalize)\.css/i},
   // TokBox SDK assets, see bug 1032469.
   {sourceName: /loop\/.*sdk-content\/.*\.css$/i},
   // Loop standalone client CSS uses placeholder cross browser pseudo-element
   {sourceName: /loop\/.*\.css/i,
    errorMessage: /Unknown pseudo-class.*placeholder/i},
+  // Loop issues that crept in since this test was broken, see bug ...
+  {sourceName: /loop\/.*shared\/css\/conversation.css/i,
+   errorMessage: /Error in parsing value for 'display'/i},
+  {sourceName: /loop\/.*shared\/css\/common.css/i,
+   errorMessage: /Unknown property 'user-select'/i},
+  {sourceName: /loop\/.*css\/panel.css/i,
+   errorMessage: /Expected color but found 'none'/i},
   // Highlighter CSS uses chrome-only pseudo-class, see bug 985597.
   {sourceName: /highlighter\.css/i,
    errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i},
 ];
 
 var moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
 var {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
 
@@ -60,16 +65,31 @@ function once(target, name) {
     let cb = () => {
       target.removeEventListener(name, cb);
       resolve();
     };
     target.addEventListener(name, cb);
   });
 }
 
+function messageIsCSSError(msg, innerWindowID, outerWindowID) {
+  // Only care about CSS errors generated by our iframe:
+  if ((msg instanceof Ci.nsIScriptError) &&
+      msg.category.includes("CSS") &&
+      msg.innerWindowID === innerWindowID && msg.outerWindowID === outerWindowID) {
+    // Check if this error is whitelisted in kWhitelist
+    if (!ignoredError(msg)) {
+      ok(false, "Got error message for " + msg.sourceName + ": " + msg.errorMessage);
+      return true;
+    }
+    info("Ignored error for " + msg.sourceName + " because of filter.");
+  }
+  return false;
+}
+
 add_task(function checkAllTheCSS() {
   let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
   // This asynchronously produces a list of URLs (sadly, mostly sync on our
   // test infrastructure because it runs against jarfiles there, and
   // our zipreader APIs are all sync)
   let uris = yield generateURIsFromDirTree(appDir, ".css");
 
   // Create a clean iframe to load all the files into. This needs to live at a
@@ -81,69 +101,54 @@ add_task(function checkAllTheCSS() {
   let testFile = resHandler.resolveURI(resURI);
   let windowless = Services.appShell.createWindowlessBrowser();
   let iframe = windowless.document.createElementNS("http://www.w3.org/1999/xhtml", "html:iframe");
   windowless.document.documentElement.appendChild(iframe);
   let iframeLoaded = once(iframe, 'load');
   iframe.contentWindow.location = testFile;
   yield iframeLoaded;
   let doc = iframe.contentWindow.document;
-
-  // Listen for errors caused by the CSS:
-  let errorListener = {
-    observe: function(aMessage) {
-      if (!aMessage || !(aMessage instanceof Ci.nsIScriptError)) {
-        return;
-      }
-      // Only care about CSS errors generated by our iframe:
-      if (aMessage.category.includes("CSS") && aMessage.innerWindowID === 0 && aMessage.outerWindowID === 0) {
-        // Check if this error is whitelisted in kWhitelist
-        if (!ignoredError(aMessage)) {
-          ok(false, "Got error message for " + aMessage.sourceName + ": " + aMessage.errorMessage);
-          errors++;
-        } else {
-          info("Ignored error for " + aMessage.sourceName + " because of filter.");
-        }
-      }
-    }
-  };
+  let windowUtils = iframe.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                                        .getInterface(Ci.nsIDOMWindowUtils);
+  let innerWindowID = windowUtils.currentInnerWindowID;
+  let outerWindowID = windowUtils.outerWindowID;
 
   // We build a list of promises that get resolved when their respective
   // files have loaded and produced no errors.
   let allPromises = [];
-  let errors = 0;
-  // Register the error listener to keep track of errors.
-  Services.console.registerListener(errorListener);
   for (let uri of uris) {
     let linkEl = doc.createElement("link");
     linkEl.setAttribute("rel", "stylesheet");
     let promiseForThisSpec = Promise.defer();
     let onLoad = (e) => {
       promiseForThisSpec.resolve();
       linkEl.removeEventListener("load", onLoad);
       linkEl.removeEventListener("error", onError);
     };
     let onError = (e) => {
-      promiseForThisSpec.reject({error: e, href: linkEl.getAttribute("href")});
+      ok(false, "Loading " + linkEl.getAttribute("href") + " threw an error!");
+      promiseForThisSpec.resolve();
       linkEl.removeEventListener("load", onLoad);
       linkEl.removeEventListener("error", onError);
     };
     linkEl.addEventListener("load", onLoad);
     linkEl.addEventListener("error", onError);
     linkEl.setAttribute("type", "text/css");
     linkEl.setAttribute("href", uri.spec);
     allPromises.push(promiseForThisSpec.promise);
     doc.head.appendChild(linkEl);
   }
 
   // Wait for all the files to have actually loaded:
   yield Promise.all(allPromises);
+
+  let messages = Services.console.getMessageArray();
   // Count errors (the test output will list actual issues for us, as well
-  // as the ok(false) in the error listener)
-  is(errors, 0, "All the styles (" + allPromises.length + ") loaded without errors.");
+  // as the ok(false) in messageIsCSSError.
+  let errors = messages.filter(m => messageIsCSSError(m, innerWindowID, outerWindowID));
+  is(errors.length, 0, "All the styles (" + allPromises.length + ") loaded without errors.");
 
   // Clean up to avoid leaks:
-  Services.console.unregisterListener(errorListener);
   iframe.remove();
   doc.head.innerHTML = '';
   doc = null;
   iframe = null;
 });
--- a/browser/base/content/test/general/parsingTestHelpers.jsm
+++ b/browser/base/content/test/general/parsingTestHelpers.jsm
@@ -59,18 +59,22 @@ function iterateOverPath(path, extension
   let files = [];
 
   let pathEntryIterator = (entry) => {
     if (entry.isDir) {
       subdirs.push(entry.path);
     } else if (extensions.some((extension) => entry.name.endsWith(extension))) {
       let file = parentDir.clone();
       file.append(entry.name);
-      let uriSpec = getURLForFile(file);
-      files.push(Services.io.newURI(uriSpec, null, null));
+      // the build system might leave dead symlinks hanging around, which are
+      // returned as part of the directory iterator, but don't actually exist:
+      if (file.exists()) {
+        let uriSpec = getURLForFile(file);
+        files.push(Services.io.newURI(uriSpec, null, null));
+      }
     } else if (entry.name.endsWith(".ja") || entry.name.endsWith(".jar")) {
       let file = parentDir.clone();
       file.append(entry.name);
       for (let extension of extensions) {
         let jarEntryIterator = generateEntriesFromJarFile(file, extension);
         files.push(...jarEntryIterator);
       }
     }
--- a/browser/themes/shared/devtools/floating-scrollbars-light.css
+++ b/browser/themes/shared/devtools/floating-scrollbars-light.css
@@ -1,10 +1,10 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-@import url("floating-scrollbars.css");
+@import url("chrome://browser/skin/devtools/floating-scrollbars.css");
 
 scrollbar thumb {
   background-color: rgba(170,170,170,0.2) !important;
 }