Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

/**
* Tests tombstones in address/creditcard records.
*/
"use strict";
let FormAutofillStorage;
add_setup(async () => {
({ FormAutofillStorage } = ChromeUtils.importESModule(
"resource://autofill/FormAutofillStorage.sys.mjs"
));
});
const TEST_STORE_FILE_NAME = "test-tombstones.json";
const TEST_ADDRESS_1 = {
"given-name": "Timothy",
"additional-name": "John",
"family-name": "Berners-Lee",
organization: "World Wide Web Consortium",
"street-address": "32 Vassar Street\nMIT Room 32-G524",
"address-level2": "Cambridge",
"address-level1": "MA",
"postal-code": "02139",
country: "US",
tel: "+1 617 253 5702",
email: "timbl@w3.org",
};
const TEST_CC_1 = {
"cc-name": "John Doe",
"cc-number": "4111111111111111",
"cc-exp-month": 4,
"cc-exp-year": 2017,
};
let do_check_tombstone_record = profile => {
Assert.ok(profile.deleted);
Assert.deepEqual(
Object.keys(profile).sort(),
["guid", "timeLastModified", "deleted"].sort()
);
};
// Like add_task, but actually adds 2 - one for addresses and one for cards.
function add_storage_task(test_function) {
add_task(async function () {
let path = getTempFile(TEST_STORE_FILE_NAME).path;
let profileStorage = new FormAutofillStorage(path);
let testCC1 = Object.assign({}, TEST_CC_1);
await profileStorage.initialize();
for (let [storage, record] of [
[profileStorage.addresses, TEST_ADDRESS_1],
[profileStorage.creditCards, testCC1],
]) {
await test_function(storage, record);
}
});
}
add_storage_task(async function test_simple_tombstone(storage, record) {
info("check simple tombstone semantics");
let guid = await storage.add(record);
Assert.equal((await storage.getAll()).length, 1);
storage.remove(guid);
// should be unable to get it normally.
Assert.equal(await storage.get(guid), null);
// and getAll should also not return it.
Assert.equal((await storage.getAll()).length, 0);
// but getAll allows us to access deleted items - but we didn't create
// a tombstone here, so even that will not get it.
let all = await storage.getAll({ includeDeleted: true });
Assert.equal(all.length, 0);
});
add_storage_task(async function test_simple_synctombstone(storage, record) {
info("check simple tombstone semantics for synced records");
let guid = await storage.add(record);
Assert.equal((await storage.getAll()).length, 1);
storage.pullSyncChanges(); // force sync metadata, which triggers tombstone behaviour.
storage.remove(guid);
// should be unable to get it normally.
Assert.equal(await storage.get(guid), null);
// and getAll should also not return it.
Assert.equal((await storage.getAll()).length, 0);
// but getAll allows us to access deleted items.
let all = await storage.getAll({ includeDeleted: true });
Assert.equal(all.length, 1);
do_check_tombstone_record(all[0]);
// a tombstone got from API should look exactly the same as it got from the
// disk (besides "_sync").
let tombstoneInDisk = Object.assign(
{},
storage._store.data[storage._collectionName][0]
);
delete tombstoneInDisk._sync;
do_check_tombstone_record(tombstoneInDisk);
});
add_storage_task(async function test_add_tombstone(storage, _record) {
info("Should be able to add a new tombstone");
let guid = await storage.add({ guid: "test-guid-1", deleted: true });
// should be unable to get it normally.
Assert.equal(await storage.get(guid), null);
// and getAll should also not return it.
Assert.equal((await storage.getAll()).length, 0);
// but getAll allows us to access deleted items.
let all = await storage.getAll({ rawData: true, includeDeleted: true });
Assert.equal(all.length, 1);
do_check_tombstone_record(all[0]);
// a tombstone got from API should look exactly the same as it got from the
// disk (besides "_sync").
let tombstoneInDisk = Object.assign(
{},
storage._store.data[storage._collectionName][0]
);
delete tombstoneInDisk._sync;
do_check_tombstone_record(tombstoneInDisk);
});
add_storage_task(
async function test_add_tombstone_without_guid(storage, _record) {
info(
"Should not be able to add a new tombstone without specifying the guid"
);
await Assert.rejects(storage.add({ deleted: true }), /Record missing GUID/);
Assert.equal((await storage.getAll({ includeDeleted: true })).length, 0);
}
);
add_storage_task(
async function test_add_tombstone_existing_guid(storage, record) {
info(
"Should not be able to add a new tombstone when a record with that ID exists"
);
let guid = await storage.add(record);
await Assert.rejects(
storage.add({ guid, deleted: true }),
/a record with this GUID already exists/
);
// same if the existing item is already a tombstone.
await storage.add({ guid: "test-guid-1", deleted: true });
await Assert.rejects(
storage.add({ guid: "test-guid-1", deleted: true }),
/a record with this GUID already exists/
);
}
);
add_storage_task(async function test_update_tombstone(storage, _record) {
info("Updating a tombstone should fail");
let guid = await storage.add({ guid: "test-guid-1", deleted: true });
await Assert.rejects(storage.update(guid, {}), /No matching record./);
});
add_storage_task(
async function test_remove_existing_tombstone(storage, _record) {
info("Removing a record that's already a tombstone should be a no-op");
let guid = await storage.add({
guid: "test-guid-1",
deleted: true,
timeLastModified: 1234,
});
storage.remove(guid);
let all = await storage.getAll({ rawData: true, includeDeleted: true });
Assert.equal(all.length, 1);
do_check_tombstone_record(all[0]);
equal(all[0].timeLastModified, 1234); // should not be updated to now().
}
);