Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
/**
* Any copyright is dedicated to the Public Domain.
*/
/* exported testSteps */
// Test that corrupted/missing external files produce a NotReadableError as
// specified in
// step 3.
const name = "test_external_file_corruption.js";
const objectStoreName = "store";
const dataSize = 100000;
const dataThreshold = 4096;
async function storeLargeData() {
info("Setting data threshold to force external file storage");
setDataThreshold(dataThreshold);
info("Opening database and storing large data");
{
const request = indexedDB.open(name);
const event = await expectingUpgrade(request);
event.target.result.createObjectStore(objectStoreName);
const db = (await expectingSuccess(request)).target.result;
const view = getView(dataSize);
for (let i = 0; i < dataSize; i++) {
view[i] = i % 251;
}
const tx = db.transaction(objectStoreName, "readwrite");
tx.objectStore(objectStoreName).put(view, "key");
await new Promise(resolve => {
tx.oncomplete = resolve;
});
db.close();
}
info("Verifying external file was created");
const filesDir = getChromeFilesDir();
let externalFile = null;
let entries = filesDir.directoryEntries;
while (entries.hasMoreElements()) {
let entry = entries.nextFile;
if (entry.isFile()) {
externalFile = entry;
break;
}
}
ok(externalFile, "External file exists");
ok(externalFile.fileSize > 0, "External file is not empty");
info("Resetting database to release connection");
await new Promise(resolve => {
resetAllDatabases(resolve);
});
return externalFile;
}
async function corruptFile(externalFile) {
const path = externalFile.path;
info("Corrupting external file: " + path);
const sizeBefore = (await IOUtils.stat(path)).size;
info("Size before corruption: " + sizeBefore);
const data = new TextEncoder().encode("corrupt");
const bytesWritten = await IOUtils.write(path, data);
info("Bytes written: " + bytesWritten);
const sizeAfter = (await IOUtils.stat(path)).size;
info("Size after corruption: " + sizeAfter);
ok(sizeAfter < 100, "External file was truncated");
}
async function readBack() {
info("Reopening database and reading corrupted data");
{
const request = indexedDB.open(name);
const db = (await expectingSuccess(request)).target.result;
const tx = db.transaction(objectStoreName, "readonly");
const getRequest = tx.objectStore(objectStoreName).get("key");
await new Promise(resolve => {
getRequest.onsuccess = () => {
ok(false, "Read should have failed due to corruption");
resolve();
};
getRequest.onerror = event => {
event.preventDefault();
is(
event.target.error.name,
"NotReadableError",
"Should get NotReadableError for corrupted/deleted external file"
);
resolve();
};
});
db.close();
}
}
async function cleanup() {
info("Cleaning up");
resetDataThreshold();
{
const request = indexedDB.deleteDatabase(name);
await new Promise(resolve => {
request.onsuccess = resolve;
request.onerror = resolve;
});
}
}
async function testFileCorrupted() {
let externalFile = await storeLargeData();
await corruptFile(externalFile);
await readBack();
await cleanup();
}
async function testFileDeleted() {
let externalFile = await storeLargeData();
info("Deleting external file: " + externalFile.path);
await IOUtils.remove(externalFile.path, { ignoreAbsent: false });
ok(!externalFile.exists(), "External file was deleted");
await readBack();
await cleanup();
}
async function testSteps() {
add_task(testFileCorrupted);
add_task(testFileDeleted);
}