test_largeItems.js (2466B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 6 /** 7 * Test repeatedly setting values that are just under the LocalStorage quota 8 * limit without yielding control flow in order to verify that the write 9 * optimizer is present / works. If there was no write optimizer present, the 10 * IPC message size limit would be exceeded, resulting in a crash. 11 */ 12 13 add_task(async function testSteps() { 14 const globalLimitKB = 5 * 1024; 15 16 // 18 and more iterations would produce an IPC message with size greater than 17 // 256 MB if write optimizer was not present. This number was determined 18 // experimentally by running the test with disabled write optimizer. 19 const numberOfIterations = 18; 20 21 const randomStringBlockSize = 65536; 22 23 // We need to use a random string because LS internally tries to compress 24 // values. 25 function getRandomString(size) { 26 let crypto = this.window ? this.window.crypto : this.crypto; 27 let decoder = new TextDecoder("ISO-8859-2"); 28 29 function getRandomStringBlock(array) { 30 crypto.getRandomValues(array); 31 return decoder.decode(array); 32 } 33 34 let string = ""; 35 36 let quotient = size / randomStringBlockSize; 37 if (quotient) { 38 let array = new Uint8Array(randomStringBlockSize); 39 for (let i = 1; i <= quotient; i++) { 40 string += getRandomStringBlock(array); 41 } 42 } 43 44 let remainder = size % randomStringBlockSize; 45 if (remainder) { 46 let array = new Uint8Array(remainder); 47 string += getRandomStringBlock(array); 48 } 49 50 return string; 51 } 52 53 const data = {}; 54 data.key = "foo"; 55 data.value = getRandomString( 56 globalLimitKB * 1024 - 57 data.key.length - 58 numberOfIterations.toString().length 59 ); 60 61 info("Setting pref"); 62 63 // By disabling snapshot reusing, we guarantee that the snapshot will be 64 // checkpointed once control returns to the event loop. 65 if (this.window) { 66 await SpecialPowers.pushPrefEnv({ 67 set: [["dom.storage.snapshot_reusing", false]], 68 }); 69 } else { 70 Services.prefs.setBoolPref("dom.storage.snapshot_reusing", false); 71 } 72 73 info("Getting storage"); 74 75 let storage = getLocalStorage(); 76 77 info("Adding/updating item"); 78 79 for (var i = 0; i < numberOfIterations; i++) { 80 storage.setItem(data.key, data.value + i); 81 } 82 83 info("Returning to event loop"); 84 85 await returnToEventLoop(); 86 87 ok(!storage.hasSnapshot, "Snapshot successfully finished"); 88 });