Backed out 2 changesets (bug 1427007) for failing xpcshell on browser/components/sessionstore/test/unit/test_shutdown_cleanup.js

Backed out changeset 79b25461de35 (bug 1427007)
Backed out changeset 986dab420f52 (bug 1427007)
This commit is contained in:
Dorel Luca 2018-02-02 18:07:05 +02:00
Родитель 475c6b33c7
Коммит 94c2a48ce5
3 изменённых файлов: 56 добавлений и 90 удалений

Просмотреть файл

@ -37,6 +37,8 @@ ChromeUtils.import("resource://gre/modules/AsyncShutdown.jsm");
ChromeUtils.defineModuleGetter(this, "console",
"resource://gre/modules/Console.jsm");
ChromeUtils.defineModuleGetter(this, "PromiseUtils",
"resource://gre/modules/PromiseUtils.jsm");
ChromeUtils.defineModuleGetter(this, "RunState",
"resource:///modules/sessionstore/RunState.jsm");
ChromeUtils.defineModuleGetter(this, "TelemetryStopwatch",
@ -198,17 +200,14 @@ var SessionFileInternal = {
failures: 0
},
// `true` once we have started initialization of the worker.
// Resolved once initialization is complete.
// The promise never rejects.
_deferredInitialized: PromiseUtils.defer(),
// `true` once we have started initialization, i.e. once something
// has been scheduled that will eventually resolve `_deferredInitialized`.
_initializationStarted: false,
// A string that will be set to the session file name part that was read from
// disk. It will be available _after_ a session file read() is done.
_readOrigin: null,
// `true` if the old, uncompressed, file format was used to read from disk, as
// a fallback mechanism.
_usingOldExtension: false,
// The ID of the latest version of Gecko for which we have an upgrade backup
// or |undefined| if no upgrade backup was ever written.
get latestUpgradeBackupID() {
@ -222,7 +221,6 @@ var SessionFileInternal = {
async _readInternal(useOldExtension) {
let result;
let noFilesFound = true;
this._usingOldExtension = useOldExtension;
// Attempt to load by order of priority from the various backups
for (let key of this.Paths.loadOrder) {
@ -287,6 +285,8 @@ var SessionFileInternal = {
// Find the correct session file, read it and setup the worker.
async read() {
this._initializationStarted = true;
// Load session files with lz4 compression.
let {result, noFilesFound} = await this._readInternal(false);
if (!result) {
@ -310,55 +310,39 @@ var SessionFileInternal = {
useOldExtension: false
};
}
this._readOrigin = result.origin;
result.noFilesFound = noFilesFound;
// Initialize the worker (in the background) to let it handle backups and also
// as a workaround for bug 964531.
this._initWorker();
let promiseInitialized = SessionWorker.post("init", [result.origin, result.useOldExtension, this.Paths, {
maxUpgradeBackups: Services.prefs.getIntPref(PREF_MAX_UPGRADE_BACKUPS, 3),
maxSerializeBack: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_BACK, 10),
maxSerializeForward: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_FWD, -1)
}]);
promiseInitialized.catch(err => {
// Ensure that we report errors but that they do not stop us.
Promise.reject(err);
}).then(() => this._deferredInitialized.resolve());
return result;
},
// Initialize the worker in the background.
// Since this called _before_ any other messages are posted to the worker (see
// `_postToWorker()`), we know that this initialization process will be completed
// on time.
// Thus, effectively, this blocks callees on its completion.
// In case of a worker crash/ shutdown during its initialization phase,
// `_checkWorkerHealth()` will detect it and flip the `_initializationStarted`
// property back to `false`. This means that we'll respawn the worker upon the
// next request, followed by the initialization sequence here. In other words;
// exactly the same procedure as when the worker crashed/ shut down 'regularly'.
//
// This will never throw an error.
_initWorker() {
return new Promise(resolve => {
if (this._initializationStarted) {
resolve();
return;
}
if (!this._readOrigin) {
throw new Error("_initWorker called too early! Please read the session file from disk first.");
}
this._initializationStarted = true;
SessionWorker.post("init", [this._readOrigin, this._usingOldExtension, this.Paths, {
maxUpgradeBackups: Services.prefs.getIntPref(PREF_MAX_UPGRADE_BACKUPS, 3),
maxSerializeBack: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_BACK, 10),
maxSerializeForward: Services.prefs.getIntPref(PREF_MAX_SERIALIZE_FWD, -1)
}]).catch(err => {
// Ensure that we report errors but that they do not stop us.
Promise.reject(err);
}).then(resolve);
});
},
// Post a message to the worker, making sure that it has been initialized first.
// Post a message to the worker, making sure that it has been initialized
// first.
async _postToWorker(...args) {
await this._initWorker();
if (!this._initializationStarted) {
// Initializing the worker is somewhat complex, as proper handling of
// backups requires us to first read and check the session. Consequently,
// the only way to initialize the worker is to first call `this.read()`.
// The call to `this.read()` causes background initialization of the worker.
// Initialization will be complete once `this._deferredInitialized.promise`
// resolves.
this.read();
}
await this._deferredInitialized.promise;
return SessionWorker.post(...args);
},
@ -371,10 +355,6 @@ var SessionFileInternal = {
_checkWorkerHealth() {
if (this._workerHealth.failures >= kMaxWriteFailures) {
SessionWorker.terminate();
// Flag as not-initialized, to ensure that the worker state init is performed
// upon the next request.
this._initializationStarted = false;
// Reset the counter and report to telemetry.
this._workerHealth.failures = 0;
Telemetry.scalarAdd("browser.session.restore.worker_restart_count", 1);
}
@ -451,11 +431,7 @@ var SessionFileInternal = {
},
wipe() {
return this._postToWorker("wipe").then(() => {
// After a wipe, we need to make sure to re-initialize upon the next read(),
// because the state variables as sent to the worker have changed.
this._initializationStarted = false;
});
return this._postToWorker("wipe");
},
_recordTelemetry(telemetry) {

Просмотреть файл

@ -22,11 +22,6 @@ function promiseRead(path) {
return File.read(path, {encoding: "utf-8", compression: "lz4"});
}
async function reInitSessionFile() {
await SessionFile.wipe();
await SessionFile.read();
}
add_task(async function init() {
// Make sure that we are not racing with SessionSaver's time based
// saves.
@ -45,7 +40,8 @@ add_task(async function test_creation() {
await File.writeAtomic(OLD_BACKUP, "sessionstore.bak");
await File.writeAtomic(OLD_UPGRADE_BACKUP, "sessionstore upgrade backup");
await reInitSessionFile();
await SessionFile.wipe();
await SessionFile.read(); // Reinitializes SessionFile
// Ensure none of the sessionstore files and backups exists
for (let k of Paths.loadOrder) {
@ -67,8 +63,7 @@ add_task(async function test_creation() {
ok((await File.exists(Paths.recovery)), "After write, recovery sessionstore file exists again");
ok(!(await File.exists(Paths.recoveryBackup)), "After write, recoveryBackup sessionstore doesn't exist");
ok((await promiseRead(Paths.recovery)).includes(URL), "Recovery sessionstore file contains the required tab");
ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown " +
"sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown sessionstore doesn't exist, since we haven't shutdown yet");
// Open a second tab, save session, ensure that the correct files exist.
info("Testing situation after a second write");
@ -84,20 +79,17 @@ add_task(async function test_creation() {
let backup = await promiseRead(Paths.recoveryBackup);
ok(!backup.includes(URL2), "Recovery backup doesn't contain the latest url");
ok(backup.includes(URL), "Recovery backup contains the original url");
ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown " +
"sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.clean)), "After first write, clean shutdown sessinstore doesn't exist, since we haven't shutdown yet");
info("Reinitialize, ensure that we haven't leaked sensitive files");
await SessionFile.read(); // Reinitializes SessionFile
await SessionSaver.run();
ok(!(await File.exists(Paths.clean)), "After second write, clean shutdown " +
"sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.upgradeBackup)), "After second write, clean " +
"shutdown sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.nextUpgradeBackup)), "After second write, clean " +
"shutdown sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.clean)), "After second write, clean shutdown sessonstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.upgradeBackup)), "After second write, clean shutdwn sessionstore doesn't exist, since we haven't shutdown yet");
ok(!(await File.exists(Paths.nextUpgradeBackup)), "After second write, clean sutdown sessionstore doesn't exist, since we haven't shutdown yet");
gBrowser.removeTab(tab);
await SessionFile.wipe();
});
var promiseSource = async function(name) {
@ -115,7 +107,8 @@ var promiseSource = async function(name) {
};
add_task(async function test_recovery() {
await reInitSessionFile();
// Remove all files.
await SessionFile.wipe();
info("Attempting to recover from the recovery file");
// Create Paths.recovery, ensure that we can recover from it.
@ -123,6 +116,7 @@ add_task(async function test_recovery() {
await File.makeDir(Paths.backups);
await File.writeAtomic(Paths.recovery, SOURCE, {encoding: "utf-8", compression: "lz4"});
is((await SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file");
await SessionFile.wipe();
info("Corrupting recovery file, attempting to recover from recovery backup");
SOURCE = await promiseSource("Paths.recoveryBackup");
@ -130,6 +124,7 @@ add_task(async function test_recovery() {
await File.writeAtomic(Paths.recoveryBackup, SOURCE, {encoding: "utf-8", compression: "lz4"});
await File.writeAtomic(Paths.recovery, "<Invalid JSON>", {encoding: "utf-8", compression: "lz4"});
is((await SessionFile.read()).source, SOURCE, "Recovered the correct source from the recovery file");
await SessionFile.wipe();
});
add_task(async function test_recovery_inaccessible() {
@ -138,7 +133,6 @@ add_task(async function test_recovery_inaccessible() {
return;
}
await reInitSessionFile();
info("Making recovery file inaccessible, attempting to recover from recovery backup");
let SOURCE_RECOVERY = await promiseSource("Paths.recovery");
let SOURCE = await promiseSource("Paths.recoveryBackup");
@ -154,13 +148,12 @@ add_task(async function test_recovery_inaccessible() {
});
add_task(async function test_clean() {
await reInitSessionFile();
await SessionFile.wipe();
let SOURCE = await promiseSource("Paths.clean");
await File.writeAtomic(Paths.clean, SOURCE, {encoding: "utf-8", compression: "lz4"});
await SessionFile.read();
await SessionSaver.run();
is((await promiseRead(Paths.cleanBackup)), SOURCE, "After first read/write, " +
"clean shutdown file has been moved to cleanBackup");
is((await promiseRead(Paths.cleanBackup)), SOURCE, "After first read/write, clean shutdown file has been moved to cleanBackup");
});
@ -187,7 +180,6 @@ add_task(async function test_version() {
* Tests fallback to previous backups if format version is unknown.
*/
add_task(async function test_version_fallback() {
await reInitSessionFile();
info("Preparing data, making sure that it has a version number");
let SOURCE = await promiseSource("Paths.clean");
let BACKUP_SOURCE = await promiseSource("Paths.cleanBackup");
@ -213,5 +205,5 @@ add_task(async function test_version_fallback() {
});
add_task(async function cleanup() {
await reInitSessionFile();
await SessionFile.wipe();
});

Просмотреть файл

@ -14,7 +14,7 @@ const PREF_MAX_UPGRADE_BACKUPS = "browser.sessionstore.upgradeBackup.maxUpgradeB
* build where the last backup was created and creating arbitrary JSON data
* for a new backup.
*/
function prepareTest() {
var prepareTest = async function() {
let result = {};
result.buildID = Services.appinfo.platformBuildID;
@ -22,12 +22,12 @@ function prepareTest() {
result.contents = JSON.stringify({"browser_upgrade_backup.js": Math.random()});
return result;
}
};
/**
* Retrieves all upgrade backups and returns them in an array.
*/
async function getUpgradeBackups() {
var getUpgradeBackups = async function() {
let iterator;
let backups = [];
@ -50,17 +50,17 @@ async function getUpgradeBackups() {
// return results
return backups;
}
};
add_task(async function init() {
// Wait until initialization is complete
await SessionStore.promiseInitialized;
await SessionFile.wipe();
});
add_task(async function test_upgrade_backup() {
let test = prepareTest();
let test = await prepareTest();
info("Let's check if we create an upgrade backup");
await SessionFile.wipe();
await OS.File.writeAtomic(Paths.clean, test.contents, {encoding: "utf-8", compression: "lz4"});
await SessionFile.read(); // First call to read() initializes the SessionWorker
await SessionFile.write(""); // First call to write() triggers the backup
@ -82,11 +82,9 @@ add_task(async function test_upgrade_backup() {
});
add_task(async function test_upgrade_backup_removal() {
let test = prepareTest();
let test = await prepareTest();
let maxUpgradeBackups = Preferences.get(PREF_MAX_UPGRADE_BACKUPS, 3);
info("Let's see if we remove backups if there are too many");
await SessionFile.wipe();
await OS.File.makeDir(Paths.backups);
await OS.File.writeAtomic(Paths.clean, test.contents, {encoding: "utf-8", compression: "lz4"});
// if the nextUpgradeBackup already exists (from another test), remove it