diff options
Diffstat (limited to '')
-rw-r--r-- | browser/extensions/formautofill/test/unit/test_migrateRecords.js | 382 |
1 files changed, 382 insertions, 0 deletions
diff --git a/browser/extensions/formautofill/test/unit/test_migrateRecords.js b/browser/extensions/formautofill/test/unit/test_migrateRecords.js new file mode 100644 index 0000000000..24b13b4322 --- /dev/null +++ b/browser/extensions/formautofill/test/unit/test_migrateRecords.js @@ -0,0 +1,382 @@ +/** + * Tests the migration algorithm in profileStorage. + */ + +"use strict"; + +let FormAutofillStorage; +add_setup(async () => { + ({ FormAutofillStorage } = ChromeUtils.importESModule( + "resource://autofill/FormAutofillStorage.sys.mjs" + )); +}); + +const TEST_STORE_FILE_NAME = "test-profile.json"; + +const { ADDRESS_SCHEMA_VERSION } = ChromeUtils.importESModule( + "resource://autofill/FormAutofillStorageBase.sys.mjs" +); +const { CREDIT_CARD_SCHEMA_VERSION } = ChromeUtils.importESModule( + "resource://autofill/FormAutofillStorageBase.sys.mjs" +); + +const ADDRESS_TESTCASES = [ + { + description: + "The record version is equal to the current version. The migration shouldn't be invoked.", + record: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "John", // The cached name field doesn't align "given-name" but it + // won't be recomputed because the migration isn't invoked. + }, + expectedResult: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "John", + }, + }, + { + description: + "The record version is greater than the current version. The migration shouldn't be invoked.", + record: { + guid: "test-guid", + version: 99, + "given-name": "Timothy", + name: "John", + }, + expectedResult: { + guid: "test-guid", + version: 99, + "given-name": "Timothy", + name: "John", + }, + }, + { + description: + "The record version is less than the current version. The migration should be invoked.", + record: { + guid: "test-guid", + version: 0, + "given-name": "Timothy", + name: "John", + }, + expectedResult: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "Timothy", + }, + }, + { + description: + "The record version is omitted. The migration should be invoked.", + record: { + guid: "test-guid", + "given-name": "Timothy", + name: "John", + "unknown-1": "an unknown field from another client", + }, + expectedResult: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "Timothy", + "unknown-1": "an unknown field from another client", + }, + }, + { + description: + "The record version is an invalid value. The migration should be invoked.", + record: { + guid: "test-guid", + version: "ABCDE", + "given-name": "Timothy", + name: "John", + "unknown-1": "an unknown field from another client", + }, + expectedResult: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "Timothy", + "unknown-1": "an unknown field from another client", + }, + }, + { + description: + "The omitted computed fields should be always recomputed even the record version is up-to-date.", + record: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + }, + expectedResult: { + guid: "test-guid", + version: ADDRESS_SCHEMA_VERSION, + "given-name": "Timothy", + name: "Timothy", + }, + }, + { + description: "The migration shouldn't be invoked on tombstones.", + record: { + guid: "test-guid", + timeLastModified: 12345, + deleted: true, + }, + expectedResult: { + guid: "test-guid", + timeLastModified: 12345, + deleted: true, + + // Make sure no new fields are appended. + version: undefined, + name: undefined, + }, + }, +]; + +const CREDIT_CARD_TESTCASES = [ + { + description: + "The record version is equal to the current version. The migration shouldn't be invoked.", + record: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "John", // The cached "cc-given-name" field doesn't align + // "cc-name" but it won't be recomputed because + // the migration isn't invoked. + }, + expectedResult: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "John", + }, + }, + { + description: + "The record version is greater than the current version. The migration shouldn't be invoked.", + record: { + guid: "test-guid", + version: 99, + "cc-name": "Timothy", + "cc-given-name": "John", + }, + expectedResult: { + guid: "test-guid", + version: 99, + "cc-name": "Timothy", + "cc-given-name": "John", + }, + }, + { + description: + "The record version is less than the current version. The migration should be invoked.", + record: { + guid: "test-guid", + version: 0, + "cc-name": "Timothy", + "cc-given-name": "John", + }, + expectedResult: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "Timothy", + }, + }, + { + description: + "The record version is omitted. The migration should be invoked.", + record: { + guid: "test-guid", + "cc-name": "Timothy", + "cc-given-name": "John", + "unknown-1": "an unknown field from another client", + }, + expectedResult: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "Timothy", + "unknown-1": "an unknown field from another client", + }, + }, + { + description: + "The record version is an invalid value. The migration should be invoked.", + record: { + guid: "test-guid", + version: "ABCDE", + "cc-name": "Timothy", + "cc-given-name": "John", + "unknown-1": "an unknown field from another client", + }, + expectedResult: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "Timothy", + "unknown-1": "an unknown field from another client", + }, + }, + { + description: + "The omitted computed fields should be always recomputed even the record version is up-to-date.", + record: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + }, + expectedResult: { + guid: "test-guid", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Timothy", + "cc-given-name": "Timothy", + }, + }, + { + description: "The migration shouldn't be invoked on tombstones.", + record: { + guid: "test-guid", + timeLastModified: 12345, + deleted: true, + }, + expectedResult: { + guid: "test-guid", + timeLastModified: 12345, + deleted: true, + + // Make sure no new fields are appended. + version: undefined, + "cc-given-name": undefined, + }, + }, +]; + +let do_check_record_matches = (expectedRecord, record) => { + for (let key in expectedRecord) { + Assert.equal(expectedRecord[key], record[key]); + } +}; + +add_task(async function test_migrateAddressRecords() { + let path = getTempFile(TEST_STORE_FILE_NAME).path; + + let profileStorage = new FormAutofillStorage(path); + await profileStorage.initialize(); + + for (let testcase of ADDRESS_TESTCASES) { + info(testcase.description); + profileStorage._store.data.addresses = [testcase.record]; + await profileStorage.addresses._migrateRecord(testcase.record, 0); + do_check_record_matches( + testcase.expectedResult, + profileStorage.addresses._data[0] + ); + } +}); + +add_task(async function test_migrateCreditCardRecords() { + let path = getTempFile(TEST_STORE_FILE_NAME).path; + + let profileStorage = new FormAutofillStorage(path); + await profileStorage.initialize(); + + for (let testcase of CREDIT_CARD_TESTCASES) { + info(testcase.description); + profileStorage._store.data.creditCards = [testcase.record]; + await profileStorage.creditCards._migrateRecord(testcase.record, 0); + do_check_record_matches( + testcase.expectedResult, + profileStorage.creditCards._data[0] + ); + } +}); + +add_task(async function test_migrateEncryptedCreditCardNumber() { + let path = getTempFile(TEST_STORE_FILE_NAME).path; + + let profileStorage = new FormAutofillStorage(path); + await profileStorage.initialize(); + + info("v1 and v2 schema cards should be abandoned."); + + let v1record = { + guid: "test-guid1", + version: 1, + "cc-name": "Timothy", + "cc-number-encrypted": "aaaa", + }; + + let v2record = { + guid: "test-guid2", + version: 2, + "cc-name": "Bob", + "cc-number-encrypted": "bbbb", + }; + + profileStorage._store.data.creditCards = [v1record, v2record]; + await profileStorage.creditCards._migrateRecord(v1record, 0); + await profileStorage.creditCards._migrateRecord(v2record, 1); + v1record = profileStorage.creditCards._data[0]; + v2record = profileStorage.creditCards._data[1]; + + Assert.ok(v1record.deleted); + Assert.ok(v2record.deleted); +}); + +add_task(async function test_migrateDeprecatedCreditCardV4() { + let path = getTempFile(TEST_STORE_FILE_NAME).path; + + let profileStorage = new FormAutofillStorage(path); + await profileStorage.initialize(); + + let records = [ + { + guid: "test-guid1", + version: CREDIT_CARD_SCHEMA_VERSION, + "cc-name": "Alice", + _sync: { + changeCounter: 0, + lastSyncedFields: {}, + }, + }, + { + guid: "test-guid2", + version: 4, + "cc-name": "Timothy", + _sync: { + changeCounter: 0, + lastSyncedFields: {}, + }, + }, + { + guid: "test-guid3", + version: 4, + "cc-name": "Bob", + }, + ]; + + profileStorage._store.data.creditCards = records; + for (let idx = 0; idx < records.length; idx++) { + await profileStorage.creditCards._migrateRecord(records[idx], idx); + } + + profileStorage.creditCards.pullSyncChanges(); + + // Record that has already synced before, do not sync again + equal(getSyncChangeCounter(profileStorage.creditCards, records[0].guid), 0); + + // alaways force sync v4 record + equal(records[1].version, CREDIT_CARD_SCHEMA_VERSION); + equal(getSyncChangeCounter(profileStorage.creditCards, records[1].guid), 1); + + equal(records[2].version, CREDIT_CARD_SCHEMA_VERSION); + equal(getSyncChangeCounter(profileStorage.creditCards, records[2].guid), 1); +}); |