From 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:47:29 +0200 Subject: Adding upstream version 115.8.0esr. Signed-off-by: Daniel Baumann --- .../test/unit/test_remote_settings_offline.js | 141 +++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 services/settings/test/unit/test_remote_settings_offline.js (limited to 'services/settings/test/unit/test_remote_settings_offline.js') diff --git a/services/settings/test/unit/test_remote_settings_offline.js b/services/settings/test/unit/test_remote_settings_offline.js new file mode 100644 index 0000000000..d3403d4d89 --- /dev/null +++ b/services/settings/test/unit/test_remote_settings_offline.js @@ -0,0 +1,141 @@ +const { RemoteSettingsClient } = ChromeUtils.importESModule( + "resource://services-settings/RemoteSettingsClient.sys.mjs" +); +const { RemoteSettingsWorker } = ChromeUtils.importESModule( + "resource://services-settings/RemoteSettingsWorker.sys.mjs" +); +const { SharedUtils } = ChromeUtils.import( + "resource://services-settings/SharedUtils.jsm" +); + +// A collection with a dump that's packaged on all builds where this test runs, +// including on Android at mobile/android/installer/package-manifest.in +const TEST_BUCKET = "main"; +const TEST_COLLECTION = "password-recipes"; + +let client; +let DUMP_RECORDS; +let DUMP_LAST_MODIFIED; + +add_task(async function setup() { + // "services.settings.server" pref is not set. + // Test defaults to an unreachable server, + // and will only load from the dump if any. + + client = new RemoteSettingsClient(TEST_COLLECTION, { + bucketName: TEST_BUCKET, + }); + + const dump = await SharedUtils.loadJSONDump(TEST_BUCKET, TEST_COLLECTION); + DUMP_RECORDS = dump.data; + DUMP_LAST_MODIFIED = dump.timestamp; + + // Dumps are fetched via the following, which sorts the records, newest first. + // https://searchfox.org/mozilla-central/rev/5b3444ad300e244b5af4214212e22bd9e4b7088a/taskcluster/docker/periodic-updates/scripts/periodic_file_updates.sh#304 + equal( + DUMP_LAST_MODIFIED, + DUMP_RECORDS[0].last_modified, + "records in dump ought to be sorted by last_modified" + ); +}); + +async function importData(records) { + await RemoteSettingsWorker._execute("_test_only_import", [ + TEST_BUCKET, + TEST_COLLECTION, + records, + records[0]?.last_modified || 0, + ]); +} + +async function clear_state() { + await client.db.clear(); +} + +add_task(async function test_load_from_dump_when_offline() { + // Baseline: verify that the collection is empty at first, + // but non-empty after loading from the dump. + const before = await client.get({ syncIfEmpty: false }); + equal(before.length, 0, "collection empty when offline"); + + // should import from dump since collection was not initialized. + const after = await client.get(); + equal(after.length, DUMP_RECORDS.length, "collection loaded from dump"); + equal(await client.getLastModified(), DUMP_LAST_MODIFIED, "dump's timestamp"); +}); +add_task(clear_state); + +add_task(async function test_optional_skip_dump_after_empty_import() { + // clear_state should have wiped the database. + const before = await client.get({ syncIfEmpty: false }); + equal(before.length, 0, "collection empty after clearing"); + + // Verify that the dump is not imported again by client.get() + // when the database is initialized with an empty dump + // with `loadDumpIfNewer` disabled. + await importData([]); // <-- Empty set of records. + + const after = await client.get({ loadDumpIfNewer: false }); + equal(after.length, 0, "collection still empty due to import"); + equal(await client.getLastModified(), 0, "Empty dump has no timestamp"); +}); +add_task(clear_state); + +add_task(async function test_optional_skip_dump_after_non_empty_import() { + await importData([{ last_modified: 1234, id: "dummy" }]); + + const after = await client.get({ loadDumpIfNewer: false }); + equal(after.length, 1, "Imported dummy data"); + equal(await client.getLastModified(), 1234, "Expected timestamp of import"); + + await importData([]); + const after2 = await client.get({ loadDumpIfNewer: false }); + equal(after2.length, 0, "Previous data wiped on duplicate import"); + equal(await client.getLastModified(), 0, "Timestamp of empty collection"); +}); +add_task(clear_state); + +add_task(async function test_load_dump_after_empty_import() { + await importData([]); // <-- Empty set of records, i.e. last_modified = 0. + + const after = await client.get(); + equal(after.length, DUMP_RECORDS.length, "Imported dump"); + equal(await client.getLastModified(), DUMP_LAST_MODIFIED, "dump's timestamp"); +}); +add_task(clear_state); + +add_task(async function test_load_dump_after_non_empty_import() { + // Dump is updated regularly, verify that the dump matches our expectations + // before running the test. + ok(DUMP_LAST_MODIFIED > 1234, "Assuming dump to be newer than dummy 1234"); + + await importData([{ last_modified: 1234, id: "dummy" }]); + + const after = await client.get(); + equal(after.length, DUMP_RECORDS.length, "Imported dump"); + equal(await client.getLastModified(), DUMP_LAST_MODIFIED, "dump's timestamp"); +}); +add_task(clear_state); + +add_task(async function test_load_dump_after_import_from_broken_distro() { + // Dump is updated regularly, verify that the dump matches our expectations + // before running the test. + ok(DUMP_LAST_MODIFIED > 1234, "Assuming dump to be newer than dummy 1234"); + + // No last_modified time. + await importData([{ id: "dummy" }]); + + const after = await client.get(); + equal(after.length, DUMP_RECORDS.length, "Imported dump"); + equal(await client.getLastModified(), DUMP_LAST_MODIFIED, "dump's timestamp"); +}); +add_task(clear_state); + +add_task(async function test_skip_dump_if_same_last_modified() { + await importData([{ last_modified: DUMP_LAST_MODIFIED, id: "dummy" }]); + + const after = await client.get(); + equal(after.length, 1, "Not importing dump when time matches"); + equal(await client.getLastModified(), DUMP_LAST_MODIFIED, "Same timestamp"); +}); +add_task(clear_state); -- cgit v1.2.3