summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/update/tests/unit_base_updater
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/mozapps/update/tests/unit_base_updater')
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/head_update.js7
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFileNotInInstallDirFailure.js32
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFilePathTooLongFailure.js39
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTooLongFailure.js53
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTraversalFailure.js50
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallWorkingDirPathNotSameFailure_win.js45
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgPatchDirPathTraversalFailure.js32
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgStageDirNotInInstallDirFailure_win.js45
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathLocalUNCFailure_win.js45
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathRelativeFailure.js44
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js29
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateAppBinInUseStageSuccess_win.js50
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSkippedWriteAccess_win.js74
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageOldVersionFailure.js64
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js49
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSuccess.js47
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppInUseBackgroundTaskFailure_win.js51
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js37
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js68
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js26
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js30
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js30
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js24
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js24
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marCallbackUmask_unix.js42
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js39
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js40
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js40
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js29
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js29
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js27
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js26
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js34
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js33
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettings.js42
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettingsStage.js35
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marPIDPersistsSuccessComplete_win.js25
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js43
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js41
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js31
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js29
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js31
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js71
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js35
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js26
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js29
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartialWhileBackgroundTaskRunning.js125
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js41
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js43
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/marWrongChannelStage.js36
-rw-r--r--toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini136
51 files changed, 2153 insertions, 0 deletions
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/head_update.js b/toolkit/mozapps/update/tests/unit_base_updater/head_update.js
new file mode 100644
index 0000000000..1ab1a70a0b
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/head_update.js
@@ -0,0 +1,7 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* import-globals-from ../data/xpcshellUtilsAUS.js */
+load("xpcshellUtilsAUS.js");
+gIsServiceTest = false;
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFileNotInInstallDirFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFileNotInInstallDirFailure.js
new file mode 100644
index 0000000000..cc61a75dd7
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFileNotInInstallDirFailure.js
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Callback file not in install directory or a sub-directory of the install
+ directory failure */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = STATE_FAILED_INVALID_CALLBACK_DIR_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = getTestDirFile(FILE_HELPER_BIN).path;
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, null, null, path);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_CALLBACK_DIR_ERROR,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFilePathTooLongFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFilePathTooLongFailure.js
new file mode 100644
index 0000000000..0b432e2e15
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgCallbackFilePathTooLongFailure.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Too long callback file path failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = STATE_FAILED_INVALID_CALLBACK_PATH_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = "123456789";
+ if (AppConstants.platform == "win") {
+ path = "\\" + path;
+ path = path.repeat(30); // 300 characters
+ path = "C:" + path;
+ } else {
+ path = "/" + path;
+ path = path.repeat(1000); // 10000 characters
+ }
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, null, null, path);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_CALLBACK_PATH_ERROR,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTooLongFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTooLongFailure.js
new file mode 100644
index 0000000000..c2746e2bd1
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTooLongFailure.js
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Too long install directory path failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_INSTALL_DIR_PATH_ERROR
+ : STATE_FAILED_INVALID_INSTALL_DIR_PATH_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = "123456789";
+ if (AppConstants.platform == "win") {
+ path = "\\" + path;
+ path = path.repeat(30); // 300 characters
+ path = "C:" + path;
+ } else {
+ path = "/" + path;
+ path = path.repeat(1000); // 10000 characters
+ }
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, path, null, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_INSTALL_DIR_PATH_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTraversalFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTraversalFailure.js
new file mode 100644
index 0000000000..b611fac972
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallDirPathTraversalFailure.js
@@ -0,0 +1,50 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Install directory path traversal failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_INSTALL_DIR_PATH_ERROR
+ : STATE_FAILED_INVALID_INSTALL_DIR_PATH_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = "123456789";
+ if (AppConstants.platform == "win") {
+ path = "C:\\" + path + "\\..\\" + path;
+ } else {
+ path = "/" + path + "/../" + path;
+ }
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, path, null, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_INSTALL_DIR_PATH_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallWorkingDirPathNotSameFailure_win.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallWorkingDirPathNotSameFailure_win.js
new file mode 100644
index 0000000000..0506d100fd
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgInstallWorkingDirPathNotSameFailure_win.js
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Different install and working directories for a regular update failure */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_APPLYTO_DIR_ERROR
+ : STATE_FAILED_INVALID_APPLYTO_DIR_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = getApplyDirFile("..", false).path;
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, null, path, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_APPLYTO_DIR_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgPatchDirPathTraversalFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgPatchDirPathTraversalFailure.js
new file mode 100644
index 0000000000..cf053e3ff5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgPatchDirPathTraversalFailure.js
@@ -0,0 +1,32 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Patch directory path traversal failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = getUpdateDirFile(DIR_PATCH);
+ if (AppConstants.platform == "win") {
+ path = path + "\\..\\";
+ } else {
+ path = path + "/../";
+ }
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, path, null, null, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgStageDirNotInInstallDirFailure_win.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgStageDirNotInInstallDirFailure_win.js
new file mode 100644
index 0000000000..4624179bfd
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgStageDirNotInInstallDirFailure_win.js
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Different install and working directories for a regular update failure */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_APPLYTO_DIR_STAGED_ERROR
+ : STATE_FAILED_INVALID_APPLYTO_DIR_STAGED_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = getApplyDirFile("..", false).path;
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true, null, null, path, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_APPLYTO_DIR_STAGED_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathLocalUNCFailure_win.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathLocalUNCFailure_win.js
new file mode 100644
index 0000000000..7c0af26e37
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathLocalUNCFailure_win.js
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Working directory path local UNC failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_WORKING_DIR_PATH_ERROR
+ : STATE_FAILED_INVALID_WORKING_DIR_PATH_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ let path = "\\\\.\\" + getApplyDirFile(null, false).path;
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, null, path, null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_WORKING_DIR_PATH_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathRelativeFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathRelativeFailure.js
new file mode 100644
index 0000000000..cfbd9eaec9
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/invalidArgWorkingDirPathRelativeFailure.js
@@ -0,0 +1,44 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Relative working directory path failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_FAILED_SERVICE_INVALID_WORKING_DIR_PATH_ERROR
+ : STATE_FAILED_INVALID_WORKING_DIR_PATH_ERROR;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ runUpdate(STATE_AFTER_RUNUPDATE, false, 1, true, null, null, "test", null);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ if (gIsServiceTest) {
+ // The invalid argument service tests launch the maintenance service
+ // directly so the unelevated updater doesn't handle the invalid argument.
+ // By doing this it is possible to test that the maintenance service
+ // properly handles the invalid argument but since the updater isn't used to
+ // launch the maintenance service the update.status file isn't copied from
+ // the secure log directory to the patch directory and the update manager
+ // won't read the failure from the update.status file.
+ checkUpdateManager(STATE_NONE, false, STATE_PENDING_SVC, 0, 1);
+ } else {
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ INVALID_WORKING_DIR_PATH_ERROR,
+ 1
+ );
+ }
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js
new file mode 100644
index 0000000000..a845cb70c5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyDirLockedStageFailure_win.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test applying an update by staging an update and launching an application to
+ * apply it.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ createUpdateInProgressLockFile(getGREBinDir());
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, false);
+ removeUpdateInProgressLockFile(getGREBinDir());
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(PERFORMING_STAGED_UPDATE);
+ checkUpdateLogContains(ERR_UPDATE_IN_PROGRESS);
+ await waitForUpdateXMLFiles(true, false);
+ checkUpdateManager(STATE_AFTER_STAGE, true, STATE_AFTER_STAGE, 0, 0);
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateAppBinInUseStageSuccess_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateAppBinInUseStageSuccess_win.js
new file mode 100644
index 0000000000..319aee8e34
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateAppBinInUseStageSuccess_win.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test applying an update by staging an update and launching an application to
+ * apply it.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true, false);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ lockDirectory(getGREBinDir().path);
+ // Switch the application to the staged application that was updated.
+ await runUpdateUsingApp(STATE_SUCCEEDED);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+
+ let updatesDir = getUpdateDirFile(DIR_PATCH);
+ Assert.ok(
+ updatesDir.exists(),
+ MSG_SHOULD_EXIST + getMsgPath(updatesDir.path)
+ );
+
+ let log = getUpdateDirFile(FILE_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_LAST_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_BACKUP_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSkippedWriteAccess_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSkippedWriteAccess_win.js
new file mode 100644
index 0000000000..aa1336b7ed
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSkippedWriteAccess_win.js
@@ -0,0 +1,74 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test an update isn't attempted when the update.status file can't be written
+ * to.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+
+ // To simulate a user that doesn't have write access to the update directory
+ // lock the relevant files in the update directory.
+ let filesToLock = [
+ FILE_ACTIVE_UPDATE_XML,
+ FILE_UPDATE_MAR,
+ FILE_UPDATE_STATUS,
+ FILE_UPDATE_TEST,
+ FILE_UPDATE_VERSION,
+ ];
+ filesToLock.forEach(function (aFileLeafName) {
+ let file = getUpdateDirFile(aFileLeafName);
+ if (!file.exists()) {
+ file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o444);
+ }
+ file.QueryInterface(Ci.nsILocalFileWin);
+ file.readOnly = true;
+ Assert.ok(file.exists(), MSG_SHOULD_EXIST + getMsgPath(file.path));
+ Assert.ok(!file.isWritable(), "the file should not be writeable");
+ });
+
+ registerCleanupFunction(() => {
+ filesToLock.forEach(function (aFileLeafName) {
+ let file = getUpdateDirFile(aFileLeafName);
+ if (file.exists()) {
+ file.QueryInterface(Ci.nsILocalFileWin);
+ file.readOnly = false;
+ file.remove(false);
+ }
+ });
+ });
+
+ // Reload the update manager now that the update directory files are locked.
+ reloadUpdateManagerData();
+ await runUpdateUsingApp(STATE_PENDING);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateManager(STATE_PENDING, false, STATE_NONE, 0, 0);
+
+ let dir = getUpdateDirFile(DIR_PATCH);
+ Assert.ok(dir.exists(), MSG_SHOULD_EXIST + getMsgPath(dir.path));
+
+ let file = getUpdateDirFile(FILE_UPDATES_XML);
+ Assert.ok(!file.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(file.path));
+
+ file = getUpdateDirFile(FILE_UPDATE_LOG);
+ Assert.ok(!file.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(file.path));
+
+ file = getUpdateDirFile(FILE_LAST_UPDATE_LOG);
+ Assert.ok(!file.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(file.path));
+
+ file = getUpdateDirFile(FILE_BACKUP_UPDATE_LOG);
+ Assert.ok(!file.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(file.path));
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageOldVersionFailure.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageOldVersionFailure.js
new file mode 100644
index 0000000000..3dfad0f58e
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageOldVersionFailure.js
@@ -0,0 +1,64 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test a replace request for a staged update with a version file that specifies
+ * an older version failure. The same check is used in nsUpdateDriver.cpp for
+ * all update types which is why there aren't tests for the maintenance service
+ * as well as for other update types.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, null, "", false);
+ let patchProps = { state: STATE_AFTER_STAGE };
+ let patches = getLocalPatchString(patchProps);
+ let updateProps = { appVersion: "0.9" };
+ let updates = getLocalUpdateString(updateProps, patches);
+ writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
+ getUpdateDirFile(FILE_UPDATE_LOG).create(
+ Ci.nsIFile.NORMAL_FILE_TYPE,
+ PERMS_FILE
+ );
+ writeStatusFile(STATE_AFTER_STAGE);
+ // Create the version file with an older version to simulate installing a new
+ // version of the application while there is an update that has been staged.
+ writeVersionFile("0.9");
+ // Try to switch the application to the fake staged application.
+ await runUpdateUsingApp(STATE_AFTER_STAGE);
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ ERR_OLDER_VERSION_OR_SAME_BUILD,
+ 1
+ );
+
+ let updatesDir = getUpdateDirFile(DIR_PATCH);
+ Assert.ok(
+ updatesDir.exists(),
+ MSG_SHOULD_EXIST + getMsgPath(updatesDir.path)
+ );
+
+ let log = getUpdateDirFile(FILE_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_LAST_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_BACKUP_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js
new file mode 100644
index 0000000000..34b47866b1
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js
@@ -0,0 +1,49 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test applying an update by staging an update and launching an application to
+ * apply it.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, true);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ await runUpdateUsingApp(STATE_SUCCEEDED);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+
+ let updatesDir = getUpdateDirFile(DIR_PATCH);
+ Assert.ok(
+ updatesDir.exists(),
+ MSG_SHOULD_EXIST + getMsgPath(updatesDir.path)
+ );
+
+ let log = getUpdateDirFile(FILE_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_LAST_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_BACKUP_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSuccess.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSuccess.js
new file mode 100644
index 0000000000..980b0cb89a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateSuccess.js
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Test applying an update by launching an application to apply it.
+ */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ // The third parameter will test that a full path to the post update binary
+ // doesn't execute.
+ await setupUpdaterTest(
+ FILE_COMPLETE_MAR,
+ undefined,
+ getApplyDirFile(null, true).path + "/"
+ );
+ await runUpdateUsingApp(STATE_SUCCEEDED);
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+
+ let updatesDir = getUpdateDirFile(DIR_PATCH);
+ Assert.ok(
+ updatesDir.exists(),
+ MSG_SHOULD_EXIST + getMsgPath(updatesDir.path)
+ );
+
+ let log = getUpdateDirFile(FILE_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_LAST_UPDATE_LOG);
+ Assert.ok(log.exists(), MSG_SHOULD_EXIST + getMsgPath(log.path));
+
+ log = getUpdateDirFile(FILE_BACKUP_UPDATE_LOG);
+ Assert.ok(!log.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(log.path));
+
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseBackgroundTaskFailure_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseBackgroundTaskFailure_win.js
new file mode 100644
index 0000000000..bcb24bee94
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseBackgroundTaskFailure_win.js
@@ -0,0 +1,51 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Fail to apply a complete MAR when the application is in use and the callback is a background task. */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+
+ // Add a dummy --backgroundtask arg; this will have no effect on the
+ // callback (TestAUSHelper) but will cause the updater to detect
+ // that this is a background task.
+ gCallbackArgs = gCallbackArgs.concat(["--backgroundtask", "not_found"]);
+
+ // Run the update with the helper file in use, expecting failure.
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(DIR_RESOURCES + gCallbackBinFile, false);
+ runUpdate(
+ STATE_FAILED_WRITE_ERROR_BACKGROUND_TASK_SHARING_VIOLATION,
+ false, // aSwitchApp
+ 1, // aExpectedExitValue
+ true // aCheckSvcLog
+ );
+ await waitForHelperExit();
+
+ standardInit();
+
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_BGTASK_EXCLUSIVE);
+
+ // Check that the update was reset to "pending".
+ await waitForUpdateXMLFiles(
+ true, // aActiveUpdateExists
+ false // aUpdatesExists
+ );
+ checkUpdateManager(
+ STATE_PENDING, // aStatusFileState
+ true, // aHasActiveUpdate
+ STATE_PENDING, // aUpdateStatusState
+ WRITE_ERROR_BACKGROUND_TASK_SHARING_VIOLATION,
+ 0 // aUpdateCount
+ );
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js
new file mode 100644
index 0000000000..502561ed1e
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageFailureComplete_win.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file staged patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(DIR_RESOURCES + gCallbackBinFile, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(
+ ERR_MOVE_DESTDIR_7 + "\n" + STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT
+ );
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js
new file mode 100644
index 0000000000..29c2c2a30e
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseStageSuccessComplete_unix.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file staged patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 1].originalContents = null;
+ gTestFiles[gTestFiles.length - 1].compareContents = "FromComplete\n";
+ gTestFiles[gTestFiles.length - 1].comparePerms = 0o644;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, true);
+ setupSymLinks();
+ await runHelperFileInUse(DIR_RESOURCES + gCallbackBinFile, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_SUCCEEDED, true, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ checkSymLinks();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
+
+/**
+ * Setup symlinks for the test.
+ */
+function setupSymLinks() {
+ if (AppConstants.platform == "macosx" || AppConstants.platform == "linux") {
+ removeSymlink();
+ createSymlink();
+ registerCleanupFunction(removeSymlink);
+ gTestFiles.splice(gTestFiles.length - 3, 0, {
+ description: "Readable symlink",
+ fileName: "link",
+ relPathDir: DIR_RESOURCES,
+ originalContents: "test",
+ compareContents: "test",
+ originalFile: null,
+ compareFile: null,
+ originalPerms: 0o666,
+ comparePerms: 0o666,
+ });
+ }
+}
+
+/**
+ * Checks the state of the symlinks for the test.
+ */
+function checkSymLinks() {
+ if (AppConstants.platform == "macosx" || AppConstants.platform == "linux") {
+ checkSymlink();
+ }
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js
new file mode 100644
index 0000000000..e08777d042
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marAppInUseSuccessComplete.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(DIR_RESOURCES + gCallbackBinFile, false);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js
new file mode 100644
index 0000000000..2f8155c790
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessComplete_win.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Replace app binary complete MAR file staged patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ gCallbackBinFile = "exe0.exe";
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_SUCCEEDED, true, 0, true);
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js
new file mode 100644
index 0000000000..04c72896b4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppStageSuccessPartial_win.js
@@ -0,0 +1,30 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Patch app binary partial MAR file staged patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ gCallbackBinFile = "exe0.exe";
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_SUCCEEDED, true, 0, true);
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js
new file mode 100644
index 0000000000..fa13f07f46
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessComplete_win.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Replace app binary complete MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ gCallbackBinFile = "exe0.exe";
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js
new file mode 100644
index 0000000000..e74509c06e
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackAppSuccessPartial_win.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Patch app binary partial MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ gCallbackBinFile = "exe0.exe";
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marCallbackUmask_unix.js b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackUmask_unix.js
new file mode 100644
index 0000000000..be3b3707b4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marCallbackUmask_unix.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Verify that app callback is launched with the same umask as was set
+ * before applying an update. */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ preventDistributionFiles();
+
+ // Our callback is `TestAUSHelper check-umask <umask from before updating>`.
+ // Including the umask from before updating as an argument allows to re-use
+ // the callback log checking code below. The argument is also used as the log
+ // file name, so we prefix it with "umask" so that it doesn't clash with
+ // numericfile and directory names in the update data. In particular, "2"
+ // clashes with an existing directory name in the update data, leading to
+ // failing tests.
+ let umask = Services.sysinfo.getProperty("umask");
+ gCallbackArgs = ["check-umask", `umask-${umask}`];
+
+ await setupUpdaterTest(FILE_COMPLETE_MAR, true);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, false, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+
+ // This compares the callback arguments given, including the umask before
+ // updating, to the umask set when the app callback is launched. They should
+ // be the same.
+ checkCallbackLog(getApplyDirFile(DIR_RESOURCES + "callback_app.log"));
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js b/toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js
new file mode 100644
index 0000000000..de8db067bc
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFailurePartial.js
@@ -0,0 +1,39 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Partial MAR File Patch Apply Failure Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestFiles[11].originalFile = "partial.png";
+ gTestDirs = gTestDirsPartialSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ // If execv is used the updater process will turn into the callback process
+ // and the updater's return code will be that of the callback process.
+ runUpdate(
+ STATE_FAILED_LOADSOURCE_ERROR_WRONG_SIZE,
+ false,
+ USE_EXECV ? 0 : 1,
+ true
+ );
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContents(LOG_PARTIAL_FAILURE);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ LOADSOURCE_ERROR_WRONG_SIZE,
+ 1
+ );
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js
new file mode 100644
index 0000000000..b93b023934
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailureComplete_win.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use complete MAR file staged patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(
+ gTestFiles[13].relPathDir + gTestFiles[13].fileName,
+ false
+ );
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(
+ ERR_MOVE_DESTDIR_7 + "\n" + STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT
+ );
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js
new file mode 100644
index 0000000000..b41da12396
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseStageFailurePartial_win.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use partial MAR file staged patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperFileInUse(
+ gTestFiles[11].relPathDir + gTestFiles[11].fileName,
+ false
+ );
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(
+ ERR_MOVE_DESTDIR_7 + "\n" + STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT
+ );
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js
new file mode 100644
index 0000000000..4b946ac3e4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessComplete_win.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use complete MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(
+ gTestFiles[13].relPathDir + gTestFiles[13].fileName,
+ false
+ );
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContains(ERR_BACKUP_DISCARD);
+ checkUpdateLogContains(STATE_SUCCEEDED + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js
new file mode 100644
index 0000000000..15c3a1121a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileInUseSuccessPartial_win.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use partial MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperFileInUse(
+ gTestFiles[11].relPathDir + gTestFiles[11].fileName,
+ false
+ );
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContains(ERR_BACKUP_DISCARD);
+ checkUpdateLogContains(STATE_SUCCEEDED + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js
new file mode 100644
index 0000000000..698ccb7fe5
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailureComplete_win.js
@@ -0,0 +1,27 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked complete MAR file patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperLockFile(gTestFiles[3]);
+ runUpdate(STATE_FAILED_WRITE_ERROR, false, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(ERR_BACKUP_CREATE_7);
+ checkUpdateLogContains(STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles(true, false);
+ checkUpdateManager(STATE_PENDING, true, STATE_PENDING, WRITE_ERROR, 0);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js
new file mode 100644
index 0000000000..c8c019ec5c
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedFailurePartial_win.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked partial MAR file patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperLockFile(gTestFiles[2]);
+ runUpdate(STATE_FAILED_READ_ERROR, false, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_UNABLE_OPEN_DEST);
+ checkUpdateLogContains(STATE_FAILED_READ_ERROR + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_FAILED, READ_ERROR, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js
new file mode 100644
index 0000000000..7b582dbd45
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailureComplete_win.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked complete MAR file staged patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperLockFile(gTestFiles[3]);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ // Files aren't checked after staging since this test locks a file which
+ // prevents reading the file.
+ checkUpdateLogContains(ERR_ENSURE_COPY);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_FAILED_WRITE_ERROR, false, 1, false);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(ERR_BACKUP_CREATE_7);
+ checkUpdateLogContains(STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles(true, false);
+ checkUpdateManager(STATE_PENDING, true, STATE_PENDING, WRITE_ERROR, 0);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js
new file mode 100644
index 0000000000..bf3abd8c37
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marFileLockedStageFailurePartial_win.js
@@ -0,0 +1,33 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File locked partial MAR file staged patch apply failure test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_PENDING;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperLockFile(gTestFiles[2]);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ // Files aren't checked after staging since this test locks a file which
+ // prevents reading the file.
+ checkUpdateLogContains(ERR_ENSURE_COPY);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_FAILED_READ_ERROR, false, 1, false);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_UNABLE_OPEN_DEST);
+ checkUpdateLogContains(STATE_FAILED_READ_ERROR + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_FAILED, READ_ERROR, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettings.js b/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettings.js
new file mode 100644
index 0000000000..b0a0cfe657
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettings.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Test update-settings.ini missing channel MAR security check */
+
+async function run_test() {
+ if (!MOZ_VERIFY_MAR_SIGNATURE) {
+ return;
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 2].originalContents = null;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ // If execv is used the updater process will turn into the callback process
+ // and the updater's return code will be that of the callback process.
+ runUpdate(
+ STATE_FAILED_UPDATE_SETTINGS_FILE_CHANNEL,
+ false,
+ USE_EXECV ? 0 : 1,
+ false
+ );
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(STATE_FAILED_UPDATE_SETTINGS_FILE_CHANNEL);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ UPDATE_SETTINGS_FILE_CHANNEL,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettingsStage.js b/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettingsStage.js
new file mode 100644
index 0000000000..e26d2aefc3
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marMissingUpdateSettingsStage.js
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Test update-settings.ini missing channel MAR security check */
+
+async function run_test() {
+ if (!MOZ_VERIFY_MAR_SIGNATURE) {
+ return;
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_FAILED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 2].originalContents = null;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(STATE_FAILED_UPDATE_SETTINGS_FILE_CHANNEL);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ UPDATE_SETTINGS_FILE_CHANNEL,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marPIDPersistsSuccessComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marPIDPersistsSuccessComplete_win.js
new file mode 100644
index 0000000000..4918fea140
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marPIDPersistsSuccessComplete_win.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* Application in use complete MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperPIDPersists(DIR_RESOURCES + gCallbackBinFile, false);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContains(ERR_PARENT_PID_PERSISTS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js
new file mode 100644
index 0000000000..31c5b8bd7a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailureComplete_win.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use inside removed dir complete MAR file staged patch apply failure
+ test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(
+ gTestDirs[4].relPathDir +
+ gTestDirs[4].subDirs[0] +
+ gTestDirs[4].subDirFiles[0],
+ true
+ );
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(
+ ERR_MOVE_DESTDIR_7 + "\n" + STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT
+ );
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js
new file mode 100644
index 0000000000..b57f8c81b7
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseStageFailurePartial_win.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use inside removed dir partial MAR file staged patch apply failure
+ test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ const STATE_AFTER_RUNUPDATE = gIsServiceTest
+ ? STATE_PENDING_SVC
+ : STATE_PENDING;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperFileInUse(
+ gTestDirs[2].relPathDir + gTestDirs[2].files[0],
+ true
+ );
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_AFTER_RUNUPDATE, true, 1, true);
+ await waitForHelperExit();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ setTestFilesAndDirsForFailure();
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_RENAME_FILE);
+ checkUpdateLogContains(
+ ERR_MOVE_DESTDIR_7 + "\n" + STATE_FAILED_WRITE_ERROR + "\n" + CALL_QUIT
+ );
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_AFTER_RUNUPDATE, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js
new file mode 100644
index 0000000000..0683df0d8d
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessComplete_win.js
@@ -0,0 +1,31 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use inside removed dir complete MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await runHelperFileInUse(
+ gTestDirs[4].relPathDir +
+ gTestDirs[4].subDirs[0] +
+ gTestDirs[4].subDirFiles[0],
+ true
+ );
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContains(ERR_BACKUP_DISCARD);
+ checkUpdateLogContains(STATE_SUCCEEDED + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js
new file mode 100644
index 0000000000..d4da3a5f37
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marRMRFDirFileInUseSuccessPartial_win.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/* File in use inside removed dir partial MAR file patch apply success test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestDirs = gTestDirsPartialSuccess;
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await runHelperFileInUse(
+ gTestDirs[2].relPathDir + gTestDirs[2].files[0],
+ true
+ );
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await waitForHelperExit();
+ await checkPostUpdateAppLog();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContains(ERR_BACKUP_DISCARD);
+ checkUpdateLogContains(STATE_SUCCEEDED + "\n" + CALL_QUIT);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js b/toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js
new file mode 100644
index 0000000000..a1a0de0fe4
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageFailurePartial.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Partial MAR File Staged Patch Apply Failure Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_FAILED;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestFiles[11].originalFile = "partial.png";
+ gTestDirs = gTestDirsPartialSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(ERR_LOADSOURCEFILE_FAILED);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ LOADSOURCE_ERROR_WRONG_SIZE,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js
new file mode 100644
index 0000000000..943a45ba95
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessComplete.js
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Complete MAR File Staged Patch Apply Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 1].originalContents = null;
+ gTestFiles[gTestFiles.length - 1].compareContents = "FromComplete\n";
+ gTestFiles[gTestFiles.length - 1].comparePerms = 0o644;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setupSymLinks();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_SUCCEEDED, true, 0, true);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ checkSymLinks();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
+
+/**
+ * Setup symlinks for the test.
+ */
+function setupSymLinks() {
+ // Don't test symlinks on Mac OS X in this test since it tends to timeout.
+ // It is tested on Mac OS X in marAppInUseStageSuccessComplete_unix.js
+ if (AppConstants.platform == "linux") {
+ removeSymlink();
+ createSymlink();
+ registerCleanupFunction(removeSymlink);
+ gTestFiles.splice(gTestFiles.length - 3, 0, {
+ description: "Readable symlink",
+ fileName: "link",
+ relPathDir: DIR_RESOURCES,
+ originalContents: "test",
+ compareContents: "test",
+ originalFile: null,
+ compareFile: null,
+ originalPerms: 0o666,
+ comparePerms: 0o666,
+ });
+ }
+}
+
+/**
+ * Checks the state of the symlinks for the test.
+ */
+function checkSymLinks() {
+ // Don't test symlinks on Mac OS X in this test since it tends to timeout.
+ // It is tested on Mac OS X in marAppInUseStageSuccessComplete_unix.js
+ if (AppConstants.platform == "linux") {
+ checkSymlink();
+ }
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js
new file mode 100644
index 0000000000..dd5c240919
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marStageSuccessPartial.js
@@ -0,0 +1,35 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Partial MAR File Staged Patch Apply Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = gIsServiceTest ? STATE_APPLIED_SVC : STATE_APPLIED;
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestFiles[gTestFiles.length - 1].originalContents = null;
+ gTestFiles[gTestFiles.length - 1].compareContents = "FromPartial\n";
+ gTestFiles[gTestFiles.length - 1].comparePerms = 0o644;
+ gTestDirs = gTestDirsPartialSuccess;
+ preventDistributionFiles();
+ await setupUpdaterTest(FILE_PARTIAL_MAR, true);
+ await stageUpdate(STATE_AFTER_STAGE, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getStageDirFile, true);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS, true, false, true);
+ // Switch the application to the staged application that was updated.
+ runUpdate(STATE_SUCCEEDED, true, 0, true);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile, false, true);
+ checkUpdateLogContents(LOG_REPLACE_SUCCESS, false, true, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js
new file mode 100644
index 0000000000..2dd1e54f90
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessComplete.js
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Complete MAR File Patch Apply Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ preventDistributionFiles();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, true);
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ await checkPostUpdateAppLog();
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(true);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_COMPLETE_SUCCESS, false, false, true);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js
new file mode 100644
index 0000000000..8e8e9d094a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartial.js
@@ -0,0 +1,29 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Partial MAR File Patch Apply Test */
+
+async function run_test() {
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesPartialSuccess;
+ gTestFiles[gTestFiles.length - 1].originalContents = null;
+ gTestFiles[gTestFiles.length - 1].compareContents = "FromPartial\n";
+ gTestFiles[gTestFiles.length - 1].comparePerms = 0o644;
+ gTestDirs = gTestDirsPartialSuccess;
+ // The third parameter will test that a relative path that contains a
+ // directory traversal to the post update binary doesn't execute.
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false, "test/../");
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartialWhileBackgroundTaskRunning.js b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartialWhileBackgroundTaskRunning.js
new file mode 100644
index 0000000000..6ad589a32c
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marSuccessPartialWhileBackgroundTaskRunning.js
@@ -0,0 +1,125 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* General Partial MAR File Patch Apply Test */
+
+const { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+const { BackgroundTasksTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/BackgroundTasksTestUtils.sys.mjs"
+);
+BackgroundTasksTestUtils.init(this);
+const do_backgroundtask = BackgroundTasksTestUtils.do_backgroundtask.bind(
+ BackgroundTasksTestUtils
+);
+
+const { PromiseUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/PromiseUtils.sys.mjs"
+);
+
+async function run_test() {
+ // Without omnijars, the background task apparatus will fail to find task
+ // definitions.
+ {
+ let omniJa = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
+ omniJa.append("omni.ja");
+ if (!omniJa.exists()) {
+ Assert.ok(
+ false,
+ "This test requires a packaged build, " +
+ "run 'mach package' and then use 'mach xpcshell-test --xre-path=...'"
+ );
+ return;
+ }
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+
+ // `channel-prefs.js` is required for Firefox to launch, including in
+ // background task mode. The testing partial MAR updates `channel-prefs.js`
+ // to have contents `FromPartial`, which is not a valid prefs file and causes
+ // Firefox to crash. However, `channel-prefs.js` is listed as `add-if-not
+ // "defaults/pref/channel-prefs.js" "defaults/pref/channel-prefs.js"`, so it
+ // won't be updated if it already exists. The manipulations below arrange a)
+ // for the file to exist and b) for the comparison afterward to succeed.
+ gTestFiles = gTestFilesPartialSuccess;
+ let channelPrefs = gTestFiles[gTestFiles.length - 1];
+ Assert.equal("channel-prefs.js", channelPrefs.fileName);
+ let f = gGREDirOrig.clone();
+ f.append("defaults");
+ f.append("pref");
+ f.append("channel-prefs.js");
+ // `originalFile` is a relative path, so we can't just point to the one in the
+ // original GRE directory.
+ channelPrefs.originalFile = null;
+ channelPrefs.originalContents = readFile(f);
+ channelPrefs.compareContents = channelPrefs.originalContents;
+ gTestDirs = gTestDirsPartialSuccess;
+ // The third parameter will test that a relative path that contains a
+ // directory traversal to the post update binary doesn't execute.
+ await setupUpdaterTest(FILE_PARTIAL_MAR, false, "test/../", true, {
+ // We need packaged JavaScript to run background tasks.
+ requiresOmnijar: true,
+ });
+
+ // `0/00/00text2` is just a random file in the testing partial MAR that does
+ // not exist before the update and is always written by the update.
+ let exitCode;
+ exitCode = await do_backgroundtask("file_exists", {
+ extraArgs: [getApplyDirFile(DIR_RESOURCES + "0/00/00text2").path],
+ });
+ // Before updating, file doesn't exist.
+ Assert.equal(11, exitCode);
+
+ // This task will wait 10 seconds before exiting, which should overlap with
+ // the update below. We wait for some output from the wait background task,
+ // so that there is meaningful overlap.
+ let taskStarted = PromiseUtils.defer();
+ let p = do_backgroundtask("wait", {
+ onStdoutLine: (line, proc) => {
+ // This sentinel seems pretty safe: it's printed by the task itself and so
+ // there should be a straight line between future test failures and
+ // logging changes.
+ if (line.includes("runBackgroundTask: wait")) {
+ taskStarted.resolve(proc);
+ }
+ },
+ });
+ let proc = await taskStarted.promise;
+
+ runUpdate(STATE_SUCCEEDED, false, 0, true);
+
+ checkAppBundleModTime();
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateSuccess(getApplyDirFile);
+ checkUpdateLogContents(LOG_PARTIAL_SUCCESS);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
+
+ // Once we've seen what we want, there's no need to let the task wait complete.
+ await proc.kill();
+
+ Assert.ok("Waiting for background task to die after kill()");
+ exitCode = await p;
+
+ // Windows does not support killing processes gracefully, so they will
+ // always exit with -9 there.
+ let retVal = AppConstants.platform == "win" ? -9 : -15;
+ Assert.equal(retVal, exitCode);
+
+ exitCode = await do_backgroundtask("file_exists", {
+ extraArgs: [getApplyDirFile(DIR_RESOURCES + "0/00/00text2").path],
+ });
+ // After updating, file exists.
+ Assert.equal(0, exitCode);
+
+ // This finishes the test, so must be last.
+ checkCallbackLog();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js b/toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js
new file mode 100644
index 0000000000..6f3e26fe0f
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marVersionDowngrade.js
@@ -0,0 +1,41 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Test version downgrade MAR security check */
+
+async function run_test() {
+ if (!MOZ_VERIFY_MAR_SIGNATURE) {
+ return;
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_OLD_VERSION_MAR, false);
+ // If execv is used the updater process will turn into the callback process
+ // and the updater's return code will be that of the callback process.
+ runUpdate(
+ STATE_FAILED_VERSION_DOWNGRADE_ERROR,
+ false,
+ USE_EXECV ? 0 : 1,
+ false
+ );
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(STATE_FAILED_VERSION_DOWNGRADE_ERROR);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ VERSION_DOWNGRADE_ERROR,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js b/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js
new file mode 100644
index 0000000000..d31188dcca
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannel.js
@@ -0,0 +1,43 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Test product/channel MAR security check */
+
+async function run_test() {
+ if (!MOZ_VERIFY_MAR_SIGNATURE) {
+ return;
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 2].originalContents =
+ UPDATE_SETTINGS_CONTENTS.replace("xpcshell-test", "wrong-channel");
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ // If execv is used the updater process will turn into the callback process
+ // and the updater's return code will be that of the callback process.
+ runUpdate(
+ STATE_FAILED_MAR_CHANNEL_MISMATCH_ERROR,
+ false,
+ USE_EXECV ? 0 : 1,
+ false
+ );
+ standardInit();
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(STATE_FAILED_MAR_CHANNEL_MISMATCH_ERROR);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ MAR_CHANNEL_MISMATCH_ERROR,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannelStage.js b/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannelStage.js
new file mode 100644
index 0000000000..4d512fd12a
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/marWrongChannelStage.js
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/* Test product/channel MAR security check */
+
+async function run_test() {
+ if (!MOZ_VERIFY_MAR_SIGNATURE) {
+ return;
+ }
+
+ if (!setupTestCommon()) {
+ return;
+ }
+ const STATE_AFTER_STAGE = STATE_FAILED;
+ gTestFiles = gTestFilesCompleteSuccess;
+ gTestFiles[gTestFiles.length - 2].originalContents =
+ UPDATE_SETTINGS_CONTENTS.replace("xpcshell-test", "wrong-channel");
+ gTestDirs = gTestDirsCompleteSuccess;
+ setTestFilesAndDirsForFailure();
+ await setupUpdaterTest(FILE_COMPLETE_MAR, false);
+ await stageUpdate(STATE_AFTER_STAGE, true, true);
+ checkPostUpdateRunningFile(false);
+ checkFilesAfterUpdateFailure(getApplyDirFile);
+ checkUpdateLogContains(STATE_FAILED_MAR_CHANNEL_MISMATCH_ERROR);
+ await waitForUpdateXMLFiles();
+ checkUpdateManager(
+ STATE_NONE,
+ false,
+ STATE_FAILED,
+ MAR_CHANNEL_MISMATCH_ERROR,
+ 1
+ );
+ waitForFilesInUse();
+}
diff --git a/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini b/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
new file mode 100644
index 0000000000..84325c4312
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
@@ -0,0 +1,136 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Tests that require the updater binary.
+
+[DEFAULT]
+tags = appupdate
+head = head_update.js
+skip-if =
+ (os == 'win' && (ccov || msix)) # Our updater is disabled in MSIX builds
+support-files =
+ ../data/shared.js
+ ../data/sharedUpdateXML.js
+ ../data/xpcshellUtilsAUS.js
+
+[invalidArgCallbackFileNotInInstallDirFailure.js]
+[invalidArgCallbackFilePathTooLongFailure.js]
+[invalidArgInstallDirPathTooLongFailure.js]
+[invalidArgInstallDirPathTraversalFailure.js]
+[invalidArgInstallWorkingDirPathNotSameFailure_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[invalidArgPatchDirPathTraversalFailure.js]
+[invalidArgStageDirNotInInstallDirFailure_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[invalidArgWorkingDirPathLocalUNCFailure_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[invalidArgWorkingDirPathRelativeFailure.js]
+[marSuccessComplete.js]
+[marSuccessPartial.js]
+[marSuccessPartialWhileBackgroundTaskRunning.js]
+skip-if =
+ apple_silicon # Bug 1754931
+ apple_catalina # Bug 1754931
+[marFailurePartial.js]
+[marStageSuccessComplete.js]
+skip-if =
+ apple_silicon # bug 1707753
+ apple_catalina # Bug 1713329
+[marStageSuccessPartial.js]
+skip-if =
+ apple_silicon # bug 1707753
+ apple_catalina # Bug 1713329
+[marVersionDowngrade.js]
+[marMissingUpdateSettings.js]
+[marMissingUpdateSettingsStage.js]
+[marWrongChannel.js]
+[marWrongChannelStage.js]
+[marStageFailurePartial.js]
+[marCallbackAppSuccessComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marCallbackAppSuccessPartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marCallbackAppStageSuccessComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marCallbackAppStageSuccessPartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marCallbackUmask_unix.js]
+skip-if =
+ os == 'win' # not a Windows test
+reason = Unix only test
+[marAppInUseBackgroundTaskFailure_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marAppInUseSuccessComplete.js]
+[marAppInUseStageSuccessComplete_unix.js]
+skip-if =
+ os == 'win' # not a Windows test
+ apple_silicon # bug 1707753
+ apple_catalina # Bug 1713329
+[marAppInUseStageFailureComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileLockedFailureComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileLockedFailurePartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileLockedStageFailureComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileLockedStageFailurePartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileInUseSuccessComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileInUseSuccessPartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marRMRFDirFileInUseSuccessComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marRMRFDirFileInUseSuccessPartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileInUseStageFailureComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marFileInUseStageFailurePartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marRMRFDirFileInUseStageFailureComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marRMRFDirFileInUseStageFailurePartial_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marPIDPersistsSuccessComplete_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marAppApplyDirLockedStageFailure_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marAppApplyUpdateAppBinInUseStageSuccess_win.js]
+skip-if = os != 'win'
+reason = Windows only test
+[marAppApplyUpdateSuccess.js]
+skip-if =
+ apple_silicon # bug 1724579
+[marAppApplyUpdateStageSuccess.js]
+skip-if =
+ apple_silicon # bug 1707753
+ apple_catalina # Bug 1713329
+[marAppApplyUpdateStageOldVersionFailure.js]
+[marAppApplyUpdateSkippedWriteAccess_win.js]
+skip-if = os != 'win'
+reason = Windows only test