Bug 760577 - Part 4: Add full round-trip tests for keeping the mar file around and falling back to apply it at startup if replacing the application fails; r=rstrong
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 08 Jun 2012 15:06:53 -0400
changeset 96687 d5f72bc8b49dd47bb182cd525a28a7e84dff90a3
parent 96686 3c9425ee322254bdb3494bc87dc009499d5d46cf
child 96688 12e5dbd60ed8e0e3b2471795e564ad9f8bf0357b
push id10660
push usereakhgari@mozilla.com
push dateThu, 14 Jun 2012 13:37:41 +0000
treeherdermozilla-inbound@3d4982f32837 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrstrong
bugs760577
milestone16.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 760577 - Part 4: Add full round-trip tests for keeping the mar file around and falling back to apply it at startup if replacing the application fails; r=rstrong
toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js
toolkit/mozapps/update/test/unit/xpcshell_updater_windows.ini
toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js
toolkit/mozapps/update/test_svc/unit/xpcshell.ini
toolkit/mozapps/update/updater/updater.cpp
copy from toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js
copy to toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js
--- a/toolkit/mozapps/update/test/unit/test_0201_app_launch_apply_update.js
+++ b/toolkit/mozapps/update/test/unit/test_0203_app_launch_apply_update.js
@@ -3,33 +3,41 @@
  */
 
 /**
  * Test applying an update by applying an update in the background and
  * launching an application
  */
 
 /**
+ * This test is identical to test_0201_app_launch_apply_update.js, except
+ * that it locks the application directory when the test is launched to
+ * make the updater fall back to apply the update regularly.
+ */
+
+/**
  * The MAR file used for this test should not contain a version 2 update
  * manifest file (e.g. updatev2.manifest).
  */
 
