summaryrefslogtreecommitdiffstats
path: root/dom/localstorage/test/unit/test_largeItems.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/localstorage/test/unit/test_largeItems.js')
-rw-r--r--dom/localstorage/test/unit/test_largeItems.js88
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");
+});