// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// The purpose of this test is to asserts that errors are returned appropriately
// when commit() fails. See crbug.com/1203335. This test is a near-duplicate of
// quota_test.js, with the difference being that this test commit()s
// transactions.
function test() {
if (navigator.storage) {
window.jsTestIsAsync = true;
navigator.storage.estimate()
.then(initUsageCallback)
.catch(unexpectedErrorCallback);
} else
debug('This test requires navigator.storage.');
}
function initUsageCallback(result) {
origReturnedUsage = returnedUsage = result.usage;
origReturnedQuota = returnedQuota = result.quota;
debug('original quota is ' + displaySize(origReturnedQuota));
debug('original usage is ' + displaySize(origReturnedUsage));
indexedDBTest(prepareDatabase, initQuotaEnforcing);
}
function prepareDatabase() {
db = event.target.result;
objectStore = db.createObjectStore('test123');
}
function displaySize(bytes) {
var k = bytes / 1024;
var m = k / 1024;
return bytes + ' (' + k + 'k) (' + m + 'm)';
}
function initQuotaEnforcing() {
var availableSpace = origReturnedQuota - origReturnedUsage;
var kMaxMbPerWrite = 5;
var kMinWrites = 5;
var len = Math.min(
kMaxMbPerWrite * 1024 * 1024, Math.floor(availableSpace / kMinWrites));
maxExpectedWrites = Math.floor(availableSpace / len) + 1;
debug('Chunk size: ' + displaySize(len));
debug(
'Expecting at most ' + maxExpectedWrites + ' writes, but we could ' +
'have more if snappy is used or LevelDB is about to compact.');
// The data needs to be randomized to avoid compression.
data = '';
for (let i = 0; i < 1 + len / 8; i++) {
data += Math.random().toString(36).slice(2, 10);
}
dataLength = data.length;
dataAdded = 0;
successfulWrites = 0;
startNewTransaction();
}
function startNewTransaction() {
if (dataAdded > origReturnedQuota) {
fail('dataAdded > quota ' + dataAdded + ' > ' + origReturnedQuota);
return;
}
debug('');
debug('Starting new transaction.');
var trans = db.transaction(['test123'], 'readwrite');
trans.onabort = onAbort;
trans.oncomplete = getQuotaAndUsage;
var store = trans.objectStore('test123');
request = store.put({x: data}, dataAdded);
request.onerror = logError;
// Unlike quota_test.js, commit() the transaction.
trans.commit();
}
function getQuotaAndUsage() {
successfulWrites++;
if (successfulWrites > maxExpectedWrites) {
debug(
'Weird: too many writes. There were ' + successfulWrites +
' but we only expected ' + maxExpectedWrites);
}
navigator.webkitTemporaryStorage.queryUsageAndQuota(
usageCallback, unexpectedErrorCallback);
}
function usageCallback(usage, quota) {
debug('Transaction finished.');
dataAdded += dataLength;
debug('We\'ve added ' + displaySize(dataAdded));
returnedUsage = usage;
returnedQuota = quota;
debug('Allotted quota is ' + displaySize(returnedQuota));
debug('LevelDB usage is ' + displaySize(returnedUsage));
startNewTransaction();
}
function onAbort() {
shouldBeEqualToString('event.target.error.name', 'QuotaExceededError');
done('Transaction aborted. Data added: ' + displaySize(dataAdded));
debug('There were ' + successfulWrites + ' successful writes');
}
function logError() {
debug(
'Error function called: (' + event.target.error.name + ') ' +
event.target.error.message);
event.preventDefault();
}