diff options
Diffstat (limited to 'dom/localstorage/test/unit/test_largeItems.js')
-rw-r--r-- | dom/localstorage/test/unit/test_largeItems.js | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/dom/localstorage/test/unit/test_largeItems.js b/dom/localstorage/test/unit/test_largeItems.js new file mode 100644 index 0000000000..3ea6bd21b4 --- /dev/null +++ b/dom/localstorage/test/unit/test_largeItems.js @@ -0,0 +1,88 @@ +/** + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +/** + * Test repeatedly setting values that are just under the LocalStorage quota + * limit without yielding control flow in order to verify that the write + * optimizer is present / works. If there was no write optimizer present, the + * IPC message size limit would be exceeded, resulting in a crash. + */ + +add_task(async function testSteps() { + const globalLimitKB = 5 * 1024; + + // 18 and more iterations would produce an IPC message with size greater than + // 256 MB if write optimizer was not present. This number was determined + // experimentally by running the test with disabled write optimizer. + const numberOfIterations = 18; + + const randomStringBlockSize = 65536; + + // We need to use a random string because LS internally tries to compress + // values. + function getRandomString(size) { + let crypto = this.window ? this.window.crypto : this.crypto; + let decoder = new TextDecoder("ISO-8859-2"); + + function getRandomStringBlock(array) { + crypto.getRandomValues(array); + return decoder.decode(array); + } + + let string = ""; + + let quotient = size / randomStringBlockSize; + if (quotient) { + let array = new Uint8Array(randomStringBlockSize); + for (let i = 1; i <= quotient; i++) { + string += getRandomStringBlock(array); + } + } + + let remainder = size % randomStringBlockSize; + if (remainder) { + let array = new Uint8Array(remainder); + string += getRandomStringBlock(array); + } + + return string; + } + + const data = {}; + data.key = "foo"; + data.value = getRandomString( + globalLimitKB * 1024 - + data.key.length - + numberOfIterations.toString().length + ); + + info("Setting pref"); + + // By disabling snapshot reusing, we guarantee that the snapshot will be + // checkpointed once control returns to the event loop. + if (this.window) { + await SpecialPowers.pushPrefEnv({ + set: [["dom.storage.snapshot_reusing", false]], + }); + } else { + Services.prefs.setBoolPref("dom.storage.snapshot_reusing", false); + } + + info("Getting storage"); + + let storage = getLocalStorage(); + + info("Adding/updating item"); + + for (var i = 0; i < numberOfIterations; i++) { + storage.setItem(data.key, data.value + i); + } + + info("Returning to event loop"); + + await returnToEventLoop(); + + ok(!storage.hasSnapshot, "Snapshot successfully finished"); +}); |