2. tests - Bug 466778 - [Win] Unable to update when files to be patched are in use on Windows. r=dtownsend, a=blocking2.0-BetaN
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 18 Nov 2010 17:20:58 -0800
changeset 57884 7bb86e5cc3b7877a65420350bc7d11af9929a98e
parent 57883 31504d26526632c2488cd4d06d1c3383922936ec
child 57885 302e3ea21728ddea642652f30e3d3b45fae0a454
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdtownsend, blocking2
bugs2, 466778
milestone2.0b8pre
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
2. tests - Bug 466778 - [Win] Unable to update when files to be patched are in use on Windows. r=dtownsend, a=blocking2.0-BetaN
toolkit/mozapps/update/test/TestAUSHelper.cpp
toolkit/mozapps/update/test/shared.js
toolkit/mozapps/update/test/unit/data/aus-0110_general.mar
toolkit/mozapps/update/test/unit/data/aus-0110_general_ref_image.png
toolkit/mozapps/update/test/unit/data/aus-0111_general.mar
toolkit/mozapps/update/test/unit/data/aus-0111_general_ref_image.png
toolkit/mozapps/update/test/unit/data/complete.mar
toolkit/mozapps/update/test/unit/data/complete.png
toolkit/mozapps/update/test/unit/data/partial.mar
toolkit/mozapps/update/test/unit/data/partial.png
toolkit/mozapps/update/test/unit/data/partial_in_use_win.mar
toolkit/mozapps/update/test/unit/data/partial_in_use_win_after.exe
toolkit/mozapps/update/test/unit/data/partial_in_use_win_before.exe
toolkit/mozapps/update/test/unit/head_update.js.in
toolkit/mozapps/update/test/unit/test_0110_general.js
toolkit/mozapps/update/test/unit/test_0111_general.js
toolkit/mozapps/update/test/unit/test_0112_general.js
toolkit/mozapps/update/test/unit/test_0160_appInUse_xp_unix_complete.js
toolkit/mozapps/update/test/unit/test_0160_appInUse_xp_win_complete.js
toolkit/mozapps/update/test/unit/test_0170_fileLocked_xp_win_complete.js
toolkit/mozapps/update/test/unit/test_0171_fileLocked_xp_win_partial.js
toolkit/mozapps/update/test/unit/test_0180_fileInUse_xp_win_complete.js
toolkit/mozapps/update/test/unit/test_0181_fileInUse_xp_win_partial.js
--- a/toolkit/mozapps/update/test/TestAUSHelper.cpp
+++ b/toolkit/mozapps/update/test/TestAUSHelper.cpp
@@ -9,28 +9,34 @@
   typedef WCHAR NS_tchar;
 # define NS_main wmain
 # define NS_T(str) L ## str
 # define NS_tsnprintf(dest, count, fmt, ...) \
     int _count = count - 1; \
     _snwprintf(dest, _count, fmt, ##__VA_ARGS__); \
     dest[_count] = L'\0';
 # define NS_tfopen _wfopen
+# define NS_tstrcmp wcscmp
+# define NS_ttoi _wtoi
 # define LOG_S "%S"
 #else
 # include <unistd.h>
 # define NS_main main
   typedef char NS_tchar;
 # define NS_T(str) str
 # define NS_tsnprintf snprintf
 # define NS_tfopen fopen
+# define NS_tstrcmp strcmp
+# define NS_ttoi atoi
 # define LOG_S "%s"
 #endif
 
+#include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 
 #ifndef MAXPATHLEN
 # ifdef PATH_MAX
 #  define MAXPATHLEN PATH_MAX
 # elif defined(MAX_PATH)
 #  define MAXPATHLEN MAX_PATH
 # elif defined(_MAX_PATH)
 #  define MAXPATHLEN _MAX_PATH
@@ -38,28 +44,74 @@
 #  define MAXPATHLEN CCHMAXPATH
 # else
 #  define MAXPATHLEN 1024
 # endif
 #endif
 
 int NS_main(int argc, NS_tchar **argv)
 {
+
+  if (argc < 2) {
+    fprintf(stderr, \
+            "\n" \
+            "Application Update Service Test Helper\n" \
+            "\n" \
+            "Usage: -s SECONDS [LOCKTYPE FILETOLOCK]\n"  \
+            "   or: LOGFILE [ARG2 ARG3...]\n" \
+            "\n" \
+            "  SECONDS     \tThe number of seconds to sleep.\n" \
+            "  FILETOLOCK  \tThe relative path to an existing file to open exlusively.\n" \
+            "              \tOnly available on Windows platforms and silently ignored on" \
+            "              \tother platforms.\n" \
+            "  LOGFILE     \tThe file path relative to the working directory to log the\n" \
+            "              \targuments passed to.\n" \
+            "  ARG2 ARG3...\tArguments to write to the log file.\n" \
+            "\n" \
+            "All paths should be relative since paths in a build environment can have a\n" \
+            "path length that is larger than the maximum path length on Windows.\n" \
+            "\n");
+    return 1;
+  }
+
+  // File in use test helper section
+  if (NS_tstrcmp(argv[1], NS_T("-s")) == 0) {
+#ifdef XP_WIN
+    int milliseconds = NS_ttoi(argv[2]) * 1000;
+    HANDLE hFile = INVALID_HANDLE_VALUE;
+    if (argc == 4) {
+      hFile = CreateFileW(argv[3],
+#ifdef WINCE
+                          GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+#else
+                          DELETE | GENERIC_WRITE, 0,
+#endif
+                          NULL, OPEN_EXISTING, 0, NULL);
+      if (hFile == INVALID_HANDLE_VALUE) {
+        return 1;
+      }
+    }
+
+    Sleep(milliseconds);
+
+    if (argc == 5) {
+      CloseHandle(hFile);
+    }
+#else
+    int seconds = NS_ttoi(argv[2]);
+    sleep(seconds);
+#endif
+    return 0;
+  }
+
+  // Command line argument test helper section
   NS_tchar logFilePath[MAXPATHLEN];
 
-#ifdef XP_WIN
-  NS_tchar exePath[MAXPATHLEN];
-
-  ::GetModuleFileNameW(0, exePath, MAXPATHLEN);
   NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
-               NS_T("%s.log"), exePath);
-#else
-  NS_tsnprintf(logFilePath, sizeof(logFilePath)/sizeof(logFilePath[0]),
-               NS_T("%s.log"), argv[0]);
-#endif
+               NS_T("%s"), argv[1]);
 
   FILE* logFP = NS_tfopen(logFilePath, NS_T("w"));
 
   fprintf(logFP, "executed\n");
 
   int i;
   for (i = 1; i < argc; ++i) {
     fprintf(logFP, LOG_S "\n", argv[i]);
--- a/toolkit/mozapps/update/test/shared.js
+++ b/toolkit/mozapps/update/test/shared.js
@@ -310,17 +310,17 @@ function readFileBytes(aFile) {
   bis.setInputStream(fis);
   var data = [];
   var count = fis.available();
   while (count > 0) {
     var bytes = bis.readByteArray(Math.min(65535, count));
     data.push(String.fromCharCode.apply(null, bytes));
     count -= bytes.length;
     if (bytes.length == 0)
-      do_throw("Nothing read from input stream!");
+      throw "Nothing read from input stream!";
   }
   data.join('');
   fis.close();
   return data.toString();
 }
 
 /* Returns human readable status text from the updates.properties bundle */
 function getStatusText(aErrCode) {
@@ -427,17 +427,18 @@ function cleanUpdatesDir(aDir) {
     }
   }
 }
 
 /**
  * Deletes a directory and its children. First it tries nsIFile::Remove(true).
  * If that fails it will fall back to recursing, setting the appropriate
  * permissions, and deleting the current entry.
- * @param   dir
+ *
+ * @param   aDir
  *          A nsIFile for the directory to be deleted
  */
 function removeDirRecursive(aDir) {
   if (!aDir.exists())
     return;
   try {
     aDir.remove(true);
     return;
rename from toolkit/mozapps/update/test/unit/data/aus-0110_general.mar
rename to toolkit/mozapps/update/test/unit/data/complete.mar
rename from toolkit/mozapps/update/test/unit/data/aus-0110_general_ref_image.png
rename to toolkit/mozapps/update/test/unit/data/complete.png
rename from toolkit/mozapps/update/test/unit/data/aus-0111_general.mar
rename to toolkit/mozapps/update/test/unit/data/partial.mar
rename from toolkit/mozapps/update/test/unit/data/aus-0111_general_ref_image.png
rename to toolkit/mozapps/update/test/unit/data/partial.png
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e4d1e27d2e8e2eb9551f097e9cde8ae520d34dce
GIT binary patch
literal 1583
zc$}3~Sx}Q#7`<6Yf`)=10zoh&0Re%mSV0N_5vV2t2C%rXOBiHPg9t?kAd9R@SkkB%
zBneBSQdAVQfQW*CnjmV`S{AXRMyw7MDvE!9YFj$vv@^Xk_dMM1%=ylJIEU-Lkq&^C
zkH==d6Wu-7iWi(7gXICRdy5e0`5`U<08TxA#3q7#{bGt*!3ChflFm{~GDV(R6Sdu*
z+bdGr4XiJt$4gC)n*3a8!^%=CH<qsx$>jlEjK2QOg9!_YqgzeCIpWKkESoS{Gp6yz
zKNPRprF*g}C3&^SK-d7)m_T__<W|^9I%@6X#>#FG&U^V>;}QgbAOnIDh9T(PJ7^k$
z-egQ?Kp7owZo?fAlmR7wfS}>&PQ+~ejuw3FAV9JC7@-Pagy65EgOCEi2Pk(%Zmy7k
z7XsVr+JO74+dMB&#0O%&n9LC)&24f;R)eNq5-%~Q=(?M~jNUL#=IUDD`$9R0FF2~@
zvhGebgRfR_sue|S01#3FEUlKZ=EQpmKnG7G@Kx{{cry$rwu%pMwG>~^-s=t7Ji;0)
zbZ50R)Dh2RMTY8iA~6;U9V;@sQxcBB_0nm;KwE^SaU_h$RPJ-)%l4+J;=+idw)<~B
zO}LaNis2$aFcHl7kQIweJU?hB*TrwPE>Tl<@r*~TnbqgW1&+>*=g(+x_4KL9D)9#c
z)bj+s#@pib#9it6MI~7y3)4FGIzGDde5AXdzeK&VavFOo{`k;%bznk7MI^Sb%_+UP
zVRC!BhY$Nk$nnAr6qa|SOAL49a<=)clcj3SE9!KcvF`qy@#GbrI|ccJ(lEcS)N7eD
zCj#%7RP~%R^xvz~hrJ;&kEPOT9zR)Q)YS8%p^|8oAZnEHo#bV<P9rzJ7+YZP;*W{j
z#3DDAT`~(Ygsk#7Ufu1o?t**7)Vv_2!<Q*&efPS!p-uJuyc5l%zDp|~xZ161Iw<;O
zn1Sollgtz&19-`~Em`qvg`?#Tp<|(Uk<Jv}vm1w0)eqm>w5OG|c5K}nj_Ap*%``lq
z`)s5<%VQ`H*Fs>8p_ObSmc_D4r{W+{X*xzz=%MX#Ua?%6_FMex_uCF!)soqnT*Olj
zmF%a6+i$@{x>tXTAg#yKjL@qGlCbnf@mH^V&Iok1a{S0=Ri-*RUSlOAx4yIFbP3h&
zvi#_+mb1g2C7Kzfk(|Rb%|jO?BOKMf;!WdhDBy*?shhyNDg~<=y{ut0Tld$DKCox-
z$5fds1K+3D9FuE(7BDplYPPF^>}?%sAA($uKqkp|c=oM}4&Fm5b=}Zua;&0l_;!i$
zY+nfj`PSI^*H|p+`}@Y6Z9ALq2Gplz#)ex0;c3PJyIH4*!`N*9iGw3w;|_}t-<p=h
zx<KK%%MyQhkb<7-&9QBwMOE!w8ua4OPe%7PT4!Cd$K(#RrL{0okyoy{L^14^6q%Ld
zI&;>ZJ9V}f>z4B<t1J`|Cs$vDEI@N8^f92OZ>m>-`G7vvtdPMuxC($CKw^nfKq5r=
z<)TD*o3WQZbqn;(%%TMU$n(NHr8_{n#zC(z;p@Ukfh27JaDWYv0LjirpaB~VK)w_t
z>G<#oEPxt%W6pD5T+8F)B`7kdsOX5XTCrHa*U+^q-@s=vyCX>?rx9u3shHZ<wA@47
zJlxXiH&D;CUwCCbHzK44b6vZFZCUy{nZnD_1{YGh_2!+}o$+-3(>M`e01;S7_)IQM
z`O&skB|ne-zsT_TF_`-d07Y;+v?L`)h6$n^;=<x%c0}zF%=J(?TnjaGv$(L`Ap-c3
zN~h98{<tAAabeL>bce+FXotiwK?K|&0PP3^^<VgcsC@$Z94Qipf=@_M`(QB`=EYvZ
XVE-RtOn9zk`U#0iWx^!p-y44ij{|R*
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..b8a25fab661316b90ddfc0060fd74050479b7c08
GIT binary patch
literal 69632
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
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..fe74dddc81b397f5de54ae2727d7b0591d50eba9
GIT binary patch
literal 69632
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
--- a/toolkit/mozapps/update/test/unit/head_update.js.in
+++ b/toolkit/mozapps/update/test/unit/head_update.js.in
@@ -30,19 +30,76 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+const INSTALL_LOCALE = "@AB_CD@";
+const APP_BIN_NAME = "@MOZ_APP_NAME@";
+const BIN_SUFFIX = "@BIN_SUFFIX@";
+
+#ifdef XP_UNIX
+const APP_BIN_SUFFIX = "-bin";
+#else
+const APP_BIN_SUFFIX = "@BIN_SUFFIX@";
+#endif
+
+#ifdef XP_WIN
+const IS_WIN = true;
+#else
+const IS_WIN = false;
+#endif
+
+#ifdef WINCE
+const IS_WINCE = true;
+#else
+const IS_WINCE = false;
+#endif
+
+#ifdef XP_OS2
+const IS_OS2 = true;
+#else
+const IS_OS2 = false;
+#endif
+
+#ifdef XP_MACOSX
+const IS_MACOSX = true;
+#else
+const IS_MACOSX = false;
+#endif
+
+#ifdef XP_UNIX
+const IS_UNIX = true;
+#else
+const IS_UNIX = false;
+#endif
+
+#ifdef ANDROID
+const IS_ANDROID = true;
+#else
+const IS_ANDROID = false;
+#endif
+
 const URL_HOST = "http://localhost:4444/";
 const URL_PATH = "data";
 
+const AFTER_APPLY_DIR = "afterApplyDir";
+const APPLY_TO_DIR_SUFFIX = "_applyToDir";
+const HELPER_BIN_FILE = "TestAUSHelper" + BIN_SUFFIX;
+const MAR_COMPLETE_FILE = "data/complete.mar";
+const MAR_PARTIAL_FILE = "data/partial.mar";
+const UPDATER_BIN_FILE = "updater" + BIN_SUFFIX;
+const UPDATES_DIR_SUFFIX = "_mar";
+
+const CALLBACK_BIN_FILE = "callback_app" + BIN_SUFFIX;
+const CALLBACK_ARGS = [AFTER_APPLY_DIR + "/output.log", "Test Arg 2", "Test Arg 3"];
+
 var gTestserver;
 
 var gXHR;
 var gXHRCallback;
 
 var gCheckFunc;
 var gResponseBody;
 var gResponseStatusCode = 200;
@@ -119,78 +176,402 @@ function standardInit() {
 /* Custom path handler for the http server */
 function pathHandler(metadata, response) {
   response.setHeader("Content-Type", "text/xml", false);
   response.setStatusLine(metadata.httpVersion, gResponseStatusCode, "OK");
   response.bodyOutputStream.write(gResponseBody, gResponseBody.length);
 }
 
 /**
- * Launches the updater binary to apply a mar file using the current working
- * directory for the location to apply the mar.
+ * Helper function for updater tests for launching the updater binary to apply
+ * a mar file.
  *
- * @param   aUpdater
- *          The updater binary binary to copy to aUpdatesDir.
- * @param   aUpdatesDir
- *          The directory to copy the update mar, binary, etc.
- * @param   aApplyToDir
- *          The directory where the update will be applied.
- * @param   aCallbackApp (optional)
- *          The application to launch after the update.
- * @param   aAppArgs (optional)
- *          The arguments to pass to the callback application.
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
  * @return  The exit value returned from the updater binary.
  */
-function runUpdate(aUpdater, aUpdatesDir, aApplyToDir, aCallbackApp, aAppArgs) {
-  // Copy the updater binary to the update directory so the updater.ini is not
-  // in the same directory as it is. This prevents the PostUpdate executable
-  // which is defined in the updater.ini from launching and the updater ui from
-  // displaying.
-  aUpdater.copyTo(aUpdatesDir, aUpdater.leafName);
-  var updateBin = aUpdatesDir.clone();
-  updateBin.append(aUpdater.leafName);
+function runUpdate(aTestID) {
+  // Copy the updater binary to the updates directory.
+  let binDir = getGREDir();
+  let updater = binDir.clone();
+  updater.append("updater.app");
+  if (!updater.exists()) {
+    updater = binDir.clone();
+    updater.append(UPDATER_BIN_FILE);
+    if (!updater.exists()) {
+      do_throw("Unable to find updater binary!");
+    }
+  }
+
+  let updatesDir = do_get_file(aTestID + UPDATES_DIR_SUFFIX, true);
+  updater.copyTo(updatesDir, updater.leafName);
+  let updateBin = updatesDir.clone();
+  updateBin.append(updater.leafName);
   if (updateBin.leafName == "updater.app") {
     updateBin.append("Contents");
     updateBin.append("MacOS");
     updateBin.append("updater");
     if (!updateBin.exists())
       do_throw("Unable to find the updater executable!");
   }
 
-  var updatesDirPath = aUpdatesDir.path;
+  let updatesDirPath = updatesDir.path;
   if (/ /.test(updatesDirPath))
     updatesDirPath = '"' + updatesDirPath + '"';
 
-  var applyToPath = aApplyToDir.path;
-  if (/ /.test(applyToPath))
-    applyToPath = '"' + applyToPath + '"';
+  let applyToDir = do_get_file(aTestID + APPLY_TO_DIR_SUFFIX, true);
+  let applyToDirPath = applyToDir.path;
+  if (/ /.test(applyToDirPath))
+    applyToDirPath = '"' + applyToDirPath + '"';
 
-  var args;
-  if (aCallbackApp) {
-    var cwdPath = aCallbackApp.parent.parent.path;
-    if (/ /.test(cwdPath))
-      cwdPath = '"' + cwdPath + '"';
+  let callbackApp = applyToDir.clone();
+  callbackApp.append(AFTER_APPLY_DIR);
+  callbackApp.append(CALLBACK_BIN_FILE);
+  callbackApp.permissions = PERMS_DIRECTORY;
 
-    var testAppPath = aCallbackApp.path;
-    if (/ /.test(testAppPath))
-      testAppPath = '"' + testAppPath + '"';
-    args = [updatesDirPath, applyToPath, 0, cwdPath, testAppPath].
-           concat(aAppArgs);
-  }
-  else {
-    args = [updatesDirPath, applyToPath];
-  }
-  var process = AUS_Cc["@mozilla.org/process/util;1"].
+  let cwdPath = callbackApp.parent.parent.path;
+  if (/ /.test(cwdPath))
+    cwdPath = '"' + cwdPath + '"';
+
+  let callbackAppPath = callbackApp.path;
+  if (/ /.test(callbackAppPath))
+    callbackAppPath = '"' + callbackAppPath + '"';
+
+  let args = [updatesDirPath, applyToDirPath, 0, cwdPath, callbackAppPath].
+             concat(CALLBACK_ARGS);
+  let process = AUS_Cc["@mozilla.org/process/util;1"].
                 createInstance(AUS_Ci.nsIProcess);
   process.init(updateBin);
   process.run(true, args, args.length);
   return process.exitValue;
 }
 
 /**
+ * Helper function for updater tests for setting up the files and directories
+ * used by the updater tests.
+ *
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
+ * @param   aMarFile
+ *          The mar file to copy the update mar to.
+ * @param   aTestFiles
+ *          An array of JavaScript objects representing the test files to create
+ *          for the test.
+ */
+function setupUpdaterTest(aTestID, aMarFile, aTestFiles) {
+  // Remove the directory where the updater, mar file, etc. will be copied to
+  let updatesDir = do_get_file(aTestID + UPDATES_DIR_SUFFIX, true);
+  try {
+    removeDirRecursive(updatesDir);
+  }
+  catch (e) {
+    dump("Unable to remove directory\n" +
+         "path: " + updatesDir.path + "\n" +
+         "Exception: " + e + "\n");
+  }
+  if (!updatesDir.exists()) {
+    updatesDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
+  }
+
+  // Remove the directory where the update will be applied if it exists.
+  let applyToDir = do_get_file(aTestID + APPLY_TO_DIR_SUFFIX, true);
+  try {
+    removeDirRecursive(applyToDir);
+  }
+  catch (e) {
+    dump("Unable to remove directory\n" +
+         "path: " + applyToDir.path + "\n" +
+         "Exception: " + e + "\n");
+  }
+  logTestInfo("testing successful removal of the directory used to apply the " +
+              "mar file");
+  do_check_false(applyToDir.exists());
+
+  // Add the test files that will be updated for a successful update or left in
+  // the initial state for a failed update.
+  for (let i = 0; i < aTestFiles.length; i++) {
+    let f = aTestFiles[i];
+    if (f.originalFile || f.originalContents) {
+      let testDir = do_get_file(f.destinationDir, true);
+      if (!testDir.exists())
+        testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
+
+      let testFile;
+      if (f.originalFile) {
+        testFile = do_get_file(f.originalFile);
+        testFile.copyTo(testDir, f.fileName);
+        testFile = do_get_file(f.destinationDir + f.fileName);
+      }
+      else {
+        testFile = do_get_file(f.destinationDir + f.fileName, true);
+        writeFile(testFile, f.originalContents);
+      }
+
+      // Skip these tests on Windows (includes WinCE) and OS/2 since their
+      // implementaions of chmod doesn't really set permissions.
+      if (!IS_WIN && !IS_OS2 && f.originalPerms) {
+        testFile.permissions = f.originalPerms;
+        // Store the actual permissions on the file for reference later after
+        // setting the permissions.
+        if (!f.comparePerms)
+          f.comparePerms = testFile.permissions;
+      }
+    }
+  }
+
+  let afterApplyBinDir = applyToDir.clone();
+  afterApplyBinDir.append(AFTER_APPLY_DIR);
+
+  let helperBin = do_get_file(HELPER_BIN_FILE);
+  helperBin.copyTo(afterApplyBinDir, CALLBACK_BIN_FILE);
+
+  let updaterIniContents = "[Strings]\n" +
+                           "Title=Update XPCShell Test\n" +
+                           "Info=Application Update Test - " + aTestID + "\n";
+  let updaterIni = updatesDir.clone();
+  updaterIni.append(FILE_UPDATER_INI);
+  writeFile(updaterIni, updaterIniContents);
+  updaterIni.copyTo(afterApplyBinDir, FILE_UPDATER_INI);
+
+  // Copy the mar that will be applied
+  let mar = do_get_file(aMarFile);
+  mar.copyTo(updatesDir, FILE_UPDATE_ARCHIVE);
+}
+
+/**
+ * Helper function for updater tests for cleaning up the state after an updater
+ * test has finished.
+ *
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
+ */
+function cleanupUpdaterTest(aTestID) {
+  let updatesDir = do_get_file(aTestID + UPDATES_DIR_SUFFIX, true);
+  try {
+    removeDirRecursive(updatesDir);
+  }
+  catch (e) {
+    dump("Unable to remove directory\n" +
+         "path: " + updatesDir.path + "\n" +
+         "Exception: " + e + "\n");
+  }
+
+  // Try to remove the updates and the apply to directories.
+  let applyToDir = do_get_file(aTestID + APPLY_TO_DIR_SUFFIX, true);
+  try {
+    removeDirRecursive(applyToDir);
+  }
+  catch (e) {
+    dump("Unable to remove directory\n" +
+         "path: " + applyToDir.path + "\n" +
+         "Exception: " + e + "\n");
+  }
+
+  cleanUp();
+}
+
+/**
+ * Helper function for updater tests for verifying the state of files and
+ * directories after a successful update.
+ *
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
+ * @param   aTestFiles
+ *          An array of JavaScript objects representing the test files to create
+ *          for the test.
+ */
+function checkFilesAfterUpdateSuccess(aTestID, aTestFiles) {
+  logTestInfo("testing contents of files after a successful update");
+  for (let i = 0; i < aTestFiles.length; i++) {
+    let f = aTestFiles[i];
+    let testFile = do_get_file(f.destinationDir + f.fileName, true);
+    logTestInfo("testing file: " + testFile.path);
+    if (f.compareFile || f.compareContents) {
+      do_check_true(testFile.exists());
+
+      // Skip these tests on Windows (includes WinCE) and OS/2 since their
+      // implementaions of chmod doesn't really set permissions.
+      if (!IS_WIN && !IS_OS2 && f.comparePerms) {
+        // Check if the permssions as set in the complete mar file are correct.
+        let logPerms = "testing file permissions - ";
+        if (f.originalPerms) {
+          logPerms += "original permissions: " + f.originalPerms.toString(8) + ", ";
+        }
+        logPerms += "compare permissions : " + f.comparePerms.toString(8) + ", ";
+        logPerms += "updated permissions : " + testFile.permissions.toString(8);
+        logTestInfo(logPerms);
+        do_check_eq(testFile.permissions & 0xfff, f.comparePerms & 0xfff);
+      }
+
+      if (f.compareFile) {
+        do_check_eq(readFileBytes(testFile),
+                    readFileBytes(do_get_file(f.compareFile)));
+        if (f.originalFile) {
+          // Verify that readFileBytes returned the entire contents by checking
+          // the contents against the original file.
+          do_check_neq(readFileBytes(testFile),
+                       readFileBytes(do_get_file(f.originalFile)));
+        }
+      }
+      else {
+        do_check_eq(readFileBytes(testFile), f.compareContents);
+      }
+    }
+    else {
+      do_check_false(testFile.exists());
+    }
+  }
+
+  checkFilesAfterUpdateCommon(aTestID);
+}
+
+/**
+ * Helper function for updater tests for verifying the state of files and
+ * directories after a failed update.
+ *
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
+ * @param   aTestFiles
+ *          An array of JavaScript objects representing the test files to create
+ *          for the test.
+ */
+function checkFilesAfterUpdateFailure(aTestID, aTestFiles) {
+  logTestInfo("testing contents of files after a failed update");
+  for (let i = 0; i < aTestFiles.length; i++) {
+    let f = aTestFiles[i];
+    let testFile = do_get_file(f.destinationDir + f.fileName, true);
+    logTestInfo("testing file: " + testFile.path);
+    if (f.compareFile || f.compareContents) {
+      do_check_true(testFile.exists());
+
+      // Skip these tests on Windows (includes WinCE) and OS/2 since their
+      // implementaions of chmod doesn't really set permissions.
+      if (!IS_WIN && !IS_OS2 && f.comparePerms) {
+        // Check the original permssions are retained on the file.
+        let logPerms = "testing file permissions - ";
+        if (f.originalPerms) {
+          logPerms += "original permissions: " + f.originalPerms.toString(8) + ", ";
+        }
+        logPerms += "compare permissions : " + f.comparePerms.toString(8) + ", ";
+        logPerms += "updated permissions : " + testFile.permissions.toString(8);
+        logTestInfo(logPerms);
+        do_check_eq(testFile.permissions & 0xfff, f.comparePerms & 0xfff);
+      }
+
+      if (f.compareFile) {
+        do_check_eq(readFileBytes(testFile),
+                    readFileBytes(do_get_file(f.compareFile)));
+      }
+      else {
+        do_check_eq(readFileBytes(testFile), f.compareContents);
+      }
+    }
+    else {
+      do_check_false(testFile.exists());
+    }
+  }
+
+  checkFilesAfterUpdateCommon(aTestID);
+}
+
+/**
+ * Helper function for updater tests for verifying patch files and moz-backup
+ * files aren't left behind after a successful or failed update.
+ *
+ * @param   aTestID
+ *          A string used to identify the name of directories for a test.
+ */
+function checkFilesAfterUpdateCommon(aTestID) {
+  logTestInfo("testing patch files should not be left behind");
+  let updatesDir = do_get_file(aTestID + UPDATES_DIR_SUFFIX, true);
+  let entries = updatesDir.QueryInterface(AUS_Ci.nsIFile).directoryEntries;
+  while (entries.hasMoreElements()) {
+    let entry = entries.getNext().QueryInterface(AUS_Ci.nsIFile);
+    do_check_neq(getFileExtension(entry), "patch");
+  }
+
+  logTestInfo("testing backup files should not be left behind");
+  let applyToDir = do_get_file(aTestID + APPLY_TO_DIR_SUFFIX, true);
+  checkFilesInDirRecursive(applyToDir, checkForBackupFiles);
+}
+
+/**
+ * Helper function for updater tests for verifying the contents of the updater
+ * callback application log which should contain the string executed and the
+ * arguments passed to the callback application.
+ */
+function checkCallbackAppLog(aTestID) {
+  let appLaunchLog = do_get_file(aTestID + APPLY_TO_DIR_SUFFIX + "/" +
+                                 CALLBACK_ARGS[0], true);
+  if (!appLaunchLog.exists()) {
+    do_timeout(0, function() {
+      checkCallbackAppLog(aTestID);
+    });
+    return;
+  }
+
+  let expectedLogContents = "executed\n" + CALLBACK_ARGS.join("\n") + "\n";
+  let logContents = readFile(appLaunchLog).replace(/\r\n/g, "\n");
+  // It is possible for the log file contents check to occur before the log file
+  // contents are completely written so wait until the contents are the expected
+  // value. If the contents are never the expected value then the test will
+  // fail by timing out.
+  if (logContents != expectedLogContents) {
+    do_timeout(0, function() {
+      checkCallbackAppLog(aTestID);
+    });
+    return;
+  }
+
+  logTestInfo("testing that the callback application successfully launched " +
+              "and the expected command line arguments passed to it");
+  do_check_eq(logContents, expectedLogContents);
+
+  do_test_finished();
+}
+
+/**
+ * Helper function for updater tests for verifying there are no update backup
+ * files left behind after an update.
+ *
+ * @param   aFile
+ *          An nsIFile to check if it has moz-backup for its extension.
+ */
+function checkForBackupFiles(aFile) {
+  do_check_neq(getFileExtension(aFile), "moz-backup");
+}
+
+/**
+ * Helper function for updater tests for recursively enumerating a directory and
+ * calls a callback function with the file as a parameter for each file found.
+ *
+ * @param   aDir
+ *          A nsIFile for the directory to be deleted
+ * @param   aCallback
+ *          A callback function that will be called with the file as a
+ *          parameter for each file found.
+ */
+function checkFilesInDirRecursive(aDir, aCallback) {
+  if (!aDir.exists())
+    do_throw("Directory must exist!");
+
+  let dirEntries = aDir.directoryEntries;
+  while (dirEntries.hasMoreElements()) {
+    let entry = dirEntries.getNext().QueryInterface(AUS_Ci.nsIFile);
+
+    if (entry.isDirectory()) {
+      checkFilesInDirRecursive(entry, aCallback);
+    }
+    else {
+      aCallback(entry);
+    }
+  }
+}
+
+/**
  * Sets up the bare bones XMLHttpRequest implementation below. 
  *
  * @param   callback
  *          The callback function that will call the nsIDomEventListener's
  *          handleEvent method.
  *
  *          Example of the callback function
  *
@@ -395,58 +776,8 @@ var gDirProvider = {
   QueryInterface: function(iid) {
     if (iid.equals(AUS_Ci.nsIDirectoryServiceProvider) ||
         iid.equals(AUS_Ci.nsISupports))
       return this;
     throw AUS_Cr.NS_ERROR_NO_INTERFACE;
   }
 };
 Services.dirsvc.QueryInterface(AUS_Ci.nsIDirectoryService).registerProvider(gDirProvider);
-
-const INSTALL_LOCALE = "@AB_CD@";
-
-// These are placed at the end so they don't mess up line numbering
-
-const APP_BIN_NAME = "@MOZ_APP_NAME@";
-
-#ifdef XP_UNIX
-const APP_BIN_SUFFIX = "-bin";
-#else
-const APP_BIN_SUFFIX = "@BIN_SUFFIX@";
-#endif
-
-const BIN_SUFFIX = "@BIN_SUFFIX@";
-
-#ifdef XP_WIN
-const IS_WIN = true;
-#else
-const IS_WIN = false;
-#endif
-
-#ifdef WINCE
-const IS_WINCE = true;
-#else
-const IS_WINCE = false;
-#endif
-
-#ifdef XP_OS2
-const IS_OS2 = true;
-#else
-const IS_OS2 = false;
-#endif
-
-#ifdef XP_MACOSX
-const IS_MACOSX = true;
-#else
-const IS_MACOSX = false;
-#endif
-
-#ifdef XP_UNIX
-const IS_UNIX = true;
-#else
-const IS_UNIX = false;
-#endif
-
-#ifdef ANDROID
-const IS_ANDROID = true;
-#else
-const IS_ANDROID = false;
-#endif
--- a/toolkit/mozapps/update/test/unit/test_0110_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0110_general.js
@@ -6,25 +6,25 @@
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
- * The Original Code is the Application Update Service.
+ * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
- * Robert Strong <robert.bugzilla@gmail.com>.
- *
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2008
- * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Robert Strong <robert.bugzilla@gmail.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -33,68 +33,63 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK *****
  */
 
 /* General Complete MAR File Patch Apply Test */
 
-const APPLY_TO_DIR = "applyToDir_0110";
-const UPDATES_DIR  = "0110_mar";
-const AFTER_APPLY_DIR = "afterApplyDir";
-const UPDATER_BIN_FILE = "updater" + BIN_SUFFIX;
-const AFTER_APPLY_BIN_FILE = "TestAUSHelper" + BIN_SUFFIX;
-const RELAUNCH_BIN_FILE = "relaunch_app" + BIN_SUFFIX;
-const RELAUNCH_ARGS = ["Test Arg 1", "Test Arg 2", "Test Arg 3"];
+const TEST_ID = "0110";
 // All we care about is that the last modified time has changed so that Mac OS
 // X Launch Services invalidates its cache so the test allows up to one minute
 // difference in the last modified time.
 const MAX_TIME_DIFFERENCE = 60000;
 
-var gTestFiles = [
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
 {
-  fileName         : "1_exe1.exe",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/",
-  originalContents : null,
-  compareContents  : null,
-  originalFile     : "data/aus-0111_general_ref_image.png",
-  compareFile      : "data/aus-0110_general_ref_image.png",
-  originalPerms    : 0777,
-  comparePerms     : 0755
-}, {
   fileName         : "1_1_image1.png",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : null,
   compareContents  : null,
   originalFile     : null,
-  compareFile      : "data/aus-0110_general_ref_image.png",
+  compareFile      : "data/complete.png",
   originalPerms    : 0776,
   comparePerms     : 0644
 }, {
   fileName         : "1_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : "ToBeReplacedWithToBeModified\n",
   compareContents  : "ToBeModified\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0775,
   comparePerms     : 0644
 }, {
   fileName         : "1_1_text2",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : "ToBeReplacedWithToBeDeleted\n",
   compareContents  : "ToBeDeleted\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0677,
   comparePerms     : 0644
 }, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/complete.png",
+  originalPerms    : 0777,
+  comparePerms     : 0755
+}, {
   fileName         : "2_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/2/2_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
   originalContents : "ToBeReplacedWithToBeDeleted\n",
   compareContents  : "ToBeDeleted\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0767,
   comparePerms     : 0644
 }];
 
@@ -102,240 +97,60 @@ function run_test() {
   if (IS_ANDROID) {
     logTestInfo("this test is not applicable to Android... returning early");
     return;
   }
 
   do_test_pending();
   do_register_cleanup(end_test);
 
-  var testDir, testFile;
-
-  // The directory the updates will be applied to is the directory name stored
-  // in the APPLY_TO_DIR constant located in the current working directory and
-  // not dist/bin.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
+  setupUpdaterTest(TEST_ID, MAR_COMPLETE_FILE, TEST_FILES);
 
-  // Remove the directory where the update will be applied if it exists.
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  logTestInfo("testing successful removal of the directory used to apply the " +
-              "mar file");
-  do_check_false(applyToDir.exists());
-
-  // Use a directory outside of dist/bin to lessen the garbage in dist/bin
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    // Mac OS X intermittently fails when removing the dir where the updater
-    // binary was launched.
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  if (!updatesDir.exists()) {
-    updatesDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-  }
+  // The testUpdate function is used for consistency with the tests that require
+  // a timeout before continuing the test.
+  testUpdate();
+}
 
-  // Create the files to test the complete mar's ability to replace files.
-  for (var i = 0; i < gTestFiles.length; i++) {
-    var f = gTestFiles[i];
-    if (f.originalFile || f.originalContents) {
-      testDir = do_get_file(f.destinationDir, true);
-      if (!testDir.exists())
-        testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-
-      if (f.originalFile) {
-        testFile = do_get_file(f.originalFile);
-        testFile.copyTo(testDir, f.fileName);
-        testFile = do_get_file(f.destinationDir + f.fileName);
-      }
-      else {
-        testFile = do_get_file(f.destinationDir + f.fileName, true);
-        writeFile(testFile, f.originalContents);
-      }
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
 
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.originalPerms) {
-        testFile.permissions = f.originalPerms;
-        // Store the actual permissions on the file for reference later after
-        // setting the permissions.
-        if (!f.comparePerms)
-          f.comparePerms = testFile.permissions;
-      }
-    }
-  }
-
-  var afterApplyBinDir = applyToDir.clone();
-  afterApplyBinDir.append(AFTER_APPLY_DIR);
-
-  var afterApplyBin = do_get_file(AFTER_APPLY_BIN_FILE);
-  afterApplyBin.copyTo(afterApplyBinDir, RELAUNCH_BIN_FILE);
-
-  var relaunchApp = afterApplyBinDir.clone();
-  relaunchApp.append(RELAUNCH_BIN_FILE);
-  relaunchApp.permissions = PERMS_DIRECTORY;
-
-  let updaterIniContents = "[Strings]\n" +
-                           "Title=Update Test\n" +
-                           "Info=Application Update XPCShell Test - " +
-                           "test_0110_general.js\n";
-  var updaterIni = updatesDir.clone();
-  updaterIni.append(FILE_UPDATER_INI);
-  writeFile(updaterIni, updaterIniContents);
-  updaterIni.copyTo(afterApplyBinDir, FILE_UPDATER_INI);
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
 
   // For Mac OS X set the last modified time for the root directory to a date in
   // the past to test that the last modified time is updated on a successful
   // update (bug 600098).
   if (IS_MACOSX) {
-    var now = Date.now();
-    var yesterday = now - (1000 * 60 * 60 * 24);
+    let now = Date.now();
+    let yesterday = now - (1000 * 60 * 60 * 24);
     applyToDir.lastModifiedTime = yesterday;
   }
 
-  var binDir = getGREDir();
-
-  // The updater binary file
-  var updater = binDir.clone();
-  updater.append("updater.app");
-  if (!updater.exists()) {
-    updater = binDir.clone();
-    updater.append(UPDATER_BIN_FILE);
-    if (!updater.exists()) {
-      do_throw("Unable to find updater binary!");
-    }
-  }
-
-  var mar = do_get_file("data/aus-0110_general.mar");
-  mar.copyTo(updatesDir, FILE_UPDATE_ARCHIVE);
-
-  // apply the complete mar and check the innards of the files
-  var exitValue = runUpdate(updater, updatesDir, applyToDir, relaunchApp,
-                            RELAUNCH_ARGS);
+  // apply the complete mar
+  let exitValue = runUpdate(TEST_ID);
   logTestInfo("testing updater binary process exitValue for success when " +
               "applying a complete mar");
   do_check_eq(exitValue, 0);
 
   logTestInfo("testing update.status should be " + STATE_SUCCEEDED);
   do_check_eq(readStatusFile(updatesDir), STATE_SUCCEEDED);
 
   // For Mac OS X check that the last modified time for a directory has been
   // updated after a successful update (bug 600098).
   if (IS_MACOSX) {
     logTestInfo("testing last modified time on the apply to directory has " +
                 "changed after a successful update (bug 600098)");
-    now = Date.now();
-    var timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
+    let now = Date.now();
+    let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
     do_check_true(timeDiff < MAX_TIME_DIFFERENCE);
   }
 
-  logTestInfo("testing contents of files added by a complete mar");
-  for (i = 0; i < gTestFiles.length; i++) {
-    f = gTestFiles[i];
-    testFile = do_get_file(f.destinationDir + f.fileName, true);
-    logTestInfo("testing file: " + testFile.path);
-    if (f.compareFile || f.compareContents) {
-      do_check_true(testFile.exists());
-
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.comparePerms) {
-        // Check if the permssions as set in the complete mar file are correct.
-        let logPerms = "testing file permissions - ";
-        if (f.originalPerms) {
-          logPerms += "original permissions: " + f.originalPerms.toString(8) + ", ";
-        }
-        logPerms += "compare permissions : " + f.comparePerms.toString(8) + ", ";
-        logPerms += "updated permissions : " + testFile.permissions.toString(8);
-        logTestInfo(logPerms);
-        do_check_eq(testFile.permissions & 0xfff, f.comparePerms & 0xfff);
-      }
-
-      if (f.compareFile) {
-        do_check_eq(readFileBytes(testFile),
-                    readFileBytes(do_get_file(f.compareFile)));
-        if (f.originalFile) {
-          // Verify that readFileBytes returned the entire contents by checking
-          // the contents against the original file.
-          do_check_neq(readFileBytes(testFile),
-                       readFileBytes(do_get_file(f.originalFile)));
-        }
-      }
-      else {
-        do_check_eq(readFileBytes(testFile), f.compareContents);
-      }
-    }
-    else {
-      do_check_false(testFile.exists());
-    }
-  }
-
-  logTestInfo("testing patch files should not be left behind");
-  var entries = updatesDir.QueryInterface(AUS_Ci.nsIFile).directoryEntries;
-  while (entries.hasMoreElements()) {
-    var entry = entries.getNext().QueryInterface(AUS_Ci.nsIFile);
-    do_check_neq(getFileExtension(entry), "patch");
-  }
-
-  check_app_launch_log();
-}
+  checkFilesAfterUpdateSuccess(TEST_ID, TEST_FILES);
 
-function end_test() {
-  // Try to remove the updates and the apply to directories.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-
-  cleanUp();
-}
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
 
-function check_app_launch_log() {
-  var appLaunchLog = do_get_file(APPLY_TO_DIR);
-  appLaunchLog.append(AFTER_APPLY_DIR);
-  appLaunchLog.append(RELAUNCH_BIN_FILE + ".log");
-  if (!appLaunchLog.exists()) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  var expectedLogContents = "executed\n" + RELAUNCH_ARGS.join("\n") + "\n";
-  var logContents = readFile(appLaunchLog).replace(/\r\n/g, "\n");
-  // It is possible for the log file contents check to occur before the log file
-  // contents are completely written so wait until the contents are the expected
-  // value. If the contents are never the expected value then the test will
-  // fail by timing out.
-  if (logContents != expectedLogContents) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  logTestInfo("testing that the callback application successfully launched " +
-              "and the expected command line arguments passed to it");
-  do_check_eq(logContents, expectedLogContents);
-
-  do_test_finished();
+  checkCallbackAppLog(TEST_ID);
 }
--- a/toolkit/mozapps/update/test/unit/test_0111_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0111_general.js
@@ -6,25 +6,25 @@
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
- * The Original Code is the Application Update Service.
+ * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
- * Robert Strong <robert.bugzilla@gmail.com>.
- *
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2008
- * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Robert Strong <robert.bugzilla@gmail.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -33,86 +33,81 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK *****
  */
 
 /* General Partial MAR File Patch Apply Test */
 
-const APPLY_TO_DIR = "applyToDir_0111";
-const UPDATES_DIR  = "0111_mar";
-const AFTER_APPLY_DIR = "afterApplyDir";
-const UPDATER_BIN_FILE = "updater" + BIN_SUFFIX;
-const AFTER_APPLY_BIN_FILE = "TestAUSHelper" + BIN_SUFFIX;
-const RELAUNCH_BIN_FILE = "relaunch_app" + BIN_SUFFIX;
-const RELAUNCH_ARGS = ["Test Arg 1", "Test Arg 2", "Test Arg 3"];
+const TEST_ID = "0111";
 // All we care about is that the last modified time has changed so that Mac OS
 // X Launch Services invalidates its cache so the test allows up to one minute
 // difference in the last modified time.
 const MAX_TIME_DIFFERENCE = 60000;
 
-var gTestFiles = [
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
 {
-  fileName         : "1_exe1.exe",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/",
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : null,
   compareContents  : null,
-  originalFile     : "data/aus-0110_general_ref_image.png",
-  compareFile      : "data/aus-0111_general_ref_image.png",
-  originalPerms    : 0755,
-  comparePerms     : null
-}, {
-  fileName         : "1_1_image1.png",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
-  originalContents : null,
-  compareContents  : null,
-  originalFile     : "data/aus-0110_general_ref_image.png",
-  compareFile      : "data/aus-0111_general_ref_image.png",
+  originalFile     : "data/complete.png",
+  compareFile      : "data/partial.png",
   originalPerms    : 0644,
   comparePerms     : null
 }, {
   fileName         : "1_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : "ToBeModified\n",
   compareContents  : "Modified\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0644,
   comparePerms     : null
 }, {
   fileName         : "1_1_text2",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeDeleted\n",
+  compareContents  : null,
+  originalFile     : null,
+  compareFile      : null,
+  originalPerms    : null,
+  comparePerms     : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/complete.png",
+  compareFile      : "data/partial.png",
+  originalPerms    : 0755,
+  comparePerms     : null
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
   originalContents : "ToBeDeleted\n",
   compareContents  : null,
   originalFile     : null,
   compareFile      : null,
   originalPerms    : null,
   comparePerms     : null
 }, {
   fileName         : "1_1_text3",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : null,
   compareContents  : "Added\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : null,
   comparePerms     : 0644
 }, {
-  fileName         : "2_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/2/2_1/",
-  originalContents : "ToBeDeleted\n",
-  compareContents  : null,
-  originalFile     : null,
-  compareFile      : null,
-  originalPerms    : null,
-  comparePerms     : null
-}, {
   fileName         : "3_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/3/3_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/3/3_1/",
   originalContents : null,
   compareContents  : "Added\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : null,
   comparePerms     : 0644
 }];
 
@@ -120,246 +115,66 @@ function run_test() {
   if (IS_ANDROID) {
     logTestInfo("this test is not applicable to Android... returning early");
     return;
   }
 
   do_test_pending();
   do_register_cleanup(end_test);
 
-  var testDir, testFile;
-
-  // The directory the updates will be applied to is the directory name stored
-  // in the APPLY_TO_DIR constant located in the current working directory and
-  // not dist/bin.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
+  setupUpdaterTest(TEST_ID, MAR_PARTIAL_FILE, TEST_FILES);
 
-  // Remove the directory where the update will be applied if it exists.
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  logTestInfo("testing successful removal of the directory used to apply the " +
-              "mar file");
-  do_check_false(applyToDir.exists());
-
-  // Use a directory outside of dist/bin to lessen the garbage in dist/bin
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    // Mac OS X intermittently fails when removing the dir where the updater
-    // binary was launched.
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  if (!updatesDir.exists()) {
-    updatesDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-  }
+  // The testUpdate function is used for consistency with the tests that require
+  // a timeout before continuing the test.
+  testUpdate();
+}
 
-  // Create the files to test the partial mar's ability to modify and delete
-  // files.
-  for (var i = 0; i < gTestFiles.length; i++) {
-    var f = gTestFiles[i];
-    if (f.originalFile || f.originalContents) {
-      testDir = do_get_file(f.destinationDir, true);
-      if (!testDir.exists())
-        testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-
-      if (f.originalFile) {
-        testFile = do_get_file(f.originalFile);
-        testFile.copyTo(testDir, f.fileName);
-        testFile = do_get_file(f.destinationDir + f.fileName);
-      }
-      else {
-        testFile = do_get_file(f.destinationDir + f.fileName, true);
-        writeFile(testFile, f.originalContents);
-      }
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
 
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.originalPerms) {
-        testFile.permissions = f.originalPerms;
-        // Store the actual permissions on the file for reference later after
-        // setting the permissions.
-        if (!f.comparePerms)
-          f.comparePerms = testFile.permissions;
-      }
-    }
-  }
-
-  var afterApplyBinDir = applyToDir.clone();
-  afterApplyBinDir.append(AFTER_APPLY_DIR);
-
-  var afterApplyBin = do_get_file(AFTER_APPLY_BIN_FILE);
-  afterApplyBin.copyTo(afterApplyBinDir, RELAUNCH_BIN_FILE);
-
-  var relaunchApp = afterApplyBinDir.clone();
-  relaunchApp.append(RELAUNCH_BIN_FILE);
-  relaunchApp.permissions = PERMS_DIRECTORY;
-
-  let updaterIniContents = "[Strings]\n" +
-                           "Title=Update Test\n" +
-                           "Info=Application Update XPCShell Test - " +
-                           "test_0111_general.js\n";
-  var updaterIni = updatesDir.clone();
-  updaterIni.append(FILE_UPDATER_INI);
-  writeFile(updaterIni, updaterIniContents);
-  updaterIni.copyTo(afterApplyBinDir, FILE_UPDATER_INI);
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
 
   // For Mac OS X set the last modified time for the root directory to a date in
   // the past to test that the last modified time is updated on a successful
   // update (bug 600098).
   if (IS_MACOSX) {
-    var now = Date.now();
-    var yesterday = now - (1000 * 60 * 60 * 24);
+    let now = Date.now();
+    let yesterday = now - (1000 * 60 * 60 * 24);
     applyToDir.lastModifiedTime = yesterday;
   }
 
-  var binDir = getGREDir();
-
-  // The updater binary file
-  var updater = binDir.clone();
-  updater.append("updater.app");
-  if (!updater.exists()) {
-    updater = binDir.clone();
-    updater.append(UPDATER_BIN_FILE);
-    if (!updater.exists()) {
-      do_throw("Unable to find updater binary!");
-    }
-  }
-
-  var mar = do_get_file("data/aus-0111_general.mar");
-  mar.copyTo(updatesDir, FILE_UPDATE_ARCHIVE);
-
-  // apply the partial mar and check the innards of the files
-  var exitValue = runUpdate(updater, updatesDir, applyToDir, relaunchApp,
-                            RELAUNCH_ARGS);
+  // apply the partial mar
+  let exitValue = runUpdate(TEST_ID);
   logTestInfo("testing updater binary process exitValue for success when " +
               "applying a partial mar");
   do_check_eq(exitValue, 0);
 
   logTestInfo("testing update.status should be " + STATE_SUCCEEDED);
   do_check_eq(readStatusFile(updatesDir), STATE_SUCCEEDED);
 
   // For Mac OS X check that the last modified time for a directory has been
   // updated after a successful update (bug 600098).
   if (IS_MACOSX) {
     logTestInfo("testing last modified time on the apply to directory has " +
                 "changed after a successful update (bug 600098)");
-    now = Date.now();
-    var timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
+    let now = Date.now();
+    let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
     do_check_true(timeDiff < MAX_TIME_DIFFERENCE);
   }
 
-  logTestInfo("testing the removal of files and the contents of added / " +
-              "modified files by a partial mar");
-  for (i = 0; i < gTestFiles.length; i++) {
-    f = gTestFiles[i];
-    testFile = do_get_file(f.destinationDir + f.fileName, true);
-    logTestInfo("testing file: " + testFile.path);
-    if (f.compareFile || f.compareContents) {
-      do_check_true(testFile.exists());
-
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.comparePerms) {
-        // Check the original permssions are retained on the file.
-        let logPerms = "testing file permissions - ";
-        if (f.originalPerms) {
-          logPerms += "original permissions: " + f.originalPerms.toString(8) + ", ";
-        }
-        logPerms += "compare permissions : " + f.comparePerms.toString(8) + ", ";
-        logPerms += "updated permissions : " + testFile.permissions.toString(8);
-        logTestInfo(logPerms);
-        do_check_eq(testFile.permissions & 0xfff, f.comparePerms & 0xfff);
-      }
-
-      if (f.compareFile) {
-        do_check_eq(readFileBytes(testFile),
-                    readFileBytes(do_get_file(f.compareFile)));
-        if (f.originalFile) {
-          // Verify that readFileBytes returned the entire contents by checking
-          // the contents against the original file.
-          do_check_neq(readFileBytes(testFile),
-                       readFileBytes(do_get_file(f.originalFile)));
-        }
-      }
-      else {
-        do_check_eq(readFileBytes(testFile), f.compareContents);
-      }
-    }
-    else {
-      do_check_false(testFile.exists());
-    }
-  }
+  checkFilesAfterUpdateSuccess(TEST_ID, TEST_FILES);
 
   logTestInfo("testing directory still exists after removal of the last file " +
               "in the directory (bug 386760)");
-  do_check_true(do_get_file(APPLY_TO_DIR + "/mar_test/2/2_1/", true).exists());
-
-  logTestInfo("testing patch files should not be left behind");
-  var entries = updatesDir.QueryInterface(AUS_Ci.nsIFile).directoryEntries;
-  while (entries.hasMoreElements()) {
-    var entry = entries.getNext().QueryInterface(AUS_Ci.nsIFile);
-    do_check_neq(getFileExtension(entry), "patch");
-  }
-
-  check_app_launch_log();
-}
-
-function end_test() {
-  // Try to remove the updates and the apply to directories.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
+  let testDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+                            true);
+  do_check_true(testDir.exists());
 
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-
-  cleanUp();
-}
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
 
