Bug 1700158 - Add test that Background Update Tasks don't interfere with an in-progress internal download r=bhearsum

Differential Revision: https://phabricator.services.mozilla.com/D154477
This commit is contained in:
Kirk Steuber 2022-08-12 19:18:08 +00:00
parent f0b12076e5
commit 244c64dc64
3 changed files with 114 additions and 13 deletions

View File

@ -71,6 +71,7 @@ const DIR_TOBEDELETED = "tobedeleted";
const DIR_UPDATES = "updates";
const DIR_UPDATED =
AppConstants.platform == "macosx" ? "Updated.app" : "updated";
const DIR_DOWNLOADING = "downloading";
const FILE_ACTIVE_UPDATE_XML = "active-update.xml";
const FILE_ACTIVE_UPDATE_XML_TMP = "active-update.xml.tmp";
@ -442,9 +443,17 @@ function getFileExtension(aFile) {
*
* @param aLogLeafName
* The leafName of the file or directory to get.
* @param aWhichDir
* Since we started having a separate patch directory and downloading
* directory, there are now files with the same name that can be in
* either directory. This argument is optional and defaults to the
* patch directory for historical reasons. But if it is specified as
* DIR_DOWNLOADING, this function will provide the version of the file
* in the downloading directory. For files that aren't in the patch
* directory or the downloading directory, this value is ignored.
* @return nsIFile for the file or directory.
*/
function getUpdateDirFile(aLeafName) {
function getUpdateDirFile(aLeafName, aWhichDir = null) {
let file = Services.dirsvc.get(XRE_UPDATE_ROOT_DIR, Ci.nsIFile);
switch (aLeafName) {
case undefined:
@ -460,6 +469,7 @@ function getUpdateDirFile(aLeafName) {
file.append(aLeafName);
return file;
case DIR_PATCH:
case DIR_DOWNLOADING:
case FILE_BACKUP_UPDATE_LOG:
case FILE_LAST_UPDATE_LOG:
file.append(DIR_UPDATES);
@ -472,7 +482,11 @@ function getUpdateDirFile(aLeafName) {
case FILE_UPDATE_VERSION:
case FILE_UPDATER_INI:
file.append(DIR_UPDATES);
file.append(DIR_PATCH);
if (aWhichDir == DIR_DOWNLOADING) {
file.append(DIR_DOWNLOADING);
} else {
file.append(DIR_PATCH);
}
file.append(aLeafName);
return file;
}
@ -530,25 +544,26 @@ function getStageDirFile(aRelPath) {
*/
function removeUpdateFiles(aRemoveLogFiles) {
let files = [
FILE_ACTIVE_UPDATE_XML,
FILE_UPDATES_XML,
FILE_BT_RESULT,
FILE_UPDATE_STATUS,
FILE_UPDATE_VERSION,
FILE_UPDATE_MAR,
FILE_UPDATER_INI,
[FILE_ACTIVE_UPDATE_XML],
[FILE_UPDATES_XML],
[FILE_BT_RESULT],
[FILE_UPDATE_STATUS],
[FILE_UPDATE_VERSION],
[FILE_UPDATE_MAR],
[FILE_UPDATE_MAR, DIR_DOWNLOADING],
[FILE_UPDATER_INI],
];
if (aRemoveLogFiles) {
files = files.concat([
FILE_BACKUP_UPDATE_LOG,
FILE_LAST_UPDATE_LOG,
FILE_UPDATE_LOG,
[FILE_BACKUP_UPDATE_LOG],
[FILE_LAST_UPDATE_LOG],
[FILE_UPDATE_LOG],
]);
}
for (let i = 0; i < files.length; i++) {
let file = getUpdateDirFile(files[i]);
let file = getUpdateDirFile.apply(null, files[i]);
try {
if (file.exists()) {
file.remove(false);

View File

@ -0,0 +1,85 @@
/* 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/.
*/
"use strict";
/**
* This test ensures that we don't resume an update download with the internal
* downloader when we are running background updates. Normally, the background
* update task won't even run if we can't use BITS. But it is possible for us to
* fall back from BITS to the internal downloader. Background update should
* prevent this fallback and just abort.
*
* But interactive Firefox allows that fallback. And once the internal
* download has started, the background update task must leave that download
* untouched and allow it to finish.
*/
var TEST_MAR_CONTENTS = "Arbitrary MAR contents";
add_task(async function setup() {
setupTestCommon();
start_httpserver();
setUpdateURL(gURLData + gHTTPHandlerPath);
setUpdateChannel("test_channel");
// Pretend that this is a background task.
const bts = Cc["@mozilla.org/backgroundtasks;1"].getService(
Ci.nsIBackgroundTasks
);
bts.overrideBackgroundTaskNameForTesting("test-task");
// No need for cleanup needed for changing update files. These will be cleaned
// up by removeUpdateFiles.
const downloadingMarFile = getUpdateDirFile(FILE_UPDATE_MAR, DIR_DOWNLOADING);
await IOUtils.writeUTF8(downloadingMarFile.path, TEST_MAR_CONTENTS);
writeStatusFile(STATE_DOWNLOADING);
let patchProps = {
state: STATE_DOWNLOADING,
bitsResult: Cr.NS_ERROR_FAILURE,
};
let patches = getLocalPatchString(patchProps);
let updateProps = { appVersion: "1.0" };
let updates = getLocalUpdateString(updateProps, patches);
writeUpdatesToXMLFile(getLocalUpdatesXMLString(updates), true);
});
add_task(async function backgroundUpdate() {
let patches = getRemotePatchString({});
let updateString = getRemoteUpdateString({}, patches);
gResponseBody = getRemoteUpdatesXMLString(updateString);
let { updates } = await waitForUpdateCheck(true);
let bestUpdate = gAUS.selectUpdate(updates);
let success = gAUS.downloadUpdate(bestUpdate, false);
Assert.equal(
success,
false,
"We should not attempt to download an update in the background when an " +
"internal update download is already in progress."
);
Assert.equal(
readStatusFile(),
STATE_DOWNLOADING,
"Background update during an internally downloading update should not " +
"change update status"
);
const downloadingMarFile = getUpdateDirFile(FILE_UPDATE_MAR, DIR_DOWNLOADING);
Assert.ok(
await IOUtils.exists(downloadingMarFile.path),
"Downloading MAR should still exist"
);
Assert.equal(
await IOUtils.readUTF8(downloadingMarFile.path),
TEST_MAR_CONTENTS,
"Downloading MAR should not have been modified"
);
});
add_task(async function finish() {
stop_httpserver(doTestFinish);
});

View File

@ -71,3 +71,4 @@ reason = Feature is Firefox-specific and Windows-specific.
[verifyChannelPrefsFile.js]
run-if = appname == 'firefox'
reason = File being verified is Firefox-specific.
[backgroundUpdateTaskInternalUpdater.js]