зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1606318 - Enhance QM_FIRST_INITIALIZATION_ATTEMPT testing; r=asuth
Changes: - use separate directory for testing of telemetry - use separate zip packages - test entire histogram snapshots (not just particular key) - a test doesn't need to do own cleanup anymore - general cleanup Differential Revision: https://phabricator.services.mozilla.com/D58382 --HG-- rename : dom/quota/test/unit/head.js => dom/quota/test/unit/head-shared.js rename : dom/quota/test/unit/test_qm_first_initialization_attempt.js => dom/quota/test/unit/telemetry/test_qm_first_initialization_attempt.js rename : dom/quota/test/unit/version2_0upgrade_profile.zip => dom/quota/test/unit/telemetry/version1_0_profile.zip rename : dom/quota/test/unit/version2_1upgrade_profile.zip => dom/quota/test/unit/telemetry/version2_0_profile.zip rename : dom/quota/test/unit/version2_2upgrade_profile.zip => dom/quota/test/unit/telemetry/version2_1_profile.zip extra : moz-landing-system : lando
This commit is contained in:
Родитель
b6698c1d76
Коммит
88ce749554
|
@ -12,6 +12,7 @@ MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
|||
BROWSER_CHROME_MANIFESTS += ['test/browser.ini']
|
||||
|
||||
XPCSHELL_TESTS_MANIFESTS += [
|
||||
'test/unit/telemetry/xpcshell.ini',
|
||||
'test/unit/xpcshell.ini'
|
||||
]
|
||||
|
||||
|
@ -19,6 +20,10 @@ TEST_HARNESS_FILES.xpcshell.dom.quota.test += [
|
|||
'test/head-shared.js',
|
||||
]
|
||||
|
||||
TEST_HARNESS_FILES.xpcshell.dom.quota.test.unit += [
|
||||
'test/unit/head-shared.js',
|
||||
]
|
||||
|
||||
TEST_DIRS += ['test/gtest']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
|
|
Двоичные данные
dom/quota/test/unit/broken2_2_profile.zip
Двоичные данные
dom/quota/test/unit/broken2_2_profile.zip
Двоичный файл не отображается.
|
@ -0,0 +1,400 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const NS_OK = Cr.NS_OK;
|
||||
const NS_ERROR_FAILURE = Cr.NS_ERROR_FAILURE;
|
||||
const NS_ERROR_UNEXPECTED = Cr.NS_ERROR_UNEXPECTED;
|
||||
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
|
||||
const NS_ERROR_FILE_NO_DEVICE_SPACE = Cr.NS_ERROR_FILE_NO_DEVICE_SPACE;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function is(a, b, msg) {
|
||||
Assert.equal(a, b, msg);
|
||||
}
|
||||
|
||||
function ok(cond, msg) {
|
||||
Assert.ok(!!cond, msg);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
runTest();
|
||||
}
|
||||
|
||||
if (!this.runTest) {
|
||||
this.runTest = function() {
|
||||
do_get_profile();
|
||||
|
||||
enableTesting();
|
||||
|
||||
Cu.importGlobalProperties(["indexedDB", "File", "Blob", "FileReader"]);
|
||||
|
||||
// In order to support converting tests to using async functions from using
|
||||
// generator functions, we detect async functions by checking the name of
|
||||
// function's constructor.
|
||||
Assert.ok(
|
||||
typeof testSteps === "function",
|
||||
"There should be a testSteps function"
|
||||
);
|
||||
if (testSteps.constructor.name === "AsyncFunction") {
|
||||
// Do run our existing cleanup function that would normally be called by
|
||||
// the generator's call to finishTest().
|
||||
registerCleanupFunction(resetTesting);
|
||||
|
||||
add_task(testSteps);
|
||||
|
||||
// Since we defined run_test, we must invoke run_next_test() to start the
|
||||
// async test.
|
||||
run_next_test();
|
||||
} else {
|
||||
Assert.ok(
|
||||
testSteps.constructor.name === "GeneratorFunction",
|
||||
"Unsupported function type"
|
||||
);
|
||||
|
||||
do_test_pending();
|
||||
|
||||
testGenerator.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
resetTesting();
|
||||
|
||||
executeSoon(function() {
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
||||
function grabArgAndContinueHandler(arg) {
|
||||
testGenerator.next(arg);
|
||||
}
|
||||
|
||||
function continueToNextStep() {
|
||||
executeSoon(function() {
|
||||
testGenerator.next();
|
||||
});
|
||||
}
|
||||
|
||||
function continueToNextStepSync() {
|
||||
testGenerator.next();
|
||||
}
|
||||
|
||||
function enableTesting() {
|
||||
SpecialPowers.setBoolPref("dom.quotaManager.testing", true);
|
||||
SpecialPowers.setBoolPref("dom.simpleDB.enabled", true);
|
||||
}
|
||||
|
||||
function resetTesting() {
|
||||
SpecialPowers.clearUserPref("dom.quotaManager.testing");
|
||||
SpecialPowers.clearUserPref("dom.simpleDB.enabled");
|
||||
}
|
||||
|
||||
function setGlobalLimit(globalLimit) {
|
||||
SpecialPowers.setIntPref(
|
||||
"dom.quotaManager.temporaryStorage.fixedLimit",
|
||||
globalLimit
|
||||
);
|
||||
}
|
||||
|
||||
function resetGlobalLimit() {
|
||||
SpecialPowers.clearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
|
||||
}
|
||||
|
||||
function init(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().init();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initTemporaryStorage(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().initTemporaryStorage();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initStorageAndOrigin(principal, persistence, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().initStorageAndOrigin(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initStorageAndChromeOrigin(persistence, callback) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().initStorageAndOrigin(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clear(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clear();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearClient(principal, persistence, client, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
persistence,
|
||||
client
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearOrigin(principal, persistence, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearChromeOrigin(callback) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
"persistent"
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function reset(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().reset();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function persist(principal, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().persist(principal);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function persisted(principal, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().persisted(principal);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function listOrigins(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().listOrigins(callback);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function installPackage(packageName) {
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(
|
||||
Ci.nsIProperties
|
||||
);
|
||||
|
||||
let currentDir = directoryService.get("CurWorkD", Ci.nsIFile);
|
||||
|
||||
let packageFile = currentDir.clone();
|
||||
packageFile.append(packageName + ".zip");
|
||||
|
||||
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(
|
||||
Ci.nsIZipReader
|
||||
);
|
||||
zipReader.open(packageFile);
|
||||
|
||||
let entryNames = Array.from(zipReader.findEntries(null));
|
||||
entryNames.sort();
|
||||
|
||||
for (let entryName of entryNames) {
|
||||
let zipentry = zipReader.getEntry(entryName);
|
||||
|
||||
let file = getRelativeFile(entryName);
|
||||
|
||||
if (zipentry.isDirectory) {
|
||||
if (!file.exists()) {
|
||||
file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
}
|
||||
} else {
|
||||
let istream = zipReader.getInputStream(entryName);
|
||||
|
||||
var ostream = Cc[
|
||||
"@mozilla.org/network/file-output-stream;1"
|
||||
].createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(file, -1, parseInt("0644", 8), 0);
|
||||
|
||||
let bostream = Cc[
|
||||
"@mozilla.org/network/buffered-output-stream;1"
|
||||
].createInstance(Ci.nsIBufferedOutputStream);
|
||||
bostream.init(ostream, 32768);
|
||||
|
||||
bostream.writeFrom(istream, istream.available());
|
||||
|
||||
istream.close();
|
||||
bostream.close();
|
||||
}
|
||||
}
|
||||
|
||||
zipReader.close();
|
||||
}
|
||||
|
||||
function getProfileDir() {
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(
|
||||
Ci.nsIProperties
|
||||
);
|
||||
|
||||
return directoryService.get("ProfD", Ci.nsIFile);
|
||||
}
|
||||
|
||||
// Given a "/"-delimited path relative to the profile directory,
|
||||
// return an nsIFile representing the path. This does not test
|
||||
// for the existence of the file or parent directories.
|
||||
// It is safe even on Windows where the directory separator is not "/",
|
||||
// but make sure you're not passing in a "\"-delimited path.
|
||||
function getRelativeFile(relativePath) {
|
||||
let profileDir = getProfileDir();
|
||||
|
||||
let file = profileDir.clone();
|
||||
relativePath.split("/").forEach(function(component) {
|
||||
file.append(component);
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
function getPersistedFromMetadata(readBuffer) {
|
||||
const persistedPosition = 8; // Persisted state is stored in the 9th byte
|
||||
let view =
|
||||
readBuffer instanceof Uint8Array ? readBuffer : new Uint8Array(readBuffer);
|
||||
|
||||
return !!view[persistedPosition];
|
||||
}
|
||||
|
||||
function grabResultAndContinueHandler(request) {
|
||||
testGenerator.next(request.result);
|
||||
}
|
||||
|
||||
function grabUsageAndContinueHandler(request) {
|
||||
testGenerator.next(request.result.usage);
|
||||
}
|
||||
|
||||
function getUsage(usageHandler, getAll) {
|
||||
let request = SpecialPowers._getQuotaManager().getUsage(usageHandler, getAll);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getOriginUsage(principal, fromMemory = false) {
|
||||
let request = Services.qms.getUsageForPrincipal(
|
||||
principal,
|
||||
function() {},
|
||||
fromMemory
|
||||
);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getCurrentUsage(usageHandler) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().getUsageForPrincipal(
|
||||
principal,
|
||||
usageHandler
|
||||
);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getPrincipal(url, attr = {}) {
|
||||
let uri = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI(url);
|
||||
let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(
|
||||
Ci.nsIScriptSecurityManager
|
||||
);
|
||||
return ssm.createContentPrincipal(uri, attr);
|
||||
}
|
||||
|
||||
function getCurrentPrincipal() {
|
||||
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
}
|
||||
|
||||
function getSimpleDatabase(principal) {
|
||||
let connection = Cc["@mozilla.org/dom/sdb-connection;1"].createInstance(
|
||||
Ci.nsISDBConnection
|
||||
);
|
||||
|
||||
if (!principal) {
|
||||
principal = getCurrentPrincipal();
|
||||
}
|
||||
|
||||
connection.init(principal);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
function requestFinished(request) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
request.callback = function(req) {
|
||||
if (req.resultCode == Cr.NS_OK) {
|
||||
resolve(req.result);
|
||||
} else {
|
||||
reject(req.resultCode);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var SpecialPowers = {
|
||||
getBoolPref(prefName) {
|
||||
return this._getPrefs().getBoolPref(prefName);
|
||||
},
|
||||
|
||||
setBoolPref(prefName, value) {
|
||||
this._getPrefs().setBoolPref(prefName, value);
|
||||
},
|
||||
|
||||
setIntPref(prefName, value) {
|
||||
this._getPrefs().setIntPref(prefName, value);
|
||||
},
|
||||
|
||||
clearUserPref(prefName) {
|
||||
this._getPrefs().clearUserPref(prefName);
|
||||
},
|
||||
|
||||
_getPrefs() {
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"].getService(
|
||||
Ci.nsIPrefService
|
||||
);
|
||||
return prefService.getBranch(null);
|
||||
},
|
||||
|
||||
_getQuotaManager() {
|
||||
return Cc["@mozilla.org/dom/quota-manager-service;1"].getService(
|
||||
Ci.nsIQuotaManagerService
|
||||
);
|
||||
},
|
||||
};
|
|
@ -3,411 +3,13 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const NS_OK = Cr.NS_OK;
|
||||
const NS_ERROR_FAILURE = Cr.NS_ERROR_FAILURE;
|
||||
const NS_ERROR_UNEXPECTED = Cr.NS_ERROR_UNEXPECTED;
|
||||
const NS_ERROR_STORAGE_BUSY = Cr.NS_ERROR_STORAGE_BUSY;
|
||||
const NS_ERROR_FILE_NO_DEVICE_SPACE = Cr.NS_ERROR_FILE_NO_DEVICE_SPACE;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function is(a, b, msg) {
|
||||
Assert.equal(a, b, msg);
|
||||
}
|
||||
|
||||
function ok(cond, msg) {
|
||||
Assert.ok(!!cond, msg);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
runTest();
|
||||
}
|
||||
|
||||
if (!this.runTest) {
|
||||
this.runTest = function() {
|
||||
do_get_profile();
|
||||
|
||||
enableTesting();
|
||||
|
||||
Cu.importGlobalProperties(["indexedDB", "File", "Blob", "FileReader"]);
|
||||
|
||||
// In order to support converting tests to using async functions from using
|
||||
// generator functions, we detect async functions by checking the name of
|
||||
// function's constructor.
|
||||
Assert.ok(
|
||||
typeof testSteps === "function",
|
||||
"There should be a testSteps function"
|
||||
);
|
||||
if (testSteps.constructor.name === "AsyncFunction") {
|
||||
// Do run our existing cleanup function that would normally be called by
|
||||
// the generator's call to finishTest().
|
||||
registerCleanupFunction(resetTesting);
|
||||
|
||||
add_task(testSteps);
|
||||
|
||||
// Since we defined run_test, we must invoke run_next_test() to start the
|
||||
// async test.
|
||||
run_next_test();
|
||||
} else {
|
||||
Assert.ok(
|
||||
testSteps.constructor.name === "GeneratorFunction",
|
||||
"Unsupported function type"
|
||||
);
|
||||
|
||||
do_test_pending();
|
||||
|
||||
testGenerator.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
resetTesting();
|
||||
|
||||
executeSoon(function() {
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
|
||||
function grabArgAndContinueHandler(arg) {
|
||||
testGenerator.next(arg);
|
||||
}
|
||||
|
||||
function continueToNextStep() {
|
||||
executeSoon(function() {
|
||||
testGenerator.next();
|
||||
});
|
||||
}
|
||||
|
||||
function continueToNextStepSync() {
|
||||
testGenerator.next();
|
||||
}
|
||||
|
||||
function enableTesting() {
|
||||
SpecialPowers.setBoolPref("dom.quotaManager.testing", true);
|
||||
SpecialPowers.setBoolPref("dom.simpleDB.enabled", true);
|
||||
}
|
||||
|
||||
function resetTesting() {
|
||||
SpecialPowers.clearUserPref("dom.quotaManager.testing");
|
||||
SpecialPowers.clearUserPref("dom.simpleDB.enabled");
|
||||
}
|
||||
|
||||
function setGlobalLimit(globalLimit) {
|
||||
SpecialPowers.setIntPref(
|
||||
"dom.quotaManager.temporaryStorage.fixedLimit",
|
||||
globalLimit
|
||||
);
|
||||
}
|
||||
|
||||
function resetGlobalLimit() {
|
||||
SpecialPowers.clearUserPref("dom.quotaManager.temporaryStorage.fixedLimit");
|
||||
}
|
||||
|
||||
function init(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().init();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initTemporaryStorage(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().initTemporaryStorage();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initStorageAndOrigin(principal, persistence, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().initStorageAndOrigin(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function initStorageAndChromeOrigin(persistence, callback) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().initStorageAndOrigin(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clear(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clear();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearClient(principal, persistence, client, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
persistence,
|
||||
client
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearOrigin(principal, persistence, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
persistence
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function clearChromeOrigin(callback) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().clearStoragesForPrincipal(
|
||||
principal,
|
||||
"persistent"
|
||||
);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function reset(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().reset();
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function persist(principal, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().persist(principal);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function persisted(principal, callback) {
|
||||
let request = SpecialPowers._getQuotaManager().persisted(principal);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function listOrigins(callback) {
|
||||
let request = SpecialPowers._getQuotaManager().listOrigins(callback);
|
||||
request.callback = callback;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function installPackage(packageName) {
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(
|
||||
Ci.nsIProperties
|
||||
);
|
||||
|
||||
let currentDir = directoryService.get("CurWorkD", Ci.nsIFile);
|
||||
|
||||
let packageFile = currentDir.clone();
|
||||
packageFile.append(packageName + ".zip");
|
||||
|
||||
let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(
|
||||
Ci.nsIZipReader
|
||||
);
|
||||
zipReader.open(packageFile);
|
||||
|
||||
let entryNames = Array.from(zipReader.findEntries(null));
|
||||
entryNames.sort();
|
||||
|
||||
for (let entryName of entryNames) {
|
||||
let zipentry = zipReader.getEntry(entryName);
|
||||
|
||||
let file = getRelativeFile(entryName);
|
||||
|
||||
if (zipentry.isDirectory) {
|
||||
if (!file.exists()) {
|
||||
file.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
|
||||
}
|
||||
} else {
|
||||
let istream = zipReader.getInputStream(entryName);
|
||||
|
||||
var ostream = Cc[
|
||||
"@mozilla.org/network/file-output-stream;1"
|
||||
].createInstance(Ci.nsIFileOutputStream);
|
||||
ostream.init(file, -1, parseInt("0644", 8), 0);
|
||||
|
||||
let bostream = Cc[
|
||||
"@mozilla.org/network/buffered-output-stream;1"
|
||||
].createInstance(Ci.nsIBufferedOutputStream);
|
||||
bostream.init(ostream, 32768);
|
||||
|
||||
bostream.writeFrom(istream, istream.available());
|
||||
|
||||
istream.close();
|
||||
bostream.close();
|
||||
}
|
||||
}
|
||||
|
||||
zipReader.close();
|
||||
}
|
||||
|
||||
function getProfileDir() {
|
||||
let directoryService = Cc["@mozilla.org/file/directory_service;1"].getService(
|
||||
Ci.nsIProperties
|
||||
);
|
||||
|
||||
return directoryService.get("ProfD", Ci.nsIFile);
|
||||
}
|
||||
|
||||
// Given a "/"-delimited path relative to the profile directory,
|
||||
// return an nsIFile representing the path. This does not test
|
||||
// for the existence of the file or parent directories.
|
||||
// It is safe even on Windows where the directory separator is not "/",
|
||||
// but make sure you're not passing in a "\"-delimited path.
|
||||
function getRelativeFile(relativePath) {
|
||||
let profileDir = getProfileDir();
|
||||
|
||||
let file = profileDir.clone();
|
||||
relativePath.split("/").forEach(function(component) {
|
||||
file.append(component);
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
function getPersistedFromMetadata(readBuffer) {
|
||||
const persistedPosition = 8; // Persisted state is stored in the 9th byte
|
||||
let view =
|
||||
readBuffer instanceof Uint8Array ? readBuffer : new Uint8Array(readBuffer);
|
||||
|
||||
return !!view[persistedPosition];
|
||||
}
|
||||
|
||||
function grabResultAndContinueHandler(request) {
|
||||
testGenerator.next(request.result);
|
||||
}
|
||||
|
||||
function grabUsageAndContinueHandler(request) {
|
||||
testGenerator.next(request.result.usage);
|
||||
}
|
||||
|
||||
function getUsage(usageHandler, getAll) {
|
||||
let request = SpecialPowers._getQuotaManager().getUsage(usageHandler, getAll);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getOriginUsage(principal, fromMemory = false) {
|
||||
let request = Services.qms.getUsageForPrincipal(
|
||||
principal,
|
||||
function() {},
|
||||
fromMemory
|
||||
);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getCurrentUsage(usageHandler) {
|
||||
let principal = Cc["@mozilla.org/systemprincipal;1"].createInstance(
|
||||
Ci.nsIPrincipal
|
||||
);
|
||||
let request = SpecialPowers._getQuotaManager().getUsageForPrincipal(
|
||||
principal,
|
||||
usageHandler
|
||||
);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
function getPrincipal(url, attr = {}) {
|
||||
let uri = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI(url);
|
||||
let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"].getService(
|
||||
Ci.nsIScriptSecurityManager
|
||||
);
|
||||
return ssm.createContentPrincipal(uri, attr);
|
||||
}
|
||||
|
||||
function getCurrentPrincipal() {
|
||||
return Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal);
|
||||
}
|
||||
|
||||
function getSimpleDatabase(principal) {
|
||||
let connection = Cc["@mozilla.org/dom/sdb-connection;1"].createInstance(
|
||||
Ci.nsISDBConnection
|
||||
);
|
||||
|
||||
if (!principal) {
|
||||
principal = getCurrentPrincipal();
|
||||
}
|
||||
|
||||
connection.init(principal);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
function requestFinished(request) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
request.callback = function(req) {
|
||||
if (req.resultCode == Cr.NS_OK) {
|
||||
resolve(req.result);
|
||||
} else {
|
||||
reject(req.resultCode);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
var SpecialPowers = {
|
||||
getBoolPref(prefName) {
|
||||
return this._getPrefs().getBoolPref(prefName);
|
||||
},
|
||||
|
||||
setBoolPref(prefName, value) {
|
||||
this._getPrefs().setBoolPref(prefName, value);
|
||||
},
|
||||
|
||||
setIntPref(prefName, value) {
|
||||
this._getPrefs().setIntPref(prefName, value);
|
||||
},
|
||||
|
||||
clearUserPref(prefName) {
|
||||
this._getPrefs().clearUserPref(prefName);
|
||||
},
|
||||
|
||||
_getPrefs() {
|
||||
let prefService = Cc["@mozilla.org/preferences-service;1"].getService(
|
||||
Ci.nsIPrefService
|
||||
);
|
||||
return prefService.getBranch(null);
|
||||
},
|
||||
|
||||
_getQuotaManager() {
|
||||
return Cc["@mozilla.org/dom/quota-manager-service;1"].getService(
|
||||
Ci.nsIQuotaManagerService
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
function loadSubscript(path) {
|
||||
let file = do_get_file(path, false);
|
||||
let uri = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newFileURI(file);
|
||||
let scriptLoader = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(
|
||||
Ci.mozIJSSubScriptLoader
|
||||
);
|
||||
scriptLoader.loadSubScript(uri.spec);
|
||||
let uri = Services.io.newFileURI(file);
|
||||
Services.scriptloader.loadSubScript(uri.spec);
|
||||
}
|
||||
|
||||
loadSubscript("../head-shared.js");
|
||||
loadSubscript("head-shared.js");
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
function getOriginDir(persistence, origin) {
|
||||
return getRelativeFile(`storage/${persistence}/${origin}`);
|
||||
}
|
||||
|
||||
function getMetadataFile(persistence, origin) {
|
||||
const metadataFile = getOriginDir(persistence, origin);
|
||||
metadataFile.append(".metadata-v2");
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
function populateRepository(persistence) {
|
||||
const originDir = getOriginDir(persistence, "https+++good-example.com");
|
||||
originDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
|
||||
function makeRepositoryUnusable(persistence) {
|
||||
// For the purpose of testing, we make a repository unusable by creating an
|
||||
// origin directory with the metadata file created as a directory (not a
|
||||
// file).
|
||||
const metadataFile = getMetadataFile(persistence, "https+++bad-example.com");
|
||||
metadataFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
|
||||
function loadSubscript(path) {
|
||||
let file = do_get_file(path, false);
|
||||
let uri = Services.io.newFileURI(file);
|
||||
Services.scriptloader.loadSubScript(uri.spec);
|
||||
}
|
||||
|
||||
loadSubscript("../../head-shared.js");
|
||||
loadSubscript("../head-shared.js");
|
|
@ -0,0 +1,710 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const { AppConstants } = Cu.import("resource://gre/modules/AppConstants.jsm");
|
||||
const { TelemetryTestUtils } = Cu.import(
|
||||
"resource://testing-common/TelemetryTestUtils.jsm"
|
||||
);
|
||||
|
||||
const storageDirName = "storage";
|
||||
const storageFileName = "storage.sqlite";
|
||||
const histogramName = "QM_FIRST_INITIALIZATION_ATTEMPT";
|
||||
|
||||
const testcases = [
|
||||
{
|
||||
mainKey: "Storage",
|
||||
async setup(expectedInitResult) {
|
||||
if (!expectedInitResult) {
|
||||
// Make the database unusable by creating it as a directory (not a
|
||||
// file).
|
||||
const storageFile = getRelativeFile(storageFileName);
|
||||
storageFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "TemporaryStorage",
|
||||
async setup(expectedInitResult) {
|
||||
// We need to initialize storage before populating the repositories. If
|
||||
// we don't do that, the storage directory created for the repositories
|
||||
// would trigger storage upgrades (from version 0 to current version).
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
populateRepository("temporary");
|
||||
populateRepository("default");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
makeRepositoryUnusable("temporary");
|
||||
makeRepositoryUnusable("default");
|
||||
}
|
||||
},
|
||||
initFunction: initTemporaryStorage,
|
||||
getExpectedSnapshots() {
|
||||
const expectedSnapshotsInNightly = {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryStorage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryStorage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const expectedSnapshotsInOthers = {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryStorage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryStorage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return AppConstants.NIGHTLY_BUILD
|
||||
? expectedSnapshotsInNightly
|
||||
: expectedSnapshotsInOthers;
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "DefaultRepository",
|
||||
async setup(expectedInitResult) {
|
||||
// See the comment for "TemporaryStorage".
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
populateRepository("default");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
makeRepositoryUnusable("default");
|
||||
}
|
||||
},
|
||||
initFunction: initTemporaryStorage,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
DefaultRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
// mainKey
|
||||
DefaultRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "TemporaryRepository",
|
||||
async setup(expectedInitResult) {
|
||||
// See the comment for "TemporaryStorage".
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
populateRepository("temporary");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
makeRepositoryUnusable("temporary");
|
||||
}
|
||||
},
|
||||
initFunction: initTemporaryStorage,
|
||||
getExpectedSnapshots() {
|
||||
const expectedSnapshotsInNightly = {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const expectedSnapshotsInOthers = {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryRepository: {
|
||||
values: [1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryRepository: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return AppConstants.NIGHTLY_BUILD
|
||||
? expectedSnapshotsInNightly
|
||||
: expectedSnapshotsInOthers;
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "UpgradeStorageFrom0_0To1_0",
|
||||
async setup(expectedInitResult) {
|
||||
// storage used prior FF 49 (storage version 0.0)
|
||||
installPackage("version0_0_profile");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
installPackage("version0_0_make_it_unusable");
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom0_0To1_0: {
|
||||
values: [1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom0_0To1_0: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom1_0To2_0: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_0To2_1: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_1To2_2: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "UpgradeStorageFrom1_0To2_0",
|
||||
async setup(expectedInitResult) {
|
||||
// storage used by FF 49-54 (storage version 1.0)
|
||||
installPackage("version1_0_profile");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
installPackage("version1_0_make_it_unusable");
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom1_0To2_0: {
|
||||
values: [1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom1_0To2_0: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_0To2_1: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_1To2_2: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "UpgradeStorageFrom2_0To2_1",
|
||||
async setup(expectedInitResult) {
|
||||
// storage used by FF 55-56 (storage version 2.0)
|
||||
installPackage("version2_0_profile");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
installPackage("version2_0_make_it_unusable");
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_0To2_1: {
|
||||
values: [1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_0To2_1: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_1To2_2: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "UpgradeStorageFrom2_1To2_2",
|
||||
async setup(expectedInitResult) {
|
||||
// storage used by FF 57-67 (storage version 2.1)
|
||||
installPackage("version2_1_profile");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
installPackage("version2_1_make_it_unusable");
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_1To2_2: {
|
||||
values: [1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_1To2_2: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "UpgradeStorageFrom2_2To2_3",
|
||||
async setup(expectedInitResult) {
|
||||
// storage used by FF 68-69 (storage version 2.2)
|
||||
installPackage("version2_2_profile");
|
||||
|
||||
if (!expectedInitResult) {
|
||||
installPackage("version2_2_make_it_unusable");
|
||||
}
|
||||
},
|
||||
initFunction: init,
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
// mainKey
|
||||
UpgradeStorageFrom2_2To2_3: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
Storage: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "PersistentOrigin",
|
||||
async setup(expectedInitResult) {
|
||||
if (!expectedInitResult) {
|
||||
const originFiles = [
|
||||
getRelativeFile("storage/permanent/https+++example.com"),
|
||||
getRelativeFile("storage/permanent/https+++example1.com"),
|
||||
getRelativeFile("storage/default/https+++example2.com"),
|
||||
];
|
||||
|
||||
// We need to initialize storage before creating the origin files. If
|
||||
// we don't do that, the storage directory created for the origin files
|
||||
// would trigger storage upgrades (from version 0 to current version).
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
for (const originFile of originFiles) {
|
||||
originFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
|
||||
}
|
||||
}
|
||||
},
|
||||
initFunction: initStorageAndOrigin,
|
||||
initArgs: [
|
||||
[getPrincipal("https://example.com"), "persistent"],
|
||||
[getPrincipal("https://example1.com"), "persistent"],
|
||||
[getPrincipal("https://example2.com"), "default"],
|
||||
],
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
PersistentOrigin: {
|
||||
values: [2, 0],
|
||||
},
|
||||
TemporaryOrigin: {
|
||||
values: [1, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
// mainKey
|
||||
PersistentOrigin: {
|
||||
values: [2, 2, 0],
|
||||
},
|
||||
TemporaryOrigin: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
mainKey: "TemporaryOrigin",
|
||||
async setup(expectedInitResult) {
|
||||
if (!expectedInitResult) {
|
||||
const originFiles = [
|
||||
getRelativeFile("storage/temporary/https+++example.com"),
|
||||
getRelativeFile("storage/default/https+++example.com"),
|
||||
getRelativeFile("storage/default/https+++example1.com"),
|
||||
getRelativeFile("storage/permanent/https+++example2.com"),
|
||||
];
|
||||
|
||||
// See the comment for "PersistentOrigin".
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
for (const originFile of originFiles) {
|
||||
originFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
|
||||
}
|
||||
}
|
||||
},
|
||||
initFunction: initStorageAndOrigin,
|
||||
initArgs: [
|
||||
[getPrincipal("https://example.com"), "temporary"],
|
||||
[getPrincipal("https://example.com"), "default"],
|
||||
[getPrincipal("https://example1.com"), "default"],
|
||||
[getPrincipal("https://example2.com"), "persistent"],
|
||||
],
|
||||
// Only the first result of EnsureTemporaryOriginIsInitialized per origin
|
||||
// should be reported. Thus, only the results for (temporary, example.com),
|
||||
// and (default, example1.com) should be reported.
|
||||
expectedSnapshots: {
|
||||
initFailure: {
|
||||
Storage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [0, 1, 0],
|
||||
},
|
||||
PersistentOrigin: {
|
||||
values: [1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryOrigin: {
|
||||
values: [2, 0],
|
||||
},
|
||||
},
|
||||
initFailureThenSuccess: {
|
||||
Storage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
DefaultRepository: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
TemporaryStorage: {
|
||||
values: [0, 2, 0],
|
||||
},
|
||||
PersistentOrigin: {
|
||||
values: [1, 1, 0],
|
||||
},
|
||||
// mainKey
|
||||
TemporaryOrigin: {
|
||||
values: [2, 2, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function verifyHistogram(histogram, mainKey, expectedSnapshot) {
|
||||
const snapshot = histogram.snapshot();
|
||||
|
||||
ok(
|
||||
mainKey in snapshot,
|
||||
`The histogram ${histogram.name()} must contain the main key ${mainKey}`
|
||||
);
|
||||
|
||||
const keys = Object.keys(snapshot);
|
||||
|
||||
is(
|
||||
keys.length,
|
||||
Object.keys(expectedSnapshot).length,
|
||||
`The number of keys must match the expected number of keys for ` +
|
||||
`${histogram.name()}`
|
||||
);
|
||||
|
||||
for (const key of keys) {
|
||||
ok(
|
||||
key in expectedSnapshot,
|
||||
`The key ${key} must match the expected keys for ${histogram.name()}`
|
||||
);
|
||||
|
||||
const values = Object.entries(snapshot[key].values);
|
||||
const expectedValues = expectedSnapshot[key].values;
|
||||
|
||||
is(
|
||||
values.length,
|
||||
expectedValues.length,
|
||||
`The number of values should match the expected number of values for ` +
|
||||
`${histogram.name()}`
|
||||
);
|
||||
|
||||
for (let [i, val] of values) {
|
||||
is(
|
||||
val,
|
||||
expectedValues[i],
|
||||
`Expected counts should match for ${histogram.name()} at index ${i}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function testSteps() {
|
||||
let request;
|
||||
for (const testcase of testcases) {
|
||||
const mainKey = testcase.mainKey;
|
||||
|
||||
info(`Verifying ${histogramName} histogram for the main key ${mainKey}`);
|
||||
|
||||
const histogram = TelemetryTestUtils.getAndClearKeyedHistogram(
|
||||
histogramName
|
||||
);
|
||||
|
||||
for (const expectedInitResult of [false, true]) {
|
||||
info(
|
||||
`Verifying the histogram when the initialization ` +
|
||||
`${expectedInitResult ? "failed and then succeeds" : "fails"}`
|
||||
);
|
||||
|
||||
await testcase.setup(expectedInitResult);
|
||||
|
||||
const msg = `Should ${expectedInitResult ? "not " : ""} have thrown`;
|
||||
|
||||
// Call the initialization function twice, so we can verify below that
|
||||
// only the first initialization attempt has been reported.
|
||||
for (let i = 0; i < 2; ++i) {
|
||||
const initArgs = testcase.initArgs ? testcase.initArgs : [[]];
|
||||
for (const initArg of initArgs) {
|
||||
request = testcase.initFunction(...initArg);
|
||||
try {
|
||||
await requestFinished(request);
|
||||
ok(expectedInitResult, msg);
|
||||
} catch (ex) {
|
||||
ok(!expectedInitResult, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expectedSnapshots = testcase.getExpectedSnapshots
|
||||
? testcase.getExpectedSnapshots()
|
||||
: testcase.expectedSnapshots;
|
||||
|
||||
const expectedSnapshot = expectedInitResult
|
||||
? expectedSnapshots.initFailureThenSuccess
|
||||
: expectedSnapshots.initFailure;
|
||||
|
||||
verifyHistogram(histogram, mainKey, expectedSnapshot);
|
||||
|
||||
// The first initialization attempt has been reported in the histogram
|
||||
// and any new attemps wouldn't be reported if we didn't reset or clear
|
||||
// the storage here. We need a clean profile for the next iteration
|
||||
// anyway.
|
||||
// However, the clear storage operation needs initialized storage, so
|
||||
// clearing can fail if the storage is unusable and it can also increase
|
||||
// some of the telemetry counters. Instead of calling clear, we can just
|
||||
// call reset and clear profile manually.
|
||||
request = reset();
|
||||
await requestFinished(request);
|
||||
|
||||
const storageDir = getRelativeFile(storageDirName);
|
||||
if (storageDir.exists()) {
|
||||
storageDir.remove(true);
|
||||
}
|
||||
|
||||
const storageFile = getRelativeFile(storageFileName);
|
||||
if (storageFile.exists()) {
|
||||
// It could be a non empty directory, so remove it recursively.
|
||||
storageFile.remove(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -0,0 +1,20 @@
|
|||
# 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/.
|
||||
|
||||
[DEFAULT]
|
||||
head = head.js
|
||||
support-files =
|
||||
version0_0_make_it_unusable.zip
|
||||
version0_0_profile.zip
|
||||
version1_0_make_it_unusable.zip
|
||||
version1_0_profile.zip
|
||||
version2_0_make_it_unusable.zip
|
||||
version2_0_profile.zip
|
||||
version2_1_make_it_unusable.zip
|
||||
version2_1_profile.zip
|
||||
version2_2_make_it_unusable.zip
|
||||
version2_2_profile.zip
|
||||
|
||||
[test_qm_first_initialization_attempt.js]
|
||||
skip-if = appname == "thunderbird"
|
|
@ -1,428 +0,0 @@
|
|||
/**
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
const { TelemetryTestUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/TelemetryTestUtils.jsm"
|
||||
);
|
||||
|
||||
const telemetry = "QM_FIRST_INITIALIZATION_ATTEMPT";
|
||||
|
||||
const testcases = [
|
||||
{
|
||||
key: "Storage",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
async breakInit() {
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "TemporaryStorage",
|
||||
initFunction: initTemporaryStorage,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
async breakInit() {
|
||||
// We need to initialize storage before creating the metadata directory.
|
||||
// If we don't do that, the storage directory created for the metadata
|
||||
// directory would trigger storage upgrades (from version 0 to current
|
||||
// version) which would fail due to the metadata directory entry being
|
||||
// a directory (not a file).
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "PersistentOrigin",
|
||||
initFunction: initStorageAndOrigin,
|
||||
initArgs: [
|
||||
[getPrincipal("https://example.com"), "persistent"],
|
||||
[getPrincipal("https://example1.com"), "persistent"],
|
||||
[getPrincipal("https://example2.com"), "default"],
|
||||
],
|
||||
get originFiles() {
|
||||
return [
|
||||
getRelativeFile("storage/permanent/https+++example.com"),
|
||||
getRelativeFile("storage/permanent/https+++example1.com"),
|
||||
getRelativeFile("storage/default/https+++example2.com"),
|
||||
];
|
||||
},
|
||||
async breakInit() {
|
||||
// We need to initialize temporary storage before creating the origin
|
||||
// file. If we don't do that, the initialization would fail while
|
||||
// initializating the temporary storage.
|
||||
let request = initTemporaryStorage();
|
||||
await requestFinished(request);
|
||||
|
||||
for (let originFile of this.originFiles) {
|
||||
originFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
|
||||
}
|
||||
},
|
||||
unbreakInit() {
|
||||
for (let originFile of this.originFiles) {
|
||||
originFile.remove(false);
|
||||
}
|
||||
},
|
||||
expectedResult: {
|
||||
// Only the first init results for (persistent, example1.com) and
|
||||
// (persistent, example2.com) should be reported.
|
||||
initFailure: [2, 0],
|
||||
initFailureThenSuccess: [2, 2, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "TemporaryOrigin",
|
||||
initFunction: initStorageAndOrigin,
|
||||
initArgs: [
|
||||
[getPrincipal("https://example.com"), "temporary"],
|
||||
[getPrincipal("https://example.com"), "default"],
|
||||
[getPrincipal("https://example1.com"), "default"],
|
||||
[getPrincipal("https://example2.com"), "persistent"],
|
||||
],
|
||||
get originFiles() {
|
||||
return [
|
||||
getRelativeFile("storage/temporary/https+++example.com"),
|
||||
getRelativeFile("storage/default/https+++example.com"),
|
||||
getRelativeFile("storage/default/https+++example1.com"),
|
||||
getRelativeFile("storage/permanent/https+++example2.com"),
|
||||
];
|
||||
},
|
||||
async breakInit() {
|
||||
// We need to initialize temporary storage before creating the origin
|
||||
// file. If we don't do that, the initialization would fail while
|
||||
// initializating the temporary storage.
|
||||
let request = initTemporaryStorage();
|
||||
await requestFinished(request);
|
||||
|
||||
for (let originFile of this.originFiles) {
|
||||
originFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0o666);
|
||||
}
|
||||
},
|
||||
unbreakInit() {
|
||||
for (let originFile of this.originFiles) {
|
||||
originFile.remove(false);
|
||||
}
|
||||
},
|
||||
expectedResult: {
|
||||
// Only the first result of EnsureTemporaryOriginIsInitialized per origin
|
||||
// should be reported. Thus, only the results for
|
||||
// (temporary, example.com), and (default, example1.com) should be
|
||||
// reported.
|
||||
initFailure: [2, 0],
|
||||
initFailureThenSuccess: [2, 2, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
// Tests for upgrade functions are sligthy different from others because
|
||||
// it's impossible to run the testing function in the success cases twice
|
||||
// without calling reset().
|
||||
|
||||
key: "UpgradeStorageFrom0_0To1_0",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
initSetting() {
|
||||
let db = getRelativeFile("storage.sqlite");
|
||||
if (db.exists()) {
|
||||
// Remove the storage.sqlite to test the code path for version0_0To1_0
|
||||
db.remove(false);
|
||||
}
|
||||
},
|
||||
async breakInit() {
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "UpgradeStorageFrom1_0To2_0",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
initSetting() {
|
||||
// The zipped file contins only one storage:
|
||||
// - storage.sqlite
|
||||
// To make it become the profile in the test, we need:
|
||||
// 1. Get the storage.sqlite from a clean profile.
|
||||
// 2. Make the version of it to 1_0 version by
|
||||
// sqlite3 PROFILE/storage.sqlite "PRAGMA user_version = 65536;"
|
||||
installPackage("version2_0upgrade_profile");
|
||||
},
|
||||
async breakInit() {
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "UpgradeStorageFrom2_0To2_1",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
initSetting() {
|
||||
installPackage("version2_1upgrade_profile");
|
||||
},
|
||||
async breakInit() {
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "UpgradeStorageFrom2_1To2_2",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
initSetting() {
|
||||
installPackage("version2_2upgrade_profile");
|
||||
},
|
||||
async breakInit() {
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "UpgradeStorageFrom2_2To2_3",
|
||||
initFunction: init,
|
||||
initArgs: [[]],
|
||||
initSetting() {
|
||||
// Reuse the version2_1 storage.sqlite to test the code path for 2_2To2_3
|
||||
// upgrade
|
||||
installPackage("version2_2upgrade_profile");
|
||||
},
|
||||
async breakInit() {
|
||||
// The zipped file contins only one storage:
|
||||
// - storage.sqlite
|
||||
// To make it become the profile in the test, we need:
|
||||
// 1. Get the storage.sqlite from a clean profile.
|
||||
// 2. Make the version of it to 2_2 version by
|
||||
// sqlite3 PROFILE/storage.sqlite "PRAGMA user_version = 131074;"
|
||||
// 3. Make it broken by creating the table in the upgrading function by
|
||||
// sqlite3 PROFILE/storage.sqlite "CREATE TABLE database ( \
|
||||
// "cache_version INTEGER NOT NULL DEFAULT 0);"
|
||||
installPackage("broken2_2_profile");
|
||||
},
|
||||
unbreakInit() {
|
||||
let db = getRelativeFile("storage.sqlite");
|
||||
db.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "DefaultRepository",
|
||||
initFunction: initTemporaryStorage,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/default/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
async initSetting() {
|
||||
// Create a valid file/directtory in the target repository is needed.
|
||||
// Otherwise, we can not test the code path.
|
||||
let originDir = getRelativeFile("storage/default/https+++example1.com/");
|
||||
|
||||
if (!originDir.exists()) {
|
||||
originDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
},
|
||||
async breakInit() {
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
{
|
||||
key: "TemporaryRepository",
|
||||
initFunction: initTemporaryStorage,
|
||||
initArgs: [[]],
|
||||
get metadataDir() {
|
||||
return getRelativeFile(
|
||||
"storage/temporary/https+++example.com/.metadata-v2"
|
||||
);
|
||||
},
|
||||
async initSetting() {
|
||||
let originDir = getRelativeFile(
|
||||
"storage/temporary/https+++example1.com/"
|
||||
);
|
||||
|
||||
if (!originDir.exists()) {
|
||||
originDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
}
|
||||
},
|
||||
async breakInit() {
|
||||
let request = init();
|
||||
await requestFinished(request);
|
||||
|
||||
this.metadataDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
|
||||
},
|
||||
unbreakInit() {
|
||||
this.metadataDir.remove(false);
|
||||
},
|
||||
expectedResult: {
|
||||
initFailure: [1, 0],
|
||||
initFailureThenSuccess: [1, 1, 0],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function verifyResult(histogram, key, expectedResult) {
|
||||
const snapshot = histogram.snapshot();
|
||||
|
||||
ok(key in snapshot, `The histogram ${histogram.name()} must contain ${key}`);
|
||||
|
||||
is(
|
||||
Object.entries(snapshot[key].values).length,
|
||||
expectedResult.length,
|
||||
`Reported telemetry should have the same size as expected result (${
|
||||
expectedResult.length
|
||||
})`
|
||||
);
|
||||
|
||||
for (let i = 0; i < expectedResult.length; ++i) {
|
||||
is(
|
||||
snapshot[key].values[i],
|
||||
expectedResult[i],
|
||||
`Expected counts should match for ${histogram.name()} at index ${i}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function testSteps() {
|
||||
let request;
|
||||
for (let testcase of testcases) {
|
||||
const key = testcase.key;
|
||||
|
||||
info("Verifying the telemetry probe " + telemetry + " for the key " + key);
|
||||
|
||||
const histogram = TelemetryTestUtils.getAndClearKeyedHistogram(telemetry);
|
||||
|
||||
for (let expectedInitResult of [false, true]) {
|
||||
info(
|
||||
"Verifying the reported result on the Telemetry is expected when " +
|
||||
"the init " +
|
||||
(expectedInitResult ? "succeeds" : "fails")
|
||||
);
|
||||
|
||||
if (testcase.initSetting) {
|
||||
await testcase.initSetting();
|
||||
}
|
||||
|
||||
if (!expectedInitResult) {
|
||||
await testcase.breakInit();
|
||||
}
|
||||
|
||||
const msg =
|
||||
"Should " + (expectedInitResult ? "not " : "") + "have thrown";
|
||||
|
||||
// The steps below verify we should get the result of the first attempt
|
||||
// for the initialization.
|
||||
for (let i = 0; i < 2; ++i) {
|
||||
for (let initArg of testcase.initArgs) {
|
||||
request = testcase.initFunction(...initArg);
|
||||
try {
|
||||
await requestFinished(request);
|
||||
ok(expectedInitResult, msg);
|
||||
} catch (ex) {
|
||||
ok(!expectedInitResult, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectedInitResult) {
|
||||
// Remove the setting (e.g. files) created by the breakInit(). We need
|
||||
// to do that for the next iteration in which the initialization is
|
||||
// supposed to succeed.
|
||||
testcase.unbreakInit();
|
||||
}
|
||||
|
||||
const expectedResultForThisRun = expectedInitResult
|
||||
? testcase.expectedResult.initFailureThenSuccess
|
||||
: testcase.expectedResult.initFailure;
|
||||
verifyResult(histogram, key, expectedResultForThisRun);
|
||||
|
||||
// The first initialization attempt has been reported in telemetry and
|
||||
// any new attemps wouldn't be reported if we don't reset the storage
|
||||
// here.
|
||||
request = reset();
|
||||
await requestFinished(request);
|
||||
}
|
||||
|
||||
request = clear();
|
||||
await requestFinished(request);
|
||||
}
|
||||
}
|
Двоичные данные
dom/quota/test/unit/version2_0upgrade_profile.zip
Двоичные данные
dom/quota/test/unit/version2_0upgrade_profile.zip
Двоичный файл не отображается.
|
@ -24,10 +24,8 @@ support-files =
|
|||
removeLocalStorage2_profile.zip
|
||||
storagePersistentUpgrade_profile.zip
|
||||
tempMetadataCleanup_profile.zip
|
||||
version2_0upgrade_profile.zip
|
||||
version2_1upgrade_profile.zip
|
||||
version2_2upgrade_profile.zip
|
||||
broken2_2_profile.zip
|
||||
|
||||
[test_allowListFiles.js]
|
||||
[test_basics.js]
|
||||
|
@ -54,8 +52,6 @@ support-files =
|
|||
[test_persist_eviction.js]
|
||||
[test_persist_globalLimit.js]
|
||||
[test_persist_groupLimit.js]
|
||||
[test_qm_first_initialization_attempt.js]
|
||||
skip-if = appname == "thunderbird"
|
||||
[test_removeLocalStorage.js]
|
||||
[test_simpledb.js]
|
||||
[test_specialOrigins.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче