test_temporary_storage.js (8413B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 6 7 var testGenerator = testSteps(); 8 9 function* testSteps() { 10 const name = this.window 11 ? window.location.pathname 12 : "test_temporary_storage.js"; 13 const finalVersion = 2; 14 15 const tempStorageLimitKB = 1024; 16 const checkpointSleepTimeSec = 5; 17 18 function getSpec(index) { 19 return "http://foo" + index + ".com"; 20 } 21 22 for (let temporary of [true, false]) { 23 info("Testing '" + (temporary ? "temporary" : "default") + "' storage"); 24 25 setTemporaryStorageLimit(tempStorageLimitKB); 26 27 clearAllDatabases(continueToNextStepSync); 28 yield undefined; 29 30 info("Stage 1 - Creating empty databases until we reach the quota limit"); 31 32 let databases = []; 33 let options = { version: finalVersion }; 34 if (temporary) { 35 options.storage = "temporary"; 36 } 37 38 while (true) { 39 let spec = getSpec(databases.length); 40 41 info("Opening database for " + spec + " with version " + options.version); 42 43 let gotUpgradeIncomplete = false; 44 let gotUpgradeComplete = false; 45 46 let request = indexedDB.openForPrincipal( 47 getPrincipal(spec), 48 name, 49 options 50 ); 51 request.onerror = function (event) { 52 is( 53 request.error.name, 54 gotUpgradeIncomplete ? "AbortError" : "QuotaExceededError", 55 "Reached quota limit" 56 ); 57 event.preventDefault(); 58 testGenerator.next(false); 59 }; 60 request.onupgradeneeded = function (event) { 61 event.target.transaction.onabort = function (e) { 62 gotUpgradeIncomplete = true; 63 is(e.target.error.name, "QuotaExceededError", "Reached quota limit"); 64 }; 65 event.target.transaction.oncomplete = function () { 66 gotUpgradeComplete = true; 67 }; 68 }; 69 request.onsuccess = function (event) { 70 let db = event.target.result; 71 is(db.version, finalVersion, "Correct version " + finalVersion); 72 databases.push(db); 73 testGenerator.next(true); 74 }; 75 76 let shouldContinue = yield undefined; 77 if (shouldContinue) { 78 is(gotUpgradeComplete, true, "Got upgradeneeded event"); 79 ok(true, "Got success event"); 80 } else { 81 break; 82 } 83 } 84 85 while (true) { 86 info( 87 "Sleeping for " + 88 checkpointSleepTimeSec + 89 " seconds to let all " + 90 "checkpoints finish so that we know we have reached quota limit" 91 ); 92 setTimeout(continueToNextStepSync, checkpointSleepTimeSec * 1000); 93 yield undefined; 94 95 let spec = getSpec(databases.length); 96 97 info("Opening database for " + spec + " with version " + options.version); 98 99 let gotUpgradeIncomplete = false; 100 let gotUpgradeComplete = false; 101 102 let request = indexedDB.openForPrincipal( 103 getPrincipal(spec), 104 name, 105 options 106 ); 107 request.onerror = function (event) { 108 is( 109 request.error.name, 110 gotUpgradeIncomplete ? "AbortError" : "QuotaExceededError", 111 "Reached quota limit" 112 ); 113 event.preventDefault(); 114 testGenerator.next(false); 115 }; 116 request.onupgradeneeded = function (event) { 117 event.target.transaction.onabort = function (e) { 118 gotUpgradeIncomplete = true; 119 is(e.target.error.name, "QuotaExceededError", "Reached quota limit"); 120 }; 121 event.target.transaction.oncomplete = function () { 122 gotUpgradeComplete = true; 123 }; 124 }; 125 request.onsuccess = function (event) { 126 let db = event.target.result; 127 is(db.version, finalVersion, "Correct version " + finalVersion); 128 databases.push(db); 129 testGenerator.next(true); 130 }; 131 132 let shouldContinue = yield undefined; 133 if (shouldContinue) { 134 is(gotUpgradeComplete, true, "Got upgradeneeded event"); 135 ok(true, "Got success event"); 136 } else { 137 break; 138 } 139 } 140 141 let databaseCount = databases.length; 142 info("Created " + databaseCount + " databases before quota limit reached"); 143 144 info( 145 "Stage 2 - " + 146 "Closing all databases and then attempting to create one more, then " + 147 "verifying that the oldest origin was cleared" 148 ); 149 150 for (let i = 0; i < databases.length; i++) { 151 info("Closing database for " + getSpec(i)); 152 databases[i].close(); 153 154 // Timer resolution on Windows is low so wait for 40ms just to be safe. 155 setTimeout(continueToNextStepSync, 40); 156 yield undefined; 157 } 158 databases = null; 159 160 let spec = getSpec(databaseCount); 161 info("Opening database for " + spec + " with version " + options.version); 162 163 let request = indexedDB.openForPrincipal(getPrincipal(spec), name, options); 164 request.onerror = errorHandler; 165 request.onupgradeneeded = grabEventAndContinueHandler; 166 request.onsuccess = unexpectedSuccessHandler; 167 let event = yield undefined; 168 169 is(event.type, "upgradeneeded", "Got upgradeneeded event"); 170 171 request.onupgradeneeded = unexpectedSuccessHandler; 172 request.onsuccess = grabEventAndContinueHandler; 173 event = yield undefined; 174 175 is(event.type, "success", "Got success event"); 176 177 let db = event.target.result; 178 is(db.version, finalVersion, "Correct version " + finalVersion); 179 db.close(); 180 db = null; 181 182 setTemporaryStorageLimit(tempStorageLimitKB * 2); 183 184 resetAllDatabases(continueToNextStepSync); 185 yield undefined; 186 187 delete options.version; 188 189 spec = getSpec(0); 190 info("Opening database for " + spec + " with unspecified version"); 191 192 request = indexedDB.openForPrincipal(getPrincipal(spec), name, options); 193 request.onerror = errorHandler; 194 request.onupgradeneeded = grabEventAndContinueHandler; 195 request.onsuccess = unexpectedSuccessHandler; 196 event = yield undefined; 197 198 is(event.type, "upgradeneeded", "Got upgradeneeded event"); 199 200 request.onupgradeneeded = unexpectedSuccessHandler; 201 request.onsuccess = grabEventAndContinueHandler; 202 event = yield undefined; 203 204 is(event.type, "success", "Got success event"); 205 206 db = event.target.result; 207 is(db.version, 1, "Correct version 1 (database was recreated)"); 208 db.close(); 209 db = null; 210 211 info( 212 "Stage 3 - " + 213 "Cutting storage limit in half to force deletion of some databases" 214 ); 215 216 setTemporaryStorageLimit(tempStorageLimitKB / 2); 217 218 resetAllDatabases(continueToNextStepSync); 219 yield undefined; 220 221 info("Opening database for " + spec + " with unspecified version"); 222 223 // Open the same db again to force QM to delete others. The first origin (0) 224 // should be the most recent so it should not be deleted and we should not 225 // get an upgradeneeded event here. 226 request = indexedDB.openForPrincipal(getPrincipal(spec), name, options); 227 request.onerror = errorHandler; 228 request.onupgradeneeded = unexpectedSuccessHandler; 229 request.onsuccess = grabEventAndContinueHandler; 230 event = yield undefined; 231 232 is(event.type, "success", "Got correct event type"); 233 234 db = event.target.result; 235 is(db.version, 1, "Correct version 1"); 236 db.close(); 237 db = null; 238 239 setTemporaryStorageLimit(tempStorageLimitKB * 2); 240 241 resetAllDatabases(continueToNextStepSync); 242 yield undefined; 243 244 options.version = finalVersion; 245 246 let newDatabaseCount = 0; 247 for (let i = 0; i < databaseCount; i++) { 248 let spec = getSpec(i); 249 info("Opening database for " + spec + " with version " + options.version); 250 251 let request = indexedDB.openForPrincipal( 252 getPrincipal(spec), 253 name, 254 options 255 ); 256 request.onerror = errorHandler; 257 request.onupgradeneeded = function (event) { 258 if (!event.oldVersion) { 259 newDatabaseCount++; 260 } 261 }; 262 request.onsuccess = grabEventAndContinueHandler; 263 let event = yield undefined; 264 265 is(event.type, "success", "Got correct event type"); 266 267 let db = request.result; 268 is(db.version, finalVersion, "Correct version " + finalVersion); 269 db.close(); 270 } 271 272 info("Needed to recreate " + newDatabaseCount + " databases"); 273 ok(newDatabaseCount, "Created some new databases"); 274 ok(newDatabaseCount < databaseCount, "Didn't recreate all databases"); 275 } 276 277 finishTest(); 278 yield undefined; 279 }