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 --- .../unit/test_service_sync_updateEnabledEngines.js | 587 +++++++++++++++++++++ 1 file changed, 587 insertions(+) create mode 100644 services/sync/tests/unit/test_service_sync_updateEnabledEngines.js (limited to 'services/sync/tests/unit/test_service_sync_updateEnabledEngines.js') diff --git a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js new file mode 100644 index 0000000000..fd8b3f71bc --- /dev/null +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js @@ -0,0 +1,587 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { Service } = ChromeUtils.importESModule( + "resource://services-sync/service.sys.mjs" +); + +const { EngineSynchronizer } = ChromeUtils.importESModule( + "resource://services-sync/stages/enginesync.sys.mjs" +); + +function QuietStore() { + Store.call("Quiet"); +} +QuietStore.prototype = { + async getAllIDs() { + return []; + }, +}; + +function SteamEngine() { + SyncEngine.call(this, "Steam", Service); +} +SteamEngine.prototype = { + // We're not interested in engine sync but what the service does. + _storeObj: QuietStore, + + _sync: async function _sync() { + await this._syncStartup(); + }, +}; +Object.setPrototypeOf(SteamEngine.prototype, SyncEngine.prototype); + +function StirlingEngine() { + SyncEngine.call(this, "Stirling", Service); +} +StirlingEngine.prototype = { + // This engine's enabled state is the same as the SteamEngine's. + get prefName() { + return "steam"; + }, +}; +Object.setPrototypeOf(StirlingEngine.prototype, SteamEngine.prototype); + +// Tracking info/collections. +var collectionsHelper = track_collections_helper(); +var upd = collectionsHelper.with_updated_collection; + +function sync_httpd_setup(handlers) { + handlers["/1.1/johndoe/info/collections"] = collectionsHelper.handler; + delete collectionsHelper.collections.crypto; + delete collectionsHelper.collections.meta; + + let cr = new ServerWBO("keys"); + handlers["/1.1/johndoe/storage/crypto/keys"] = upd("crypto", cr.handler()); + + let cl = new ServerCollection(); + handlers["/1.1/johndoe/storage/clients"] = upd("clients", cl.handler()); + + return httpd_setup(handlers); +} + +async function setUp(server) { + await SyncTestingInfrastructure(server, "johndoe", "ilovejane"); + // Ensure that the server has valid keys so that logging in will work and not + // result in a server wipe, rendering many of these tests useless. + await generateNewKeys(Service.collectionKeys); + let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); + await serverKeys.encrypt(Service.identity.syncKeyBundle); + let { success } = await serverKeys.upload( + Service.resource(Service.cryptoKeysURL) + ); + ok(success); +} + +const PAYLOAD = 42; + +add_task(async function setup() { + await Service.engineManager.clear(); + validate_all_future_pings(); + + await Service.engineManager.register(SteamEngine); + await Service.engineManager.register(StirlingEngine); +}); + +add_task(async function test_newAccount() { + enableValidationPrefs(); + + _("Test: New account does not disable locally enabled engines."); + let engine = Service.engineManager.get("steam"); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": new ServerWBO("global", {}).handler(), + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), + }); + await setUp(server); + + try { + _("Engine is enabled from the beginning."); + Service._ignorePrefObserver = true; + engine.enabled = true; + Service._ignorePrefObserver = false; + + _("Sync."); + await Service.sync(); + + _("Engine continues to be enabled."); + Assert.ok(engine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_enabledLocally() { + enableValidationPrefs(); + + _("Test: Engine is disabled on remote clients and enabled locally"); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: {}, + }); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), + }); + await setUp(server); + + try { + _("Enable engine locally."); + engine.enabled = true; + + _("Sync."); + await Service.sync(); + + _("Meta record now contains the new engine."); + Assert.ok(!!metaWBO.data.engines.steam); + + _("Engine continues to be enabled."); + Assert.ok(engine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_disabledLocally() { + enableValidationPrefs(); + + _("Test: Engine is enabled on remote clients and disabled locally"); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let syncID = await engine.resetLocalSyncID(); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: { steam: { syncID, version: engine.version } }, + }); + let steamCollection = new ServerWBO("steam", PAYLOAD); + + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": steamCollection.handler(), + }); + await setUp(server); + + try { + _("Disable engine locally."); + Service._ignorePrefObserver = true; + engine.enabled = true; + Service._ignorePrefObserver = false; + engine.enabled = false; + + _("Sync."); + await Service.sync(); + + _("Meta record no longer contains engine."); + Assert.ok(!metaWBO.data.engines.steam); + + _("Server records are wiped."); + Assert.equal(steamCollection.payload, undefined); + + _("Engine continues to be disabled."); + Assert.ok(!engine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_disabledLocally_wipe503() { + enableValidationPrefs(); + + _("Test: Engine is enabled on remote clients and disabled locally"); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let syncID = await engine.resetLocalSyncID(); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: { steam: { syncID, version: engine.version } }, + }); + + function service_unavailable(request, response) { + let body = "Service Unavailable"; + response.setStatusLine(request.httpVersion, 503, "Service Unavailable"); + response.setHeader("Retry-After", "23"); + response.bodyOutputStream.write(body, body.length); + } + + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": service_unavailable, + }); + await setUp(server); + + _("Disable engine locally."); + Service._ignorePrefObserver = true; + engine.enabled = true; + Service._ignorePrefObserver = false; + engine.enabled = false; + + _("Sync."); + await Service.sync(); + Assert.equal(Service.status.sync, SERVER_MAINTENANCE); + + await Service.startOver(); + await promiseStopServer(server); +}); + +add_task(async function test_enabledRemotely() { + enableValidationPrefs(); + + _("Test: Engine is disabled locally and enabled on a remote client"); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let syncID = await engine.resetLocalSyncID(); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: { steam: { syncID, version: engine.version } }, + }); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": upd("meta", metaWBO.handler()), + + "/1.1/johndoe/storage/steam": upd( + "steam", + new ServerWBO("steam", {}).handler() + ), + }); + await setUp(server); + + // We need to be very careful how we do this, so that we don't trigger a + // fresh start! + try { + _("Upload some keys to avoid a fresh start."); + let wbo = await Service.collectionKeys.generateNewKeysWBO(); + await wbo.encrypt(Service.identity.syncKeyBundle); + Assert.equal( + 200, + (await wbo.upload(Service.resource(Service.cryptoKeysURL))).status + ); + + _("Engine is disabled."); + Assert.ok(!engine.enabled); + + _("Sync."); + await Service.sync(); + + _("Engine is enabled."); + Assert.ok(engine.enabled); + + _("Meta record still present."); + Assert.equal(metaWBO.data.engines.steam.syncID, await engine.getSyncID()); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_disabledRemotelyTwoClients() { + enableValidationPrefs(); + + _( + "Test: Engine is enabled locally and disabled on a remote client... with two clients." + ); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: {}, + }); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": upd("meta", metaWBO.handler()), + + "/1.1/johndoe/storage/steam": upd( + "steam", + new ServerWBO("steam", {}).handler() + ), + }); + await setUp(server); + + try { + _("Enable engine locally."); + Service._ignorePrefObserver = true; + engine.enabled = true; + Service._ignorePrefObserver = false; + + _("Sync."); + await Service.sync(); + + _("Disable engine by deleting from meta/global."); + let d = metaWBO.data; + delete d.engines.steam; + metaWBO.payload = JSON.stringify(d); + metaWBO.modified = Date.now() / 1000; + + _("Add a second client and verify that the local pref is changed."); + Service.clientsEngine._store._remoteClients.foobar = { + name: "foobar", + type: "desktop", + }; + await Service.sync(); + + _("Engine is disabled."); + Assert.ok(!engine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_disabledRemotely() { + enableValidationPrefs(); + + _("Test: Engine is enabled locally and disabled on a remote client"); + Service.syncID = "abcdefghij"; + let engine = Service.engineManager.get("steam"); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: {}, + }); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), + }); + await setUp(server); + + try { + _("Enable engine locally."); + Service._ignorePrefObserver = true; + engine.enabled = true; + Service._ignorePrefObserver = false; + + _("Sync."); + await Service.sync(); + + _("Engine is not disabled: only one client."); + Assert.ok(engine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_dependentEnginesEnabledLocally() { + enableValidationPrefs(); + + _("Test: Engine is disabled on remote clients and enabled locally"); + Service.syncID = "abcdefghij"; + let steamEngine = Service.engineManager.get("steam"); + let stirlingEngine = Service.engineManager.get("stirling"); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: {}, + }); + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), + "/1.1/johndoe/storage/stirling": new ServerWBO("stirling", {}).handler(), + }); + await setUp(server); + + try { + _("Enable engine locally. Doing it on one is enough."); + steamEngine.enabled = true; + + _("Sync."); + await Service.sync(); + + _("Meta record now contains the new engines."); + Assert.ok(!!metaWBO.data.engines.steam); + Assert.ok(!!metaWBO.data.engines.stirling); + + _("Engines continue to be enabled."); + Assert.ok(steamEngine.enabled); + Assert.ok(stirlingEngine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_dependentEnginesDisabledLocally() { + enableValidationPrefs(); + + _( + "Test: Two dependent engines are enabled on remote clients and disabled locally" + ); + Service.syncID = "abcdefghij"; + let steamEngine = Service.engineManager.get("steam"); + let steamSyncID = await steamEngine.resetLocalSyncID(); + let stirlingEngine = Service.engineManager.get("stirling"); + let stirlingSyncID = await stirlingEngine.resetLocalSyncID(); + let metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + engines: { + steam: { syncID: steamSyncID, version: steamEngine.version }, + stirling: { syncID: stirlingSyncID, version: stirlingEngine.version }, + }, + }); + + let steamCollection = new ServerWBO("steam", PAYLOAD); + let stirlingCollection = new ServerWBO("stirling", PAYLOAD); + + let server = sync_httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + "/1.1/johndoe/storage/steam": steamCollection.handler(), + "/1.1/johndoe/storage/stirling": stirlingCollection.handler(), + }); + await setUp(server); + + try { + _("Disable engines locally. Doing it on one is enough."); + Service._ignorePrefObserver = true; + steamEngine.enabled = true; + Assert.ok(stirlingEngine.enabled); + Service._ignorePrefObserver = false; + steamEngine.enabled = false; + Assert.ok(!stirlingEngine.enabled); + + _("Sync."); + await Service.sync(); + + _("Meta record no longer contains engines."); + Assert.ok(!metaWBO.data.engines.steam); + Assert.ok(!metaWBO.data.engines.stirling); + + _("Server records are wiped."); + Assert.equal(steamCollection.payload, undefined); + Assert.equal(stirlingCollection.payload, undefined); + + _("Engines continue to be disabled."); + Assert.ok(!steamEngine.enabled); + Assert.ok(!stirlingEngine.enabled); + } finally { + await Service.startOver(); + await promiseStopServer(server); + } +}); + +add_task(async function test_service_updateLocalEnginesState() { + Service.syncID = "abcdefghij"; + const engine = Service.engineManager.get("steam"); + const metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + declined: ["steam"], + engines: {}, + }); + const server = httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + }); + await SyncTestingInfrastructure(server, "johndoe"); + + // Disconnect sync. + await Service.startOver(); + Service._ignorePrefObserver = true; + // Steam engine is enabled on our machine. + engine.enabled = true; + Service._ignorePrefObserver = false; + Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/"; + + // Update engine state from the server. + await Service.updateLocalEnginesState(); + // Now disabled. + Assert.ok(!engine.enabled); +}); + +add_task(async function test_service_enableAfterUpdateState() { + Service.syncID = "abcdefghij"; + const engine = Service.engineManager.get("steam"); + const metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + declined: ["steam"], + engines: { someengine: {} }, + }); + const server = httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + }); + await SyncTestingInfrastructure(server, "johndoe"); + + // Disconnect sync. + await Service.startOver(); + Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/"; + + // Update engine state from the server. + await Service.updateLocalEnginesState(); + // Now disabled, reflecting what's on the server. + Assert.ok(!engine.enabled); + // Enable the engine, as though the user selected it via CWTS. + engine.enabled = true; + + // Do the "reconcile local and remote states" dance. + let engineSync = new EngineSynchronizer(Service); + await engineSync._updateEnabledEngines(); + await Service._maybeUpdateDeclined(); + // engine should remain enabled. + Assert.ok(engine.enabled); + // engine should no longer appear in declined on the server. + Assert.deepEqual(metaWBO.data.declined, []); +}); + +add_task(async function test_service_disableAfterUpdateState() { + Service.syncID = "abcdefghij"; + const engine = Service.engineManager.get("steam"); + const metaWBO = new ServerWBO("global", { + syncID: Service.syncID, + storageVersion: STORAGE_VERSION, + declined: [], + engines: { steam: {} }, + }); + const server = httpd_setup({ + "/1.1/johndoe/storage/meta/global": metaWBO.handler(), + }); + await SyncTestingInfrastructure(server, "johndoe"); + + // Disconnect sync. + await Service.startOver(); + Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/"; + + // Update engine state from the server. + await Service.updateLocalEnginesState(); + // Now enabled, reflecting what's on the server. + Assert.ok(engine.enabled); + // Disable the engine, as though via CWTS. + engine.enabled = false; + + // Do the "reconcile local and remote states" dance. + let engineSync = new EngineSynchronizer(Service); + await engineSync._updateEnabledEngines(); + await Service._maybeUpdateDeclined(); + // engine should remain disabled. + Assert.ok(!engine.enabled); + // engine should now appear in declined on the server. + Assert.deepEqual(metaWBO.data.declined, ["steam"]); + // and should have been removed from engines. + Assert.deepEqual(metaWBO.data.engines, {}); +}); + +add_task(async function test_service_updateLocalEnginesState_no_meta_global() { + Service.syncID = "abcdefghij"; + const engine = Service.engineManager.get("steam"); + // The server doesn't contain /meta/global (sync was never enabled). + const server = httpd_setup({}); + await SyncTestingInfrastructure(server, "johndoe"); + + // Disconnect sync. + await Service.startOver(); + Service._ignorePrefObserver = true; + // Steam engine is enabled on our machine. + engine.enabled = true; + Service._ignorePrefObserver = false; + Service.identity._findCluster = () => server.baseURI + "/1.1/johndoe/"; + + // Update engine state from the server. + await Service.updateLocalEnginesState(); + // Still enabled. + Assert.ok(engine.enabled); +}); -- cgit v1.2.3