Bug 1253148: [webext] Cleanup running extensions on test failure. r?billm draft
authorKris Maglione <maglione.k@gmail.com>
Wed, 02 Mar 2016 20:58:28 -0800
changeset 336419 66d1f93fa451f174bfae09136db01e5cc5eaf86a
parent 336418 afa990f7034a12b78e1cba02b532a254c2d1990f
child 515388 99ff32b83e3226767c41dbead6de885c1c403532
push id12059
push usermaglione.k@gmail.com
push dateThu, 03 Mar 2016 04:59:09 +0000
reviewersbillm
bugs1253148
milestone47.0a1
Bug 1253148: [webext] Cleanup running extensions on test failure. r?billm MozReview-Commit-ID: HTFZk6y6ZEp
testing/mochitest/browser-test.js
testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
testing/specialpowers/content/specialpowersAPI.js
--- a/testing/mochitest/browser-test.js
+++ b/testing/mochitest/browser-test.js
@@ -140,17 +140,21 @@ function Tester(aTests, structuredLogger
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/specialpowersAPI.js", simpleTestScope);
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/SpecialPowersObserverAPI.js", simpleTestScope);
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ChromePowers.js", simpleTestScope);
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/SimpleTest.js", simpleTestScope);
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/MemoryStats.js", simpleTestScope);
   this._scriptLoader.loadSubScript("chrome://mochikit/content/chrome-harness.js", simpleTestScope);
   this.SimpleTest = simpleTestScope.SimpleTest;
 
-  var extensionUtilsScope = {};
+  var extensionUtilsScope = {
+    registerCleanupFunction: (fn) => {
+      this.currentTest.scope.registerCleanupFunction(fn);
+    },
+  };
   extensionUtilsScope.SimpleTest = this.SimpleTest;
   this._scriptLoader.loadSubScript("chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js", extensionUtilsScope);
   this.ExtensionTestUtils = extensionUtilsScope.ExtensionTestUtils;
 
   this.SimpleTest.harnessParameters = gConfig;
 
   this.MemoryStats = simpleTestScope.MemoryStats;
   this.Task = Task;
--- a/testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
+++ b/testing/mochitest/tests/SimpleTest/ExtensionTestUtils.js
@@ -1,21 +1,30 @@
 var ExtensionTestUtils = {};
 
 ExtensionTestUtils.loadExtension = function(ext, id = null)
 {
+  // Cleanup functions need to be registered differently depending on
+  // whether we're in browser chrome or plain mochitests.
+  var registerCleanup;
+  if (typeof registerCleanupFunction != "undefined") {
+    registerCleanup = registerCleanupFunction;
+  } else {
+    registerCleanup = SimpleTest.registerCleanupFunction.bind(SimpleTest);
+  }
+
   var testResolve;
   var testDone = new Promise(resolve => { testResolve = resolve; });
 
   var messageHandler = new Map();
   var messageAwaiter = new Map();
 
   var messageQueue = new Set();
 
-  SimpleTest.registerCleanupFunction(() => {
+  registerCleanup(() => {
     if (messageQueue.size) {
       SimpleTest.is(messageQueue.size, 0, "message queue is empty");
     }
     if (messageAwaiter.size) {
       SimpleTest.is(messageAwaiter.size, 0, "no tasks awaiting on messages");
     }
   });
 
@@ -69,16 +78,25 @@ ExtensionTestUtils.loadExtension = funct
         checkMessages();
       }
 
     },
   };
 
   var extension = SpecialPowers.loadExtension(id, ext, handler);
 
+  registerCleanup(() => {
+    if (extension.state == "pending" || extension.state == "running") {
+      SimpleTest.ok(false, "Extension left running at test shutdown")
+      return extension.unload();
+    } else if (extension.state == "unloading") {
+      SimpleTest.ok(false, "Extension not fully unloaded at test shutdown")
+    }
+  });
+
   extension.awaitMessage = (msg) => {
     return new Promise(resolve => {
       checkDuplicateListeners(msg);
 
       messageAwaiter.set(msg, {resolve});
       checkMessages();
     });
   };
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -1876,44 +1876,52 @@ SpecialPowersAPI.prototype = {
     startupPromise.catch(() => {
       this._removeMessageListener("SPExtensionMessage", listener);
     });
 
     handler = Cu.waiveXrays(handler);
     ext = Cu.waiveXrays(ext);
 
     let sp = this;
+    let state = "uninitialized";
     let extension = {
       id,
 
+      get state() { return state; },
+
       startup() {
+        state = "pending";
         sp._sendAsyncMessage("SPStartupExtension", {id});
         return startupPromise;
       },
 
       unload() {
+        state = "unloading";
         sp._sendAsyncMessage("SPUnloadExtension", {id});
         return unloadPromise;
       },
 
       sendMessage(...args) {
         sp._sendAsyncMessage("SPExtensionMessage", {id, args});
       },
     };
 
     this._sendAsyncMessage("SPLoadExtension", {ext, id});
 
     let listener = (msg) => {
       if (msg.data.id == id) {
         if (msg.data.type == "extensionStarted") {
+          state = "running";
           resolveStartup();
         } else if (msg.data.type == "extensionFailed") {
+          state = "failed";
           rejectStartup("startup failed");
         } else if (msg.data.type == "extensionUnloaded") {
           this._removeMessageListener("SPExtensionMessage", listener);
+          state = "unloaded";
           resolveUnload();
         } else if (msg.data.type in handler) {
           handler[msg.data.type](...msg.data.args);
         } else {
           dump(`Unexpected: ${msg.data.type}\n`);
         }
       }
     };