-const TEST_ID = "0201";
+const TEST_ID = "0203";
 
 // Backup the updater.ini and use a custom one to prevent the updater from
 // launching a post update executable.
 const FILE_UPDATER_INI_BAK = "updater.ini.bak";
 
 // Number of milliseconds for each do_timeout call.
 const CHECK_TIMEOUT_MILLI = 1000;
 
 // Maximum number of milliseconds the process that is launched can run before
 // the test will try to kill it.
 const APP_TIMER_TIMEOUT = 15000;
 
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+
 let gAppTimer;
 let gProcess;
 let gActiveUpdate;
 
 // Override getUpdatesRootDir on Mac because we need to apply the update
 // inside the bundle directory.
 function symlinkUpdateFilesIntoBundleDirectory() {
   if (!shouldAdjustPathsOnMac()) {
@@ -166,16 +174,37 @@ function run_test() {
   checkUpdateApplied();
 }
 
 function switchApp() {
   let launchBin = getLaunchBin();
   let args = getProcessArgs();
   logTestInfo("launching " + launchBin.path + " " + args.join(" "));
 
+  // Lock the installation directory
+  const LPCWSTR = ctypes.jschar.ptr;
+  const DWORD = ctypes.uint32_t;
+  const LPVOID = ctypes.voidptr_t;
+  const GENERIC_READ = 0x80000000;
+  const FILE_SHARE_READ = 1;
+  const FILE_SHARE_WRITE = 2;
+  const OPEN_EXISTING = 3;
+  const FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
+  const INVALID_HANDLE_VALUE = LPVOID(0xffffffff);
+  let kernel32 = ctypes.open("kernel32");
+  let CreateFile = kernel32.declare("CreateFileW", ctypes.default_abi,
+                                    LPVOID, LPCWSTR, DWORD, DWORD,
+                                    LPVOID, DWORD, DWORD, LPVOID);
+  logTestInfo(gWindowsBinDir.path);
+  let handle = CreateFile(gWindowsBinDir.path, GENERIC_READ,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE, LPVOID(0),
+                          OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, LPVOID(0));
+  do_check_neq(handle.toString(), INVALID_HANDLE_VALUE.toString());
+  kernel32.close();
+
   gProcess = AUS_Cc["@mozilla.org/process/util;1"].
                 createInstance(AUS_Ci.nsIProcess);
   gProcess.init(launchBin);
 
   gAppTimer = AUS_Cc["@mozilla.org/timer;1"].createInstance(AUS_Ci.nsITimer);
   gAppTimer.initWithCallback(gTimerCallback, APP_TIMER_TIMEOUT,
                              AUS_Ci.nsITimer.TYPE_ONE_SHOT);
 
--- a/toolkit/mozapps/update/test/unit/xpcshell_updater_windows.ini
+++ b/toolkit/mozapps/update/test/unit/xpcshell_updater_windows.ini
@@ -22,8 +22,9 @@
 [test_0186_rmrfdirFileInUse_xp_win_complete.js]
 [test_0187_rmrfdirFileInUse_xp_win_partial.js]
 [test_0188_fileInUse_xp_win_complete.js]
 [test_0189_fileInUse_xp_win_partial.js]
 [test_0190_rmrfdirFileInUse_xp_win_complete.js]
 [test_0191_rmrfdirFileInUse_xp_win_partial.js]
 [test_0202_app_launch_apply_update_dirlocked.js]
 skip-if = true
+[test_0203_app_launch_apply_update.js]
copy from toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js
copy to toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js
--- a/toolkit/mozapps/update/test_svc/unit/test_0201_app_launch_apply_update_svc.js
+++ b/toolkit/mozapps/update/test_svc/unit/test_0203_app_launch_apply_update_svc.js
@@ -3,33 +3,41 @@
  */
 
 /**
  * Test applying an update by applying an update in the background and
  * launching an application
  */
 
 /**
+ * This test is identical to test_0201_app_launch_apply_update_svc.js, except
+ * that it locks the application directory when the test is launched to
+ * make the updater fall back to apply the update regularly.
+ */
+
+/**
  * The MAR file used for this test should not contain a version 2 update
  * manifest file (e.g. updatev2.manifest).
  */
 
-const TEST_ID = "0201_svc";
+const TEST_ID = "0203_svc";
 
 // Backup the updater.ini and use a custom one to prevent the updater from
 // launching a post update executable.
 const FILE_UPDATER_INI_BAK = "updater.ini.bak";
 
 // Number of milliseconds for each do_timeout call.
 const CHECK_TIMEOUT_MILLI = 1000;
 
 // Maximum number of milliseconds the process that is launched can run before
 // the test will try to kill it.
 const APP_TIMER_TIMEOUT = 15000;
 
+Components.utils.import("resource://gre/modules/ctypes.jsm");
+
 let gAppTimer;
 let gProcess;
 let gActiveUpdate;
 
 // Override getUpdatesRootDir on Mac because we need to apply the update
 // inside the bundle directory.
 function symlinkUpdateFilesIntoBundleDirectory() {
   if (!shouldAdjustPathsOnMac()) {
@@ -174,16 +182,37 @@ function run_test() {
   checkUpdateApplied();
 }
 
 function switchApp() {
   let launchBin = getLaunchBin();
   let args = getProcessArgs();
   logTestInfo("launching " + launchBin.path + " " + args.join(" "));
 
+  // Lock the installation directory
+  const LPCWSTR = ctypes.jschar.ptr;
+  const DWORD = ctypes.uint32_t;
+  const LPVOID = ctypes.voidptr_t;
+  const GENERIC_READ = 0x80000000;
+  const FILE_SHARE_READ = 1;
+  const FILE_SHARE_WRITE = 2;
+  const OPEN_EXISTING = 3;
+  const FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
+  const INVALID_HANDLE_VALUE = LPVOID(0xffffffff);
+  let kernel32 = ctypes.open("kernel32");
+  let CreateFile = kernel32.declare("CreateFileW", ctypes.default_abi,
+                                    LPVOID, LPCWSTR, DWORD, DWORD,
+                                    LPVOID, DWORD, DWORD, LPVOID);
+  logTestInfo(gWindowsBinDir.path);
+  let handle = CreateFile(gWindowsBinDir.path, GENERIC_READ,
+                          FILE_SHARE_READ | FILE_SHARE_WRITE, LPVOID(0),
+                          OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, LPVOID(0));
+  do_check_neq(handle.toString(), INVALID_HANDLE_VALUE.toString());
+  kernel32.close();
+
   gProcess = AUS_Cc["@mozilla.org/process/util;1"].
                 createInstance(AUS_Ci.nsIProcess);
   gProcess.init(launchBin);
 
   gAppTimer = AUS_Cc["@mozilla.org/timer;1"].createInstance(AUS_Ci.nsITimer);
   gAppTimer.initWithCallback(gTimerCallback, APP_TIMER_TIMEOUT,
                              AUS_Ci.nsITimer.TYPE_ONE_SHOT);
 
--- a/toolkit/mozapps/update/test_svc/unit/xpcshell.ini
+++ b/toolkit/mozapps/update/test_svc/unit/xpcshell.ini
@@ -36,8 +36,9 @@ tail =
 [test_0187_rmrfdirFileInUse_xp_win_partial_svc.js]
 [test_0188_fileInUse_xp_win_complete_svc.js]
 [test_0189_fileInUse_xp_win_partial_svc.js]
 [test_0190_rmrfdirFileInUse_xp_win_complete_svc.js]
 [test_0191_rmrfdirFileInUse_xp_win_partial_svc.js]
 [test_0200_app_launch_apply_update_svc.js]
 [test_0201_app_launch_apply_update_svc.js]
 [test_0202_app_launch_apply_update_dirlocked_svc.js]
+[test_0203_app_launch_apply_update_svc.js]
--- a/toolkit/mozapps/update/updater/updater.cpp
+++ b/toolkit/mozapps/update/updater/updater.cpp
@@ -2062,16 +2062,17 @@ UpdateThreadFunc(void *param)
                    NS_T("%s/Updated.app"),
 #else
                    NS_T("%s/updated"),
 #endif
                    installDir);
 
       ensure_remove_recursive(stageDir);
       WriteStatusText(sUsingService ? "pending-service" : "pending");
+      putenv("MOZ_PROCESS_UPDATES="); // We need to use -process-updates again in the tests
       reportRealResults = false; // pretend success
     }
   }
 
   if (reportRealResults) {
     if (rv) {
       LOG(("failed: %d\n", rv));
     }