-function check_app_launch_log() {
-  var appLaunchLog = do_get_file(APPLY_TO_DIR);
-  appLaunchLog.append(AFTER_APPLY_DIR);
-  appLaunchLog.append(RELAUNCH_BIN_FILE + ".log");
-  if (!appLaunchLog.exists()) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  var expectedLogContents = "executed\n" + RELAUNCH_ARGS.join("\n") + "\n";
-  var logContents = readFile(appLaunchLog).replace(/\r\n/g, "\n");
-  // It is possible for the log file contents check to occur before the log file
-  // contents are completely written so wait until the contents are the expected
-  // value. If the contents are never the expected value then the test will
-  // fail by timing out.
-  if (logContents != expectedLogContents) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  logTestInfo("testing that the callback application successfully launched " +
-              "and the expected command line arguments passed to it");
-  do_check_eq(logContents, expectedLogContents);
-
-  do_test_finished();
+  checkCallbackAppLog(TEST_ID);
 }
--- a/toolkit/mozapps/update/test/unit/test_0112_general.js
+++ b/toolkit/mozapps/update/test/unit/test_0112_general.js
@@ -6,25 +6,25 @@
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
  * Software distributed under the License is distributed on an "AS IS" basis,
  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  * for the specific language governing rights and limitations under the
  * License.
  *
