michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Cu.import("resource://services-sync/constants.js"); michael@0: Cu.import("resource://services-sync/engines.js"); michael@0: Cu.import("resource://services-sync/engines/clients.js"); michael@0: Cu.import("resource://services-sync/record.js"); michael@0: Cu.import("resource://services-sync/service.js"); michael@0: Cu.import("resource://services-sync/util.js"); michael@0: Cu.import("resource://testing-common/services/sync/utils.js"); michael@0: michael@0: initTestLogging(); michael@0: Service.engineManager.clear(); michael@0: michael@0: function QuietStore() { michael@0: Store.call("Quiet"); michael@0: } michael@0: QuietStore.prototype = { michael@0: getAllIDs: function getAllIDs() { michael@0: return []; michael@0: } michael@0: } michael@0: michael@0: function SteamEngine() { michael@0: SyncEngine.call(this, "Steam", Service); michael@0: } michael@0: SteamEngine.prototype = { michael@0: __proto__: SyncEngine.prototype, michael@0: // We're not interested in engine sync but what the service does. michael@0: _storeObj: QuietStore, michael@0: michael@0: _sync: function _sync() { michael@0: this._syncStartup(); michael@0: } michael@0: }; michael@0: Service.engineManager.register(SteamEngine); michael@0: michael@0: function StirlingEngine() { michael@0: SyncEngine.call(this, "Stirling", Service); michael@0: } michael@0: StirlingEngine.prototype = { michael@0: __proto__: SteamEngine.prototype, michael@0: // This engine's enabled state is the same as the SteamEngine's. michael@0: get prefName() "steam" michael@0: }; michael@0: Service.engineManager.register(StirlingEngine); michael@0: michael@0: // Tracking info/collections. michael@0: let collectionsHelper = track_collections_helper(); michael@0: let upd = collectionsHelper.with_updated_collection; michael@0: michael@0: function sync_httpd_setup(handlers) { michael@0: michael@0: handlers["/1.1/johndoe/info/collections"] = collectionsHelper.handler; michael@0: delete collectionsHelper.collections.crypto; michael@0: delete collectionsHelper.collections.meta; michael@0: michael@0: let cr = new ServerWBO("keys"); michael@0: handlers["/1.1/johndoe/storage/crypto/keys"] = michael@0: upd("crypto", cr.handler()); michael@0: michael@0: let cl = new ServerCollection(); michael@0: handlers["/1.1/johndoe/storage/clients"] = michael@0: upd("clients", cl.handler()); michael@0: michael@0: return httpd_setup(handlers); michael@0: } michael@0: michael@0: function setUp(server) { michael@0: new SyncTestingInfrastructure(server, "johndoe", "ilovejane", michael@0: "abcdeabcdeabcdeabcdeabcdea"); michael@0: // Ensure that the server has valid keys so that logging in will work and not michael@0: // result in a server wipe, rendering many of these tests useless. michael@0: generateNewKeys(Service.collectionKeys); michael@0: let serverKeys = Service.collectionKeys.asWBO("crypto", "keys"); michael@0: serverKeys.encrypt(Service.identity.syncKeyBundle); michael@0: return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success; michael@0: } michael@0: michael@0: const PAYLOAD = 42; michael@0: michael@0: michael@0: function run_test() { michael@0: initTestLogging("Trace"); michael@0: Log.repository.getLogger("Sync.Service").level = Log.Level.Trace; michael@0: Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace; michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: add_test(function test_newAccount() { michael@0: _("Test: New account does not disable locally enabled engines."); michael@0: let engine = Service.engineManager.get("steam"); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": new ServerWBO("global", {}).handler(), michael@0: "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Engine is enabled from the beginning."); michael@0: Service._ignorePrefObserver = true; michael@0: engine.enabled = true; michael@0: Service._ignorePrefObserver = false; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Engine continues to be enabled."); michael@0: do_check_true(engine.enabled); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_enabledLocally() { michael@0: _("Test: Engine is disabled on remote clients and enabled locally"); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", {syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {}}); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Enable engine locally."); michael@0: engine.enabled = true; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Meta record now contains the new engine."); michael@0: do_check_true(!!metaWBO.data.engines.steam); michael@0: michael@0: _("Engine continues to be enabled."); michael@0: do_check_true(engine.enabled); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_disabledLocally() { michael@0: _("Test: Engine is enabled on remote clients and disabled locally"); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", { michael@0: syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {steam: {syncID: engine.syncID, michael@0: version: engine.version}} michael@0: }); michael@0: let steamCollection = new ServerWBO("steam", PAYLOAD); michael@0: michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": steamCollection.handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Disable engine locally."); michael@0: Service._ignorePrefObserver = true; michael@0: engine.enabled = true; michael@0: Service._ignorePrefObserver = false; michael@0: engine.enabled = false; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Meta record no longer contains engine."); michael@0: do_check_false(!!metaWBO.data.engines.steam); michael@0: michael@0: _("Server records are wiped."); michael@0: do_check_eq(steamCollection.payload, undefined); michael@0: michael@0: _("Engine continues to be disabled."); michael@0: do_check_false(engine.enabled); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_disabledLocally_wipe503() { michael@0: _("Test: Engine is enabled on remote clients and disabled locally"); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", { michael@0: syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {steam: {syncID: engine.syncID, michael@0: version: engine.version}} michael@0: }); michael@0: let steamCollection = new ServerWBO("steam", PAYLOAD); michael@0: michael@0: function service_unavailable(request, response) { michael@0: let body = "Service Unavailable"; michael@0: response.setStatusLine(request.httpVersion, 503, "Service Unavailable"); michael@0: response.setHeader("Retry-After", "23"); michael@0: response.bodyOutputStream.write(body, body.length); michael@0: } michael@0: michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": service_unavailable michael@0: }); michael@0: setUp(server); michael@0: michael@0: _("Disable engine locally."); michael@0: Service._ignorePrefObserver = true; michael@0: engine.enabled = true; michael@0: Service._ignorePrefObserver = false; michael@0: engine.enabled = false; michael@0: michael@0: Svc.Obs.add("weave:ui:sync:error", function onSyncError() { michael@0: Svc.Obs.remove("weave:ui:sync:error", onSyncError); michael@0: michael@0: do_check_eq(Service.status.sync, SERVER_MAINTENANCE); michael@0: michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: }); michael@0: michael@0: _("Sync."); michael@0: Service.errorHandler.syncAndReportErrors(); michael@0: }); michael@0: michael@0: add_test(function test_enabledRemotely() { michael@0: _("Test: Engine is disabled locally and enabled on a remote client"); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", { michael@0: syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {steam: {syncID: engine.syncID, michael@0: version: engine.version}} michael@0: }); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": michael@0: upd("meta", metaWBO.handler()), michael@0: michael@0: "/1.1/johndoe/storage/steam": michael@0: upd("steam", new ServerWBO("steam", {}).handler()) michael@0: }); michael@0: setUp(server); michael@0: michael@0: // We need to be very careful how we do this, so that we don't trigger a michael@0: // fresh start! michael@0: try { michael@0: _("Upload some keys to avoid a fresh start."); michael@0: let wbo = Service.collectionKeys.generateNewKeysWBO(); michael@0: wbo.encrypt(Service.identity.syncKeyBundle); michael@0: do_check_eq(200, wbo.upload(Service.resource(Service.cryptoKeysURL)).status); michael@0: michael@0: _("Engine is disabled."); michael@0: do_check_false(engine.enabled); michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Engine is enabled."); michael@0: do_check_true(engine.enabled); michael@0: michael@0: _("Meta record still present."); michael@0: do_check_eq(metaWBO.data.engines.steam.syncID, engine.syncID); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_disabledRemotelyTwoClients() { michael@0: _("Test: Engine is enabled locally and disabled on a remote client... with two clients."); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", {syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {}}); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": michael@0: upd("meta", metaWBO.handler()), michael@0: michael@0: "/1.1/johndoe/storage/steam": michael@0: upd("steam", new ServerWBO("steam", {}).handler()) michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Enable engine locally."); michael@0: Service._ignorePrefObserver = true; michael@0: engine.enabled = true; michael@0: Service._ignorePrefObserver = false; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Disable engine by deleting from meta/global."); michael@0: let d = metaWBO.data; michael@0: delete d.engines["steam"]; michael@0: metaWBO.payload = JSON.stringify(d); michael@0: metaWBO.modified = Date.now() / 1000; michael@0: michael@0: _("Add a second client and verify that the local pref is changed."); michael@0: Service.clientsEngine._store._remoteClients["foobar"] = {name: "foobar", type: "desktop"}; michael@0: Service.sync(); michael@0: michael@0: _("Engine is disabled."); michael@0: do_check_false(engine.enabled); michael@0: michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_disabledRemotely() { michael@0: _("Test: Engine is enabled locally and disabled on a remote client"); michael@0: Service.syncID = "abcdefghij"; michael@0: let engine = Service.engineManager.get("steam"); michael@0: let metaWBO = new ServerWBO("global", {syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {}}); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Enable engine locally."); michael@0: Service._ignorePrefObserver = true; michael@0: engine.enabled = true; michael@0: Service._ignorePrefObserver = false; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Engine is not disabled: only one client."); michael@0: do_check_true(engine.enabled); michael@0: michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_dependentEnginesEnabledLocally() { michael@0: _("Test: Engine is disabled on remote clients and enabled locally"); michael@0: Service.syncID = "abcdefghij"; michael@0: let steamEngine = Service.engineManager.get("steam"); michael@0: let stirlingEngine = Service.engineManager.get("stirling"); michael@0: let metaWBO = new ServerWBO("global", {syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {}}); michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": new ServerWBO("steam", {}).handler(), michael@0: "/1.1/johndoe/storage/stirling": new ServerWBO("stirling", {}).handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Enable engine locally. Doing it on one is enough."); michael@0: steamEngine.enabled = true; michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Meta record now contains the new engines."); michael@0: do_check_true(!!metaWBO.data.engines.steam); michael@0: do_check_true(!!metaWBO.data.engines.stirling); michael@0: michael@0: _("Engines continue to be enabled."); michael@0: do_check_true(steamEngine.enabled); michael@0: do_check_true(stirlingEngine.enabled); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: add_test(function test_dependentEnginesDisabledLocally() { michael@0: _("Test: Two dependent engines are enabled on remote clients and disabled locally"); michael@0: Service.syncID = "abcdefghij"; michael@0: let steamEngine = Service.engineManager.get("steam"); michael@0: let stirlingEngine = Service.engineManager.get("stirling"); michael@0: let metaWBO = new ServerWBO("global", { michael@0: syncID: Service.syncID, michael@0: storageVersion: STORAGE_VERSION, michael@0: engines: {steam: {syncID: steamEngine.syncID, michael@0: version: steamEngine.version}, michael@0: stirling: {syncID: stirlingEngine.syncID, michael@0: version: stirlingEngine.version}} michael@0: }); michael@0: michael@0: let steamCollection = new ServerWBO("steam", PAYLOAD); michael@0: let stirlingCollection = new ServerWBO("stirling", PAYLOAD); michael@0: michael@0: let server = sync_httpd_setup({ michael@0: "/1.1/johndoe/storage/meta/global": metaWBO.handler(), michael@0: "/1.1/johndoe/storage/steam": steamCollection.handler(), michael@0: "/1.1/johndoe/storage/stirling": stirlingCollection.handler() michael@0: }); michael@0: setUp(server); michael@0: michael@0: try { michael@0: _("Disable engines locally. Doing it on one is enough."); michael@0: Service._ignorePrefObserver = true; michael@0: steamEngine.enabled = true; michael@0: do_check_true(stirlingEngine.enabled); michael@0: Service._ignorePrefObserver = false; michael@0: steamEngine.enabled = false; michael@0: do_check_false(stirlingEngine.enabled); michael@0: michael@0: _("Sync."); michael@0: Service.sync(); michael@0: michael@0: _("Meta record no longer contains engines."); michael@0: do_check_false(!!metaWBO.data.engines.steam); michael@0: do_check_false(!!metaWBO.data.engines.stirling); michael@0: michael@0: _("Server records are wiped."); michael@0: do_check_eq(steamCollection.payload, undefined); michael@0: do_check_eq(stirlingCollection.payload, undefined); michael@0: michael@0: _("Engines continue to be disabled."); michael@0: do_check_false(steamEngine.enabled); michael@0: do_check_false(stirlingEngine.enabled); michael@0: } finally { michael@0: Service.startOver(); michael@0: server.stop(run_next_test); michael@0: } michael@0: });