author | Jan Varga <jan.varga@gmail.com> |
Tue, 15 Mar 2016 07:00:44 +0100 | |
changeset 288739 | 27762ee249eb7d4c18c7e0f58a765a43b8496ed6 |
parent 288738 | 72f31b1f6186b228835d2f4e36c3b96c94674743 |
child 288740 | b22ef40863a05144cf013de13d2fc1e2959cee8a |
push id | 30089 |
push user | kwierso@gmail.com |
push date | Wed, 16 Mar 2016 00:26:08 +0000 |
treeherder | mozilla-central@7773387a9a2f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | baku |
bugs | 1182987 |
milestone | 48.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
new file mode 100644 --- /dev/null +++ b/dom/indexedDB/test/unit/test_quotaExceeded_recovery.js @@ -0,0 +1,153 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +var disableWorkerTest = "Need a way to set temporary prefs from a worker"; + +var testGenerator = testSteps(); + +function testSteps() +{ + const spec = "http://foo.com"; + const name = + this.window ? window.location.pathname : "test_quotaExceeded_recovery"; + const objectStoreName = "foo"; + + // We want 32 MB database file, but there's the group limit so we need to + // multiply by 5. + const tempStorageLimitKB = 32 * 1024 * 5; + + // Store in 1 MB chunks. + const dataSize = 1024 * 1024; + + for (let blobs of [false, true]) { + setTemporaryStorageLimit(tempStorageLimitKB); + + clearAllDatabases(continueToNextStepSync); + yield undefined; + + info("Opening database"); + + let request = indexedDB.openForPrincipal(getPrincipal(spec), name); + request.onerror = errorHandler; + request.onupgradeneeded = grabEventAndContinueHandler;; + request.onsuccess = unexpectedSuccessHandler; + + yield undefined; + + // upgradeneeded + request.onupgradeneeded = unexpectedSuccessHandler; + request.onsuccess = grabEventAndContinueHandler; + + info("Creating objectStore"); + + request.result.createObjectStore(objectStoreName); + + yield undefined; + + // success + let db = request.result; + db.onerror = errorHandler; + + ok(true, "Adding data until quota is reached"); + + let obj = { + name: "foo" + } + + if (!blobs) { + obj.data = getRandomView(dataSize); + } + + let i = 1; + let j = 1; + while (true) { + if (blobs) { + obj.data = getBlob(getView(dataSize)); + } + + let trans = db.transaction(objectStoreName, "readwrite"); + request = trans.objectStore(objectStoreName).add(obj, i); + request.onerror = function(event) + { + event.stopPropagation(); + } + + trans.oncomplete = function(event) { + i++; + j++; + testGenerator.send(true); + } + trans.onabort = function(event) { + is(trans.error.name, "QuotaExceededError", "Reached quota limit"); + testGenerator.send(false); + } + + let shouldContinue = yield undefined; + if (shouldContinue) { + ok(true, "Got complete event"); + } else { + ok(true, "Got abort event"); + + if (j==1) { + break; + } else { + j = 1; + + trans = db.transaction(objectStoreName, "cleanup"); + trans.onabort = unexpectedSuccessHandler;; + trans.oncomplete = grabEventAndContinueHandler; + + yield undefined; + } + } + } + + info("Reopening database"); + + db.close(); + + request = indexedDB.openForPrincipal(getPrincipal(spec), name); + request.onerror = errorHandler; + request.onsuccess = grabEventAndContinueHandler; + + yield undefined; + + db = request.result; + db.onerror = errorHandler; + + info("Deleting some data") + + let trans = db.transaction(objectStoreName, "cleanup"); + trans.objectStore(objectStoreName).delete(1); + + trans.onabort = unexpectedSuccessHandler;; + trans.oncomplete = grabEventAndContinueHandler; + + yield undefined; + + info("Adding data again") + + trans = db.transaction(objectStoreName, "readwrite"); + trans.objectStore(objectStoreName).add(obj, 1); + + trans.onabort = unexpectedSuccessHandler; + trans.oncomplete = grabEventAndContinueHandler; + + yield undefined; + + info("Deleting database"); + + db.close(); + + request = indexedDB.deleteForPrincipal(getPrincipal(spec), name); + request.onerror = errorHandler; + request.onsuccess = grabEventAndContinueHandler; + + yield undefined; + } + + finishTest(); + yield undefined; +}
--- a/dom/indexedDB/test/unit/test_temporary_storage.js +++ b/dom/indexedDB/test/unit/test_temporary_storage.js @@ -10,44 +10,24 @@ function testSteps() const name = this.window ? window.location.pathname : "test_temporary_storage.js"; const finalVersion = 2; const tempStorageLimitKB = 1024; const checkpointSleepTimeSec = 5; - function setLimit(limit) { - const pref = "dom.quotaManager.temporaryStorage.fixedLimit"; - if (limit) { - info("Setting temporary storage limit to " + limit); - SpecialPowers.setIntPref(pref, limit); - } else { - info("Removing temporary storage limit"); - SpecialPowers.clearUserPref(pref); - } - } - function getSpec(index) { return "http://foo" + index + ".com"; } - function getPrincipal(url) { - let uri = Cc["@mozilla.org/network/io-service;1"] - .getService(Ci.nsIIOService) - .newURI(url, null, null); - let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"] - .getService(Ci.nsIScriptSecurityManager); - return ssm.createCodebasePrincipal(uri, {}); - } - for (let temporary of [true, false]) { info("Testing '" + (temporary ? "temporary" : "default") + "' storage"); - setLimit(tempStorageLimitKB); + setTemporaryStorageLimit(tempStorageLimitKB); clearAllDatabases(continueToNextStepSync); yield undefined; info("Stage 1 - Creating empty databases until we reach the quota limit"); let databases = []; let options = { version: finalVersion }; @@ -160,17 +140,17 @@ function testSteps() is(event.type, "success", "Got success event"); let db = event.target.result; is(db.version, finalVersion, "Correct version " + finalVersion); db.close(); db = null; - setLimit(tempStorageLimitKB * 2); + setTemporaryStorageLimit(tempStorageLimitKB * 2); resetAllDatabases(continueToNextStepSync); yield undefined; delete options.version; spec = getSpec(0); info("Opening database for " + spec + " with unspecified version"); @@ -192,17 +172,17 @@ function testSteps() db = event.target.result; is(db.version, 1, "Correct version 1 (database was recreated)"); db.close(); db = null; info("Stage 3 - " + "Cutting storage limit in half to force deletion of some databases"); - setLimit(tempStorageLimitKB / 2); + setTemporaryStorageLimit(tempStorageLimitKB / 2); resetAllDatabases(continueToNextStepSync); yield undefined; info("Opening database for " + spec + " with unspecified version"); // Open the same db again to force QM to delete others. The first origin (0) // should be the most recent so it should not be deleted and we should not @@ -215,17 +195,17 @@ function testSteps() is(event.type, "success", "Got correct event type"); db = event.target.result; is(db.version, 1, "Correct version 1"); db.close(); db = null; - setLimit(tempStorageLimitKB * 2); + setTemporaryStorageLimit(tempStorageLimitKB * 2); resetAllDatabases(continueToNextStepSync); yield undefined; options.version = finalVersion; let newDatabaseCount = 0; for (let i = 0; i < databaseCount; i++) {
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js +++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js @@ -326,16 +326,33 @@ function installPackagedProfile(packageN istream.close(); bostream.close(); } } zipReader.close(); } +function getView(size) +{ + let buffer = new ArrayBuffer(size); + let view = new Uint8Array(buffer); + is(buffer.byteLength, size, "Correct byte length"); + return view; +} + +function getRandomView(size) +{ + let view = getView(size); + for (let i = 0; i < size; i++) { + view[i] = parseInt(Math.random() * 255) + } + return view; +} + function getBlob(str) { return new Blob([str], {type: "type/text"}); } function getFile(name, type, str) { return new File([str], name, {type: type}); @@ -413,16 +430,38 @@ function verifyMutableFile(mutableFile1, "Instance of IDBMutableFile"); is(mutableFile1.name, file2.name, "Correct name"); is(mutableFile1.type, file2.type, "Correct type"); executeSoon(function() { testGenerator.next(); }); } +function setTemporaryStorageLimit(limit) +{ + const pref = "dom.quotaManager.temporaryStorage.fixedLimit"; + if (limit) { + info("Setting temporary storage limit to " + limit); + SpecialPowers.setIntPref(pref, limit); + } else { + info("Removing temporary storage limit"); + SpecialPowers.clearUserPref(pref); + } +} + +function getPrincipal(url) +{ + let uri = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService) + .newURI(url, null, null); + let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"] + .getService(Ci.nsIScriptSecurityManager); + return ssm.createCodebasePrincipal(uri, {}); +} + var SpecialPowers = { isMainProcess: function() { return Components.classes["@mozilla.org/xre/app-info;1"] .getService(Components.interfaces.nsIXULRuntime) .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; }, notifyObservers: function(subject, topic, data) { var obsvc = Cc['@mozilla.org/observer-service;1']
--- a/dom/indexedDB/test/unit/xpcshell-parent-process.ini +++ b/dom/indexedDB/test/unit/xpcshell-parent-process.ini @@ -30,14 +30,15 @@ support-files = skip-if = toolkit == 'android' [test_idle_maintenance.js] [test_invalidate.js] # disabled for the moment. skip-if = true [test_lowDiskSpace.js] [test_metadataRestore.js] [test_mutableFileUpgrade.js] +[test_quotaExceeded_recovery.js] [test_readwriteflush_disabled.js] [test_schema18upgrade.js] [test_schema21upgrade.js] [test_temporary_storage.js] # bug 951017: intermittent failure on Android x86 emulator skip-if = os == "android" && processor == "x86"