- * The Original Code is the Application Update Service.
+ * The Original Code is mozilla.org code.
  *
  * The Initial Developer of the Original Code is
- * Robert Strong <robert.bugzilla@gmail.com>.
- *
+ * the Mozilla Foundation.
  * Portions created by the Initial Developer are Copyright (C) 2008
- * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
+ * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Robert Strong <robert.bugzilla@gmail.com> (Original Author)
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -33,64 +33,59 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK *****
  */
 
 /* General Partial MAR File Patch Apply Failure Test */
 
-const APPLY_TO_DIR = "applyToDir_0112";
-const UPDATES_DIR  = "0112_mar";
-const AFTER_APPLY_DIR = "afterApplyDir";
-const UPDATER_BIN_FILE = "updater" + BIN_SUFFIX;
-const AFTER_APPLY_BIN_FILE = "TestAUSHelper" + BIN_SUFFIX;
-const RELAUNCH_BIN_FILE = "relaunch_app" + BIN_SUFFIX;
-const RELAUNCH_ARGS = ["Test Arg 1", "Test Arg 2", "Test Arg 3"];
+const TEST_ID = "0112";
 
-var gTestFiles = [
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
 {
-  fileName         : "1_exe1.exe",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/",
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : null,
   compareContents  : null,
-  originalFile     : "data/aus-0111_general_ref_image.png",
-  compareFile      : "data/aus-0111_general_ref_image.png",
-  originalPerms    : 0755,
-  comparePerms     : null
-}, {
-  fileName         : "1_1_image1.png",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
-  originalContents : null,
-  compareContents  : null,
-  originalFile     : "data/aus-0110_general_ref_image.png",
-  compareFile      : "data/aus-0110_general_ref_image.png",
+  originalFile     : "data/complete.png",
+  compareFile      : "data/complete.png",
   originalPerms    : 0644,
   comparePerms     : null
 }, {
   fileName         : "1_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : "ShouldNotBeDeleted\n",
   compareContents  : "ShouldNotBeDeleted\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0644,
   comparePerms     : null
 }, {
   fileName         : "1_1_text2",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/1/1_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
   originalContents : "ShouldNotBeDeleted\n",
   compareContents  : "ShouldNotBeDeleted\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0644,
   comparePerms     : null
 }, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png",
+  originalPerms    : 0755,
+  comparePerms     : null
+}, {
   fileName         : "2_1_text1",
-  destinationDir   : APPLY_TO_DIR + "/mar_test/2/2_1/",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
   originalContents : "ShouldNotBeDeleted\n",
   compareContents  : "ShouldNotBeDeleted\n",
   originalFile     : null,
   compareFile      : null,
   originalPerms    : 0644,
   comparePerms     : null
 }];
 
