Bug 1359733 - (pt. 3) Move update tests to browser/components draft
authorDoug Thayer <dothayer@mozilla.com>
Mon, 15 May 2017 09:31:58 -0700
changeset 578006 f97cabea81e9824cdaacab7513bce2a22982fa28
parent 578005 542e9e203202d51155366c4d9e6b674a518c08e9
child 578007 aab3abffab2097ef5f741f33caf1a23238ac1a81
push id58858
push userbmo:dothayer@mozilla.com
push dateMon, 15 May 2017 19:12:31 +0000
bugs1359733
milestone55.0a1
Bug 1359733 - (pt. 3) Move update tests to browser/components This is because the logic that they are testing has been moved out of browser.js into browser/components/appUpdate. MozReview-Commit-ID: DJcMg2JtnJ2
browser/base/content/moz.build
browser/base/content/test/appUpdate/.eslintrc.js
browser/base/content/test/appUpdate/browser.ini
browser/base/content/test/appUpdate/browser_updatesBackgroundWindow.js
browser/base/content/test/appUpdate/browser_updatesBackgroundWindowFailures.js
browser/base/content/test/appUpdate/browser_updatesBasicPrompt.js
browser/base/content/test/appUpdate/browser_updatesBasicPromptNoStaging.js
browser/base/content/test/appUpdate/browser_updatesCantApply.js
browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadCompleteSize.js
browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadPartialSize.js
browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadSizes.js
browser/base/content/test/appUpdate/browser_updatesCompletePatchApplyFailure.js
browser/base/content/test/appUpdate/browser_updatesCompletePatchWithBadCompleteSize.js
browser/base/content/test/appUpdate/browser_updatesDownloadFailures.js
browser/base/content/test/appUpdate/browser_updatesMalformedXml.js
browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailure.js
browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailureWithCompleteAvailable.js
browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailureWithCompleteValidationFailure.js
browser/base/content/test/appUpdate/browser_updatesPartialPatchWithBadPartialSize.js
browser/base/content/test/appUpdate/downloadPage.html
browser/base/content/test/appUpdate/head.js
browser/base/content/test/appUpdate/testConstants.js
browser/base/moz.build
browser/components/appUpdate/moz.build
browser/components/appUpdate/test/.eslintrc.js
browser/components/appUpdate/test/browser.ini
browser/components/appUpdate/test/browser_updatesBackgroundWindow.js
browser/components/appUpdate/test/browser_updatesBackgroundWindowFailures.js
browser/components/appUpdate/test/browser_updatesBasicPrompt.js
browser/components/appUpdate/test/browser_updatesBasicPromptNoStaging.js
browser/components/appUpdate/test/browser_updatesCantApply.js
browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadCompleteSize.js
browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadPartialSize.js
browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadSizes.js
browser/components/appUpdate/test/browser_updatesCompletePatchApplyFailure.js
browser/components/appUpdate/test/browser_updatesCompletePatchWithBadCompleteSize.js
browser/components/appUpdate/test/browser_updatesDownloadFailures.js
browser/components/appUpdate/test/browser_updatesMalformedXml.js
browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailure.js
browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailureWithCompleteAvailable.js
browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailureWithCompleteValidationFailure.js
browser/components/appUpdate/test/browser_updatesPartialPatchWithBadPartialSize.js
browser/components/appUpdate/test/downloadPage.html
browser/components/appUpdate/test/head.js
browser/components/appUpdate/test/testConstants.js
--- a/browser/base/content/moz.build
+++ b/browser/base/content/moz.build
@@ -26,19 +26,16 @@ with Files("pageinfo/**"):
     BUG_COMPONENT = ("Firefox", "Page Info Window")
 
 with Files("sync/**"):
     BUG_COMPONENT = ("Firefox", "Sync")
 
 with Files("test/alerts/**"):
     BUG_COMPONENT = ("Toolkit", "Notifications and Alerts")
 
