Bug 1480702: Rewrite test to avoid relying on unspecified/erroneous behavior r=asuth
authorYaron Tausky <ytausky@mozilla.com>
Thu, 23 Aug 2018 14:04:35 +0000
changeset 490758 ce2f6b168f041c540513f4d99542ed3870fb3680
parent 490757 cae4910806c7976aed9803f22e730c88f7703390
child 490759 eee49d0f606bb7423f9688d2901d76296f505a72
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1480702
milestone63.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 1480702: Rewrite test to avoid relying on unspecified/erroneous behavior r=asuth After analyzing test_request.html it became clear that it relied on two false assumptions: 1. It assumed that a service worker is notified that it's being installed before any client can interact with it. 2. It assumed that a service worker will always be installed upon registration, if it was unregistered before. The first assumption is not backed by the spec; it seems that the opposite behavior is the correct one (https://github.com/w3c/ServiceWorker/issues/1347). The second assumption ignores the possibility of resurrection, where a service worker is re- registered before getting uninstalled. This commit addresses both problems by not relying on the installation phase, instead passing the script URL as a search parameter and loading it at service worker script evaluation time. It then runs the test function in response to a message from the client. Differential Revision: https://phabricator.services.mozilla.com/D3879
dom/tests/mochitest/fetch/fetch_test_framework.js
dom/tests/mochitest/fetch/nested_worker_wrapper.js
dom/tests/mochitest/fetch/test_fetch_cors.js
dom/tests/mochitest/fetch/worker_wrapper.js
--- a/dom/tests/mochitest/fetch/fetch_test_framework.js
+++ b/dom/tests/mochitest/fetch/fetch_test_framework.js
@@ -1,9 +1,13 @@
 function testScript(script) {
+  function makeWrapperUrl(wrapper) {
+    return wrapper + "?script=" + script;
+  }
+  let workerWrapperUrl = makeWrapperUrl("worker_wrapper.js");
 
   // The framework runs the entire test in many different configurations.
   // On slow platforms and builds this can make the tests likely to
   // timeout while they are still running.  Lengthen the timeout to
   // accomodate this.
   SimpleTest.requestLongerTimeout(2);
 
   // reroute.html should have set this variable if a service worker is present!
@@ -19,17 +23,17 @@ function testScript(script) {
                 ["dom.serviceWorkers.idle_timeout", 0],
                 ["dom.serviceWorkers.exemptFromPerDomainMax", true]]
       }, resolve);
     });
   }
 
   function workerTest() {
     return new Promise(function(resolve, reject) {
-      var worker = new Worker("worker_wrapper.js");
+      var worker = new Worker(workerWrapperUrl);
       worker.onmessage = function(event) {
         if (event.data.context != "Worker") {
           return;
         }
         if (event.data.type == 'finish') {
           resolve();
         } else if (event.data.type == 'status') {
           ok(event.data.status, event.data.context + ": " + event.data.msg);
@@ -40,17 +44,17 @@ function testScript(script) {
       };
 
       worker.postMessage({ "script": script });
     });
   }
 
   function nestedWorkerTest() {
     return new Promise(function(resolve, reject) {
-      var worker = new Worker("nested_worker_wrapper.js");
+      var worker = new Worker(makeWrapperUrl("nested_worker_wrapper.js"));
       worker.onmessage = function(event) {
         if (event.data.context != "NestedWorker") {
           return;
         }
         if (event.data.type == 'finish') {
           resolve();
         } else if (event.data.type == 'status') {
           ok(event.data.status, event.data.context + ": " + event.data.msg);
@@ -99,17 +103,17 @@ function testScript(script) {
         iframe = document.createElement("iframe");
         iframe.src = "message_receiver.html";
         iframe.onload = function() {
           worker.postMessage({ script: script });
         };
         document.body.appendChild(iframe);
       }
 
-      navigator.serviceWorker.register("worker_wrapper.js", {scope: "."})
+      navigator.serviceWorker.register(workerWrapperUrl, {scope: "."})
         .then(setupSW);
     });
   }
 
   function windowTest() {
     return new Promise(function(resolve, reject) {
       var scriptEl = document.createElement("script");
       scriptEl.setAttribute("src", script);
--- a/dom/tests/mochitest/fetch/nested_worker_wrapper.js
+++ b/dom/tests/mochitest/fetch/nested_worker_wrapper.js
@@ -1,15 +1,19 @@
+function getScriptUrl() {
+  return new URL(location.href).searchParams.get('script');
+}
+
 // Hold the nested worker alive until this parent worker closes.
 var worker;
 
 addEventListener('message', function nestedWorkerWrapperOnMessage(evt) {
   removeEventListener('message', nestedWorkerWrapperOnMessage);
 
-  worker = new Worker('worker_wrapper.js');
+  worker = new Worker('worker_wrapper.js?script=' + getScriptUrl());
 
   worker.addEventListener('message', function(evt) {
     self.postMessage({
       context: 'NestedWorker',
       type: evt.data.type,
       status: evt.data.status,
       msg: evt.data.msg,
     });
--- a/dom/tests/mochitest/fetch/test_fetch_cors.js
+++ b/dom/tests/mochitest/fetch/test_fetch_cors.js
@@ -1718,17 +1718,17 @@ function testReferrer() {
     referrer = self.location.href;
   } else {
     referrer = document.documentURI;
   }
 
   var dict = {
     'Referer': referrer
   };
-  return fetch(corsServerPath + "headers=" + dict.toSource()).then(function(res) {
+  return fetch(corsServerPath + "headers=" + encodeURIComponent(dict.toSource())).then(function(res) {
     is(res.status, 200, "expected correct referrer header to be sent");
     dump(res.statusText);
   }, function(e) {
     ok(false, "expected correct referrer header to be sent");
   });
 }
 
 function runTest() {
--- a/dom/tests/mochitest/fetch/worker_wrapper.js
+++ b/dom/tests/mochitest/fetch/worker_wrapper.js
@@ -1,46 +1,50 @@
 importScripts("utils.js");
+
+function getScriptUrl() {
+  return new URL(location.href).searchParams.get('script');
+}
+
+importScripts(getScriptUrl());
+
 var client;
 var context;
 
 function ok(a, msg) {
   client.postMessage({type: 'status', status: !!a,
                       msg: a + ": " + msg, context: context});
 }
 
 function is(a, b, msg) {
   client.postMessage({type: 'status', status: a === b,
                       msg: a + " === " + b + ": " + msg, context: context});
 }
 
-var completeInstall;
-
 addEventListener('message', function workerWrapperOnMessage(e) {
   removeEventListener('message', workerWrapperOnMessage);
   var data = e.data;
 
-  function loadTest(event) {
+  function runTestAndReportToClient(event) {
     var done = function(res) {
       client.postMessage({ type: 'finish', context: context });
       return res;
     }
 
     try {
-      importScripts(data.script);
       // runTest() is provided by the test.
       var result = runTest().then(done, done);
       if ('waitUntil' in event) {
         event.waitUntil(result);
       }
     } catch(e) {
       client.postMessage({
         type: 'status',
         status: false,
-        msg: 'worker failed to import ' + data.script + "; error: " + e.message,
+        msg: 'worker failed to run ' + data.script + "; error: " + e.message,
         context: context
       });
       done();
     }
   }
 
   if ("ServiceWorker" in self) {
     // Fetch requests from a service worker are not intercepted.
@@ -52,21 +56,16 @@ addEventListener('message', function wor
           client = clients[i];
           break;
         }
       }
       if (!client) {
         dump("We couldn't find the message_receiver window, the test will fail\n");
       }
       context = "ServiceWorker";
-      loadTest(e);
-      completeInstall();
+      runTestAndReportToClient(e);
     }));
   } else {
     client = self;
     context = "Worker";
-    loadTest(e);
+    runTestAndReportToClient(e);
   }
 });
-
-addEventListener("install", e => {
-  e.waitUntil(new Promise(resolve => completeInstall = resolve));
-});