@@ -98,135 +93,48 @@ function run_test() {
   if (IS_ANDROID) {
     logTestInfo("this test is not applicable to Android... returning early");
     return;
   }
 
   do_test_pending();
   do_register_cleanup(end_test);
 
-  var testDir, testFile;
-
-  // The directory the updates will be applied to is the directory name stored
-  // in the APPLY_TO_DIR constant located in the current working directory and
-  // not dist/bin.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
+  setupUpdaterTest(TEST_ID, MAR_PARTIAL_FILE, TEST_FILES);
 
-  // Remove the directory where the update will be applied if it exists.
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  logTestInfo("testing successful removal of the directory used to apply the " +
-              "mar file");
-  do_check_false(applyToDir.exists());
-
-  // Use a directory outside of dist/bin to lessen the garbage in dist/bin
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    // Mac OS X intermittently fails when removing the dir where the updater
-    // binary was launched.
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-  if (!updatesDir.exists()) {
-    updatesDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-  }
+  // The testUpdate function is used for consistency with the tests that require
+  // a timeout before continuing the test.
+  testUpdate();
+}
 
-  // Create the files to test the partial mar's ability to rollback to the
-  // original files.
-  for (var i = 0; i < gTestFiles.length; i++) {
-    var f = gTestFiles[i];
-    if (f.originalFile || f.originalContents) {
-      testDir = do_get_file(f.destinationDir, true);
-      if (!testDir.exists())
-        testDir.create(AUS_Ci.nsIFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
-
-      if (f.originalFile) {
-        testFile = do_get_file(f.originalFile);
-        testFile.copyTo(testDir, f.fileName);
-        testFile = do_get_file(f.destinationDir + f.fileName);
-      }
-      else {
-        testFile = do_get_file(f.destinationDir + f.fileName, true);
-        writeFile(testFile, f.originalContents);
-      }
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
 
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.originalPerms) {
-        testFile.permissions = f.originalPerms;
-        // Store the actual permissions on the file for reference later after
-        // setting the permissions.
-        if (!f.comparePerms)
-          f.comparePerms = testFile.permissions;
-      }
-    }
-  }
-
-  var afterApplyBinDir = applyToDir.clone();
-  afterApplyBinDir.append(AFTER_APPLY_DIR);
-
-  var afterApplyBin = do_get_file(AFTER_APPLY_BIN_FILE);
-  afterApplyBin.copyTo(afterApplyBinDir, RELAUNCH_BIN_FILE);
-
-  var relaunchApp = afterApplyBinDir.clone();
-  relaunchApp.append(RELAUNCH_BIN_FILE);
-  relaunchApp.permissions = PERMS_DIRECTORY;
-
-  let updaterIniContents = "[Strings]\n" +
-                           "Title=Update Test\n" +
-                           "Info=Application Update XPCShell Test - " +
-                           "test_0112_general.js\n";
-  var updaterIni = updatesDir.clone();
-  updaterIni.append(FILE_UPDATER_INI);
-  writeFile(updaterIni, updaterIniContents);
-  updaterIni.copyTo(afterApplyBinDir, FILE_UPDATER_INI);
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
 
   // For Mac OS X set the last modified time for a directory to a date in the
   // past to test that the last modified time on the directories in not updated
   // when an update fails (bug 600098).