-with Files("test/appUpdate/**"):
-    BUG_COMPONENT = ("Toolkit", "Application Update")
-
 with Files("test/captivePortal/**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("test/chrome/**"):
     BUG_COMPONENT = ("Firefox", "General")
 
 with Files("test/forms/**"):
     BUG_COMPONENT = ("Core", "Layout: Form Controls")
deleted file mode 100644
--- a/browser/base/content/test/appUpdate/head.js
+++ /dev/null
@@ -1,408 +0,0 @@
-Cu.import("resource://gre/modules/FileUtils.jsm");
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
-                                  "resource://gre/modules/AppMenuNotifications.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UpdateListener",
-                                  "resource:///modules/UpdateListener.jsm");
-
-const IS_MACOSX = ("nsILocalFileMac" in Ci);
-const IS_WIN = ("@mozilla.org/windows-registry-key;1" in Cc);
-
-const BIN_SUFFIX = (IS_WIN ? ".exe" : "");
-const FILE_UPDATER_BIN = "updater" + (IS_MACOSX ? ".app" : BIN_SUFFIX);
-const FILE_UPDATER_BIN_BAK = FILE_UPDATER_BIN + ".bak";
-
-const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
-const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
-
-let gRembemberedPrefs = [];
-
-const DATA_URI_SPEC =  "chrome://mochitests/content/browser/browser/base/content/test/appUpdate/";
-
-var DEBUG_AUS_TEST = true;
-var gUseTestUpdater = false;
-
-const LOG_FUNCTION = info;
-
-/* import-globals-from testConstants.js */
-Services.scriptloader.loadSubScript(DATA_URI_SPEC + "testConstants.js", this);
-/* import-globals-from ../../../../../toolkit/mozapps/update/tests/data/shared.js */
-Services.scriptloader.loadSubScript(DATA_URI_SPEC + "shared.js", this);
-
-var gURLData = URL_HOST + "/" + REL_PATH_DATA;
-const URL_MANUAL_UPDATE = gURLData + "downloadPage.html";
-
-const gEnv = Cc["@mozilla.org/process/environment;1"].
-             getService(Components.interfaces.nsIEnvironment);
-
-const NOTIFICATIONS = [
-  "update-available",
-  "update-manual",
-  "update-restart"
-];
-
-/**
- * Delay for a very short period. Useful for moving the code after this
- * to the back of the event loop.
- *
- * @return A promise which will resolve after a very short period.
- */
-function delay() {
-  return new Promise(resolve => executeSoon(resolve));
-}
-
-/**
- * Gets the update version info for the update url parameters to send to
- * update.sjs.
- *
- * @param  aAppVersion (optional)
- *         The application version for the update snippet. If not specified the
- *         current application version will be used.
- * @return The url parameters for the application and platform version to send
- *         to update.sjs.
- */
-function getVersionParams(aAppVersion) {
-  let appInfo = Services.appinfo;
-  return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version);
-}
-
-/**
- * Clean up updates list and the updates directory.
- */
-function cleanUpUpdates() {
-  gUpdateManager.activeUpdate = null;
-  gUpdateManager.saveUpdates();
-
-  removeUpdateDirsAndFiles();
-}
-
-/**
- * Prevent nsIUpdateTimerManager from notifying nsIApplicationUpdateService
- * to check for updates by setting the app update last update time to the
- * current time minus one minute in seconds and the interval time to 12 hours
- * in seconds.
- */
-function setUpdateTimerPrefs() {
-  let now = Math.round(Date.now() / 1000) - 60;
-  Services.prefs.setIntPref(PREF_APP_UPDATE_LASTUPDATETIME, now);
-  Services.prefs.setIntPref(PREF_APP_UPDATE_INTERVAL, 43200);
-}
-
-/**
- * Runs a typical update test. Will set various common prefs for using the
- * updater doorhanger, runs the provided list of steps, and makes sure
- * everything is cleaned up afterwards.
- *
- * @param  updateParams
- *         URL-encoded params which will be sent to update.sjs.
- * @param  checkAttempts
- *         How many times to check for updates. Useful for testing the UI
- *         for check failures.
- * @param  steps
- *         A list of test steps to perform, specifying expected doorhangers
- *         and additional validation/cleanup callbacks.
- * @return A promise which will resolve once all of the steps have been run
- *         and cleanup has been performed.
- */
-function runUpdateTest(updateParams, checkAttempts, steps) {
-  return (async function() {
-    registerCleanupFunction(() => {
-      gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
-      UpdateListener.reset();
-      cleanUpUpdates();
-    });
-
-    gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
-    setUpdateTimerPrefs();
-    await SpecialPowers.pushPrefEnv({
-      set: [
-        [PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
-        [PREF_APP_UPDATE_ENABLED, true],
-        [PREF_APP_UPDATE_IDLETIME, 0],
-        [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
-        [PREF_APP_UPDATE_LOG, DEBUG_AUS_TEST],
-      ]});
-
-    await setupTestUpdater();
-
-    let url = URL_HTTP_UPDATE_SJS +
-              "?" + updateParams +
-              getVersionParams();
-
-    setUpdateURL(url);
-
-    executeSoon(() => {
-      (async function() {
-        gAUS.checkForBackgroundUpdates();
-        for (var i = 0; i < checkAttempts - 1; i++) {
-          await waitForEvent("update-error", "check-attempt-failed");
-          gAUS.checkForBackgroundUpdates();
-        }
-      })();
-    });
-
-    for (let step of steps) {
-      await processStep(step);
-    }
-
-    await finishTestRestoreUpdaterBackup();
-  })();
-}
-
-/**
- * Runs a test which processes an update. Similar to runUpdateTest.
- *
- * @param  updates
- *         A list of updates to process.
- * @param  steps
- *         A list of test steps to perform, specifying expected doorhangers
- *         and additional validation/cleanup callbacks.
- * @return A promise which will resolve once all of the steps have been run
- *         and cleanup has been performed.
- */
-function runUpdateProcessingTest(updates, steps) {
-  return (async function() {
-    registerCleanupFunction(() => {
-      gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
-      UpdateListener.reset();
-      cleanUpUpdates();
-    });
-
-    setUpdateTimerPrefs();
-    gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
-    SpecialPowers.pushPrefEnv({
-      set: [
-        [PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
-        [PREF_APP_UPDATE_ENABLED, true],
-        [PREF_APP_UPDATE_IDLETIME, 0],
-        [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
-        [PREF_APP_UPDATE_LOG, DEBUG_AUS_TEST],
-      ]});
-
-    await setupTestUpdater();
-
-    writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
-
-    writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
-    writeStatusFile(STATE_FAILED_CRC_ERROR);
-    reloadUpdateManagerData();
-
-    testPostUpdateProcessing();
-
-    for (let step of steps) {
-      await processStep(step);
-    }
-
-    await finishTestRestoreUpdaterBackup();
-  })();
-}
-
-function processStep(step) {
-  if (typeof(step) == "function") {
-    return step();
-  }
-
-  const {notificationId, button, beforeClick, cleanup} = step;
-  return (async function() {
-
-    await BrowserTestUtils.waitForEvent(PanelUI.notificationPanel, "popupshown");
-    const shownNotification = PanelUI.activeNotification.id;
-
-    is(shownNotification, notificationId, "The right notification showed up.");
-    if (shownNotification != notificationId) {
-      if (cleanup) {
-        await cleanup();
-      }
-      return;
-    }
-
-    let buttonEl = getNotificationButton(window, notificationId, button);
-    if (beforeClick) {
-      await beforeClick();
-    }
-
-
-    buttonEl.click();
-
-    if (cleanup) {
-      await cleanup();
-    }
-  })();
-}
-
-/**
- * Waits for the specified topic and (optionally) status.
- * @param  topic
- *         String representing the topic to wait for.
- * @param  status
- *         Optional String representing the status on said topic to wait for.
- * @return A promise which will resolve the first time an event occurs on the
- *         specified topic, and (optionally) with the specified status.
- */
-function waitForEvent(topic, status = null) {
-  return new Promise(resolve => Services.obs.addObserver({
-    observe(subject, innerTopic, innerStatus) {
-      if (!status || status == innerStatus) {
-        Services.obs.removeObserver(this, topic);
-        resolve(innerStatus);
-      }
-    }
-  }, topic))
-}
-
-/**
- * Gets the specified button for the notification.
- *
- * @param  window
- *         The window to get the notification button for.
- * @param  notificationId
- *         The ID of the notification to get the button for.
- * @param  button
- *         The anonid of the button to get.
- */
-function getNotificationButton(win, notificationId, button) {
-  let notification = win.document.getElementById(`appMenu-${notificationId}-notification`);
-  is(notification.hidden, false, `${notificationId} notification is showing`);
-  return win.document.getAnonymousElementByAttribute(notification, "anonid", button);
-}
-
-/**
- * Ensures that the "What's new" link with the provided ID is displayed and
- * matches the url parameter provided. If no URL is provided, it will instead
- * ensure that the link matches the default link URL.
- *
- * @param  id
- *         The ID of the "What's new" link element.
- * @param  url (optional)
- *         The URL to check against. If none is provided, a default will be used.
- */
-function checkWhatsNewLink(id, url) {
-  let whatsNewLink = document.getElementById(id);
-  is(whatsNewLink.href,
-     url || URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS",
-     "What's new link points to the test_details URL");
-  is(whatsNewLink.hidden, false, "What's new link is not hidden.");
-}
-
-/**
- * For tests that use the test updater restores the backed up real updater if
- * it exists and tries again on failure since Windows debug builds at times
- * leave the file in use. After success moveRealUpdater is called to continue
- * the setup of the test updater. For tests that don't use the test updater
- * runTest will be called.
- */
-function setupTestUpdater() {
-  return (async function() {
-    if (gUseTestUpdater) {
-      try {
-        restoreUpdaterBackup();
-      } catch (e) {
-        logTestInfo("Attempt to restore the backed up updater failed... " +
-                    "will try again, Exception: " + e);
-        await delay();
-        await setupTestUpdater();
-        return;
-      }
-      await moveRealUpdater();
-    }
-  })();
-}
-
-/**
- * Backs up the real updater and tries again on failure since Windows debug
- * builds at times leave the file in use. After success it will call
- * copyTestUpdater to continue the setup of the test updater.
- */
-function moveRealUpdater() {
-  return (async function() {
-    try {
-      // Move away the real updater
-      let baseAppDir = getAppBaseDir();
-      let updater = baseAppDir.clone();
-      updater.append(FILE_UPDATER_BIN);
-      updater.moveTo(baseAppDir, FILE_UPDATER_BIN_BAK);
-    } catch (e) {
-      logTestInfo("Attempt to move the real updater out of the way failed... " +
-                  "will try again, Exception: " + e);
-      await delay();
-      await moveRealUpdater();
-      return;
-    }
-
-    await copyTestUpdater();
-  })();
-}
-
-/**
- * Copies the test updater so it can be used by tests and tries again on failure
- * since Windows debug builds at times leave the file in use. After success it
- * will call runTest to continue the test.
- */
-function copyTestUpdater() {
-  return (async function() {
-    try {
-      // Copy the test updater
-      let baseAppDir = getAppBaseDir();
-      let testUpdaterDir = Services.dirsvc.get("CurWorkD", Ci.nsILocalFile);
-      let relPath = REL_PATH_DATA;
-      let pathParts = relPath.split("/");
-      for (let i = 0; i < pathParts.length; ++i) {
-        testUpdaterDir.append(pathParts[i]);
-      }
-
-      let testUpdater = testUpdaterDir.clone();
-      testUpdater.append(FILE_UPDATER_BIN);
-      testUpdater.copyToFollowingLinks(baseAppDir, FILE_UPDATER_BIN);
-    } catch (e) {
-      logTestInfo("Attempt to copy the test updater failed... " +
-                  "will try again, Exception: " + e);
-      await delay();
-      await copyTestUpdater();
-    }
-  })();
-}
-
-/**
- * Restores the updater that was backed up. This is called in setupTestUpdater
- * before the backup of the real updater is done in case the previous test
- * failed to restore the updater, in finishTestDefaultWaitForWindowClosed when
- * the test has finished, and in test_9999_cleanup.xul after all tests have
- * finished.
- */
-function restoreUpdaterBackup() {
-  let baseAppDir = getAppBaseDir();
-  let updater = baseAppDir.clone();
-  let updaterBackup = baseAppDir.clone();
-  updater.append(FILE_UPDATER_BIN);
-  updaterBackup.append(FILE_UPDATER_BIN_BAK);
-  if (updaterBackup.exists()) {
-    if (updater.exists()) {
-      updater.remove(true);
-    }
-    updaterBackup.moveTo(baseAppDir, FILE_UPDATER_BIN);
-  }
-}
-
-/**
- * When a test finishes this will repeatedly attempt to restore the real updater
- * for tests that use the test updater and then call
- * finishTestDefaultWaitForWindowClosed after the restore is successful.
- */
-function finishTestRestoreUpdaterBackup() {
-  return (async function() {
-    if (gUseTestUpdater) {
-      try {
-        // Windows debug builds keep the updater file in use for a short period of
-        // time after the updater process exits.
-        restoreUpdaterBackup();
-      } catch (e) {
-        logTestInfo("Attempt to restore the backed up updater failed... " +
-                    "will try again, Exception: " + e);
-
-        await delay();
-        await finishTestRestoreUpdaterBackup();
-      }
-    }
-  })();
-}
--- a/browser/base/moz.build
+++ b/browser/base/moz.build
@@ -35,33 +35,23 @@ BROWSER_CHROME_MANIFESTS += [
     'content/test/tabPrompts/browser.ini',
     'content/test/tabs/browser.ini',
     'content/test/urlbar/browser.ini',
     'content/test/webextensions/browser.ini',
     'content/test/webrtc/browser.ini',
     'content/test/windows/browser.ini',
 ]
 
-if CONFIG['MOZ_UPDATER']:
-    BROWSER_CHROME_MANIFESTS += ['content/test/appUpdate/browser.ini']
-
 DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
 DEFINES['MOZ_APP_VERSION_DISPLAY'] = CONFIG['MOZ_APP_VERSION_DISPLAY']
 
 DEFINES['APP_LICENSE_BLOCK'] = '%s/content/overrides/app-license.html' % SRCDIR
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3', 'cocoa'):
     DEFINES['CONTEXT_COPY_IMAGE_CONTENTS'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'cocoa'):
     DEFINES['CAN_DRAW_IN_TITLEBAR'] = 1
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('windows', 'gtk2', 'gtk3'):
     DEFINES['MENUBAR_CAN_AUTOHIDE'] = 1
 
-TEST_HARNESS_FILES.testing.mochitest.browser.browser.base.content.test.appUpdate += [
-    '/toolkit/mozapps/update/tests/chrome/update.sjs',
-    '/toolkit/mozapps/update/tests/data/shared.js',
-    '/toolkit/mozapps/update/tests/data/sharedUpdateXML.js',
-    '/toolkit/mozapps/update/tests/data/simple.mar',
-]
-
 JAR_MANIFESTS += ['jar.mn']
--- a/browser/components/appUpdate/moz.build
+++ b/browser/components/appUpdate/moz.build
@@ -1,14 +1,22 @@
 # -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
-# BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
+if CONFIG['MOZ_UPDATER']:
+    BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
+
+TEST_HARNESS_FILES.testing.mochitest.browser.browser.base.content.test.appUpdate += [
+    '/toolkit/mozapps/update/tests/chrome/update.sjs',
+    '/toolkit/mozapps/update/tests/data/shared.js',
+    '/toolkit/mozapps/update/tests/data/sharedUpdateXML.js',
+    '/toolkit/mozapps/update/tests/data/simple.mar',
+]
 
 EXTRA_JS_MODULES += [
     'UpdateListener.jsm',
 ]
 
 with Files('**'):
     BUG_COMPONENT = ('Toolkit', 'Application Update')
rename from browser/base/content/test/appUpdate/.eslintrc.js
rename to browser/components/appUpdate/test/.eslintrc.js
rename from browser/base/content/test/appUpdate/browser.ini
rename to browser/components/appUpdate/test/browser.ini
rename from browser/base/content/test/appUpdate/browser_updatesBackgroundWindow.js
rename to browser/components/appUpdate/test/browser_updatesBackgroundWindow.js
rename from browser/base/content/test/appUpdate/browser_updatesBackgroundWindowFailures.js
rename to browser/components/appUpdate/test/browser_updatesBackgroundWindowFailures.js
rename from browser/base/content/test/appUpdate/browser_updatesBasicPrompt.js
rename to browser/components/appUpdate/test/browser_updatesBasicPrompt.js
rename from browser/base/content/test/appUpdate/browser_updatesBasicPromptNoStaging.js
rename to browser/components/appUpdate/test/browser_updatesBasicPromptNoStaging.js
rename from browser/base/content/test/appUpdate/browser_updatesCantApply.js
rename to browser/components/appUpdate/test/browser_updatesCantApply.js
rename from browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadCompleteSize.js
rename to browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadCompleteSize.js
rename from browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadPartialSize.js
rename to browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadPartialSize.js
rename from browser/base/content/test/appUpdate/browser_updatesCompleteAndPartialPatchesWithBadSizes.js
rename to browser/components/appUpdate/test/browser_updatesCompleteAndPartialPatchesWithBadSizes.js
rename from browser/base/content/test/appUpdate/browser_updatesCompletePatchApplyFailure.js
rename to browser/components/appUpdate/test/browser_updatesCompletePatchApplyFailure.js
rename from browser/base/content/test/appUpdate/browser_updatesCompletePatchWithBadCompleteSize.js
rename to browser/components/appUpdate/test/browser_updatesCompletePatchWithBadCompleteSize.js
rename from browser/base/content/test/appUpdate/browser_updatesDownloadFailures.js
rename to browser/components/appUpdate/test/browser_updatesDownloadFailures.js
rename from browser/base/content/test/appUpdate/browser_updatesMalformedXml.js
rename to browser/components/appUpdate/test/browser_updatesMalformedXml.js
rename from browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailure.js
rename to browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailure.js
rename from browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailureWithCompleteAvailable.js
rename to browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailureWithCompleteAvailable.js
rename from browser/base/content/test/appUpdate/browser_updatesPartialPatchApplyFailureWithCompleteValidationFailure.js
rename to browser/components/appUpdate/test/browser_updatesPartialPatchApplyFailureWithCompleteValidationFailure.js
rename from browser/base/content/test/appUpdate/browser_updatesPartialPatchWithBadPartialSize.js
rename to browser/components/appUpdate/test/browser_updatesPartialPatchWithBadPartialSize.js
rename from browser/base/content/test/appUpdate/downloadPage.html
rename to browser/components/appUpdate/test/downloadPage.html
new file mode 100644
--- /dev/null
+++ b/browser/components/appUpdate/test/head.js
@@ -0,0 +1,408 @@
+Cu.import("resource://gre/modules/FileUtils.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "AppMenuNotifications",
+                                  "resource://gre/modules/AppMenuNotifications.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "UpdateListener",
+                                  "resource:///modules/UpdateListener.jsm");
+
+const IS_MACOSX = ("nsILocalFileMac" in Ci);
+const IS_WIN = ("@mozilla.org/windows-registry-key;1" in Cc);
+
+const BIN_SUFFIX = (IS_WIN ? ".exe" : "");
+const FILE_UPDATER_BIN = "updater" + (IS_MACOSX ? ".app" : BIN_SUFFIX);
+const FILE_UPDATER_BIN_BAK = FILE_UPDATER_BIN + ".bak";
+
+const PREF_APP_UPDATE_INTERVAL = "app.update.interval";
+const PREF_APP_UPDATE_LASTUPDATETIME = "app.update.lastUpdateTime.background-update-timer";
+
+let gRembemberedPrefs = [];
+
+const DATA_URI_SPEC =  "chrome://mochitests/content/browser/browser/base/content/test/appUpdate/";
+
+var DEBUG_AUS_TEST = true;
+var gUseTestUpdater = false;
+
+const LOG_FUNCTION = info;
+
+/* import-globals-from testConstants.js */
+Services.scriptloader.loadSubScript(DATA_URI_SPEC + "testConstants.js", this);
+/* import-globals-from ../../../../toolkit/mozapps/update/tests/data/shared.js */
+Services.scriptloader.loadSubScript(DATA_URI_SPEC + "shared.js", this);
+
+var gURLData = URL_HOST + "/" + REL_PATH_DATA;
+const URL_MANUAL_UPDATE = gURLData + "downloadPage.html";
+
+const gEnv = Cc["@mozilla.org/process/environment;1"].
+             getService(Components.interfaces.nsIEnvironment);
+
+const NOTIFICATIONS = [
+  "update-available",
+  "update-manual",
+  "update-restart"
+];
+
+/**
+ * Delay for a very short period. Useful for moving the code after this
+ * to the back of the event loop.
+ *
+ * @return A promise which will resolve after a very short period.
+ */
+function delay() {
+  return new Promise(resolve => executeSoon(resolve));
+}
+
+/**
+ * Gets the update version info for the update url parameters to send to
+ * update.sjs.
+ *
+ * @param  aAppVersion (optional)
+ *         The application version for the update snippet. If not specified the
+ *         current application version will be used.
+ * @return The url parameters for the application and platform version to send
+ *         to update.sjs.
+ */
+function getVersionParams(aAppVersion) {
+  let appInfo = Services.appinfo;
+  return "&appVersion=" + (aAppVersion ? aAppVersion : appInfo.version);
+}
+
+/**
+ * Clean up updates list and the updates directory.
+ */
+function cleanUpUpdates() {
+  gUpdateManager.activeUpdate = null;
+  gUpdateManager.saveUpdates();
+
+  removeUpdateDirsAndFiles();
+}
+
+/**
+ * Prevent nsIUpdateTimerManager from notifying nsIApplicationUpdateService
+ * to check for updates by setting the app update last update time to the
+ * current time minus one minute in seconds and the interval time to 12 hours
+ * in seconds.
+ */
+function setUpdateTimerPrefs() {
+  let now = Math.round(Date.now() / 1000) - 60;
+  Services.prefs.setIntPref(PREF_APP_UPDATE_LASTUPDATETIME, now);
+  Services.prefs.setIntPref(PREF_APP_UPDATE_INTERVAL, 43200);
+}
+
+/**
+ * Runs a typical update test. Will set various common prefs for using the
+ * updater doorhanger, runs the provided list of steps, and makes sure
+ * everything is cleaned up afterwards.
+ *
+ * @param  updateParams
+ *         URL-encoded params which will be sent to update.sjs.
+ * @param  checkAttempts
+ *         How many times to check for updates. Useful for testing the UI
+ *         for check failures.
+ * @param  steps
+ *         A list of test steps to perform, specifying expected doorhangers
+ *         and additional validation/cleanup callbacks.
+ * @return A promise which will resolve once all of the steps have been run
+ *         and cleanup has been performed.
+ */
+function runUpdateTest(updateParams, checkAttempts, steps) {
+  return (async function() {
+    registerCleanupFunction(() => {
+      gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
+      UpdateListener.reset();
+      cleanUpUpdates();
+    });
+
+    gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
+    setUpdateTimerPrefs();
+    await SpecialPowers.pushPrefEnv({
+      set: [
+        [PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
+        [PREF_APP_UPDATE_ENABLED, true],
+        [PREF_APP_UPDATE_IDLETIME, 0],
+        [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
+        [PREF_APP_UPDATE_LOG, DEBUG_AUS_TEST],
+      ]});
+
+    await setupTestUpdater();
+
+    let url = URL_HTTP_UPDATE_SJS +
+              "?" + updateParams +
+              getVersionParams();
+
+    setUpdateURL(url);
+
+    executeSoon(() => {
+      (async function() {
+        gAUS.checkForBackgroundUpdates();
+        for (var i = 0; i < checkAttempts - 1; i++) {
+          await waitForEvent("update-error", "check-attempt-failed");
+          gAUS.checkForBackgroundUpdates();
+        }
+      })();
+    });
+
+    for (let step of steps) {
+      await processStep(step);
+    }
+
+    await finishTestRestoreUpdaterBackup();
+  })();
+}
+
+/**
+ * Runs a test which processes an update. Similar to runUpdateTest.
+ *
+ * @param  updates
+ *         A list of updates to process.
+ * @param  steps
+ *         A list of test steps to perform, specifying expected doorhangers
+ *         and additional validation/cleanup callbacks.
+ * @return A promise which will resolve once all of the steps have been run
+ *         and cleanup has been performed.
+ */
+function runUpdateProcessingTest(updates, steps) {
+  return (async function() {
+    registerCleanupFunction(() => {
+      gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "");
+      UpdateListener.reset();
+      cleanUpUpdates();
+    });
+
+    setUpdateTimerPrefs();
+    gEnv.set("MOZ_TEST_SKIP_UPDATE_STAGE", "1");
+    SpecialPowers.pushPrefEnv({
+      set: [
+        [PREF_APP_UPDATE_DOWNLOADPROMPTATTEMPTS, 0],
+        [PREF_APP_UPDATE_ENABLED, true],
+        [PREF_APP_UPDATE_IDLETIME, 0],
+        [PREF_APP_UPDATE_URL_MANUAL, URL_MANUAL_UPDATE],
+        [PREF_APP_UPDATE_LOG, DEBUG_AUS_TEST],
+      ]});
+
+    await setupTestUpdater();
+
+    writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
+
+    writeUpdatesToXMLFile(getLocalUpdatesXMLString(""), false);
+    writeStatusFile(STATE_FAILED_CRC_ERROR);
+    reloadUpdateManagerData();
+
+    testPostUpdateProcessing();
+
+    for (let step of steps) {
+      await processStep(step);
+    }
+
+    await finishTestRestoreUpdaterBackup();
+  })();
+}
+
+function processStep(step) {
+  if (typeof(step) == "function") {
+    return step();
+  }
+
+  const {notificationId, button, beforeClick, cleanup} = step;
+  return (async function() {
+
+    await BrowserTestUtils.waitForEvent(PanelUI.notificationPanel, "popupshown");
+    const shownNotification = PanelUI.activeNotification.id;
+
+    is(shownNotification, notificationId, "The right notification showed up.");
+    if (shownNotification != notificationId) {
+      if (cleanup) {
+        await cleanup();
+      }
+      return;
+    }
+
+    let buttonEl = getNotificationButton(window, notificationId, button);
+    if (beforeClick) {
+      await beforeClick();
+    }
+
+
+    buttonEl.click();
+
+    if (cleanup) {
+      await cleanup();
+    }
+  })();
+}
+
+/**
+ * Waits for the specified topic and (optionally) status.
+ * @param  topic
+ *         String representing the topic to wait for.
+ * @param  status
+ *         Optional String representing the status on said topic to wait for.
+ * @return A promise which will resolve the first time an event occurs on the
+ *         specified topic, and (optionally) with the specified status.
+ */
+function waitForEvent(topic, status = null) {
+  return new Promise(resolve => Services.obs.addObserver({
+    observe(subject, innerTopic, innerStatus) {
+      if (!status || status == innerStatus) {
+        Services.obs.removeObserver(this, topic);
+        resolve(innerStatus);
+      }
+    }
+  }, topic))
+}
+
+/**
+ * Gets the specified button for the notification.
+ *
+ * @param  window
+ *         The window to get the notification button for.
+ * @param  notificationId
+ *         The ID of the notification to get the button for.
+ * @param  button
+ *         The anonid of the button to get.
+ */
+function getNotificationButton(win, notificationId, button) {
+  let notification = win.document.getElementById(`appMenu-${notificationId}-notification`);
+  is(notification.hidden, false, `${notificationId} notification is showing`);
+  return win.document.getAnonymousElementByAttribute(notification, "anonid", button);
+}
+
+/**
+ * Ensures that the "What's new" link with the provided ID is displayed and
+ * matches the url parameter provided. If no URL is provided, it will instead
+ * ensure that the link matches the default link URL.
+ *
+ * @param  id
+ *         The ID of the "What's new" link element.
+ * @param  url (optional)
+ *         The URL to check against. If none is provided, a default will be used.
+ */
+function checkWhatsNewLink(id, url) {
+  let whatsNewLink = document.getElementById(id);
+  is(whatsNewLink.href,
+     url || URL_HTTP_UPDATE_SJS + "?uiURL=DETAILS",
+     "What's new link points to the test_details URL");
+  is(whatsNewLink.hidden, false, "What's new link is not hidden.");
+}
+
+/**
+ * For tests that use the test updater restores the backed up real updater if
+ * it exists and tries again on failure since Windows debug builds at times
+ * leave the file in use. After success moveRealUpdater is called to continue
+ * the setup of the test updater. For tests that don't use the test updater
+ * runTest will be called.
+ */
+function setupTestUpdater() {
+  return (async function() {
+    if (gUseTestUpdater) {
+      try {
+        restoreUpdaterBackup();
+      } catch (e) {
+        logTestInfo("Attempt to restore the backed up updater failed... " +
+                    "will try again, Exception: " + e);
+        await delay();
+        await setupTestUpdater();
+        return;
+      }
+      await moveRealUpdater();
+    }
+  })();
+}
+
+/**
+ * Backs up the real updater and tries again on failure since Windows debug
+ * builds at times leave the file in use. After success it will call
+ * copyTestUpdater to continue the setup of the test updater.
+ */
+function moveRealUpdater() {
+  return (async function() {
+    try {
+      // Move away the real updater
+      let baseAppDir = getAppBaseDir();
+      let updater = baseAppDir.clone();
+      updater.append(FILE_UPDATER_BIN);
+      updater.moveTo(baseAppDir, FILE_UPDATER_BIN_BAK);
+    } catch (e) {
+      logTestInfo("Attempt to move the real updater out of the way failed... " +
+                  "will try again, Exception: " + e);
+      await delay();
+      await moveRealUpdater();
+      return;
+    }
+
+    await copyTestUpdater();
+  })();
+}
+
+/**
+ * Copies the test updater so it can be used by tests and tries again on failure
+ * since Windows debug builds at times leave the file in use. After success it
+ * will call runTest to continue the test.
+ */
+function copyTestUpdater() {
+  return (async function() {
+    try {
+      // Copy the test updater
+      let baseAppDir = getAppBaseDir();
+      let testUpdaterDir = Services.dirsvc.get("CurWorkD", Ci.nsILocalFile);
+      let relPath = REL_PATH_DATA;
+      let pathParts = relPath.split("/");
+      for (let i = 0; i < pathParts.length; ++i) {
+        testUpdaterDir.append(pathParts[i]);
+      }
+
+      let testUpdater = testUpdaterDir.clone();
+      testUpdater.append(FILE_UPDATER_BIN);
+      testUpdater.copyToFollowingLinks(baseAppDir, FILE_UPDATER_BIN);
+    } catch (e) {
+      logTestInfo("Attempt to copy the test updater failed... " +
+                  "will try again, Exception: " + e);
+      await delay();
+      await copyTestUpdater();
+    }
+  })();
+}
+
+/**
+ * Restores the updater that was backed up. This is called in setupTestUpdater
+ * before the backup of the real updater is done in case the previous test
+ * failed to restore the updater, in finishTestDefaultWaitForWindowClosed when
+ * the test has finished, and in test_9999_cleanup.xul after all tests have
+ * finished.
+ */
+function restoreUpdaterBackup() {
+  let baseAppDir = getAppBaseDir();
+  let updater = baseAppDir.clone();
+  let updaterBackup = baseAppDir.clone();
+  updater.append(FILE_UPDATER_BIN);
+  updaterBackup.append(FILE_UPDATER_BIN_BAK);
+  if (updaterBackup.exists()) {
+    if (updater.exists()) {
+      updater.remove(true);
+    }
+    updaterBackup.moveTo(baseAppDir, FILE_UPDATER_BIN);
+  }
+}
+
+/**
+ * When a test finishes this will repeatedly attempt to restore the real updater
+ * for tests that use the test updater and then call
+ * finishTestDefaultWaitForWindowClosed after the restore is successful.
+ */
+function finishTestRestoreUpdaterBackup() {
+  return (async function() {
+    if (gUseTestUpdater) {
+      try {
+        // Windows debug builds keep the updater file in use for a short period of
+        // time after the updater process exits.
+        restoreUpdaterBackup();
+      } catch (e) {
+        logTestInfo("Attempt to restore the backed up updater failed... " +
+                    "will try again, Exception: " + e);
+
+        await delay();
+        await finishTestRestoreUpdaterBackup();
+      }
+    }
+  })();
+}
rename from browser/base/content/test/appUpdate/testConstants.js
rename to browser/components/appUpdate/test/testConstants.js