зеркало из https://github.com/mozilla/pjs.git
Merge mozilla-central into mozilla-inbound
This commit is contained in:
Коммит
78d3a82d96
|
@ -1,6 +1,7 @@
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
. $topsrcdir/build/unix/mozconfig.linux
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||
|
|
|
@ -4,6 +4,7 @@ ac_add_options --enable-debug
|
|||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-accessibility
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
# Enable parallel compiling
|
||||
mk_add_options MOZ_MAKE_FLAGS="-j12"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
|
|
@ -4,6 +4,7 @@ ac_add_options --host=x86_64-pc-mingw32
|
|||
ac_add_options --enable-debug
|
||||
ac_add_options --enable-trace-malloc
|
||||
ac_add_options --enable-signmar
|
||||
ENABLE_MARIONETTE=1
|
||||
|
||||
# Needed to enable breakpad in application.ini
|
||||
export MOZILLA_OFFICIAL=1
|
||||
|
|
|
@ -156,3 +156,7 @@ installer:: removed-files
|
|||
ifdef INSTALLER_DIR
|
||||
$(MAKE) -C $(INSTALLER_DIR)
|
||||
endif
|
||||
|
||||
ifdef ENABLE_MARIONETTE
|
||||
DEFINES += -DENABLE_MARIONETTE=1
|
||||
endif
|
||||
|
|
|
@ -466,6 +466,12 @@
|
|||
|
||||
@BINPATH@/components/ContactManager.js
|
||||
@BINPATH@/components/ContactManager.manifest
|
||||
#ifdef ENABLE_MARIONETTE
|
||||
@BINPATH@/chrome/marionette@JAREXT@
|
||||
@BINPATH@/chrome/marionette.manifest
|
||||
@BINPATH@/components/MarionetteComponents.manifest
|
||||
@BINPATH@/components/marionettecomponent.js
|
||||
#endif
|
||||
|
||||
; Modules
|
||||
@BINPATH@/modules/*
|
||||
|
|
|
@ -769,18 +769,22 @@ function cleanUpUpdatesDir(aBackgroundUpdate) {
|
|||
}
|
||||
}
|
||||
f.moveTo(dir, FILE_LAST_LOG);
|
||||
continue;
|
||||
if (aBackgroundUpdate) {
|
||||
// We're not going to delete any files, so we can just
|
||||
// bail out of the loop right now.
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
LOG("cleanUpUpdatesDir - failed to move file " + f.path + " to " +
|
||||
dir.path + " and rename it to " + FILE_LAST_LOG);
|
||||
}
|
||||
} else if (f.leafName == FILE_UPDATE_STATUS && aBackgroundUpdate) {
|
||||
// Leave the update.status file alone when a background update
|
||||
// has been performed. We don't remove this file here because
|
||||
// after the application directory gets replaced by the staged
|
||||
// update, this will end up being the update.status file which
|
||||
// represents the status of the update performed.
|
||||
} else if (aBackgroundUpdate) {
|
||||
// Don't delete any files when an update has been staged, as
|
||||
// we need to keep them around in case we would have to fall
|
||||
// back to applying the update on application restart.
|
||||
continue;
|
||||
}
|
||||
// Now, recursively remove this file. The recursive removal is really
|
||||
|
@ -1010,8 +1014,9 @@ function handleUpdateFailure(update, errorCode) {
|
|||
* Fall back to downloading a complete update in case an update has failed.
|
||||
*
|
||||
* @param update the update object that has failed to apply.
|
||||
* @param postStaging true if we have just attempted to stage an update.
|
||||
*/
|
||||
function handleFallbackToCompleteUpdate(update) {
|
||||
function handleFallbackToCompleteUpdate(update, postStaging) {
|
||||
cleanupActiveUpdate();
|
||||
|
||||
update.statusText = gUpdateBundle.GetStringFromName("patchApplyFailure");
|
||||
|
@ -1024,7 +1029,7 @@ function handleFallbackToCompleteUpdate(update) {
|
|||
"failed, downloading complete patch");
|
||||
var status = Cc["@mozilla.org/updates/update-service;1"].
|
||||
getService(Ci.nsIApplicationUpdateService).
|
||||
downloadUpdate(update, true);
|
||||
downloadUpdate(update, !postStaging);
|
||||
if (status == STATE_NONE)
|
||||
cleanupActiveUpdate();
|
||||
}
|
||||
|
@ -1617,7 +1622,7 @@ UpdateService.prototype = {
|
|||
}
|
||||
|
||||
// Something went wrong with the patch application process.
|
||||
handleFallbackToCompleteUpdate(update);
|
||||
handleFallbackToCompleteUpdate(update, false);
|
||||
|
||||
prompter.showUpdateError(update);
|
||||
}
|
||||
|
@ -2432,7 +2437,7 @@ UpdateManager.prototype = {
|
|||
if (update.state == STATE_FAILED && ary[1]) {
|
||||
updateSucceeded = false;
|
||||
if (!handleUpdateFailure(update, ary[1])) {
|
||||
handleFallbackToCompleteUpdate(update);
|
||||
handleFallbackToCompleteUpdate(update, true);
|
||||
}
|
||||
}
|
||||
if (update.state == STATE_APPLIED && shouldUseService()) {
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
# define NS_ttoi atoi
|
||||
# define NS_tstat stat
|
||||
# define NS_tgetcwd getcwd
|
||||
# define NS_tfputs fputs
|
||||
# define LOG_S "%s"
|
||||
#endif
|
||||
|
||||
|
@ -171,6 +172,9 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
"Usage: WORKINGDIR INFILE OUTFILE -s SECONDS [FILETOLOCK]\n" \
|
||||
" or: WORKINGDIR LOGFILE [ARG2 ARG3...]\n" \
|
||||
" or: signature-check filepath\n" \
|
||||
" or: setup-symlink dir1 dir2 file symlink\n" \
|
||||
" or: remove-symlink dir1 dir2 file symlink\n" \
|
||||
" or: check-symlink symlink\n" \
|
||||
"\n" \
|
||||
" WORKINGDIR \tThe relative path to the working directory to use.\n" \
|
||||
" INFILE \tThe relative path from the working directory for the file to\n" \
|
||||
|
@ -205,6 +209,68 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (!NS_tstrcmp(argv[1], NS_T("setup-symlink"))) {
|
||||
#ifdef XP_UNIX
|
||||
NS_tchar path[MAXPATHLEN];
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
|
||||
mkdir(path, 0755);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
|
||||
mkdir(path, 0755);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
|
||||
FILE * file = NS_tfopen(path, NS_T("w"));
|
||||
if (file) {
|
||||
NS_tfputs(NS_T("test"), file);
|
||||
fclose(file);
|
||||
}
|
||||
symlink(path, argv[5]);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
|
||||
if (argc > 6 && !NS_tstrcmp(argv[6], NS_T("change-perm"))) {
|
||||
chmod(path, 0644);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
// Not implemented on non-Unix platforms
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!NS_tstrcmp(argv[1], NS_T("remove-symlink"))) {
|
||||
#ifdef XP_UNIX
|
||||
NS_tchar path[MAXPATHLEN];
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
|
||||
chmod(path, 0755);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3], argv[4]);
|
||||
unlink(path);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s/%s"), NS_T("/tmp"), argv[2], argv[3]);
|
||||
rmdir(path);
|
||||
NS_tsnprintf(path, sizeof(path)/sizeof(path[0]),
|
||||
NS_T("%s/%s"), NS_T("/tmp"), argv[2]);
|
||||
rmdir(path);
|
||||
return 0;
|
||||
#else
|
||||
// Not implemented on non-Unix platforms
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!NS_tstrcmp(argv[1], NS_T("check-symlink"))) {
|
||||
#ifdef XP_UNIX
|
||||
struct stat ss;
|
||||
lstat(argv[2], &ss);
|
||||
return S_ISLNK(ss.st_mode) ? 0 : 1;
|
||||
#else
|
||||
// Not implemented on non-Unix platforms
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!NS_tstrcmp(argv[1], NS_T("wait-for-service-stop"))) {
|
||||
#ifdef XP_WIN
|
||||
const int maxWaitSeconds = NS_ttoi(argv[3]);
|
||||
|
|
|
@ -100,6 +100,7 @@ var gCallbackBinFile = "callback_app" + BIN_SUFFIX;
|
|||
var gCallbackArgs = ["./", "callback.log", "Test Arg 2", "Test Arg 3"];
|
||||
var gBackgroundUpdate = false;
|
||||
var gSwitchApp = false;
|
||||
var gDisableReplaceFallback = false;
|
||||
|
||||
// Time to wait for the test helper process before continuing the test
|
||||
const TEST_HELPER_TIMEOUT = 1000;
|
||||
|
@ -513,10 +514,21 @@ function runUpdate() {
|
|||
}
|
||||
logTestInfo("Running the updater: " + updateBin.path + " " + args.join(" "));
|
||||
|
||||
let env = AUS_Cc["@mozilla.org/process/environment;1"].
|
||||
getService(AUS_Ci.nsIEnvironment);
|
||||
if (gDisableReplaceFallback) {
|
||||
env.set("MOZ_NO_REPLACE_FALLBACK", "1");
|
||||
}
|
||||
|
||||
let process = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
process.init(updateBin);
|
||||
process.run(true, args, args.length);
|
||||
|
||||
if (gDisableReplaceFallback) {
|
||||
env.set("MOZ_NO_REPLACE_FALLBACK", "");
|
||||
}
|
||||
|
||||
return process.exitValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ const MAX_TIME_DIFFERENCE = 60000;
|
|||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
var TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
|
@ -234,6 +234,39 @@ ADDITIONAL_TEST_DIRS = [
|
|||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function runHelperProcess(args) {
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let process = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
process.init(helperBin);
|
||||
logTestInfo("Running " + helperBin.path + " " + args.join(" "));
|
||||
process.run(true, args, args.length);
|
||||
do_check_eq(process.exitValue, 0);
|
||||
}
|
||||
|
||||
function createSymlink() {
|
||||
let args = ["setup-symlink", "moz-foo", "moz-bar", "target",
|
||||
getApplyDirFile().path + "/a/b/link"];
|
||||
runHelperProcess(args);
|
||||
args = ["setup-symlink", "moz-foo2", "moz-bar2", "target2",
|
||||
getApplyDirFile().path + "/a/b/link2", "change-perm"];
|
||||
runHelperProcess(args);
|
||||
}
|
||||
|
||||
function removeSymlink() {
|
||||
let args = ["remove-symlink", "moz-foo", "moz-bar", "target",
|
||||
getApplyDirFile().path + "/a/b/link"];
|
||||
runHelperProcess(args);
|
||||
args = ["remove-symlink", "moz-foo2", "moz-bar2", "target2",
|
||||
getApplyDirFile().path + "/a/b/link2"];
|
||||
runHelperProcess(args);
|
||||
}
|
||||
|
||||
function checkSymlink() {
|
||||
let args = ["check-symlink", getApplyDirFile().path + "/a/b/link"];
|
||||
runHelperProcess(args);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
@ -253,10 +286,31 @@ function run_test() {
|
|||
applyToDir.lastModifiedTime = yesterday;
|
||||
}
|
||||
|
||||
if (IS_UNIX) {
|
||||
removeSymlink();
|
||||
createSymlink();
|
||||
do_register_cleanup(removeSymlink);
|
||||
TEST_FILES.push({
|
||||
description : "Readable symlink",
|
||||
fileName : "link",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : "test",
|
||||
compareContents : "test",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0664,
|
||||
comparePerms : 0664
|
||||
});
|
||||
}
|
||||
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for success when " +
|
||||
"applying a complete mar");
|
||||
let updateLog = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX, true);
|
||||
updateLog.append(FILE_UPDATE_LOG);
|
||||
let updateLogContents = readFileBytes(updateLog);
|
||||
logTestInfo(updateLogContents);
|
||||
do_check_eq(exitValue, 0);
|
||||
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
|
@ -308,8 +362,10 @@ function run_test() {
|
|||
}
|
||||
|
||||
checkFilesAfterUpdateSuccess();
|
||||
// Sorting on Linux is different so skip this check for now.
|
||||
if (!IS_UNIX) {
|
||||
if (IS_UNIX) {
|
||||
checkSymlink();
|
||||
} else {
|
||||
// Sorting on Linux is different so skip this check for now.
|
||||
checkUpdateLogContents(LOG_COMPLETE_SWITCH_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -215,6 +215,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* Application in use complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0162";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Launch the callback helper application so it is in use during the update
|
||||
let callbackApp = getApplyDirFile("a/b/" + gCallbackBinFile);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let callbackAppProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
callbackAppProcess.init(callbackApp);
|
||||
callbackAppProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
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_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -223,6 +223,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -224,6 +224,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,247 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File locked complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0174";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Exclusively lock an existing file so it is in use during the update
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let helperDestDir = getApplyDirFile("a/b/");
|
||||
helperBin.copyTo(helperDestDir, HELPER_BIN_FILE);
|
||||
helperBin = getApplyDirFile("a/b/" + HELPER_BIN_FILE);
|
||||
// Strip off the first two directories so the path has to be from the helper's
|
||||
// working directory.
|
||||
let lockFileRelPath = TEST_FILES[3].relPathDir.split("/");
|
||||
lockFileRelPath = lockFileRelPath.slice(2);
|
||||
lockFileRelPath = lockFileRelPath.join("/") + "/" + TEST_FILES[3].fileName;
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40", lockFileRelPath];
|
||||
let lockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
lockFileProcess.init(helperBin);
|
||||
lockFileProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"applying a complete mar");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
logTestInfo("testing update.status should be " + STATE_FAILED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File locked partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0175";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch) and causes " +
|
||||
"LoadSourceFile failed",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_PARTIAL_FILE);
|
||||
|
||||
// Exclusively lock an existing file so it is in use during the update
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let helperDestDir = getApplyDirFile("a/b/");
|
||||
helperBin.copyTo(helperDestDir, HELPER_BIN_FILE);
|
||||
helperBin = getApplyDirFile("a/b/" + HELPER_BIN_FILE);
|
||||
// Strip off the first two directories so the path has to be from the helper's
|
||||
// working directory.
|
||||
let lockFileRelPath = TEST_FILES[3].relPathDir.split("/");
|
||||
lockFileRelPath = lockFileRelPath.slice(2);
|
||||
lockFileRelPath = lockFileRelPath.join("/") + "/" + TEST_FILES[3].fileName;
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40", lockFileRelPath];
|
||||
let lockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
lockFileProcess.init(helperBin);
|
||||
lockFileProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"applying a complete mar");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
logTestInfo("testing update.status should be " + STATE_FAILED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -222,6 +222,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -225,6 +225,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -231,6 +231,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -272,6 +272,7 @@ function doUpdate() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0188";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let fileInUseBin = getApplyDirFile(TEST_FILES[14].relPathDir +
|
||||
TEST_FILES[14].fileName);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
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_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0189";
|
||||
const MAR_IN_USE_WIN_FILE = "data/partial_win.mar";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_in_use_win_before.exe",
|
||||
compareFile : "data/partial_in_use_win_before.exe"
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_in_use_win_before.exe",
|
||||
compareFile : "data/partial_in_use_win_before.exe"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_IN_USE_WIN_FILE);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let fileInUseBin = getApplyDirFile(TEST_FILES[12].relPathDir +
|
||||
TEST_FILES[12].fileName);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
let exitValue = runUpdate();
|
||||
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_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,255 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use inside removed dir complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0190";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
let fileInUseBin = getApplyDirFile(TEST_DIRS[4].relPathDir +
|
||||
TEST_DIRS[4].subDirs[0] +
|
||||
TEST_DIRS[4].subDirFiles[0]);
|
||||
// Remove the empty file created for the test so the helper application can
|
||||
// replace it.
|
||||
fileInUseBin.remove(false);
|
||||
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let fileInUseDir = getApplyDirFile(TEST_DIRS[4].relPathDir +
|
||||
TEST_DIRS[4].subDirs[0]);
|
||||
helperBin.copyTo(fileInUseDir, TEST_DIRS[4].subDirFiles[0]);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
let exitValue = runUpdate();
|
||||
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_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use inside removed dir partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0191";
|
||||
const MAR_IN_USE_WIN_FILE = "data/partial.mar";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0644,
|
||||
comparePerms : 0644
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0775,
|
||||
comparePerms : 0775
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0755,
|
||||
comparePerms : 0755
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0755,
|
||||
comparePerms : 0755
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0644,
|
||||
comparePerms : 0644
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_IN_USE_WIN_FILE);
|
||||
|
||||
let fileInUseBin = getApplyDirFile(TEST_DIRS[2].relPathDir +
|
||||
TEST_DIRS[2].files[0]);
|
||||
// Remove the empty file created for the test so the helper application can
|
||||
// replace it.
|
||||
fileInUseBin.remove(false);
|
||||
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let fileInUseDir = getApplyDirFile(TEST_DIRS[2].relPathDir);
|
||||
helperBin.copyTo(fileInUseDir, TEST_DIRS[2].files[0]);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
let exitValue = runUpdate();
|
||||
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_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,584 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 = "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()) {
|
||||
return;
|
||||
}
|
||||
// Symlink active-update.xml and updates/ inside the dist/bin directory
|
||||
// to point to the bundle directory.
|
||||
// This is necessary because in order to test the code which actually ships
|
||||
// with Firefox, we need to perform the update inside the bundle directory,
|
||||
// whereas xpcshell runs from dist/bin/, and the updater service code looks
|
||||
// at the current process directory to find things like these two files.
|
||||
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
let libc = ctypes.open("/usr/lib/libc.dylib");
|
||||
// We need these two low level APIs because their functionality is not
|
||||
// provided in nsIFile APIs.
|
||||
let symlink = libc.declare("symlink", ctypes.default_abi, ctypes.int,
|
||||
ctypes.char.ptr, ctypes.char.ptr);
|
||||
let unlink = libc.declare("unlink", ctypes.default_abi, ctypes.int,
|
||||
ctypes.char.ptr);
|
||||
|
||||
// Symlink active-update.xml
|
||||
let dest = getAppDir();
|
||||
dest.append("active-update.xml");
|
||||
if (!dest.exists()) {
|
||||
dest.create(dest.NORMAL_FILE_TYPE, 0644);
|
||||
}
|
||||
do_check_true(dest.exists());
|
||||
let source = getUpdatesRootDir();
|
||||
source.append("active-update.xml");
|
||||
unlink(source.path);
|
||||
let ret = symlink(dest.path, source.path);
|
||||
do_check_eq(ret, 0);
|
||||
do_check_true(source.exists());
|
||||
|
||||
// Symlink updates/
|
||||
let dest2 = getAppDir();
|
||||
dest2.append("updates");
|
||||
if (dest2.exists()) {
|
||||
dest2.remove(true);
|
||||
}
|
||||
dest2.create(dest.DIRECTORY_TYPE, 0755);
|
||||
do_check_true(dest2.exists());
|
||||
let source2 = getUpdatesRootDir();
|
||||
source2.append("updates");
|
||||
if (source2.exists()) {
|
||||
source2.remove(true);
|
||||
}
|
||||
ret = symlink(dest2.path, source2.path);
|
||||
do_check_eq(ret, 0);
|
||||
do_check_true(source2.exists());
|
||||
|
||||
// Cleanup the symlinks when the test is finished.
|
||||
do_register_cleanup(function() {
|
||||
let ret = unlink(source.path);
|
||||
do_check_false(source.exists());
|
||||
let ret = unlink(source2.path);
|
||||
do_check_false(source2.exists());
|
||||
});
|
||||
|
||||
// Now, make sure that getUpdatesRootDir returns the application bundle
|
||||
// directory, to make the various stuff in the test framework to work
|
||||
// correctly.
|
||||
getUpdatesRootDir = getAppDir;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
do_register_cleanup(end_test);
|
||||
|
||||
removeUpdateDirsAndFiles();
|
||||
|
||||
symlinkUpdateFilesIntoBundleDirectory();
|
||||
if (IS_WIN) {
|
||||
adjustPathsOnWindows();
|
||||
}
|
||||
|
||||
if (!gAppBinPath) {
|
||||
do_throw("Main application binary not found... expected: " +
|
||||
APP_BIN_NAME + APP_BIN_SUFFIX);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't attempt to show a prompt when the update is finished.
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, true);
|
||||
|
||||
let channel = Services.prefs.getCharPref(PREF_APP_UPDATE_CHANNEL);
|
||||
let patches = getLocalPatchString(null, null, null, null, null, "true",
|
||||
STATE_PENDING);
|
||||
let updates = getLocalUpdateString(patches, null, null, null, null, null,
|
||||
null, null, null, null, null, null,
|
||||
null, "true", channel);
|
||||
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
|
||||
|
||||
// Read the application.ini and use its application version
|
||||
let processDir = getAppDir();
|
||||
let file = processDir.clone();
|
||||
file.append("application.ini");
|
||||
let ini = AUS_Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
|
||||
getService(AUS_Ci.nsIINIParserFactory).
|
||||
createINIParser(file);
|
||||
let version = ini.getString("App", "Version");
|
||||
writeVersionFile(version);
|
||||
writeStatusFile(STATE_PENDING);
|
||||
|
||||
// This is the directory where the update files will be located
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
try {
|
||||
removeDirRecursive(updateTestDir);
|
||||
}
|
||||
catch (e) {
|
||||
logTestInfo("unable to remove directory - path: " + updateTestDir.path +
|
||||
", exception: " + e);
|
||||
}
|
||||
|
||||
let updatesPatchDir = getUpdatesDir();
|
||||
updatesPatchDir.append("0");
|
||||
let mar = do_get_file("data/simple.mar");
|
||||
mar.copyTo(updatesPatchDir, FILE_UPDATE_ARCHIVE);
|
||||
|
||||
reloadUpdateManagerData();
|
||||
gActiveUpdate = gUpdateManager.activeUpdate;
|
||||
do_check_true(!!gActiveUpdate);
|
||||
|
||||
let updateSettingsIni = processDir.clone();
|
||||
updateSettingsIni.append(UPDATE_SETTINGS_INI_FILE);
|
||||
writeFile(updateSettingsIni, UPDATE_SETTINGS_CONTENTS);
|
||||
|
||||
// Initiate a background update.
|
||||
AUS_Cc["@mozilla.org/updates/update-processor;1"].
|
||||
createInstance(AUS_Ci.nsIUpdateProcessor).
|
||||
processUpdate(gActiveUpdate);
|
||||
|
||||
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);
|
||||
|
||||
setEnvironment();
|
||||
|
||||
gProcess.runAsync(args, args.length, gProcessObserver);
|
||||
|
||||
resetEnvironment();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
if (gProcess.isRunning) {
|
||||
logTestInfo("attempt to kill process");
|
||||
gProcess.kill();
|
||||
}
|
||||
|
||||
if (gAppTimer) {
|
||||
logTestInfo("cancelling timer");
|
||||
gAppTimer.cancel();
|
||||
gAppTimer = null;
|
||||
}
|
||||
|
||||
resetEnvironment();
|
||||
|
||||
// Remove the files added by the update.
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
try {
|
||||
logTestInfo("removing update test directory " + updateTestDir.path);
|
||||
removeDirRecursive(updateTestDir);
|
||||
}
|
||||
catch (e) {
|
||||
logTestInfo("unable to remove directory - path: " + updateTestDir.path +
|
||||
", exception: " + e);
|
||||
}
|
||||
|
||||
if (IS_UNIX) {
|
||||
// This will delete the launch script if it exists.
|
||||
getLaunchScript();
|
||||
if (IS_MACOSX) {
|
||||
// This will delete the version script and version file if they exist.
|
||||
getVersionScriptAndFile();
|
||||
}
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* The observer for the call to nsIProcess:runAsync.
|
||||
*/
|
||||
let gProcessObserver = {
|
||||
observe: function PO_observe(subject, topic, data) {
|
||||
logTestInfo("topic " + topic + ", process exitValue " + gProcess.exitValue);
|
||||
if (gAppTimer) {
|
||||
gAppTimer.cancel();
|
||||
gAppTimer = null;
|
||||
}
|
||||
if (topic != "process-finished" || gProcess.exitValue != 0) {
|
||||
do_throw("Failed to launch application");
|
||||
}
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIObserver])
|
||||
};
|
||||
|
||||
/**
|
||||
* The timer callback to kill the process if it takes too long.
|
||||
*/
|
||||
let gTimerCallback = {
|
||||
notify: function TC_notify(aTimer) {
|
||||
gAppTimer = null;
|
||||
if (gProcess.isRunning) {
|
||||
gProcess.kill();
|
||||
}
|
||||
do_throw("launch application timer expired");
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
function shouldAdjustPathsOnMac() {
|
||||
// When running xpcshell tests locally, xpcshell and firefox-bin do not live
|
||||
// in the same directory.
|
||||
let dir = getCurrentProcessDir();
|
||||
return (IS_MACOSX && dir.leafName != "MacOS");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function copies the entire process directory over to a new one which we
|
||||
* can write to, so that we can test under Windows which holds locks on opened
|
||||
* files.
|
||||
*/
|
||||
function adjustPathsOnWindows() {
|
||||
// We copy the entire GRE directory into another location so that xpcshell
|
||||
// running doesn't prevent the updater from moving stuff around.
|
||||
let tmpDir = do_get_profile();
|
||||
tmpDir.append("ExecutableDir.tmp");
|
||||
tmpDir.createUnique(tmpDir.DIRECTORY_TYPE, 0755);
|
||||
let procDir = getCurrentProcessDir();
|
||||
procDir.copyTo(tmpDir, "bin");
|
||||
let newDir = tmpDir.clone();
|
||||
newDir.append("bin");
|
||||
gWindowsBinDir = newDir;
|
||||
logTestInfo("Using this new bin directory: " + gWindowsBinDir.path);
|
||||
// Note that this directory will be deleted as part of the xpcshell teardown,
|
||||
// so we don't need to remove it explicitly.
|
||||
|
||||
// We need to make NS_GRE_DIR point to the new bindir, since
|
||||
// nsUpdateProcessor::ProcessUpdate uses NS_GRE_DIR to construct the
|
||||
// destination path name which would be passed to updater.exe.
|
||||
let dirProvider = {
|
||||
getFile: function DP_getFile(prop, persistent) {
|
||||
persistent.value = true;
|
||||
if (prop == NS_GRE_DIR)
|
||||
return getAppDir();
|
||||
return null;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(AUS_Ci.nsIDirectoryServiceProvider) ||
|
||||
iid.equals(AUS_Ci.nsISupports))
|
||||
return this;
|
||||
throw AUS_Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
let ds = Services.dirsvc.QueryInterface(AUS_Ci.nsIDirectoryService);
|
||||
ds.QueryInterface(AUS_Ci.nsIProperties).undefine(NS_GRE_DIR);
|
||||
ds.registerProvider(dirProvider);
|
||||
do_register_cleanup(function() {
|
||||
ds.unregisterProvider(dirProvider);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory where the update adds / removes the files contained in the
|
||||
* update.
|
||||
*
|
||||
* @return nsIFile for the directory where the update adds / removes the files
|
||||
* contained in the update mar.
|
||||
*/
|
||||
function getUpdateTestDir() {
|
||||
let updateTestDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updateTestDir = updateTestDir.parent.parent;
|
||||
}
|
||||
updateTestDir.append("update_test");
|
||||
return updateTestDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the update has finished being applied in the background.
|
||||
*/
|
||||
function checkUpdateApplied() {
|
||||
// Don't proceed until the update has been applied.
|
||||
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
|
||||
return;
|
||||
}
|
||||
|
||||
let updatedDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updatedDir = updatedDir.parent.parent;
|
||||
}
|
||||
updatedDir.append(UPDATED_DIR_SUFFIX.replace("/", ""));
|
||||
logTestInfo("testing " + updatedDir.path + " should exist");
|
||||
do_check_true(updatedDir.exists());
|
||||
|
||||
let log;
|
||||
if (IS_WIN) {
|
||||
log = getUpdatesDir();
|
||||
} else {
|
||||
log = updatedDir.clone();
|
||||
if (IS_MACOSX) {
|
||||
log.append("Contents");
|
||||
log.append("MacOS");
|
||||
}
|
||||
log.append("updates");
|
||||
}
|
||||
log.append(FILE_LAST_LOG);
|
||||
if (!log.exists()) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't proceed until the update status is no longer pending or applying.
|
||||
let status = readStatusFile();
|
||||
do_check_eq(status, STATE_APPLIED_PLATFORM);
|
||||
|
||||
// On Windows, make sure not to use the maintenance service for switching
|
||||
// the app.
|
||||
if (IS_WIN) {
|
||||
writeStatusFile(STATE_APPLIED);
|
||||
status = readStatusFile();
|
||||
do_check_eq(status, STATE_APPLIED);
|
||||
}
|
||||
|
||||
// Log the contents of the update.log so it is simpler to diagnose a test
|
||||
// failure.
|
||||
let contents = readFile(log);
|
||||
logTestInfo("contents of " + log.path + ":\n" +
|
||||
contents.replace(/\r\n/g, "\n"));
|
||||
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
logTestInfo("testing " + updateTestDir.path + " shouldn't exist");
|
||||
do_check_false(updateTestDir.exists());
|
||||
|
||||
updateTestDir = updatedDir.clone();
|
||||
updateTestDir.append("update_test");
|
||||
let file = updateTestDir.clone();
|
||||
file.append("UpdateTestRemoveFile");
|
||||
logTestInfo("testing " + file.path + " shouldn't exist");
|
||||
do_check_false(file.exists());
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("UpdateTestAddFile");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "UpdateTestAddFile\n");
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("removed-files");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "update_test/UpdateTestRemoveFile\n");
|
||||
|
||||
let updatesDir = getUpdatesDir();
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_LAST_LOG);
|
||||
if (IS_WIN) {
|
||||
// On Windows this file lives outside of the app directory, so it should exist.
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
} else {
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
}
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_BACKUP_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir = updatedDir.clone();
|
||||
if (IS_MACOSX) {
|
||||
updatesDir.append("Contents");
|
||||
updatesDir.append("MacOS");
|
||||
}
|
||||
updatesDir.append("updates");
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
if (!IS_WIN) {
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_LAST_LOG);
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
}
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_BACKUP_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir.append("0");
|
||||
logTestInfo("testing " + updatesDir.path + " shouldn't exist");
|
||||
do_check_false(updatesDir.exists());
|
||||
|
||||
// Now, switch the updated version of the app
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, switchApp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the update has finished and if it has finished performs checks for
|
||||
* the test.
|
||||
*/
|
||||
function checkUpdateFinished() {
|
||||
// Don't proceed until the update status is no longer applied.
|
||||
try {
|
||||
let status = readStatusFile();
|
||||
if (status != STATE_SUCCEEDED) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore exceptions if the status file is not found
|
||||
}
|
||||
|
||||
try {
|
||||
// This will delete the app console log file if it exists.
|
||||
getAppConsoleLogPath();
|
||||
} catch (e) {
|
||||
if (e.result == Components.results.NS_ERROR_FILE_IS_LOCKED) {
|
||||
// This might happen on Windows in case the callback application has not
|
||||
// finished its job yet. So, we'll wait some more.
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
return;
|
||||
} else {
|
||||
do_throw("getAppConsoleLogPath threw: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we need to see if the application was switched successfully.
|
||||
|
||||
let updatedDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updatedDir = updatedDir.parent.parent;
|
||||
}
|
||||
updatedDir.append(UPDATED_DIR_SUFFIX.replace("/", ""));
|
||||
logTestInfo("testing " + updatedDir.path + " shouldn't exist");
|
||||
if (updatedDir.exists()) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
return;
|
||||
}
|
||||
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
|
||||
let file = updateTestDir.clone();
|
||||
file.append("UpdateTestRemoveFile");
|
||||
logTestInfo("testing " + file.path + " shouldn't exist");
|
||||
do_check_false(file.exists());
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("UpdateTestAddFile");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "UpdateTestAddFile\n");
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("removed-files");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "update_test/UpdateTestRemoveFile\n");
|
||||
|
||||
let updatesDir = getUpdatesDir();
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
if (IS_WIN) {
|
||||
// On Windows, this log file is written to the AppData directory, and will
|
||||
// therefore exist.
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
} else {
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
}
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_LAST_LOG);
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_BACKUP_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir.append("0");
|
||||
if (IS_WIN) {
|
||||
// On Windows, this log file is written to the AppData directory, and will
|
||||
// therefore exist.
|
||||
logTestInfo("testing " + updatesDir.path + " should exist");
|
||||
do_check_true(updatesDir.exists());
|
||||
} else {
|
||||
logTestInfo("testing " + updatesDir.path + " shouldn't exist");
|
||||
do_check_false(updatesDir.exists());
|
||||
}
|
||||
|
||||
removeCallbackCopy();
|
||||
}
|
|
@ -6,10 +6,13 @@
|
|||
[test_0153_appBinPatched_xp_win_partial.js]
|
||||
[test_0160_appInUse_xp_win_complete.js]
|
||||
[test_0161_appInUse_xp_win_complete.js]
|
||||
[test_0162_appInUse_xp_win_complete.js]
|
||||
[test_0170_fileLocked_xp_win_complete.js]
|
||||
[test_0171_fileLocked_xp_win_partial.js]
|
||||
[test_0172_fileLocked_xp_win_complete.js]
|
||||
[test_0173_fileLocked_xp_win_partial.js]
|
||||
[test_0174_fileLocked_xp_win_complete.js]
|
||||
[test_0175_fileLocked_xp_win_partial.js]
|
||||
[test_0180_fileInUse_xp_win_complete.js]
|
||||
[test_0181_fileInUse_xp_win_partial.js]
|
||||
[test_0182_rmrfdirFileInUse_xp_win_complete.js]
|
||||
|
@ -18,5 +21,9 @@
|
|||
[test_0185_fileInUse_xp_win_partial.js]
|
||||
[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]
|
||||
|
|
|
@ -218,6 +218,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* Application in use complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0162_svc";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Launch the callback helper application so it is in use during the update
|
||||
let callbackApp = getApplyDirFile("a/b/" + gCallbackBinFile);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let callbackAppProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
callbackAppProcess.init(callbackApp);
|
||||
callbackAppProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_APPLIED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -226,6 +226,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -227,6 +227,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File locked complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0174_svc";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Exclusively lock an existing file so it is in use during the update
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let helperDestDir = getApplyDirFile("a/b/");
|
||||
helperBin.copyTo(helperDestDir, HELPER_BIN_FILE);
|
||||
helperBin = getApplyDirFile("a/b/" + HELPER_BIN_FILE);
|
||||
// Strip off the first two directories so the path has to be from the helper's
|
||||
// working directory.
|
||||
let lockFileRelPath = TEST_FILES[3].relPathDir.split("/");
|
||||
lockFileRelPath = lockFileRelPath.slice(2);
|
||||
lockFileRelPath = lockFileRelPath.join("/") + "/" + TEST_FILES[3].fileName;
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40", lockFileRelPath];
|
||||
let lockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
lockFileProcess.init(helperBin);
|
||||
lockFileProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_FAILED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,251 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File locked partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0175_svc";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not patched for failed update (patch) and causes " +
|
||||
"LoadSourceFile failed",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not patched for failed update (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not added for failed update (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Not removed for failed update (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ShouldNotBeDeleted\n",
|
||||
compareContents : "ShouldNotBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : false
|
||||
}, {
|
||||
description : "Not removed for failed update (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : false
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_PARTIAL_FILE);
|
||||
|
||||
// Exclusively lock an existing file so it is in use during the update
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let helperDestDir = getApplyDirFile("a/b/");
|
||||
helperBin.copyTo(helperDestDir, HELPER_BIN_FILE);
|
||||
helperBin = getApplyDirFile("a/b/" + HELPER_BIN_FILE);
|
||||
// Strip off the first two directories so the path has to be from the helper's
|
||||
// working directory.
|
||||
let lockFileRelPath = TEST_FILES[3].relPathDir.split("/");
|
||||
lockFileRelPath = lockFileRelPath.slice(2);
|
||||
lockFileRelPath = lockFileRelPath.join("/") + "/" + TEST_FILES[3].fileName;
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40", lockFileRelPath];
|
||||
let lockFileProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
lockFileProcess.init(helperBin);
|
||||
lockFileProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_FAILED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_FAILED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir).split(": ")[0], STATE_FAILED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory doesn't exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -225,6 +225,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -228,6 +228,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -234,6 +234,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -275,6 +275,7 @@ function checkUpdateApplied() {
|
|||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
gDisableReplaceFallback = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0188_svc";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let fileInUseBin = getApplyDirFile(TEST_FILES[14].relPathDir +
|
||||
TEST_FILES[14].fileName);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_APPLIED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0189_svc";
|
||||
const MAR_IN_USE_WIN_FILE = "data/partial_win.mar";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_in_use_win_before.exe",
|
||||
compareFile : "data/partial_in_use_win_before.exe"
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_in_use_win_before.exe",
|
||||
compareFile : "data/partial_in_use_win_before.exe"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_IN_USE_WIN_FILE);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let fileInUseBin = getApplyDirFile(TEST_FILES[12].relPathDir +
|
||||
TEST_FILES[12].fileName);
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
// apply the complete mar
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_APPLIED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,258 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use inside removed dir complete MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0190_svc";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_precomplete",
|
||||
compareFile : "data/partial_precomplete"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "removed-files",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial_removed-files",
|
||||
compareFile : "data/partial_removed-files"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/partial.png",
|
||||
compareFile : "data/partial.png"
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add) file in use",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : HELPER_BIN_FILE,
|
||||
compareFile : HELPER_BIN_FILE
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromComplete\n",
|
||||
compareContents : "ToBeReplacedWithFromComplete\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}, {
|
||||
description : "Removed by precomplete (remove)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/20/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by precomplete (rmdir)",
|
||||
relPathDir : "a/b/2/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_COMPLETE_FILE);
|
||||
|
||||
let fileInUseBin = getApplyDirFile(TEST_DIRS[4].relPathDir +
|
||||
TEST_DIRS[4].subDirs[0] +
|
||||
TEST_DIRS[4].subDirFiles[0]);
|
||||
// Remove the empty file created for the test so the helper application can
|
||||
// replace it.
|
||||
fileInUseBin.remove(false);
|
||||
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let fileInUseDir = getApplyDirFile(TEST_DIRS[4].relPathDir +
|
||||
TEST_DIRS[4].subDirs[0]);
|
||||
helperBin.copyTo(fileInUseDir, TEST_DIRS[4].subDirFiles[0]);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_APPLIED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/* File in use inside removed dir partial MAR file background patch apply failure fallback test */
|
||||
|
||||
const TEST_ID = "0191_svc";
|
||||
const MAR_IN_USE_WIN_FILE = "data/partial.mar";
|
||||
|
||||
// The files are listed in the same order as they are applied from the mar's
|
||||
// update.manifest. Complete updates have remove file and rmdir directory
|
||||
// operations located in the precomplete file performed first.
|
||||
const TEST_FILES = [
|
||||
{
|
||||
description : "Should never change",
|
||||
fileName : "channel-prefs.js",
|
||||
relPathDir : "a/b/defaults/pref/",
|
||||
originalContents : "ShouldNotBeReplaced\n",
|
||||
compareContents : "ShouldNotBeReplaced\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0644,
|
||||
comparePerms : 0644
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "precomplete",
|
||||
relPathDir : "",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete_precomplete",
|
||||
compareFile : "data/complete_precomplete",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "searchpluginstext0",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0775,
|
||||
comparePerms : 0775
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng1.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Patched by update.manifest if the file exists " +
|
||||
"(patch-if)",
|
||||
fileName : "searchpluginspng0.png",
|
||||
relPathDir : "a/b/searchplugins/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions1text0",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png1.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions1png0.png",
|
||||
relPathDir : "a/b/extensions/extensions1/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest if the parent directory " +
|
||||
"exists (add-if)",
|
||||
fileName : "extensions0text0",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png1.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest if the parent directory " +
|
||||
"exists (patch-if)",
|
||||
fileName : "extensions0png0.png",
|
||||
relPathDir : "a/b/extensions/extensions0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "exe0.exe",
|
||||
relPathDir : "a/b/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0755,
|
||||
comparePerms : 0755
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "0exe0.exe",
|
||||
relPathDir : "a/b/0/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0755,
|
||||
comparePerms : 0755
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text0",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeReplacedWithFromPartial\n",
|
||||
compareContents : "ToBeReplacedWithFromPartial\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : 0644,
|
||||
comparePerms : 0644
|
||||
}, {
|
||||
description : "Patched by update.manifest (patch)",
|
||||
fileName : "00png0.png",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : "data/complete.png",
|
||||
compareFile : "data/complete.png",
|
||||
originalPerms : 0666,
|
||||
comparePerms : 0666
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20text0",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "20png0.png",
|
||||
relPathDir : "a/b/2/20/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Added by update.manifest (add)",
|
||||
fileName : "00text2",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : null,
|
||||
compareContents : null,
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "10text0",
|
||||
relPathDir : "a/b/1/10/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}, {
|
||||
description : "Removed by update.manifest (remove)",
|
||||
fileName : "00text1",
|
||||
relPathDir : "a/b/0/00/",
|
||||
originalContents : "ToBeDeleted\n",
|
||||
compareContents : "ToBeDeleted\n",
|
||||
originalFile : null,
|
||||
compareFile : null,
|
||||
originalPerms : null,
|
||||
comparePerms : null
|
||||
}];
|
||||
|
||||
ADDITIONAL_TEST_DIRS = [
|
||||
{
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/10/",
|
||||
dirRemoved : true
|
||||
}, {
|
||||
description : "Removed by update.manifest (rmdir)",
|
||||
relPathDir : "a/b/1/",
|
||||
dirRemoved : true
|
||||
}];
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(cleanupUpdaterTest);
|
||||
|
||||
gBackgroundUpdate = true;
|
||||
setupUpdaterTest(MAR_IN_USE_WIN_FILE);
|
||||
|
||||
let fileInUseBin = getApplyDirFile(TEST_DIRS[2].relPathDir +
|
||||
TEST_DIRS[2].files[0]);
|
||||
// Remove the empty file created for the test so the helper application can
|
||||
// replace it.
|
||||
fileInUseBin.remove(false);
|
||||
|
||||
let helperBin = do_get_file(HELPER_BIN_FILE);
|
||||
let fileInUseDir = getApplyDirFile(TEST_DIRS[2].relPathDir);
|
||||
helperBin.copyTo(fileInUseDir, TEST_DIRS[2].files[0]);
|
||||
|
||||
// Launch an existing file so it is in use during the update
|
||||
let args = [getApplyDirPath() + "a/b/", "input", "output", "-s", "40"];
|
||||
let fileInUseProcess = AUS_Cc["@mozilla.org/process/util;1"].
|
||||
createInstance(AUS_Ci.nsIProcess);
|
||||
fileInUseProcess.init(fileInUseBin);
|
||||
fileInUseProcess.run(false, args, args.length);
|
||||
|
||||
do_timeout(TEST_HELPER_TIMEOUT, waitForHelperSleep);
|
||||
}
|
||||
|
||||
function doUpdate() {
|
||||
runUpdateUsingService(STATE_PENDING_SVC, STATE_APPLIED, checkUpdateApplied);
|
||||
}
|
||||
|
||||
function checkUpdateApplied() {
|
||||
logTestInfo("testing update.status should be " + STATE_APPLIED);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_APPLIED);
|
||||
|
||||
// Now switch the application and its updated version
|
||||
gBackgroundUpdate = false;
|
||||
gSwitchApp = true;
|
||||
exitValue = runUpdate();
|
||||
logTestInfo("testing updater binary process exitValue for failure when " +
|
||||
"switching to the updated application");
|
||||
do_check_eq(exitValue, 1);
|
||||
|
||||
setupHelperFinish();
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
logTestInfo("testing update.status should be " + STATE_PENDING);
|
||||
let updatesDir = do_get_file(TEST_ID + UPDATES_DIR_SUFFIX);
|
||||
do_check_eq(readStatusFile(updatesDir), STATE_PENDING);
|
||||
|
||||
checkFilesAfterUpdateFailure(getApplyDirFile);
|
||||
checkUpdateLogContains(ERR_RENAME_FILE);
|
||||
|
||||
logTestInfo("testing tobedeleted directory does not exist");
|
||||
let toBeDeletedDir = getApplyDirFile("tobedeleted", true);
|
||||
do_check_false(toBeDeletedDir.exists());
|
||||
|
||||
checkCallbackAppLog();
|
||||
}
|
|
@ -0,0 +1,561 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 = "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()) {
|
||||
return;
|
||||
}
|
||||
// Symlink active-update.xml and updates/ inside the dist/bin directory
|
||||
// to point to the bundle directory.
|
||||
// This is necessary because in order to test the code which actually ships
|
||||
// with Firefox, we need to perform the update inside the bundle directory,
|
||||
// whereas xpcshell runs from dist/bin/, and the updater service code looks
|
||||
// at the current process directory to find things like these two files.
|
||||
|
||||
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||
let libc = ctypes.open("/usr/lib/libc.dylib");
|
||||
// We need these two low level APIs because their functionality is not
|
||||
// provided in nsIFile APIs.
|
||||
let symlink = libc.declare("symlink", ctypes.default_abi, ctypes.int,
|
||||
ctypes.char.ptr, ctypes.char.ptr);
|
||||
let unlink = libc.declare("unlink", ctypes.default_abi, ctypes.int,
|
||||
ctypes.char.ptr);
|
||||
|
||||
// Symlink active-update.xml
|
||||
let dest = getAppDir();
|
||||
dest.append("active-update.xml");
|
||||
if (!dest.exists()) {
|
||||
dest.create(dest.NORMAL_FILE_TYPE, 0644);
|
||||
}
|
||||
do_check_true(dest.exists());
|
||||
let source = getUpdatesRootDir();
|
||||
source.append("active-update.xml");
|
||||
unlink(source.path);
|
||||
let ret = symlink(dest.path, source.path);
|
||||
do_check_eq(ret, 0);
|
||||
do_check_true(source.exists());
|
||||
|
||||
// Symlink updates/
|
||||
let dest2 = getAppDir();
|
||||
dest2.append("updates");
|
||||
if (dest2.exists()) {
|
||||
dest2.remove(true);
|
||||
}
|
||||
dest2.create(dest.DIRECTORY_TYPE, 0755);
|
||||
do_check_true(dest2.exists());
|
||||
let source2 = getUpdatesRootDir();
|
||||
source2.append("updates");
|
||||
if (source2.exists()) {
|
||||
source2.remove(true);
|
||||
}
|
||||
ret = symlink(dest2.path, source2.path);
|
||||
do_check_eq(ret, 0);
|
||||
do_check_true(source2.exists());
|
||||
|
||||
// Cleanup the symlinks when the test is finished.
|
||||
do_register_cleanup(function() {
|
||||
let ret = unlink(source.path);
|
||||
do_check_false(source.exists());
|
||||
let ret = unlink(source2.path);
|
||||
do_check_false(source2.exists());
|
||||
});
|
||||
|
||||
// Now, make sure that getUpdatesRootDir returns the application bundle
|
||||
// directory, to make the various stuff in the test framework to work
|
||||
// correctly.
|
||||
getUpdatesRootDir = getAppDir;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
if (!shouldRunServiceTest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do_test_pending();
|
||||
do_register_cleanup(end_test);
|
||||
|
||||
removeUpdateDirsAndFiles();
|
||||
|
||||
symlinkUpdateFilesIntoBundleDirectory();
|
||||
if (IS_WIN) {
|
||||
adjustPathsOnWindows();
|
||||
}
|
||||
|
||||
if (!gAppBinPath) {
|
||||
do_throw("Main application binary not found... expected: " +
|
||||
APP_BIN_NAME + APP_BIN_SUFFIX);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't attempt to show a prompt when the update is finished.
|
||||
Services.prefs.setBoolPref(PREF_APP_UPDATE_SILENT, true);
|
||||
|
||||
let channel = Services.prefs.getCharPref(PREF_APP_UPDATE_CHANNEL);
|
||||
let patches = getLocalPatchString(null, null, null, null, null, "true",
|
||||
STATE_PENDING);
|
||||
let updates = getLocalUpdateString(patches, null, null, null, null, null,
|
||||
null, null, null, null, null, null,
|
||||
null, "true", channel);
|
||||
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
|
||||
|
||||
// Read the application.ini and use its application version
|
||||
let processDir = getAppDir();
|
||||
let file = processDir.clone();
|
||||
file.append("application.ini");
|
||||
let ini = AUS_Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
|
||||
getService(AUS_Ci.nsIINIParserFactory).
|
||||
createINIParser(file);
|
||||
let version = ini.getString("App", "Version");
|
||||
writeVersionFile(version);
|
||||
writeStatusFile(STATE_PENDING_SVC);
|
||||
|
||||
// This is the directory where the update files will be located
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
try {
|
||||
removeDirRecursive(updateTestDir);
|
||||
}
|
||||
catch (e) {
|
||||
logTestInfo("unable to remove directory - path: " + updateTestDir.path +
|
||||
", exception: " + e);
|
||||
}
|
||||
|
||||
let updatesPatchDir = getUpdatesDir();
|
||||
updatesPatchDir.append("0");
|
||||
let mar = do_get_file("data/simple.mar");
|
||||
mar.copyTo(updatesPatchDir, FILE_UPDATE_ARCHIVE);
|
||||
|
||||
reloadUpdateManagerData();
|
||||
gActiveUpdate = gUpdateManager.activeUpdate;
|
||||
do_check_true(!!gActiveUpdate);
|
||||
|
||||
setEnvironment();
|
||||
|
||||
let updateSettingsIni = processDir.clone();
|
||||
updateSettingsIni.append(UPDATE_SETTINGS_INI_FILE);
|
||||
writeFile(updateSettingsIni, UPDATE_SETTINGS_CONTENTS);
|
||||
|
||||
// Initiate a background update.
|
||||
AUS_Cc["@mozilla.org/updates/update-processor;1"].
|
||||
createInstance(AUS_Ci.nsIUpdateProcessor).
|
||||
processUpdate(gActiveUpdate);
|
||||
|
||||
resetEnvironment();
|
||||
|
||||
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);
|
||||
|
||||
setEnvironment();
|
||||
|
||||
gProcess.runAsync(args, args.length, gProcessObserver);
|
||||
|
||||
resetEnvironment();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
if (gProcess.isRunning) {
|
||||
logTestInfo("attempt to kill process");
|
||||
gProcess.kill();
|
||||
}
|
||||
|
||||
if (gAppTimer) {
|
||||
logTestInfo("cancelling timer");
|
||||
gAppTimer.cancel();
|
||||
gAppTimer = null;
|
||||
}
|
||||
|
||||
resetEnvironment();
|
||||
|
||||
// Remove the files added by the update.
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
try {
|
||||
logTestInfo("removing update test directory " + updateTestDir.path);
|
||||
removeDirRecursive(updateTestDir);
|
||||
}
|
||||
catch (e) {
|
||||
logTestInfo("unable to remove directory - path: " + updateTestDir.path +
|
||||
", exception: " + e);
|
||||
}
|
||||
|
||||
if (IS_UNIX) {
|
||||
// This will delete the launch script if it exists.
|
||||
getLaunchScript();
|
||||
if (IS_MACOSX) {
|
||||
// This will delete the version script and version file if they exist.
|
||||
getVersionScriptAndFile();
|
||||
}
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
/**
|
||||
* The observer for the call to nsIProcess:runAsync.
|
||||
*/
|
||||
let gProcessObserver = {
|
||||
observe: function PO_observe(subject, topic, data) {
|
||||
logTestInfo("topic " + topic + ", process exitValue " + gProcess.exitValue);
|
||||
if (gAppTimer) {
|
||||
gAppTimer.cancel();
|
||||
gAppTimer = null;
|
||||
}
|
||||
if (topic != "process-finished" || gProcess.exitValue != 0) {
|
||||
do_throw("Failed to launch application");
|
||||
}
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsIObserver])
|
||||
};
|
||||
|
||||
/**
|
||||
* The timer callback to kill the process if it takes too long.
|
||||
*/
|
||||
let gTimerCallback = {
|
||||
notify: function TC_notify(aTimer) {
|
||||
gAppTimer = null;
|
||||
if (gProcess.isRunning) {
|
||||
gProcess.kill();
|
||||
}
|
||||
do_throw("launch application timer expired");
|
||||
},
|
||||
QueryInterface: XPCOMUtils.generateQI([AUS_Ci.nsITimerCallback])
|
||||
};
|
||||
|
||||
function shouldAdjustPathsOnMac() {
|
||||
// When running xpcshell tests locally, xpcshell and firefox-bin do not live
|
||||
// in the same directory.
|
||||
let dir = getCurrentProcessDir();
|
||||
return (IS_MACOSX && dir.leafName != "MacOS");
|
||||
}
|
||||
|
||||
/**
|
||||
* This function copies the entire process directory over to a new one which we
|
||||
* can write to, so that we can test under Windows which holds locks on opened
|
||||
* files.
|
||||
*/
|
||||
function adjustPathsOnWindows() {
|
||||
// We copy the entire GRE directory into another location so that xpcshell
|
||||
// running doesn't prevent the updater from moving stuff around.
|
||||
let tmpDir = do_get_profile();
|
||||
tmpDir.append("ExecutableDir.tmp");
|
||||
tmpDir.createUnique(tmpDir.DIRECTORY_TYPE, 0755);
|
||||
let procDir = getCurrentProcessDir();
|
||||
procDir.copyTo(tmpDir, "bin");
|
||||
let newDir = tmpDir.clone();
|
||||
newDir.append("bin");
|
||||
gWindowsBinDir = newDir;
|
||||
logTestInfo("Using this new bin directory: " + gWindowsBinDir.path);
|
||||
// Note that this directory will be deleted as part of the xpcshell teardown,
|
||||
// so we don't need to remove it explicitly.
|
||||
|
||||
// We need to make NS_GRE_DIR point to the new bindir, since
|
||||
// nsUpdateProcessor::ProcessUpdate uses NS_GRE_DIR to construct the
|
||||
// destination path name which would be passed to updater.exe.
|
||||
let dirProvider = {
|
||||
getFile: function DP_getFile(prop, persistent) {
|
||||
persistent.value = true;
|
||||
if (prop == NS_GRE_DIR)
|
||||
return getAppDir();
|
||||
return null;
|
||||
},
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(AUS_Ci.nsIDirectoryServiceProvider) ||
|
||||
iid.equals(AUS_Ci.nsISupports))
|
||||
return this;
|
||||
throw AUS_Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
};
|
||||
let ds = Services.dirsvc.QueryInterface(AUS_Ci.nsIDirectoryService);
|
||||
ds.QueryInterface(AUS_Ci.nsIProperties).undefine(NS_GRE_DIR);
|
||||
ds.registerProvider(dirProvider);
|
||||
do_register_cleanup(function() {
|
||||
ds.unregisterProvider(dirProvider);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the directory where the update adds / removes the files contained in the
|
||||
* update.
|
||||
*
|
||||
* @return nsIFile for the directory where the update adds / removes the files
|
||||
* contained in the update mar.
|
||||
*/
|
||||
function getUpdateTestDir() {
|
||||
let updateTestDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updateTestDir = updateTestDir.parent.parent;
|
||||
}
|
||||
updateTestDir.append("update_test");
|
||||
return updateTestDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the update has finished being applied in the background.
|
||||
*/
|
||||
function checkUpdateApplied() {
|
||||
// Don't proceed until the update has been applied.
|
||||
if (gUpdateManager.activeUpdate.state != STATE_APPLIED_PLATFORM) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
|
||||
return;
|
||||
}
|
||||
|
||||
let updatedDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updatedDir = updatedDir.parent.parent;
|
||||
}
|
||||
updatedDir.append(UPDATED_DIR_SUFFIX.replace("/", ""));
|
||||
logTestInfo("testing " + updatedDir.path + " should exist");
|
||||
do_check_true(updatedDir.exists());
|
||||
|
||||
let log = getUpdatesDir();
|
||||
log.append(FILE_LAST_LOG);
|
||||
if (!log.exists()) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateApplied);
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't proceed until the update status is no longer pending or applying.
|
||||
let status = readStatusFile();
|
||||
do_check_eq(status, STATE_APPLIED_PLATFORM);
|
||||
|
||||
// On Windows, make sure not to use the maintenance service for switching
|
||||
// the app.
|
||||
if (IS_WIN) {
|
||||
writeStatusFile(STATE_APPLIED);
|
||||
status = readStatusFile();
|
||||
do_check_eq(status, STATE_APPLIED);
|
||||
}
|
||||
|
||||
// Log the contents of the update.log so it is simpler to diagnose a test
|
||||
// failure.
|
||||
let contents = readFile(log);
|
||||
logTestInfo("contents of " + log.path + ":\n" +
|
||||
contents.replace(/\r\n/g, "\n"));
|
||||
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
logTestInfo("testing " + updateTestDir.path + " shouldn't exist");
|
||||
do_check_false(updateTestDir.exists());
|
||||
|
||||
updateTestDir = updatedDir.clone();
|
||||
updateTestDir.append("update_test");
|
||||
let file = updateTestDir.clone();
|
||||
file.append("UpdateTestRemoveFile");
|
||||
logTestInfo("testing " + file.path + " shouldn't exist");
|
||||
do_check_false(file.exists());
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("UpdateTestAddFile");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "UpdateTestAddFile\n");
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("removed-files");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "update_test/UpdateTestRemoveFile\n");
|
||||
|
||||
let updatesDir = getUpdatesDir();
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_LAST_LOG);
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_BACKUP_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir = updatedDir.clone();
|
||||
if (IS_MACOSX) {
|
||||
updatesDir.append("Contents");
|
||||
updatesDir.append("MacOS");
|
||||
}
|
||||
updatesDir.append("updates");
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir.append("0");
|
||||
logTestInfo("testing " + updatesDir.path + " shouldn't exist");
|
||||
do_check_false(updatesDir.exists());
|
||||
|
||||
// Now, switch the updated version of the app
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, switchApp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the update has finished and if it has finished performs checks for
|
||||
* the test.
|
||||
*/
|
||||
function checkUpdateFinished() {
|
||||
// Don't proceed until the update status is no longer applied.
|
||||
try {
|
||||
let status = readStatusFile();
|
||||
if (status != STATE_SUCCEEDED) {
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore exceptions if the status file is not found
|
||||
}
|
||||
|
||||
try {
|
||||
// This will delete the app console log file if it exists.
|
||||
getAppConsoleLogPath();
|
||||
} catch (e) {
|
||||
if (e.result == Components.results.NS_ERROR_FILE_IS_LOCKED) {
|
||||
// This might happen on Windows in case the callback application has not
|
||||
// finished its job yet. So, we'll wait some more.
|
||||
do_timeout(CHECK_TIMEOUT_MILLI, checkUpdateFinished);
|
||||
return;
|
||||
} else {
|
||||
do_throw("getAppConsoleLogPath threw: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
// At this point we need to see if the application was switched successfully.
|
||||
|
||||
let updatedDir = getAppDir();
|
||||
if (IS_MACOSX) {
|
||||
updatedDir = updatedDir.parent.parent;
|
||||
}
|
||||
updatedDir.append(UPDATED_DIR_SUFFIX.replace("/", ""));
|
||||
logTestInfo("testing " + updatedDir.path + " shouldn't exist");
|
||||
do_check_false(updatedDir.exists());
|
||||
|
||||
let updateTestDir = getUpdateTestDir();
|
||||
|
||||
let file = updateTestDir.clone();
|
||||
file.append("UpdateTestRemoveFile");
|
||||
logTestInfo("testing " + file.path + " shouldn't exist");
|
||||
do_check_false(file.exists());
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("UpdateTestAddFile");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "UpdateTestAddFile\n");
|
||||
|
||||
file = updateTestDir.clone();
|
||||
file.append("removed-files");
|
||||
logTestInfo("testing " + file.path + " should exist");
|
||||
do_check_true(file.exists());
|
||||
do_check_eq(readFileBytes(file), "update_test/UpdateTestRemoveFile\n");
|
||||
|
||||
let updatesDir = getUpdatesDir();
|
||||
log = updatesDir.clone();
|
||||
log.append("0");
|
||||
log.append(FILE_UPDATE_LOG);
|
||||
if (IS_WIN) {
|
||||
// On Windows, this log file is written to the AppData directory, and will
|
||||
// therefore exist.
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
} else {
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
}
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_LAST_LOG);
|
||||
logTestInfo("testing " + log.path + " should exist");
|
||||
do_check_true(log.exists());
|
||||
|
||||
log = updatesDir.clone();
|
||||
log.append(FILE_BACKUP_LOG);
|
||||
logTestInfo("testing " + log.path + " shouldn't exist");
|
||||
do_check_false(log.exists());
|
||||
|
||||
updatesDir.append("0");
|
||||
if (IS_WIN) {
|
||||
// On Windows, this log file is written to the AppData directory, and will
|
||||
// therefore exist.
|
||||
logTestInfo("testing " + updatesDir.path + " should exist");
|
||||
do_check_true(updatesDir.exists());
|
||||
} else {
|
||||
logTestInfo("testing " + updatesDir.path + " shouldn't exist");
|
||||
do_check_false(updatesDir.exists());
|
||||
}
|
||||
|
||||
removeCallbackCopy();
|
||||
}
|
|
@ -19,10 +19,13 @@ tail =
|
|||
[test_0153_appBinPatched_xp_win_partial_svc.js]
|
||||
[test_0160_appInUse_xp_win_complete_svc.js]
|
||||
[test_0161_appInUse_xp_win_complete_svc.js]
|
||||
[test_0162_appInUse_xp_win_complete_svc.js]
|
||||
[test_0170_fileLocked_xp_win_complete_svc.js]
|
||||
[test_0171_fileLocked_xp_win_partial_svc.js]
|
||||
[test_0172_fileLocked_xp_win_complete_svc.js]
|
||||
[test_0173_fileLocked_xp_win_partial_svc.js]
|
||||
[test_0174_fileLocked_xp_win_complete_svc.js]
|
||||
[test_0175_fileLocked_xp_win_partial_svc.js]
|
||||
[test_0180_fileInUse_xp_win_complete_svc.js]
|
||||
[test_0181_fileInUse_xp_win_partial_svc.js]
|
||||
[test_0182_rmrfdirFileInUse_xp_win_complete_svc.js]
|
||||
|
@ -31,6 +34,11 @@ tail =
|
|||
[test_0185_fileInUse_xp_win_partial_svc.js]
|
||||
[test_0186_rmrfdirFileInUse_xp_win_complete_svc.js]
|
||||
[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]
|
||||
|
|
|
@ -267,6 +267,7 @@ static ArchiveReader gArchiveReader;
|
|||
static bool gSucceeded = false;
|
||||
static bool sBackgroundUpdate = false;
|
||||
static bool sReplaceRequest = false;
|
||||
static bool sUsingService = false;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// The current working directory specified in the command line.
|
||||
|
@ -550,6 +551,27 @@ static int ensure_parent_dir(const NS_tchar *path)
|
|||
return rv;
|
||||
}
|
||||
|
||||
#ifdef XP_UNIX
|
||||
static int ensure_copy_symlink(const NS_tchar *path, const NS_tchar *dest)
|
||||
{
|
||||
// Copy symlinks by creating a new symlink to the same target
|
||||
NS_tchar target[MAXPATHLEN + 1] = {NS_T('\0')};
|
||||
int rv = readlink(path, target, MAXPATHLEN);
|
||||
if (rv == -1) {
|
||||
LOG(("ensure_copy_symlink: failed to read the link: " LOG_S ", err: %d\n",
|
||||
path, errno));
|
||||
return READ_ERROR;
|
||||
}
|
||||
rv = symlink(target, dest);
|
||||
if (rv == -1) {
|
||||
LOG(("ensure_copy_symlink: failed to create the new link: " LOG_S ", target: " LOG_S " err: %d\n",
|
||||
dest, target, errno));
|
||||
return READ_ERROR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy the file named path onto a new file named dest.
|
||||
static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
|
||||
{
|
||||
|
@ -564,13 +586,19 @@ static int ensure_copy(const NS_tchar *path, const NS_tchar *dest)
|
|||
return 0;
|
||||
#else
|
||||
struct stat ss;
|
||||
int rv = NS_tstat(path, &ss);
|
||||
int rv = NS_tlstat(path, &ss);
|
||||
if (rv) {
|
||||
LOG(("ensure_copy: failed to read file status info: " LOG_S ", err: %d\n",
|
||||
path, errno));
|
||||
return READ_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XP_UNIX
|
||||
if (S_ISLNK(ss.st_mode)) {
|
||||
return ensure_copy_symlink(path, dest);
|
||||
}
|
||||
#endif
|
||||
|
||||
AutoFile infile = ensure_open(path, NS_T("rb"), ss.st_mode);
|
||||
if (!infile) {
|
||||
LOG(("ensure_copy: failed to open the file for reading: " LOG_S ", err: %d\n",
|
||||
|
@ -645,12 +673,19 @@ static int ensure_copy_recursive(const NS_tchar *path, const NS_tchar *dest,
|
|||
copy_recursive_skiplist<N>& skiplist)
|
||||
{
|
||||
struct stat sInfo;
|
||||
int rv = NS_tstat(path, &sInfo);
|
||||
int rv = NS_tlstat(path, &sInfo);
|
||||
if (rv) {
|
||||
LOG(("ensure_copy_recursive: path doesn't exist: " LOG_S ", rv: %d, err: %d\n",
|
||||
path, rv, errno));
|
||||
return READ_ERROR;
|
||||
}
|
||||
|
||||
#ifdef XP_UNIX
|
||||
if (S_ISLNK(sInfo.st_mode)) {
|
||||
return ensure_copy_symlink(path, dest);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!S_ISDIR(sInfo.st_mode)) {
|
||||
return ensure_copy(path, dest);
|
||||
}
|
||||
|
@ -1589,7 +1624,7 @@ LaunchCallbackApp(const NS_tchar *workingDir,
|
|||
}
|
||||
|
||||
static void
|
||||
WriteStatusFile(int status)
|
||||
WriteStatusText(const char* text)
|
||||
{
|
||||
// This is how we communicate our completion status to the main application.
|
||||
|
||||
|
@ -1601,6 +1636,12 @@ WriteStatusFile(int status)
|
|||
if (file == NULL)
|
||||
return;
|
||||
|
||||
fwrite(text, strlen(text), 1, file);
|
||||
}
|
||||
|
||||
static void
|
||||
WriteStatusFile(int status)
|
||||
{
|
||||
const char *text;
|
||||
|
||||
char buf[32];
|
||||
|
@ -1614,7 +1655,8 @@ WriteStatusFile(int status)
|
|||
snprintf(buf, sizeof(buf)/sizeof(buf[0]), "failed: %d\n", status);
|
||||
text = buf;
|
||||
}
|
||||
fwrite(text, strlen(text), 1, file);
|
||||
|
||||
WriteStatusText(text);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2033,31 +2075,64 @@ UpdateThreadFunc(void *param)
|
|||
}
|
||||
}
|
||||
|
||||
if (rv) {
|
||||
LOG(("failed: %d\n", rv));
|
||||
}
|
||||
else {
|
||||
bool reportRealResults = true;
|
||||
if (sReplaceRequest && rv && !getenv("MOZ_NO_REPLACE_FALLBACK")) {
|
||||
// When attempting to replace the application, we should fall back
|
||||
// to non-staged updates in case of a failure. We do this by
|
||||
// setting the status to pending, exiting the updater, and
|
||||
// launching the callback application. The callback application's
|
||||
// startup path will see the pending status, and will start the
|
||||
// updater application again in order to apply the update without
|
||||
// staging.
|
||||
// The MOZ_NO_REPLACE_FALLBACK environment variable is used to
|
||||
// bypass this fallback, and is used in the updater tests.
|
||||
// The only special thing which we should do here is to remove the
|
||||
// staged directory as it won't be useful any more.
|
||||
NS_tchar installDir[MAXPATHLEN];
|
||||
if (GetInstallationDir(installDir)) {
|
||||
NS_tchar stageDir[MAXPATHLEN];
|
||||
NS_tsnprintf(stageDir, sizeof(stageDir)/sizeof(stageDir[0]),
|
||||
#ifdef XP_MACOSX
|
||||
// If the update was successful we need to update the timestamp
|
||||
// on the top-level Mac OS X bundle directory so that Mac OS X's
|
||||
// Launch Services picks up any major changes. Here we assume that
|
||||
// the current working directory is the top-level bundle directory.
|
||||
char* cwd = getcwd(NULL, 0);
|
||||
if (cwd) {
|
||||
if (utimes(cwd, NULL) != 0) {
|
||||
LOG(("Couldn't set access/modification time on application bundle.\n"));
|
||||
}
|
||||
free(cwd);
|
||||
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));
|
||||
}
|
||||
else {
|
||||
LOG(("Couldn't get current working directory for setting "
|
||||
"access/modification time on application bundle.\n"));
|
||||
}
|
||||
#ifdef XP_MACOSX
|
||||
// If the update was successful we need to update the timestamp
|
||||
// on the top-level Mac OS X bundle directory so that Mac OS X's
|
||||
// Launch Services picks up any major changes. Here we assume that
|
||||
// the current working directory is the top-level bundle directory.
|
||||
char* cwd = getcwd(NULL, 0);
|
||||
if (cwd) {
|
||||
if (utimes(cwd, NULL) != 0) {
|
||||
LOG(("Couldn't set access/modification time on application bundle.\n"));
|
||||
}
|
||||
free(cwd);
|
||||
}
|
||||
else {
|
||||
LOG(("Couldn't get current working directory for setting "
|
||||
"access/modification time on application bundle.\n"));
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG(("succeeded\n"));
|
||||
LOG(("succeeded\n"));
|
||||
}
|
||||
WriteStatusFile(rv);
|
||||
}
|
||||
WriteStatusFile(rv);
|
||||
|
||||
LOG(("calling QuitProgressUI\n"));
|
||||
QuitProgressUI();
|
||||
|
@ -2227,9 +2302,8 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
// argument prior to callbackIndex is the working directory.
|
||||
const int callbackIndex = 5;
|
||||
|
||||
bool usingService = false;
|
||||
#if defined(XP_WIN)
|
||||
usingService = getenv("MOZ_USING_SERVICE") != NULL;
|
||||
sUsingService = getenv("MOZ_USING_SERVICE") != NULL;
|
||||
putenv(const_cast<char*>("MOZ_USING_SERVICE="));
|
||||
// lastFallbackError keeps track of the last error for the service not being
|
||||
// used, in case of an error when fallback is not enabled we write the
|
||||
|
@ -2242,7 +2316,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
// when write access is denied to the installation directory.
|
||||
HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE;
|
||||
NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')};
|
||||
if (!usingService &&
|
||||
if (!sUsingService &&
|
||||
(argc > callbackIndex || sBackgroundUpdate || sReplaceRequest)) {
|
||||
NS_tchar updateLockFilePath[MAXPATHLEN];
|
||||
if (sBackgroundUpdate) {
|
||||
|
@ -2492,7 +2566,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
|
||||
if (argc > callbackIndex) {
|
||||
LaunchCallbackApp(argv[4], argc - callbackIndex,
|
||||
argv + callbackIndex, usingService);
|
||||
argv + callbackIndex, sUsingService);
|
||||
}
|
||||
|
||||
CloseHandle(elevatedFileHandle);
|
||||
|
@ -2583,7 +2657,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
|
||||
if (argc > callbackIndex) {
|
||||
LaunchCallbackApp(argv[4], argc - callbackIndex,
|
||||
argv + callbackIndex, usingService);
|
||||
argv + callbackIndex, sUsingService);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -2628,7 +2702,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
LaunchCallbackApp(argv[4],
|
||||
argc - callbackIndex,
|
||||
argv + callbackIndex,
|
||||
usingService);
|
||||
sUsingService);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -2701,7 +2775,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
LaunchCallbackApp(argv[4],
|
||||
argc - callbackIndex,
|
||||
argv + callbackIndex,
|
||||
usingService);
|
||||
sUsingService);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -2770,7 +2844,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
// service if the service failed to apply the update. We want to update
|
||||
// the service to a newer version in that case. If we are not running
|
||||
// through the service, then MOZ_USING_SERVICE will not exist.
|
||||
if (!usingService) {
|
||||
if (!sUsingService) {
|
||||
NS_tchar installDir[MAXPATHLEN];
|
||||
if (GetInstallationDir(installDir)) {
|
||||
if (!LaunchWinPostProcess(installDir, gSourcePath, false, NULL)) {
|
||||
|
@ -2791,7 +2865,7 @@ int NS_main(int argc, NS_tchar **argv)
|
|||
LaunchCallbackApp(argv[4],
|
||||
argc - callbackIndex,
|
||||
argv + callbackIndex,
|
||||
usingService);
|
||||
sUsingService);
|
||||
}
|
||||
|
||||
return gSucceeded ? 0 : 1;
|
||||
|
|
Загрузка…
Ссылка в новой задаче