+  let lastModTime;
   if (IS_MACOSX) {
     // All we care about is that the last modified time has not changed when an
     // update has failed.
-    var now = Date.now();
-    var lastModTime = now - (1000 * 60 * 60 * 24);
+    let now = Date.now();
+    lastModTime = now - (1000 * 60 * 60 * 24);
     applyToDir.lastModifiedTime = lastModTime;
     // Set lastModTime to the value the OS returns in case it is different than
     // the value stored by the OS.
     lastModTime = applyToDir.lastModifiedTime;
   }
 
-  var binDir = getGREDir();
-
-  // The updater binary file
-  var updater = binDir.clone();
-  updater.append("updater.app");
-  if (!updater.exists()) {
-    updater = binDir.clone();
-    updater.append(UPDATER_BIN_FILE);
-    if (!updater.exists()) {
-      do_throw("Unable to find updater binary!");
-    }
-  }
-
-  var mar = do_get_file("data/aus-0111_general.mar");
-  mar.copyTo(updatesDir, FILE_UPDATE_ARCHIVE);
-
-  // apply the partial mar and check the innards of the files
-  var exitValue = runUpdate(updater, updatesDir, applyToDir, relaunchApp,
-                            RELAUNCH_ARGS);
+  // apply the partial mar
+  let exitValue = runUpdate(TEST_ID);
   logTestInfo("testing updater binary process exitValue for success when " +
               "applying a partial mar");
   do_check_eq(exitValue, 0);
 
   logTestInfo("testing update.status should be " + STATE_FAILED);
   // The update status format for a failure is failed: # where # is the error
   // code for the failure.
   do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
