From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- services/sync/tests/unit/test_password_store.js | 400 ++++++++++++++++++++++++ 1 file changed, 400 insertions(+) create mode 100644 services/sync/tests/unit/test_password_store.js (limited to 'services/sync/tests/unit/test_password_store.js') diff --git a/services/sync/tests/unit/test_password_store.js b/services/sync/tests/unit/test_password_store.js new file mode 100644 index 0000000000..e0a4e1343f --- /dev/null +++ b/services/sync/tests/unit/test_password_store.js @@ -0,0 +1,400 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { LoginRec } = ChromeUtils.importESModule( + "resource://services-sync/engines/passwords.sys.mjs" +); +const { Service } = ChromeUtils.importESModule( + "resource://services-sync/service.sys.mjs" +); +const { SyncedRecordsTelemetry } = ChromeUtils.importESModule( + "resource://services-sync/telemetry.sys.mjs" +); + +async function checkRecord( + name, + record, + expectedCount, + timeCreated, + expectedTimeCreated, + timePasswordChanged, + expectedTimePasswordChanged, + recordIsUpdated +) { + let engine = Service.engineManager.get("passwords"); + let store = engine._store; + + let logins = Services.logins.findLogins( + record.hostname, + record.formSubmitURL, + null + ); + + _("Record" + name + ":" + JSON.stringify(logins)); + _("Count" + name + ":" + logins.length); + + Assert.equal(logins.length, expectedCount); + + if (expectedCount > 0) { + Assert.ok(!!(await store.getAllIDs())[record.id]); + let stored_record = logins[0].QueryInterface(Ci.nsILoginMetaInfo); + + if (timeCreated !== undefined) { + Assert.equal(stored_record.timeCreated, expectedTimeCreated); + } + + if (timePasswordChanged !== undefined) { + if (recordIsUpdated) { + Assert.ok( + stored_record.timePasswordChanged >= expectedTimePasswordChanged + ); + } else { + Assert.equal( + stored_record.timePasswordChanged, + expectedTimePasswordChanged + ); + } + return stored_record.timePasswordChanged; + } + } else { + Assert.ok(!(await store.getAllIDs())[record.id]); + } + return undefined; +} + +async function changePassword( + name, + hostname, + password, + expectedCount, + timeCreated, + expectedTimeCreated, + timePasswordChanged, + expectedTimePasswordChanged, + insert, + recordIsUpdated +) { + const BOGUS_GUID = "zzzzzz" + hostname; + let record = new LoginRec("passwords", BOGUS_GUID); + record.cleartext = { + id: BOGUS_GUID, + hostname, + formSubmitURL: hostname, + username: "john", + password, + usernameField: "username", + passwordField: "password", + }; + + if (timeCreated !== undefined) { + record.timeCreated = timeCreated; + } + + if (timePasswordChanged !== undefined) { + record.timePasswordChanged = timePasswordChanged; + } + + let engine = Service.engineManager.get("passwords"); + let store = engine._store; + + if (insert) { + let countTelemetry = new SyncedRecordsTelemetry(); + Assert.equal( + (await store.applyIncomingBatch([record], countTelemetry)).length, + 0 + ); + } + + return checkRecord( + name, + record, + expectedCount, + timeCreated, + expectedTimeCreated, + timePasswordChanged, + expectedTimePasswordChanged, + recordIsUpdated + ); +} + +async function test_apply_records_with_times( + hostname, + timeCreated, + timePasswordChanged +) { + // The following record is going to be inserted in the store and it needs + // to be found there. Then its timestamps are going to be compared to + // the expected values. + await changePassword( + " ", + hostname, + "password", + 1, + timeCreated, + timeCreated, + timePasswordChanged, + timePasswordChanged, + true + ); +} + +async function test_apply_multiple_records_with_times() { + // The following records are going to be inserted in the store and they need + // to be found there. Then their timestamps are going to be compared to + // the expected values. + await changePassword( + "A", + "http://foo.a.com", + "password", + 1, + undefined, + undefined, + undefined, + undefined, + true + ); + await changePassword( + "B", + "http://foo.b.com", + "password", + 1, + 1000, + 1000, + undefined, + undefined, + true + ); + await changePassword( + "C", + "http://foo.c.com", + "password", + 1, + undefined, + undefined, + 1000, + 1000, + true + ); + await changePassword( + "D", + "http://foo.d.com", + "password", + 1, + 1000, + 1000, + 1000, + 1000, + true + ); + + // The following records are not going to be inserted in the store and they + // are not going to be found there. + await changePassword( + "NotInStoreA", + "http://foo.aaaa.com", + "password", + 0, + undefined, + undefined, + undefined, + undefined, + false + ); + await changePassword( + "NotInStoreB", + "http://foo.bbbb.com", + "password", + 0, + 1000, + 1000, + undefined, + undefined, + false + ); + await changePassword( + "NotInStoreC", + "http://foo.cccc.com", + "password", + 0, + undefined, + undefined, + 1000, + 1000, + false + ); + await changePassword( + "NotInStoreD", + "http://foo.dddd.com", + "password", + 0, + 1000, + 1000, + 1000, + 1000, + false + ); +} + +async function test_apply_same_record_with_different_times() { + // The following record is going to be inserted multiple times in the store + // and it needs to be found there. Then its timestamps are going to be + // compared to the expected values. + + /* eslint-disable no-unused-vars */ + /* The eslint linter thinks that timePasswordChanged is unused, even though + it is passed as an argument to changePassword. */ + var timePasswordChanged = 100; + timePasswordChanged = await changePassword( + "A", + "http://a.tn", + "password", + 1, + 100, + 100, + 100, + timePasswordChanged, + true + ); + timePasswordChanged = await changePassword( + "A", + "http://a.tn", + "password", + 1, + 100, + 100, + 800, + timePasswordChanged, + true, + true + ); + timePasswordChanged = await changePassword( + "A", + "http://a.tn", + "password", + 1, + 500, + 100, + 800, + timePasswordChanged, + true, + true + ); + timePasswordChanged = await changePassword( + "A", + "http://a.tn", + "password2", + 1, + 500, + 100, + 1536213005222, + timePasswordChanged, + true, + true + ); + timePasswordChanged = await changePassword( + "A", + "http://a.tn", + "password2", + 1, + 500, + 100, + 800, + timePasswordChanged, + true, + true + ); + /* eslint-enable no-unused-vars */ +} + +async function test_LoginRec_toString(store, recordData) { + let rec = await store.createRecord(recordData.id); + ok(rec); + ok(!rec.toString().includes(rec.password)); +} + +add_task(async function run_test() { + const BOGUS_GUID_A = "zzzzzzzzzzzz"; + const BOGUS_GUID_B = "yyyyyyyyyyyy"; + let recordA = new LoginRec("passwords", BOGUS_GUID_A); + let recordB = new LoginRec("passwords", BOGUS_GUID_B); + recordA.cleartext = { + id: BOGUS_GUID_A, + hostname: "http://foo.bar.com", + formSubmitURL: "http://foo.bar.com", + httpRealm: "secure", + username: "john", + password: "smith", + usernameField: "username", + passwordField: "password", + }; + recordB.cleartext = { + id: BOGUS_GUID_B, + hostname: "http://foo.baz.com", + formSubmitURL: "http://foo.baz.com", + username: "john", + password: "smith", + usernameField: "username", + passwordField: "password", + unknownStr: "an unknown string from another field", + }; + + let engine = Service.engineManager.get("passwords"); + let store = engine._store; + + try { + let countTelemetry = new SyncedRecordsTelemetry(); + Assert.equal( + (await store.applyIncomingBatch([recordA, recordB], countTelemetry)) + .length, + 0 + ); + + // Only the good record makes it to Services.logins. + let badLogins = Services.logins.findLogins( + recordA.hostname, + recordA.formSubmitURL, + recordA.httpRealm + ); + let goodLogins = Services.logins.findLogins( + recordB.hostname, + recordB.formSubmitURL, + null + ); + + _("Bad: " + JSON.stringify(badLogins)); + _("Good: " + JSON.stringify(goodLogins)); + _("Count: " + badLogins.length + ", " + goodLogins.length); + + Assert.equal(goodLogins.length, 1); + Assert.equal(badLogins.length, 0); + + // applyIncoming should've put any unknown fields from the server + // into a catch-all unknownFields field + Assert.equal( + goodLogins[0].unknownFields, + JSON.stringify({ + unknownStr: "an unknown string from another field", + }) + ); + + Assert.ok(!!(await store.getAllIDs())[BOGUS_GUID_B]); + Assert.ok(!(await store.getAllIDs())[BOGUS_GUID_A]); + + await test_LoginRec_toString(store, recordB); + + await test_apply_records_with_times( + "http://afoo.baz.com", + undefined, + undefined + ); + await test_apply_records_with_times("http://bfoo.baz.com", 1000, undefined); + await test_apply_records_with_times("http://cfoo.baz.com", undefined, 2000); + await test_apply_records_with_times("http://dfoo.baz.com", 1000, 2000); + + await test_apply_multiple_records_with_times(); + + await test_apply_same_record_with_different_times(); + } finally { + await store.wipe(); + } +}); -- cgit v1.2.3