Bug 1443652 part 2. Add a bunch of web platform tests for load and error events on stylesheet links. r=bholley
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 07 Mar 2018 16:06:48 -0500
changeset 462121 7daaf289c085e05e0e4a0327a13748002fb467a0
parent 462120 ba6cef216a171782bd8abcd00a08c9ae88cbfe43
child 462122 22ba4f32a7afe64038a38cd2e1fc16ede661f9ab
push id1683
push usersfraser@mozilla.com
push dateThu, 26 Apr 2018 16:43:40 +0000
treeherdermozilla-release@5af6cb21869d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1443652
milestone60.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 1443652 part 2. Add a bunch of web platform tests for load and error events on stylesheet links. r=bholley MozReview-Commit-ID: 1lieHmpuRtH
testing/web-platform/meta/MANIFEST.json
testing/web-platform/mozilla/meta/MANIFEST.json
testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html
testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html
testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -324921,16 +324921,28 @@
     ]
    ],
    "html/semantics/document-metadata/the-link-element/document-without-browsing-context.html": [
     [
      "/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html",
      {}
     ]
    ],
+   "html/semantics/document-metadata/the-link-element/link-load-error-events.html": [
+    [
+     "/html/semantics/document-metadata/the-link-element/link-load-error-events.html",
+     {}
+    ]
+   ],
+   "html/semantics/document-metadata/the-link-element/link-load-error-events.https.html": [
+    [
+     "/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html",
+     {}
+    ]
+   ],
    "html/semantics/document-metadata/the-link-element/link-load-event.html": [
     [
      "/html/semantics/document-metadata/the-link-element/link-load-event.html",
      {}
     ]
    ],
    "html/semantics/document-metadata/the-link-element/link-rellist.html": [
     [
@@ -554814,18 +554826,26 @@
   "html/semantics/document-metadata/the-link-element/all.headers": [
    "f91c644e4334d99717310a86d43dd2330583ab62",
    "support"
   ],
   "html/semantics/document-metadata/the-link-element/document-without-browsing-context.html": [
    "1ffdecee25d1f3819f3f67241c3f0746bedbcf97",
    "testharness"
   ],
+  "html/semantics/document-metadata/the-link-element/link-load-error-events.html": [
+   "79b4a278f0e35646cfdffeebf8f0523e2772bc9b",
+   "testharness"
+  ],
+  "html/semantics/document-metadata/the-link-element/link-load-error-events.https.html": [
+   "79b4a278f0e35646cfdffeebf8f0523e2772bc9b",
+   "testharness"
+  ],
   "html/semantics/document-metadata/the-link-element/link-load-event.html": [
-   "a1a8b7b20492b7fef977f7734425f9cf55322f2a",
+   "628527090c78d90d831cb80ea8eee7ffa66722f5",
    "testharness"
   ],
   "html/semantics/document-metadata/the-link-element/link-rellist.html": [
    "e18655ffb90bb039c50b262d145d63ca5efc22ca",
    "testharness"
   ],
   "html/semantics/document-metadata/the-link-element/link-style-error-01.html": [
    "285208d6cf3113ec16bedd107c0740b8c7c8a9d8",
@@ -573611,17 +573631,17 @@
    "9285ebf2cd716ea072c18fe668e95cf6ce4ec3de",
    "manual"
   ],
   "payment-request/historical.https.html": [
    "6695acdcd1647fdd37702a7f63658dcd50f25596",
    "testharness"
   ],
   "payment-request/interfaces.https.html": [
-   "d269e8378f2a84ba96c981536667817e0db9e2d1",
+   "2280f0ef821cdc3093e10c2162d3756f5eeb78de",
    "testharness"
   ],
   "payment-request/payment-request-abort-method.https.html": [
    "30c62af4a05a4d83cbbd1e82d0df62bae9a85e96",
    "testharness"
   ],
   "payment-request/payment-request-canmakepayment-method.https.html": [
    "0d863558b996df81a36207201bbf8c649688845d",
--- a/testing/web-platform/mozilla/meta/MANIFEST.json
+++ b/testing/web-platform/mozilla/meta/MANIFEST.json
@@ -1024,17 +1024,17 @@
    "02e6acec2ff275e0e935cb6d903d348f98d5d437",
    "testharness"
   ],
   "dom/throttling/throttling-ws.window.js": [
    "67a981ba2a4d08b684947ed42aba6648dcd262b4",
    "testharness"
   ],
   "editor/initial_selection_on_focus.html": [
-   "da3d0ff5305658e18f51a4f19b34927fb2691e60",
+   "06948dbf72160a7de5a0baaa2f6cf1bb54fbeb8f",
    "testharness"
   ],
   "fetch/api/redirect/redirect-referrer-mixed-content.js": [
    "f9d7ec9cf9fa8c847e45664b05482e3f8c191385",
    "support"
   ],
   "fetch/api/redirect/redirect-referrer.https.html": [
    "99cbd16b78771f35e075e4012d8dbc5dce3209c0",
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/link-load-error-events.sub.js"></script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/link-load-error-events.sub.js"></script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js
@@ -0,0 +1,187 @@
+/**
+ * This is the guts of the load/error event tests for <link rel="stylesheet">.
+ *
+ * We have a list of tests each of which is an object containing: href value,
+ * expected load success boolean, test description.  Href values are set up in
+ * such a way that we guarantee that all stylesheet URLs are unique.  This
+ * avoids issues around caching of sheets based on URL.
+ */
+
+var isHttps = location.protocol == "https:";
+
+var tests = [
+  // Basic tests
+  {
+    href: existingSheet(),
+    success: true,
+    description: "Basic load of stylesheet",
+  },
+  {
+    href: nonexistentSheet(),
+    success: false,
+    description: "Attempted load of nonexistent stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("${existingSheet()}")`,
+    success: true,
+    description: "Import of stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("${nonexistentSheet()}")`,
+    success: false,
+    description: "Import of nonexistent stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("data:text/css,@import url('${existingSheet()}')")`,
+    success: true,
+    description: "Import of import of stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("data:text/css,@import url('${nonexistentSheet()}')")`,
+    success: false,
+    description: "Import of import of nonexistent stylesheet",
+  },
+
+  // Non-CSS-response tests.
+  {
+    href: makeUnique(""),
+    success: false,
+    description: "Load of non-CSS stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("${makeUnique("")}")`,
+    success: false,
+    description: "Import of non-CSS stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("data:text/css,@import url('${makeUnique("")}')")`,
+    success: false,
+    description: "Import of import of non-CSS stylesheet",
+  },
+
+  // http:// tests, to test what happens with mixed content blocking.
+  {
+    href: httpSheet(),
+    success: !isHttps,
+    description: "Load of http:// stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("${httpSheet()}")`,
+    success: !isHttps,
+    description: "Import of http:// stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("data:text/css,@import url('${httpSheet()}')")`,
+    success: !isHttps,
+    description: "Import of import of http:// stylesheet",
+  },
+
+  // https:// tests just as a control
+  {
+    href: httpsSheet(),
+    success: true,
+    description: "Load of https:// stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("${httpsSheet()}")`,
+    success: true,
+    description: "Import of https:// stylesheet",
+  },
+  {
+    href: `data:text/css,@import url("data:text/css,@import url('${httpsSheet()}')")`,
+    success: true,
+    description: "Import of import of https:// stylesheet",
+  },
+
+  // Tests with multiple imports some of which are slow and some are fast.
+  {
+    href: `data:text/css,@import url("${slowResponse(existingSheet())}"); @import url("${nonexistentSheet()}");`,
+    success: false,
+    description: "Slow successful import, fast failing import",
+  },
+  {
+    href: `data:text/css,@import url("${existingSheet()}"); @import url("${slowResponse(nonexistentSheet())}");`,
+    success: false,
+    description: "Fast successful import, slow failing import",
+  }
+];
+
+// Note: Here we really do need to use "let" at least for the href,
+// because we lazily evaluate it in the unreached cases.
+for (var test of tests) {
+  let {href, success, description} = test;
+  var t = async_test(description);
+  var link = document.createElement("link");
+  link.rel = "stylesheet";
+  if (success) {
+    link.onload = t.step_func_done(() => {});
+    link.onerror = t.step_func_done(() => assert_unreached(`error fired when load expected: ${href}`) );
+  } else {
+    link.onerror = t.step_func_done(() => {});
+    link.onload = t.step_func_done(() => assert_unreached(`load fired when error expected: ${href}`) );
+  }
+  link.href = href;
+  document.head.appendChild(link);
+}
+
+/* Utility function */
+function makeUnique(url) {
+  // Make sure we copy here, even if the thing coming in is a URL, so we don't
+  // mutate our caller's data.
+  url = new URL(url, location.href);
+  // We want to generate a unique URI to avoid the various caches browsers have
+  // for stylesheets.  We don't want to just use a counter, because that would
+  // not be robust to the test being reloaded or othewise run multiple times
+  // without a browser restart.  We don't want to use timstamps, because those
+  // are not likely to be unique across calls to this function, especially given
+  // the degraded timer resolution browsers have due to Spectre.
+  //
+  // So just fall back on Math.random() and assume it can't duplicate values.
+  url.searchParams.append("r", Math.random());
+  return url;
+}
+
+function existingSheet() {
+  return makeUnique("resources/good.css");
+}
+
+/**
+ * Function the add values to the "pipe" search param.  See
+ * http://wptserve.readthedocs.io/en/latest/pipes.html for why one would do
+ * this.  Because this param uses a weird '|'-separated syntax instead of just
+ * using multiple params with the same name, we need some manual code to munge
+ * the value properly.
+ */
+function addPipe(url, pipeVal) {
+  url = new URL(url, location.href);
+  var params = url.searchParams;
+  var oldVal = params.get("pipe");
+  if (oldVal) {
+    params.set("pipe", oldVal + "|" + pipeVal);
+  } else {
+    params.set("pipe", pipeVal);
+  }
+  return url;
+}
+
+function nonexistentSheet() {
+  return addPipe(existingSheet(), "status(404)");
+}
+
+function httpSheet() {
+  var url = existingSheet();
+  url.protocol = "http";
+  url.port = {{ports[http][0]}};
+  return url;
+}
+
+function httpsSheet() {
+  var url = existingSheet();
+  url.protocol = "https";
+  url.port = {{ports[https][0]}};
+  return url;
+}
+
+function slowResponse(url) {
+  return addPipe(url, "trickle(d1)");
+}