@@ -234,105 +142,17 @@ function run_test() {
   // For Mac OS X check that the last modified time for a directory has not been
   // updated after a failed update (bug 600098).
   if (IS_MACOSX) {
     logTestInfo("testing last modified time on the apply to directory has " +
                 "not changed after a failed update (bug 600098)");
     do_check_eq(applyToDir.lastModifiedTime, lastModTime);
   }
 
-  logTestInfo("testing files should not be modified or deleted when an " +
-              "update fails");
-  for (i = 0; i < gTestFiles.length; i++) {
-    f = gTestFiles[i];
-    testFile = do_get_file(f.destinationDir + f.fileName, true);
-    logTestInfo("testing file: " + testFile.path);
-    if (f.compareFile || f.compareContents) {
-      do_check_true(testFile.exists());
-
-      // Skip these tests on Windows (includes WinCE) and OS/2 since their
-      // implementaions of chmod doesn't really set permissions.
-      if (!IS_WIN && !IS_OS2 && f.comparePerms) {
-        // Check the original permssions are retained on the file.
-        let logPerms = "testing file permissions - ";
-        if (f.originalPerms) {
-          logPerms += "original permissions: " + f.originalPerms.toString(8) + ", ";
-        }
-        logPerms += "compare permissions : " + f.comparePerms.toString(8) + ", ";
-        logPerms += "updated permissions : " + testFile.permissions.toString(8);
-        logTestInfo(logPerms);
-        do_check_eq(testFile.permissions & 0xfff, f.comparePerms & 0xfff);
-      }
-
-      if (f.compareFile) {
-        do_check_eq(readFileBytes(testFile),
-                    readFileBytes(do_get_file(f.compareFile)));
-      }
-      else {
-        do_check_eq(readFileBytes(testFile), f.compareContents);
-      }
-    }
-    else {
-      do_check_false(testFile.exists());
-    }
-  }
-
-  logTestInfo("testing patch files should not be left behind");
-  var entries = updatesDir.QueryInterface(AUS_Ci.nsIFile).directoryEntries;
-  while (entries.hasMoreElements()) {
-    var entry = entries.getNext().QueryInterface(AUS_Ci.nsIFile);
-    do_check_neq(getFileExtension(entry), "patch");
-  }
-
-  check_app_launch_log();
-}
+  checkFilesAfterUpdateFailure(TEST_ID, TEST_FILES);
 
