Bug 1463635: Part 2 - Update test_temporary to use mostly WebExtensions. r?aswan draft
authorKris Maglione <maglione.k@gmail.com>
Tue, 22 May 2018 20:24:12 -0700
changeset 806326 ce48b0aaade09cea5c4811134e85b4d23677f972
parent 800400 f5a46ff56aac89e74368a83de0a2fa3af5643d0e
push id112859
push usermaglione.k@gmail.com
push dateSat, 09 Jun 2018 00:55:16 +0000
reviewersaswan
bugs1463635
milestone62.0a1
Bug 1463635: Part 2 - Update test_temporary to use mostly WebExtensions. r?aswan MozReview-Commit-ID: 1tK3FiNXgAV
testing/xpcshell/head.js
toolkit/components/extensions/ExtensionTestCommon.jsm
toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -789,17 +789,17 @@ function do_note_exception(ex, text) {
                      source_file: filename,
                      stack: _format_stack(ex.stack)
                    });
 }
 
 function do_report_result(passed, text, stack, todo) {
   // Match names like head.js, head_foo.js, and foo_head.js, but not
   // test_headache.js
-  while (/(\/head(_.+)?|head)\.js$/.test(stack.filename) && stack.caller) {
+  while (0 && /(\/head(_.+)?|head)\.js$/.test(stack.filename) && stack.caller) {
     stack = stack.caller;
   }
 
   let name = _gRunningTest ? _gRunningTest.name : stack.name;
   let message;
   if (name) {
      message = "[" + name + " : " + stack.lineNumber + "] " + text;
   } else {
--- a/toolkit/components/extensions/ExtensionTestCommon.jsm
+++ b/toolkit/components/extensions/ExtensionTestCommon.jsm
@@ -148,17 +148,37 @@ class MockExtension {
     return this._extensionPromise.then(extension => {
       return extension.broadcast("Extension:FlushJarCache", {path: this.file.path});
     }).then(() => {
       return OS.File.remove(this.file.path);
     });
   }
 }
 
+function provide(obj, keys, value, override = false) {
+  if (keys.length == 1) {
+    if (!(keys[0] in obj) || override) {
+      obj[keys[0]] = value;
+    }
+  } else {
+    if (!(keys[0] in obj)) {
+      obj[keys[0]] = {};
+    }
+    provide(obj[keys[0]], keys.slice(1), value, override);
+  }
+}
+
 var ExtensionTestCommon = class ExtensionTestCommon {
+  static generateManifest(manifest) {
+    provide(manifest, ["name"], "Generated extension");
+    provide(manifest, ["manifest_version"], 2);
+    provide(manifest, ["version"], "1.0");
+    return manifest;
+  }
+
   /**
    * This code is designed to make it easy to test a WebExtension
    * without creating a bunch of files. Everything is contained in a
    * single JSON blob.
    *
    * Properties:
    *   "background": "<JS code>"
    *     A script to be loaded as the background script.
@@ -185,29 +205,16 @@ var ExtensionTestCommon = class Extensio
   static generateXPI(data) {
     let manifest = data.manifest;
     if (!manifest) {
       manifest = {};
     }
 
     let files = Object.assign({}, data.files);
 
-    function provide(obj, keys, value, override = false) {
-      if (keys.length == 1) {
-        if (!(keys[0] in obj) || override) {
-          obj[keys[0]] = value;
-        }
-      } else {
-        if (!(keys[0] in obj)) {
-          obj[keys[0]] = {};
-        }
-        provide(obj[keys[0]], keys.slice(1), value, override);
-      }
-    }
-
     provide(manifest, ["name"], "Generated extension");
     provide(manifest, ["manifest_version"], 2);
     provide(manifest, ["version"], "1.0");
 
     if (data.background) {
       let bgScript = uuidGen.generateUUID().number + ".js";
 
       provide(manifest, ["background", "scripts"], [bgScript], true);
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -1022,16 +1022,18 @@ var AddonTestUtils = {
 
       // Create parent directories, if necessary.
       let dirPath = dir;
       for (let subDir of path) {
         dirPath = OS.Path.join(dirPath, subDir);
         await OS.File.makeDir(dirPath, {ignoreExisting: true});
       }
 
+      if (typeof data == "object" && ChromeUtils.getClassName(data) == "Object")
+        data = JSON.stringify(data);
       if (typeof data == "string")
         data = new TextEncoder("utf-8").encode(data);
 
       await OS.File.writeAtomic(OS.Path.join(dirPath, leafName), data);
     }
 
     return nsFile(dir);
   },
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -420,44 +420,48 @@ var SlightlyLessDodgyBootstrapMonitor = 
         this.started.delete(id);
         break;
       case "uninstall":
         this.checkMatches("uninstall", "install", params, this.installed.get(id));
         this.uninstalled.set(id, {reason, params});
         this.installed.delete(id);
         break;
       case "update":
-        // Close enough, for now.
-        this.onBootstrapMethod("uninstall",
-                               Object.assign({}, params, {version: params.oldVersion}),
-                               reason);
-        this.onBootstrapMethod("install", params, reason);
+        this.checkMatches("update", "install", params, this.installed.get(id));
+        this.installed.set(id, {reason, params});
         break;
     }
   },
 
   clear(id) {
     this.installed.delete(id);
     this.started.delete(id);
     this.stopped.delete(id);
     this.uninstalled.delete(id);
   },
 
   checkMatches(method, lastMethod, params, {params: lastParams} = {}) {
     ok(lastParams,
        `Expecting matching ${lastMethod} call for add-on ${params.id} ${method} call`);
 
-    equal(params.version, lastParams.version,
-          "params.version should match last call");
+    if (method == "update") {
+      equal(params.oldVersion, lastParams.version,
+            "params.version should match last call");
+    } else {
+      equal(params.version, lastParams.version,
+            "params.version should match last call");
+    }
 
-    equal(params.installPath.path, lastParams.installPath.path,
-          `params.installPath should match last call`);
+    if (method !== "update" && method !== "uninstall") {
+      equal(params.installPath.path, lastParams.installPath.path,
+            `params.installPath should match last call`);
 
-    ok(params.resourceURI.equals(lastParams.resourceURI),
-       `params.resourceURI should match: "${params.resourceURI.spec}" == "${lastParams.resourceURI.spec}"`);
+      ok(params.resourceURI.equals(lastParams.resourceURI),
+         `params.resourceURI should match: "${params.resourceURI.spec}" == "${lastParams.resourceURI.spec}"`);
+    }
   },
 
   checkStarted(id, version = undefined) {
     let started = this.started.get(id);
     ok(started, `Should have seen startup method call for ${id}`);
 
     if (version !== undefined)
       equal(started.params.version, version,
--- a/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_temporary.js
@@ -1,26 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 
 const ID = "bootstrap1@tests.mozilla.org";
-const sampleRDFManifest = {
-  id: ID,
-  version: "1.0",
-  bootstrap: true,
-  targetApplications: [{
-    id: "xpcshell@tests.mozilla.org",
-    minVersion: "1",
-    maxVersion: "1"
-  }],
-  name: "Test Bootstrap 1 (temporary)",
-};
 
 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42");
 
 function waitForBootstrapEvent(expectedEvent, addonId) {
   return new Promise(resolve => {
     function listener(msg, {method, params, reason}) {
       if (params.id === addonId && method === expectedEvent) {
         resolve({params, method, reason});
@@ -382,45 +371,44 @@ add_task(async function test_samefile() 
     type: "extension",
     isWebExtension: true,
     signedState: mozinfo.addon_signing ? AddonManager.SIGNEDSTATE_PRIVILEGED : AddonManager.SIGNEDSTATE_NOT_REQUIRED,
   });
 
   await addon.uninstall();
 });
 
+function promiseWriteWebExtensionToDir(dir, manifest) {
+  return AddonTestUtils.promiseWriteFilesToDir(dir.path, {
+    "manifest.json": ExtensionTestCommon.generateManifest(manifest),
+  });
+}
+
 // Install a temporary add-on over the top of an existing add-on.
 // Uninstall it and make sure the existing add-on comes back.
 add_task(async function() {
-  // We can't install unpacked add-ons on release builds. See above.
-  if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
-    return;
-  }
-
-  await promiseInstallAllFiles([do_get_addon("test_bootstrap1_1")], true);
+  await promiseInstallWebExtension({
+    manifest: {
+      applications: {gecko: {id: ID}},
+      version: "1.0",
+      name: "Test Bootstrap 1",
+    },
+  });
 
   Monitor.checkInstalled(ID, "1.0");
   Monitor.checkStarted(ID, "1.0");
 
-  let tempdir = gTmpD.clone();
-  await promiseWriteInstallRDFToDir({
-    id: ID,
+  let unpacked_addon = gTmpD.clone();
+  unpacked_addon.append(ID);
+
+  await promiseWriteWebExtensionToDir(unpacked_addon, {
+    applications: {gecko: {id: ID}},
     version: "2.0",
-    bootstrap: true,
-    unpack: true,
-    targetApplications: [{
-          id: "xpcshell@tests.mozilla.org",
-      minVersion: "1",
-      maxVersion: "1"
-        }],
     name: "Test Bootstrap 1 (temporary)",
-  }, tempdir);
-
-  let unpacked_addon = tempdir.clone();
-  unpacked_addon.append(ID);
+  });
 
   let extInstallCalled = false;
   AddonManager.addInstallListener({
     onExternalInstall: (aInstall) => {
       Assert.equal(aInstall.id, ID);
       Assert.equal(aInstall.version, "2.0");
       extInstallCalled = true;
     },
@@ -447,18 +435,18 @@ add_task(async function() {
   });
 
   let addon = await AddonManager.installTemporaryAddon(unpacked_addon);
 
   Assert.ok(extInstallCalled);
   Assert.ok(installingCalled);
   Assert.ok(installedCalled);
 
-  Monitor.checkNotInstalled(ID);
-  Monitor.checkNotStarted(ID);
+  Monitor.checkInstalled(ID);
+  Monitor.checkStarted(ID);
 
   // temporary add-on is installed and started
   checkAddon(ID, addon, {
     version: "2.0",
     name: "Test Bootstrap 1 (temporary)",
     isCompatible: true,
     appDisabled: false,
     isActive: true,
@@ -491,59 +479,46 @@ add_task(async function() {
   Monitor.checkNotStarted(ID);
 
   await promiseRestartManager();
 });
 
 // Install a temporary add-on as a version upgrade over the top of an
 // existing temporary add-on.
 add_task(async function() {
-  // We can't install unpacked add-ons on release builds. See above.
-  if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
-    return;
-  }
-
-  const tempdir = gTmpD.clone();
+  const unpackedAddon = gTmpD.clone();
+  unpackedAddon.append(ID);
 
-  await promiseWriteInstallRDFToDir(sampleRDFManifest, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
-
-  const unpackedAddon = tempdir.clone();
-  unpackedAddon.append(ID);
-  do_get_file("data/test_temporary/bootstrap.js")
-    .copyTo(unpackedAddon, "bootstrap.js");
+  await promiseWriteWebExtensionToDir(unpackedAddon, {
+    applications: {gecko: {id: ID}},
+    version: "1.0",
+  });
 
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   // Increment the version number, re-install it, and make sure it
   // gets marked as an upgrade.
-  await promiseWriteInstallRDFToDir(Object.assign({}, sampleRDFManifest, {
-    version: "2.0"
-  }), tempdir, "bootstrap1@tests.mozilla.org");
+  await promiseWriteWebExtensionToDir(unpackedAddon, {
+    applications: {gecko: {id: ID}},
+    version: "2.0",
+  });
 
   const onShutdown = waitForBootstrapEvent("shutdown", ID);
-  const onUninstall = waitForBootstrapEvent("uninstall", ID);
-  const onInstall = waitForBootstrapEvent("install", ID);
+  const onUpdate = waitForBootstrapEvent("update", ID);
   const onStartup = waitForBootstrapEvent("startup", ID);
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   await checkEvent(onShutdown, {
     reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
     params: {
       version: "1.0",
     },
   });
 
-  await checkEvent(onUninstall, {
-    reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
-    params: {
-      version: "1.0",
-    },
-  });
-
-  await checkEvent(onInstall, {
+  await checkEvent(onUpdate, {
     reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
     params: {
       version: "2.0",
       oldVersion: "1.0",
     },
   });
 
   await checkEvent(onStartup, {
@@ -559,61 +534,49 @@ add_task(async function() {
 
   unpackedAddon.remove(true);
   await promiseRestartManager();
 });
 
 // Install a temporary add-on as a version downgrade over the top of an
 // existing temporary add-on.
 add_task(async function() {
-  // We can't install unpacked add-ons on release builds. See above.
-  if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
-    return;
-  }
-
-  const tempdir = gTmpD.clone();
+  const unpackedAddon = gTmpD.clone();
+  unpackedAddon.append(ID);
 
-  await promiseWriteInstallRDFToDir(sampleRDFManifest, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
-
-  const unpackedAddon = tempdir.clone();
-  unpackedAddon.append(ID);
-  do_get_file("data/test_temporary/bootstrap.js")
-    .copyTo(unpackedAddon, "bootstrap.js");
+  await promiseWriteWebExtensionToDir(unpackedAddon, {
+    applications: {gecko: {id: ID}},
+    version: "1.0",
+  });
 
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   // Decrement the version number, re-install, and make sure
   // it gets marked as a downgrade.
-  await promiseWriteInstallRDFToDir(Object.assign({}, sampleRDFManifest, {
-    version: "0.8"
-  }), tempdir, "bootstrap1@tests.mozilla.org");
+  await promiseWriteWebExtensionToDir(unpackedAddon, {
+    applications: {gecko: {id: ID}},
+    version: "0.8",
+  });
 
   const onShutdown = waitForBootstrapEvent("shutdown", ID);
-  const onUninstall = waitForBootstrapEvent("uninstall", ID);
-  const onInstall = waitForBootstrapEvent("install", ID);
+  const onUpdate = waitForBootstrapEvent("update", ID);
   const onStartup = waitForBootstrapEvent("startup", ID);
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   await checkEvent(onShutdown, {
     reason: BOOTSTRAP_REASONS.ADDON_DOWNGRADE,
     params: {
       version: "1.0",
     },
   });
 
-  await checkEvent(onUninstall, {
+  await checkEvent(onUpdate, {
     reason: BOOTSTRAP_REASONS.ADDON_DOWNGRADE,
     params: {
-      version: "1.0",
-    },
-  });
-
-  await checkEvent(onInstall, {
-    reason: BOOTSTRAP_REASONS.ADDON_DOWNGRADE,
-    params: {
+      oldVersion: "1.0",
       version: "0.8",
     },
   });
 
   await checkEvent(onStartup, {
     reason: BOOTSTRAP_REASONS.ADDON_DOWNGRADE,
     params: {
       version: "0.8",
@@ -625,29 +588,23 @@ add_task(async function() {
 
   unpackedAddon.remove(true);
   await promiseRestartManager();
 });
 
 // Installing a temporary add-on over an existing add-on with the same
 // version number should be installed as an upgrade.
 add_task(async function() {
-  // We can't install unpacked add-ons on release builds. See above.
-  if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
-    return;
-  }
-
-  const tempdir = gTmpD.clone();
+  const unpackedAddon = gTmpD.clone();
+  unpackedAddon.append(ID);
 
-  await promiseWriteInstallRDFToDir(sampleRDFManifest, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
-
-  const unpackedAddon = tempdir.clone();
-  unpackedAddon.append(ID);
-  do_get_file("data/test_temporary/bootstrap.js")
-    .copyTo(unpackedAddon, "bootstrap.js");
+  await promiseWriteWebExtensionToDir(unpackedAddon, {
+    applications: {gecko: {id: ID}},
+    version: "1.0",
+  });
 
   const onInitialInstall = waitForBootstrapEvent("install", ID);
   const onInitialStartup = waitForBootstrapEvent("startup", ID);
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   await checkEvent(onInitialInstall, {
     reason: BOOTSTRAP_REASONS.ADDON_INSTALL,
     params: {
@@ -662,38 +619,31 @@ add_task(async function() {
     },
   });
 
   let info = Monitor.started.get(ID);
   Assert.equal(info.reason, BOOTSTRAP_REASONS.ADDON_INSTALL);
 
   // Install it again.
   const onShutdown = waitForBootstrapEvent("shutdown", ID);
-  const onUninstall = waitForBootstrapEvent("uninstall", ID);
-  const onInstall = waitForBootstrapEvent("install", ID);
+  const onUpdate = waitForBootstrapEvent("update", ID);
   const onStartup = waitForBootstrapEvent("startup", ID);
   await AddonManager.installTemporaryAddon(unpackedAddon);
 
   await checkEvent(onShutdown, {
     reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
     params: {
       version: "1.0",
     },
   });
 
-  await checkEvent(onUninstall, {
+  await checkEvent(onUpdate, {
     reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
     params: {
-      version: "1.0",
-    },
-  });
-
-  await checkEvent(onInstall, {
-    reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
-    params: {
+      oldVersion: "1.0",
       version: "1.0",
     },
   });
 
   await checkEvent(onStartup, {
     reason: BOOTSTRAP_REASONS.ADDON_UPGRADE,
     params: {
       version: "1.0",
@@ -705,49 +655,34 @@ add_task(async function() {
 
   unpackedAddon.remove(true);
   await promiseRestartManager();
 });
 
 // Install a temporary add-on over the top of an existing disabled add-on.
 // After restart, the existing add-on should continue to be installed and disabled.
 add_task(async function() {
-  // We can't install unpacked add-ons on release builds. See above.
-  if (!AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS) {
-    return;
-  }
-
   let {addon} = await promiseInstallFile(do_get_addon("test_bootstrap1_1"), true);
 
   Monitor.checkInstalled(ID, "1.0");
   Monitor.checkStarted(ID, "1.0");
 
   await addon.disable();
 
   Monitor.checkInstalled(ID, "1.0");
   Monitor.checkNotStarted(ID);
 
-  let tempdir = gTmpD.clone();
-  await promiseWriteInstallRDFToDir({
-    id: ID,
+  let unpacked_addon = gTmpD.clone();
+  unpacked_addon.append(ID);
+
+  await promiseWriteWebExtensionToDir(unpacked_addon, {
+    applications: {gecko: {id: ID}},
+    name: "Test Bootstrap 1 (temporary)",
     version: "2.0",
-    bootstrap: true,
-    unpack: true,
-    targetApplications: [{
-          id: "xpcshell@tests.mozilla.org",
-      minVersion: "1",
-      maxVersion: "1"
-        }],
-    name: "Test Bootstrap 1 (temporary)",
-  }, tempdir, "bootstrap1@tests.mozilla.org", "bootstrap.js");
-
-  let unpacked_addon = tempdir.clone();
-  unpacked_addon.append(ID);
-  do_get_file("data/test_temporary/bootstrap.js")
-    .copyTo(unpacked_addon, "bootstrap.js");
+  });
 
   let extInstallCalled = false;
   AddonManager.addInstallListener({
     onExternalInstall: (aInstall) => {
       Assert.equal(aInstall.id, ID);
       Assert.equal(aInstall.version, "2.0");
       extInstallCalled = true;
     },