tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_migrateRecords.js (13034B)


      1 /**
      2 * Tests the migration algorithm in profileStorage.
      3 */
      4 
      5 "use strict";
      6 
      7 let FormAutofillStorage;
      8 add_setup(async () => {
      9  ({ FormAutofillStorage } = ChromeUtils.importESModule(
     10    "resource://autofill/FormAutofillStorage.sys.mjs"
     11  ));
     12 });
     13 
     14 const TEST_STORE_FILE_NAME = "test-profile.json";
     15 
     16 const { ADDRESS_SCHEMA_VERSION } = ChromeUtils.importESModule(
     17  "resource://autofill/FormAutofillStorageBase.sys.mjs"
     18 );
     19 const { CREDIT_CARD_SCHEMA_VERSION } = ChromeUtils.importESModule(
     20  "resource://autofill/FormAutofillStorageBase.sys.mjs"
     21 );
     22 
     23 const ADDRESS_TESTCASES = [
     24  {
     25    description:
     26      "The record version is equal to the current version. The migration shouldn't be invoked.",
     27    record: {
     28      guid: "test-guid",
     29      version: ADDRESS_SCHEMA_VERSION,
     30      // The cached address-line1 field doesn't align "street-address" but it
     31      // won't be recomputed because the migration isn't invoked.
     32      "address-line1": "Some Address",
     33      "street-address": "32 Vassar Street",
     34    },
     35    expectedResult: {
     36      guid: "test-guid",
     37      version: ADDRESS_SCHEMA_VERSION,
     38      "address-line1": "Some Address",
     39      "street-address": "32 Vassar Street",
     40    },
     41  },
     42  {
     43    description:
     44      "The record version is greater than the current version. The migration shouldn't be invoked.",
     45    record: {
     46      guid: "test-guid",
     47      version: 99,
     48      "address-line1": "Some Address",
     49      "street-address": "32 Vassar Street",
     50    },
     51    expectedResult: {
     52      guid: "test-guid",
     53      version: 99,
     54      "address-line1": "Some Address",
     55      "street-address": "32 Vassar Street",
     56    },
     57  },
     58  {
     59    description:
     60      "The record version is less than the current version. The migration should be invoked.",
     61    record: {
     62      guid: "test-guid",
     63      version: 0,
     64      "address-line1": "Some Address",
     65      "street-address": "32 Vassar Street",
     66    },
     67    expectedResult: {
     68      guid: "test-guid",
     69      version: ADDRESS_SCHEMA_VERSION,
     70      "address-line1": "32 Vassar Street",
     71      "street-address": "32 Vassar Street",
     72    },
     73  },
     74  {
     75    description:
     76      "The record version is omitted. The migration should be invoked.",
     77    record: {
     78      guid: "test-guid",
     79      "address-line1": "Some Address",
     80      "street-address": "32 Vassar Street",
     81      "unknown-1": "an unknown field from another client",
     82    },
     83    expectedResult: {
     84      guid: "test-guid",
     85      version: ADDRESS_SCHEMA_VERSION,
     86      "address-line1": "32 Vassar Street",
     87      "street-address": "32 Vassar Street",
     88      "unknown-1": "an unknown field from another client",
     89    },
     90  },
     91  {
     92    description:
     93      "The record version is an invalid value. The migration should be invoked.",
     94    record: {
     95      guid: "test-guid",
     96      version: "ABCDE",
     97      "address-line1": "Some Address",
     98      "street-address": "32 Vassar Street",
     99      "unknown-1": "an unknown field from another client",
    100    },
    101    expectedResult: {
    102      guid: "test-guid",
    103      version: ADDRESS_SCHEMA_VERSION,
    104      "address-line1": "32 Vassar Street",
    105      "street-address": "32 Vassar Street",
    106      "unknown-1": "an unknown field from another client",
    107    },
    108  },
    109  {
    110    description:
    111      "The omitted computed fields should be always recomputed even the record version is up-to-date.",
    112    record: {
    113      guid: "test-guid",
    114      version: ADDRESS_SCHEMA_VERSION,
    115      "street-address": "32 Vassar Street",
    116    },
    117    expectedResult: {
    118      guid: "test-guid",
    119      version: ADDRESS_SCHEMA_VERSION,
    120      "address-line1": "32 Vassar Street",
    121      "street-address": "32 Vassar Street",
    122    },
    123  },
    124  {
    125    description: "The migration shouldn't be invoked on tombstones.",
    126    record: {
    127      guid: "test-guid",
    128      timeLastModified: 12345,
    129      deleted: true,
    130    },
    131    expectedResult: {
    132      guid: "test-guid",
    133      timeLastModified: 12345,
    134      deleted: true,
    135 
    136      // Make sure no new fields are appended.
    137      version: undefined,
    138      name: undefined,
    139    },
    140  },
    141 
    142  // Bug 1836438 - Migrate "*-name" to "name"
    143  {
    144    description:
    145      "Migrate address - `given-name`, `additional-name`, and `family-name` should be migrated to `name`",
    146    record: {
    147      guid: "test-guid",
    148      version: ADDRESS_SCHEMA_VERSION,
    149      "given-name": "Timothy",
    150      "additional-name": "John",
    151      "family-name": "Berners-Lee",
    152    },
    153    expectedResult: {
    154      guid: "test-guid",
    155      version: ADDRESS_SCHEMA_VERSION,
    156      name: "Timothy John Berners-Lee",
    157    },
    158  },
    159  {
    160    description: "Migrate address - `given-name` should be migrated to `name`",
    161    record: {
    162      guid: "test-guid",
    163      version: ADDRESS_SCHEMA_VERSION,
    164      "given-name": "Timothy",
    165    },
    166    expectedResult: {
    167      guid: "test-guid",
    168      version: ADDRESS_SCHEMA_VERSION,
    169      name: "Timothy",
    170    },
    171  },
    172  {
    173    description:
    174      "Migrate address - `additional-name` should be migrated to `name`",
    175    record: {
    176      guid: "test-guid",
    177      version: ADDRESS_SCHEMA_VERSION,
    178      "additional-name": "John",
    179    },
    180    expectedResult: {
    181      guid: "test-guid",
    182      version: ADDRESS_SCHEMA_VERSION,
    183      name: "John",
    184    },
    185  },
    186  {
    187    description: "Migrate address - `family-name` should be migrated to `name`",
    188    record: {
    189      guid: "test-guid",
    190      version: ADDRESS_SCHEMA_VERSION,
    191      "family-name": "Berners-Lee",
    192    },
    193    expectedResult: {
    194      guid: "test-guid",
    195      version: ADDRESS_SCHEMA_VERSION,
    196      name: "Berners-Lee",
    197    },
    198  },
    199  {
    200    description:
    201      "Migrate address - `name` should still be empty when there is no *-name fields in the record",
    202    record: {
    203      guid: "test-guid",
    204      version: ADDRESS_SCHEMA_VERSION,
    205    },
    206    expectedResult: {
    207      guid: "test-guid",
    208      version: ADDRESS_SCHEMA_VERSION,
    209    },
    210  },
    211  {
    212    description:
    213      "Migrate address - do not run migration as long as the name field exists",
    214    record: {
    215      guid: "test-guid",
    216      version: ADDRESS_SCHEMA_VERSION,
    217      // The cached field doesn't align "name" but it
    218      // won't be recomputed because the migration isn't invoked.
    219      "given-name": "Timothy",
    220      "additional-name": "John",
    221      "family-name": "Berners-Lee",
    222      name: "Jane",
    223    },
    224    expectedResult: {
    225      guid: "test-guid",
    226      version: ADDRESS_SCHEMA_VERSION,
    227      "given-name": "Timothy",
    228      "additional-name": "John",
    229      "family-name": "Berners-Lee",
    230      name: "Jane",
    231    },
    232  },
    233 ];
    234 
    235 const CREDIT_CARD_TESTCASES = [
    236  {
    237    description:
    238      "The record version is equal to the current version. The migration shouldn't be invoked.",
    239    record: {
    240      guid: "test-guid",
    241      version: CREDIT_CARD_SCHEMA_VERSION,
    242      "cc-name": "Timothy",
    243      "cc-given-name": "John", // The cached "cc-given-name" field doesn't align
    244      // "cc-name" but it won't be recomputed because
    245      // the migration isn't invoked.
    246    },
    247    expectedResult: {
    248      guid: "test-guid",
    249      version: CREDIT_CARD_SCHEMA_VERSION,
    250      "cc-name": "Timothy",
    251      "cc-given-name": "John",
    252    },
    253  },
    254  {
    255    description:
    256      "The record version is greater than the current version. The migration shouldn't be invoked.",
    257    record: {
    258      guid: "test-guid",
    259      version: 99,
    260      "cc-name": "Timothy",
    261      "cc-given-name": "John",
    262    },
    263    expectedResult: {
    264      guid: "test-guid",
    265      version: 99,
    266      "cc-name": "Timothy",
    267      "cc-given-name": "John",
    268    },
    269  },
    270  {
    271    description:
    272      "The record version is less than the current version. The migration should be invoked.",
    273    record: {
    274      guid: "test-guid",
    275      version: 0,
    276      "cc-name": "Timothy",
    277      "cc-given-name": "John",
    278    },
    279    expectedResult: {
    280      guid: "test-guid",
    281      version: CREDIT_CARD_SCHEMA_VERSION,
    282      "cc-name": "Timothy",
    283      "cc-given-name": "Timothy",
    284    },
    285  },
    286  {
    287    description:
    288      "The record version is omitted. The migration should be invoked.",
    289    record: {
    290      guid: "test-guid",
    291      "cc-name": "Timothy",
    292      "cc-given-name": "John",
    293      "unknown-1": "an unknown field from another client",
    294    },
    295    expectedResult: {
    296      guid: "test-guid",
    297      version: CREDIT_CARD_SCHEMA_VERSION,
    298      "cc-name": "Timothy",
    299      "cc-given-name": "Timothy",
    300      "unknown-1": "an unknown field from another client",
    301    },
    302  },
    303  {
    304    description:
    305      "The record version is an invalid value. The migration should be invoked.",
    306    record: {
    307      guid: "test-guid",
    308      version: "ABCDE",
    309      "cc-name": "Timothy",
    310      "cc-given-name": "John",
    311      "unknown-1": "an unknown field from another client",
    312    },
    313    expectedResult: {
    314      guid: "test-guid",
    315      version: CREDIT_CARD_SCHEMA_VERSION,
    316      "cc-name": "Timothy",
    317      "cc-given-name": "Timothy",
    318      "unknown-1": "an unknown field from another client",
    319    },
    320  },
    321  {
    322    description:
    323      "The omitted computed fields should be always recomputed even the record version is up-to-date.",
    324    record: {
    325      guid: "test-guid",
    326      version: CREDIT_CARD_SCHEMA_VERSION,
    327      "cc-name": "Timothy",
    328    },
    329    expectedResult: {
    330      guid: "test-guid",
    331      version: CREDIT_CARD_SCHEMA_VERSION,
    332      "cc-name": "Timothy",
    333      "cc-given-name": "Timothy",
    334    },
    335  },
    336  {
    337    description: "The migration shouldn't be invoked on tombstones.",
    338    record: {
    339      guid: "test-guid",
    340      timeLastModified: 12345,
    341      deleted: true,
    342    },
    343    expectedResult: {
    344      guid: "test-guid",
    345      timeLastModified: 12345,
    346      deleted: true,
    347 
    348      // Make sure no new fields are appended.
    349      version: undefined,
    350      "cc-given-name": undefined,
    351    },
    352  },
    353 ];
    354 
    355 let do_check_record_matches = (expectedRecord, record) => {
    356  for (let key in expectedRecord) {
    357    Assert.equal(expectedRecord[key], record[key]);
    358  }
    359 };
    360 
    361 add_task(async function test_migrateAddressRecords() {
    362  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    363 
    364  let profileStorage = new FormAutofillStorage(path);
    365  await profileStorage.initialize();
    366 
    367  for (let testcase of ADDRESS_TESTCASES) {
    368    info(testcase.description);
    369    profileStorage._store.data.addresses = [testcase.record];
    370    await profileStorage.addresses._migrateRecord(testcase.record, 0);
    371    do_check_record_matches(
    372      testcase.expectedResult,
    373      profileStorage.addresses._data[0]
    374    );
    375  }
    376 });
    377 
    378 add_task(async function test_migrateCreditCardRecords() {
    379  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    380 
    381  let profileStorage = new FormAutofillStorage(path);
    382  await profileStorage.initialize();
    383 
    384  for (let testcase of CREDIT_CARD_TESTCASES) {
    385    info(testcase.description);
    386    profileStorage._store.data.creditCards = [testcase.record];
    387    await profileStorage.creditCards._migrateRecord(testcase.record, 0);
    388    do_check_record_matches(
    389      testcase.expectedResult,
    390      profileStorage.creditCards._data[0]
    391    );
    392  }
    393 });
    394 
    395 add_task(async function test_migrateEncryptedCreditCardNumber() {
    396  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    397 
    398  let profileStorage = new FormAutofillStorage(path);
    399  await profileStorage.initialize();
    400 
    401  info("v1 and v2 schema cards should be abandoned.");
    402 
    403  let v1record = {
    404    guid: "test-guid1",
    405    version: 1,
    406    "cc-name": "Timothy",
    407    "cc-number-encrypted": "aaaa",
    408  };
    409 
    410  let v2record = {
    411    guid: "test-guid2",
    412    version: 2,
    413    "cc-name": "Bob",
    414    "cc-number-encrypted": "bbbb",
    415  };
    416 
    417  profileStorage._store.data.creditCards = [v1record, v2record];
    418  await profileStorage.creditCards._migrateRecord(v1record, 0);
    419  await profileStorage.creditCards._migrateRecord(v2record, 1);
    420  v1record = profileStorage.creditCards._data[0];
    421  v2record = profileStorage.creditCards._data[1];
    422 
    423  Assert.ok(v1record.deleted);
    424  Assert.ok(v2record.deleted);
    425 });
    426 
    427 add_task(async function test_migrateDeprecatedCreditCardV4() {
    428  let path = getTempFile(TEST_STORE_FILE_NAME).path;
    429 
    430  let profileStorage = new FormAutofillStorage(path);
    431  await profileStorage.initialize();
    432 
    433  let records = [
    434    {
    435      guid: "test-guid1",
    436      version: CREDIT_CARD_SCHEMA_VERSION,
    437      "cc-name": "Alice",
    438      _sync: {
    439        changeCounter: 0,
    440        lastSyncedFields: {},
    441      },
    442    },
    443    {
    444      guid: "test-guid2",
    445      version: 4,
    446      "cc-name": "Timothy",
    447      _sync: {
    448        changeCounter: 0,
    449        lastSyncedFields: {},
    450      },
    451    },
    452    {
    453      guid: "test-guid3",
    454      version: 4,
    455      "cc-name": "Bob",
    456    },
    457  ];
    458 
    459  profileStorage._store.data.creditCards = records;
    460  for (let idx = 0; idx < records.length; idx++) {
    461    await profileStorage.creditCards._migrateRecord(records[idx], idx);
    462  }
    463 
    464  profileStorage.creditCards.pullSyncChanges();
    465 
    466  // Record that has already synced before, do not sync again
    467  equal(getSyncChangeCounter(profileStorage.creditCards, records[0].guid), 0);
    468 
    469  // alaways force sync v4 record
    470  equal(records[1].version, CREDIT_CARD_SCHEMA_VERSION);
    471  equal(getSyncChangeCounter(profileStorage.creditCards, records[1].guid), 1);
    472 
    473  equal(records[2].version, CREDIT_CARD_SCHEMA_VERSION);
    474  equal(getSyncChangeCounter(profileStorage.creditCards, records[2].guid), 1);
    475 });