-function end_test() {
-  // Try to remove the updates and the apply to directories.
-  var applyToDir = do_get_file(APPLY_TO_DIR, true);
-  try {
-    removeDirRecursive(applyToDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + applyToDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-
-  var updatesDir = do_get_file(UPDATES_DIR, true);
-  try {
-    removeDirRecursive(updatesDir);
-  }
-  catch (e) {
-    dump("Unable to remove directory\n" +
-         "path: " + updatesDir.path + "\n" +
-         "Exception: " + e + "\n");
-  }
-
-  cleanUp();
-}
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
 
-function check_app_launch_log() {
-  var appLaunchLog = do_get_file(APPLY_TO_DIR);
-  appLaunchLog.append(AFTER_APPLY_DIR);
-  appLaunchLog.append(RELAUNCH_BIN_FILE + ".log");
-  if (!appLaunchLog.exists()) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  var expectedLogContents = "executed\n" + RELAUNCH_ARGS.join("\n") + "\n";
-  var logContents = readFile(appLaunchLog).replace(/\r\n/g, "\n");
-  // It is possible for the log file contents check to occur before the log file
-  // contents are completely written so wait until the contents are the expected
-  // value. If the contents are never the expected value then the test will
-  // fail by timing out.
-  if (logContents != expectedLogContents) {
-    do_timeout(0, check_app_launch_log);
-    return;
-  }
-
-  logTestInfo("testing that the callback application successfully launched " +
-              "and the expected command line arguments passed to it");
-  do_check_eq(logContents, expectedLogContents);
-
-  do_test_finished();
+  checkCallbackAppLog(TEST_ID);
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0160_appInUse_xp_unix_complete.js
@@ -0,0 +1,133 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file patch apply success test */
+
+const TEST_ID = "0160";
+// All we care about is that the last modified time has changed so that Mac OS
+// X Launch Services invalidates its cache so the test allows up to one minute
+// difference in the last modified time.
+const MAX_TIME_DIFFERENCE = 60000;
+
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : null,
+  compareFile      : "data/complete.png",
+  originalPerms    : 0776,
+  comparePerms     : 0644
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeReplacedWithToBeModified\n",
+  compareContents  : "ToBeModified\n",
+  originalFile     : null,
+  compareFile      : null,
+  originalPerms    : 0775,
+  comparePerms     : 0644
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeReplacedWithToBeDeleted\n",
+  compareContents  : "ToBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null,
+  originalPerms    : 0677,
+  comparePerms     : 0644
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/complete.png",
+  originalPerms    : 0777,
+  comparePerms     : 0755
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ToBeReplacedWithToBeDeleted\n",
+  compareContents  : "ToBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null,
+  originalPerms    : 0767,
+  comparePerms     : 0644
+}];
+
+let gCallbackAppProcess;
+
+function run_test() {
+  if (!IS_UNIX || IS_ANDROID) {
+    logTestInfo("this test is only applicable to XP_UNIX platforms except " +
+                "for Android... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_COMPLETE_FILE, TEST_FILES);
+
+  // Launch the callback helper application so it is in use during the update
+  let callbackApp = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+  callbackApp.append(AFTER_APPLY_DIR);
+  callbackApp.append(CALLBACK_BIN_FILE);
+  callbackApp.permissions = PERMS_DIRECTORY;
+  let args = ["-s", "20"];
+  gCallbackAppProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                        createInstance(AUS_Ci.nsIProcess);
+  gCallbackAppProcess.init(callbackApp);
+  gCallbackAppProcess.run(false, args, args.length);
+
+  // Give the lock file process time to lock the file before updating otherwise
+  // this test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // For Mac OS X set the last modified time for the root directory to a date in
+  // the past to test that the last modified time is updated on a successful
+  // update (bug 600098).
+  if (IS_MACOSX) {
+    let now = Date.now();
+    let yesterday = now - (1000 * 60 * 60 * 24);
+    applyToDir.lastModifiedTime = yesterday;
+  }
+
+  // apply the complete mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a complete mar");
+  do_check_eq(exitValue, 0);
+
+  gCallbackAppProcess.kill();
+
+  logTestInfo("testing update.status should be " + STATE_SUCCEEDED);
+  do_check_eq(readStatusFile(updatesDir), STATE_SUCCEEDED);
+
+  // For Mac OS X check that the last modified time for a directory has been
+  // updated after a successful update (bug 600098).
+  if (IS_MACOSX) {
+    logTestInfo("testing last modified time on the apply to directory has " +
+                "changed after a successful update (bug 600098)");
+    let now = Date.now();
+    let timeDiff = Math.abs(applyToDir.lastModifiedTime - now);
+    do_check_true(timeDiff < MAX_TIME_DIFFERENCE);
+  }
+
+  checkFilesAfterUpdateSuccess(TEST_ID, TEST_FILES);
+
+  checkCallbackAppLog(TEST_ID);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0160_appInUse_xp_win_complete.js
@@ -0,0 +1,105 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file patch apply failure test */
+
+const TEST_ID = "0160";
+
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}];
+
+let gCallbackAppProcess;
+
+function run_test() {
+  if (!IS_WIN || IS_WINCE) {
+    logTestInfo("this test is only applicable to Windows... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_COMPLETE_FILE, TEST_FILES);
+
+  // Launch the callback helper application so it is in use during the update
+  let callbackApp = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+  callbackApp.append(AFTER_APPLY_DIR);
+  callbackApp.append(CALLBACK_BIN_FILE);
+  let args = ["-s", "20"];
+  gCallbackAppProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                        createInstance(AUS_Ci.nsIProcess);
+  gCallbackAppProcess.init(callbackApp);
+  gCallbackAppProcess.run(false, args, args.length);
+
+  // Give the lock file process time to lock the file before updating otherwise
+  // this test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // apply the complete mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a complete mar");
+  do_check_eq(exitValue, 1);
+
+  gCallbackAppProcess.kill();
+
+  logTestInfo("testing update.status should be " + STATE_FAILED);
+  // The update status format for a failure is failed: # where # is the error
+  // code for the failure.
+  do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
+
+  checkFilesAfterUpdateFailure(TEST_ID, TEST_FILES);
+
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
+
+  checkCallbackAppLog(TEST_ID);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0170_fileLocked_xp_win_complete.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked complete MAR file patch apply failure test */
+
+const TEST_ID = "0170";
+
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ShouldNotBeReplaced\n",
+  compareContents  : "ShouldNotBeReplaced\n",
+  originalFile     : null,
+  compareFile      : null
+}];
+
+let gLockFileProcess;
+
+function run_test() {
+  if (!IS_WIN || IS_WINCE) {
+    logTestInfo("this test is only applicable to Windows... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_COMPLETE_FILE, TEST_FILES);
+
+  // Exclusively lock an existing file so it is in use during the update
+  let helperBin = do_get_file(HELPER_BIN_FILE);
+  let lockFileRelPath = TEST_FILES[3].destinationDir + TEST_FILES[3].fileName;
+  let args = ["-s", "20", lockFileRelPath];
+  gLockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                     createInstance(AUS_Ci.nsIProcess);
+  gLockFileProcess.init(helperBin);
+  gLockFileProcess.run(false, args, args.length);
+
+  // Give the lock file process time to lock the file before updating otherwise
+  // this test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // apply the complete mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a complete mar");
+  do_check_eq(exitValue, 0);
+
+  gLockFileProcess.kill();
+
+  logTestInfo("testing update.status should be " + STATE_FAILED);
+  // The update status format for a failure is failed: # where # is the error
+  // code for the failure.
+  do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
+
+  checkFilesAfterUpdateFailure(TEST_ID, TEST_FILES);
+
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
+
+  checkCallbackAppLog(TEST_ID);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0171_fileLocked_xp_win_partial.js
@@ -0,0 +1,104 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked partial MAR file patch apply failure test */
+
+const TEST_ID = "0171";
+
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeModified\n",
+  compareContents  : "ShouldNotBeModified\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ShouldNotBeDeleted\n",
+  compareContents  : "ShouldNotBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/complete.png",
+  compareFile      : "data/complete.png"
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ShouldNotBeDeleted\n",
+  compareContents  : "ShouldNotBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null
+}];
+
+let gLockFileProcess;
+
+function run_test() {
+  if (!IS_WIN || IS_WINCE) {
+    logTestInfo("this test is only applicable to Windows... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_PARTIAL_FILE, TEST_FILES);
+
+  // Exclusively lock an existing file so it is in use during the update
+  let helperBin = do_get_file(HELPER_BIN_FILE);
+  let lockFileRelPath = TEST_FILES[3].destinationDir + TEST_FILES[3].fileName;
+  let args = ["-s", "20", lockFileRelPath];
+  gLockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                     createInstance(AUS_Ci.nsIProcess);
+  gLockFileProcess.init(helperBin);
+  gLockFileProcess.run(false, args, args.length);
+
+  // Give the lock file process time to lock the file before updating otherwise
+  // this test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // apply the partial mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a partial mar");
+  do_check_eq(exitValue, 0);
+
+  gLockFileProcess.kill();
+
+  logTestInfo("testing update.status should be " + STATE_FAILED);
+  // The update status format for a failure is failed: # where # is the error
+  // code for the failure.
+  do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
+
+  checkFilesAfterUpdateFailure(TEST_ID, TEST_FILES);
+
+  logTestInfo("testing tobedeleted directory doesn't exist");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_false(toBeDeletedDir.exists());
+
+  checkCallbackAppLog(TEST_ID);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0180_fileInUse_xp_win_complete.js
@@ -0,0 +1,102 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use complete MAR file patch apply success test */
+
+const TEST_ID = "0180";
+
+// The files are in the same order as they are applied from the mar
+const TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : null,
+  compareFile      : "data/complete.png"
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeReplacedWithToBeModified\n",
+  compareContents  : "ToBeModified\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeReplacedWithToBeDeleted\n",
+  compareContents  : "ToBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : HELPER_BIN_FILE,
+  compareFile      : "data/complete.png"
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ToBeReplacedWithToBeDeleted\n",
+  compareContents  : "ToBeDeleted\n",
+  originalFile     : null,
+  compareFile      : null
+}];
+
+let gFileInUseProcess;
+
+function run_test() {
+  if (!IS_WIN || IS_WINCE) {
+    logTestInfo("this test is only applicable to Windows... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_COMPLETE_FILE, TEST_FILES);
+
+  // Launch an existing file so it is in use during the update
+  let fileInUseBin = do_get_file(TEST_FILES[3].destinationDir +
+                                 TEST_FILES[3].fileName);
+  let args = ["-s", "20"];
+  gFileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                      createInstance(AUS_Ci.nsIProcess);
+  gFileInUseProcess.init(fileInUseBin);
+  gFileInUseProcess.run(false, args, args.length);
+
+  // Give the file in use process time to launch before updating otherwise this
+  // test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // apply the complete mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a complete mar");
+  do_check_eq(exitValue, 0);
+
+  gFileInUseProcess.kill();
+
+  logTestInfo("testing update.status should be " + STATE_SUCCEEDED);
+  do_check_eq(readStatusFile(updatesDir), STATE_SUCCEEDED);
+
+  checkFilesAfterUpdateSuccess(TEST_ID, TEST_FILES);
+
+  logTestInfo("testing tobedeleted directory exists");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_true(toBeDeletedDir.exists());
+
+  checkCallbackAppLog(TEST_ID);
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/test/unit/test_0181_fileInUse_xp_win_partial.js
@@ -0,0 +1,119 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use partial MAR file patch apply success test */
+
+const TEST_ID = "0181";
+const MAR_IN_USE_WIN_FILE = "data/partial_in_use_win.mar";
+
+// The files are in the same order as they are applied from the mar
+var TEST_FILES = [
+{
+  fileName         : "1_1_image1.png",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/complete.png",
+  compareFile      : "data/partial.png"
+}, {
+  fileName         : "1_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeModified\n",
+  compareContents  : "Modified\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text2",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : "ToBeDeleted\n",
+  compareContents  : null,
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_exe1.exe",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/",
+  originalContents : null,
+  compareContents  : null,
+  originalFile     : "data/partial_in_use_win_before.exe",
+  compareFile      : "data/partial_in_use_win_after.exe"
+}, {
+  fileName         : "2_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/",
+  originalContents : "ToBeDeleted\n",
+  compareContents  : null,
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "1_1_text3",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/1/1_1/",
+  originalContents : null,
+  compareContents  : "Added\n",
+  originalFile     : null,
+  compareFile      : null
+}, {
+  fileName         : "3_1_text1",
+  destinationDir   : TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/3/3_1/",
+  originalContents : null,
+  compareContents  : "Added\n",
+  originalFile     : null,
+  compareFile      : null
+}];
+
+let gFileInUseProcess;
+
+function run_test() {
+  if (!IS_WIN || IS_WINCE) {
+    logTestInfo("this test is only applicable to Windows... returning early");
+    return;
+  }
+
+  do_test_pending();
+  do_register_cleanup(end_test);
+
+  setupUpdaterTest(TEST_ID, MAR_IN_USE_WIN_FILE, TEST_FILES);
+
+  // Launch an existing file so it is in use during the update
+  let fileInUseBin = do_get_file(TEST_FILES[3].destinationDir +
+                                 TEST_FILES[3].fileName);
+  let args = ["-s", "20"];
+  gFileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
+                      createInstance(AUS_Ci.nsIProcess);
+  gFileInUseProcess.init(fileInUseBin);
+  gFileInUseProcess.run(false, args, args.length);
+
+  // Give the file in use process time to launch before updating otherwise this
+  // test can fail intermittently on Windows debug builds.
+  do_timeout(100, testUpdate);
+}
+
+function end_test() {
+  cleanupUpdaterTest(TEST_ID);
+}
+
+function testUpdate() {
+  let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
+  let applyToDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX);
+
+  // apply the partial mar
+  let exitValue = runUpdate(TEST_ID);
+  logTestInfo("testing updater binary process exitValue for success when " +
+              "applying a partial mar");
+  do_check_eq(exitValue, 0);
+
+  gFileInUseProcess.kill();
+
+  checkFilesAfterUpdateSuccess(TEST_ID, TEST_FILES);
+
+  logTestInfo("testing directory still exists after removal of the last file " +
+              "in the directory (bug 386760)");
+  let testDir = do_get_file(TEST_ID + APPLY_TO_DIR_SUFFIX + "/mar_test/2/2_1/", true);
+  do_check_true(testDir.exists());
+
+  logTestInfo("testing tobedeleted directory exists");
+  let toBeDeletedDir = applyToDir.clone();
+  toBeDeletedDir.append("tobedeleted");
+  do_check_true(toBeDeletedDir.exists());
+
+  checkCallbackAppLog(TEST_ID);
+}