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:
Jan Varga 2019-12-31 02:26:27 +00:00
Родитель b6698c1d76
Коммит 88ce749554
20 изменённых файлов: 1176 добавлений и 833 удалений

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

@ -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

Двоичный файл не отображается.

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

@ -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);
}
}
}
}

Двоичные данные
dom/quota/test/unit/telemetry/version0_0_make_it_unusable.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version0_0_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version1_0_make_it_unusable.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version1_0_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_0_make_it_unusable.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_0_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_1_make_it_unusable.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_1_profile.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_2_make_it_unusable.zip Normal file

Двоичный файл не отображается.

Двоичные данные
dom/quota/test/unit/telemetry/version2_2_profile.zip Normal file

Двоичный файл не отображается.

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

@ -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);
}
}

Двоичный файл не отображается.

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

@ -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]