88 lines
2.4 KiB
JavaScript
88 lines
2.4 KiB
JavaScript
/**
|
|
* 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");
|
|
});
|