diff options
-rw-r--r-- | services/sync/modules/healthreport.jsm | 262 | ||||
-rw-r--r-- | services/sync/moz.build | 1 | ||||
-rw-r--r-- | services/sync/tests/unit/test_block_sync.js | 37 | ||||
-rw-r--r-- | services/sync/tests/unit/test_fxa_migration.js | 279 | ||||
-rw-r--r-- | services/sync/tests/unit/test_fxa_migration_sentinel.js | 150 | ||||
-rw-r--r-- | services/sync/tests/unit/test_healthreport.js | 194 | ||||
-rw-r--r-- | services/sync/tests/unit/test_healthreport_migration.js | 155 | ||||
-rw-r--r-- | services/sync/tests/unit/xpcshell.ini | 11 |
8 files changed, 0 insertions, 1089 deletions
diff --git a/services/sync/modules/healthreport.jsm b/services/sync/modules/healthreport.jsm deleted file mode 100644 index 47161c095..000000000 --- a/services/sync/modules/healthreport.jsm +++ /dev/null @@ -1,262 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -this.EXPORTED_SYMBOLS = [ - "SyncProvider", -]; - -const {classes: Cc, interfaces: Ci, utils: Cu} = Components; - -Cu.import("resource://gre/modules/Metrics.jsm", this); -Cu.import("resource://gre/modules/Promise.jsm", this); -Cu.import("resource://gre/modules/Services.jsm", this); -Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); - -const DAILY_LAST_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_NUMERIC}; -const DAILY_LAST_TEXT_FIELD = {type: Metrics.Storage.FIELD_DAILY_LAST_TEXT}; -const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER}; - -XPCOMUtils.defineLazyModuleGetter(this, "Weave", - "resource://services-sync/main.js"); - -function SyncMeasurement1() { - Metrics.Measurement.call(this); -} - -SyncMeasurement1.prototype = Object.freeze({ - __proto__: Metrics.Measurement.prototype, - - name: "sync", - version: 1, - - fields: { - enabled: DAILY_LAST_NUMERIC_FIELD, - preferredProtocol: DAILY_LAST_TEXT_FIELD, - activeProtocol: DAILY_LAST_TEXT_FIELD, - syncStart: DAILY_COUNTER_FIELD, - syncSuccess: DAILY_COUNTER_FIELD, - syncError: DAILY_COUNTER_FIELD, - }, -}); - -function SyncDevicesMeasurement1() { - Metrics.Measurement.call(this); -} - -SyncDevicesMeasurement1.prototype = Object.freeze({ - __proto__: Metrics.Measurement.prototype, - - name: "devices", - version: 1, - - fields: {}, - - shouldIncludeField: function (name) { - return true; - }, - - fieldType: function (name) { - return Metrics.Storage.FIELD_DAILY_COUNTER; - }, -}); - -function SyncMigrationMeasurement1() { - Metrics.Measurement.call(this); -} - -SyncMigrationMeasurement1.prototype = Object.freeze({ - __proto__: Metrics.Measurement.prototype, - - name: "migration", - version: 1, - - fields: { - state: DAILY_LAST_TEXT_FIELD, // last "user" or "internal" state we saw for the day - accepted: DAILY_COUNTER_FIELD, // number of times user tried to start migration - declined: DAILY_COUNTER_FIELD, // number of times user closed nagging infobar - unlinked: DAILY_LAST_NUMERIC_FIELD, // did the user decline and unlink - }, -}); - -this.SyncProvider = function () { - Metrics.Provider.call(this); -}; -SyncProvider.prototype = Object.freeze({ - __proto__: Metrics.Provider.prototype, - - name: "org.mozilla.sync", - - measurementTypes: [ - SyncDevicesMeasurement1, - SyncMeasurement1, - SyncMigrationMeasurement1, - ], - - _OBSERVERS: [ - "weave:service:sync:start", - "weave:service:sync:finish", - "weave:service:sync:error", - "fxa-migration:state-changed", - "fxa-migration:internal-state-changed", - "fxa-migration:internal-telemetry", - ], - - postInit: function () { - for (let o of this._OBSERVERS) { - Services.obs.addObserver(this, o, false); - } - - return Promise.resolve(); - }, - - onShutdown: function () { - for (let o of this._OBSERVERS) { - Services.obs.removeObserver(this, o); - } - - return Promise.resolve(); - }, - - observe: function (subject, topic, data) { - switch (topic) { - case "weave:service:sync:start": - case "weave:service:sync:finish": - case "weave:service:sync:error": - return this._observeSync(subject, topic, data); - - case "fxa-migration:state-changed": - case "fxa-migration:internal-state-changed": - case "fxa-migration:internal-telemetry": - return this._observeMigration(subject, topic, data); - } - Cu.reportError("unexpected topic in sync healthreport provider: " + topic); - }, - - _observeSync: function (subject, topic, data) { - let field; - switch (topic) { - case "weave:service:sync:start": - field = "syncStart"; - break; - - case "weave:service:sync:finish": - field = "syncSuccess"; - break; - - case "weave:service:sync:error": - field = "syncError"; - break; - - default: - Cu.reportError("unexpected sync topic in sync healthreport provider: " + topic); - return; - } - - let m = this.getMeasurement(SyncMeasurement1.prototype.name, - SyncMeasurement1.prototype.version); - return this.enqueueStorageOperation(function recordSyncEvent() { - return m.incrementDailyCounter(field); - }); - }, - - _observeMigration: function(subject, topic, data) { - switch (topic) { - case "fxa-migration:state-changed": - case "fxa-migration:internal-state-changed": { - // We record both "user" and "internal" states in the same field. This - // works for us as user state is always null when there is an internal - // state. - if (!data) { - return; // we don't count the |null| state - } - let m = this.getMeasurement(SyncMigrationMeasurement1.prototype.name, - SyncMigrationMeasurement1.prototype.version); - return this.enqueueStorageOperation(function() { - return m.setDailyLastText("state", data); - }); - } - - case "fxa-migration:internal-telemetry": { - // |data| is our field name. - let m = this.getMeasurement(SyncMigrationMeasurement1.prototype.name, - SyncMigrationMeasurement1.prototype.version); - return this.enqueueStorageOperation(function() { - switch (data) { - case "accepted": - case "declined": - return m.incrementDailyCounter(data); - case "unlinked": - return m.setDailyLastNumeric(data, 1); - default: - Cu.reportError("Unexpected migration field in sync healthreport provider: " + data); - return Promise.resolve(); - } - }); - } - - default: - Cu.reportError("unexpected migration topic in sync healthreport provider: " + topic); - return; - } - }, - - collectDailyData: function () { - return this.storage.enqueueTransaction(this._populateDailyData.bind(this)); - }, - - _populateDailyData: function* () { - let m = this.getMeasurement(SyncMeasurement1.prototype.name, - SyncMeasurement1.prototype.version); - - let svc = Cc["@mozilla.org/weave/service;1"] - .getService(Ci.nsISupports) - .wrappedJSObject; - - let enabled = svc.enabled; - yield m.setDailyLastNumeric("enabled", enabled ? 1 : 0); - - // preferredProtocol is constant and only changes as the client - // evolves. - yield m.setDailyLastText("preferredProtocol", "1.5"); - - let protocol = svc.fxAccountsEnabled ? "1.5" : "1.1"; - yield m.setDailyLastText("activeProtocol", protocol); - - if (!enabled) { - return; - } - - // Before grabbing more information, be sure the Sync service - // is fully initialized. This has the potential to initialize - // Sync on the spot. This may be undesired if Sync appears to - // be enabled but it really isn't. That responsibility should - // be up to svc.enabled to not return false positives, however. - yield svc.whenLoaded(); - - if (Weave.Status.service != Weave.STATUS_OK) { - return; - } - - // Device types are dynamic. So we need to dynamically create fields if - // they don't exist. - let dm = this.getMeasurement(SyncDevicesMeasurement1.prototype.name, - SyncDevicesMeasurement1.prototype.version); - let devices = Weave.Service.clientsEngine.deviceTypes; - for (let [field, count] of devices) { - let hasField = this.storage.hasFieldFromMeasurement(dm.id, field, - this.storage.FIELD_DAILY_LAST_NUMERIC); - let fieldID; - if (hasField) { - fieldID = this.storage.fieldIDFromMeasurement(dm.id, field); - } else { - fieldID = yield this.storage.registerField(dm.id, field, - this.storage.FIELD_DAILY_LAST_NUMERIC); - } - - yield this.storage.setDailyLastNumericFromFieldID(fieldID, count); - } - }, -}); diff --git a/services/sync/moz.build b/services/sync/moz.build index be3aadb0a..36607ec80 100644 --- a/services/sync/moz.build +++ b/services/sync/moz.build @@ -21,7 +21,6 @@ EXTRA_JS_MODULES['services-sync'] += [ 'modules/addonutils.js', 'modules/browserid_identity.js', 'modules/engines.js', - 'modules/healthreport.jsm', 'modules/identity.js', 'modules/jpakeclient.js', 'modules/keys.js', diff --git a/services/sync/tests/unit/test_block_sync.js b/services/sync/tests/unit/test_block_sync.js deleted file mode 100644 index f83b7b740..000000000 --- a/services/sync/tests/unit/test_block_sync.js +++ /dev/null @@ -1,37 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -Cu.import("resource://services-sync/main.js"); -Cu.import("resource://services-sync/util.js"); - -// Simple test for block/unblock. -add_task(function *() { - Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.") - Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref"); - Weave.Service.scheduler.blockSync(); - - Assert.ok(Weave.Service.scheduler.isBlocked, "sync is blocked.") - Assert.ok(Svc.Prefs.has("scheduler.blocked-until"), "have the blocked pref"); - - Weave.Service.scheduler.unblockSync(); - Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.") - Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref"); - - // now check the "until" functionality. - let until = Date.now() + 1000; - Weave.Service.scheduler.blockSync(until); - Assert.ok(Weave.Service.scheduler.isBlocked, "sync is blocked.") - Assert.ok(Svc.Prefs.has("scheduler.blocked-until"), "have the blocked pref"); - - // wait for 'until' to pass. - yield new Promise((resolve, reject) => { - CommonUtils.namedTimer(resolve, 1000, {}, "timer"); - }); - - // should have automagically unblocked and removed the pref. - Assert.ok(!Weave.Service.scheduler.isBlocked, "sync is not blocked.") - Assert.ok(!Svc.Prefs.has("scheduler.blocked-until"), "have no blocked pref"); -}); - -function run_test() { - run_next_test(); -} diff --git a/services/sync/tests/unit/test_fxa_migration.js b/services/sync/tests/unit/test_fxa_migration.js deleted file mode 100644 index 7c65d5996..000000000 --- a/services/sync/tests/unit/test_fxa_migration.js +++ /dev/null @@ -1,279 +0,0 @@ -// Test the FxAMigration module -Cu.import("resource://services-sync/FxaMigrator.jsm"); -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/FxAccounts.jsm"); -Cu.import("resource://gre/modules/FxAccountsCommon.js"); -Cu.import("resource://services-sync/browserid_identity.js"); - -// Set our username pref early so sync initializes with the legacy provider. -Services.prefs.setCharPref("services.sync.username", "foo"); -// And ensure all debug messages end up being printed. -Services.prefs.setCharPref("services.sync.log.appender.dump", "Debug"); - -// Now import sync -Cu.import("resource://services-sync/service.js"); -Cu.import("resource://services-sync/record.js"); -Cu.import("resource://services-sync/util.js"); - -// And reset the username. -Services.prefs.clearUserPref("services.sync.username"); - -Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://testing-common/services/common/logging.js"); -Cu.import("resource://testing-common/services/sync/rotaryengine.js"); - -const FXA_USERNAME = "someone@somewhere"; - -// Utilities -function promiseOneObserver(topic) { - return new Promise((resolve, reject) => { - let observer = function(subject, topic, data) { - Services.obs.removeObserver(observer, topic); - resolve({ subject: subject, data: data }); - } - Services.obs.addObserver(observer, topic, false); - }); -} - -function promiseStopServer(server) { - return new Promise((resolve, reject) => { - server.stop(resolve); - }); -} - - -// Helpers -function configureLegacySync() { - let engine = new RotaryEngine(Service); - engine.enabled = true; - Svc.Prefs.set("registerEngines", engine.name); - Svc.Prefs.set("log.logger.engine.rotary", "Trace"); - - let contents = { - meta: {global: {engines: {rotary: {version: engine.version, - syncID: engine.syncID}}}}, - crypto: {}, - rotary: {} - }; - - const USER = "foo"; - const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea"; - - setBasicCredentials(USER, "password", PASSPHRASE); - - let onRequest = function(request, response) { - // ideally we'd only do this while a legacy user is configured, but WTH. - response.setHeader("x-weave-alert", JSON.stringify({code: "soft-eol"})); - } - let server = new SyncServer({onRequest: onRequest}); - server.registerUser(USER, "password"); - server.createContents(USER, contents); - server.start(); - - Service.serverURL = server.baseURI; - Service.clusterURL = server.baseURI; - Service.identity.username = USER; - Service._updateCachedURLs(); - - Service.engineManager._engines[engine.name] = engine; - - return [engine, server]; -} - -function configureFxa() { - Services.prefs.setCharPref("identity.fxaccounts.auth.uri", "http://localhost"); -} - -add_task(function *testMigration() { - configureFxa(); - - // when we do a .startOver we want the new provider. - let oldValue = Services.prefs.getBoolPref("services.sync-testing.startOverKeepIdentity"); - Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", false); - - // disable the addons engine - this engine choice is arbitrary, but we - // want to check it remains disabled after migration. - Services.prefs.setBoolPref("services.sync.engine.addons", false); - - do_register_cleanup(() => { - Services.prefs.setBoolPref("services.sync-testing.startOverKeepIdentity", oldValue) - Services.prefs.setBoolPref("services.sync.engine.addons", true); - }); - - // No sync user - that should report no user-action necessary. - Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null, - "no user state when complete"); - - // Arrange for a legacy sync user and manually bump the migrator - let [engine, server] = configureLegacySync(); - - // Check our disabling of the "addons" engine worked, and for good measure, - // that the "passwords" engine is enabled. - Assert.ok(!Service.engineManager.get("addons").enabled, "addons is disabled"); - Assert.ok(Service.engineManager.get("passwords").enabled, "passwords is enabled"); - - // monkey-patch the migration sentinel code so we know it was called. - let haveStartedSentinel = false; - let origSetFxAMigrationSentinel = Service.setFxAMigrationSentinel; - let promiseSentinelWritten = new Promise((resolve, reject) => { - Service.setFxAMigrationSentinel = function(arg) { - haveStartedSentinel = true; - return origSetFxAMigrationSentinel.call(Service, arg).then(result => { - Service.setFxAMigrationSentinel = origSetFxAMigrationSentinel; - resolve(result); - return result; - }); - } - }); - - // We are now configured for legacy sync, but we aren't in an EOL state yet, - // so should still be not waiting for a user. - Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), null, - "no user state before server EOL"); - - // Start a sync - this will cause an EOL notification which the migrator's - // observer will notice. - let promise = promiseOneObserver("fxa-migration:state-changed"); - _("Starting sync"); - Service.sync(); - _("Finished sync"); - - // We should have seen the observer, so be waiting for an FxA user. - Assert.equal((yield promise).data, fxaMigrator.STATE_USER_FXA, "now waiting for FxA.") - - // Re-calling our user-state promise should also reflect the same state. - Assert.equal((yield fxaMigrator._queueCurrentUserState()), - fxaMigrator.STATE_USER_FXA, - "still waiting for FxA."); - - // arrange for an unverified FxA user. - let config = makeIdentityConfig({username: FXA_USERNAME}); - let fxa = new FxAccounts({}); - config.fxaccount.user.email = config.username; - delete config.fxaccount.user.verified; - // *sob* - shouldn't need this boilerplate - fxa.internal.currentAccountState.getCertificate = function(data, keyPair, mustBeValidUntil) { - this.cert = { - validUntil: fxa.internal.now() + CERT_LIFETIME, - cert: "certificate", - }; - return Promise.resolve(this.cert.cert); - }; - - // As soon as we set the FxA user the observers should fire and magically - // transition. - promise = promiseOneObserver("fxa-migration:state-changed"); - fxAccounts.setSignedInUser(config.fxaccount.user); - - let observerInfo = yield promise; - Assert.equal(observerInfo.data, - fxaMigrator.STATE_USER_FXA_VERIFIED, - "now waiting for verification"); - Assert.ok(observerInfo.subject instanceof Ci.nsISupportsString, - "email was passed to observer"); - Assert.equal(observerInfo.subject.data, - FXA_USERNAME, - "email passed to observer is correct"); - - // should have seen the user set, so state should automatically update. - Assert.equal((yield fxaMigrator._queueCurrentUserState()), - fxaMigrator.STATE_USER_FXA_VERIFIED, - "now waiting for verification"); - - // Before we verify the user, fire off a sync that calls us back during - // the sync and before it completes - this way we can ensure we do the right - // thing in terms of blocking sync and waiting for it to complete. - - let wasWaiting = false; - // This is a PITA as sync is pseudo-blocking. - engine._syncFinish = function () { - // We aren't in a generator here, so use a helper to block on promises. - function getState() { - let cb = Async.makeSpinningCallback(); - fxaMigrator._queueCurrentUserState().then(state => cb(null, state)); - return cb.wait(); - } - // should still be waiting for verification. - Assert.equal(getState(), fxaMigrator.STATE_USER_FXA_VERIFIED, - "still waiting for verification"); - - // arrange for the user to be verified. The fxAccount's mock story is - // broken, so go behind its back. - config.fxaccount.user.verified = true; - fxAccounts.setSignedInUser(config.fxaccount.user); - Services.obs.notifyObservers(null, ONVERIFIED_NOTIFICATION, null); - - // spinningly wait for the migrator to catch up - sync is running so - // we should be in a 'null' user-state as there is no user-action - // necessary. - let cb = Async.makeSpinningCallback(); - promiseOneObserver("fxa-migration:state-changed").then(({ data: state }) => cb(null, state)); - Assert.equal(cb.wait(), null, "no user action necessary while sync completes."); - - // We must not have started writing the sentinel yet. - Assert.ok(!haveStartedSentinel, "haven't written a sentinel yet"); - - // sync should be blocked from continuing - Assert.ok(Service.scheduler.isBlocked, "sync is blocked.") - - wasWaiting = true; - throw ex; - }; - - _("Starting sync"); - Service.sync(); - _("Finished sync"); - - // mock sync so we can ensure the final sync is scheduled with the FxA user. - // (letting a "normal" sync complete is a PITA without mocking huge amounts - // of FxA infra) - let promiseFinalSync = new Promise((resolve, reject) => { - let oldSync = Service.sync; - Service.sync = function() { - Service.sync = oldSync; - resolve(); - } - }); - - Assert.ok(wasWaiting, "everything was good while sync was running.") - - // The migration is now going to run to completion. - // sync should still be "blocked" - Assert.ok(Service.scheduler.isBlocked, "sync is blocked."); - - // We should see the migration sentinel written and it should return true. - Assert.ok((yield promiseSentinelWritten), "wrote the sentinel"); - - // And we should see a new sync start - yield promiseFinalSync; - - // and we should be configured for FxA - let WeaveService = Cc["@mozilla.org/weave/service;1"] - .getService(Components.interfaces.nsISupports) - .wrappedJSObject; - Assert.ok(WeaveService.fxAccountsEnabled, "FxA is enabled"); - Assert.ok(Service.identity instanceof BrowserIDManager, - "sync is configured with the browserid_identity provider."); - Assert.equal(Service.identity.username, config.username, "correct user configured") - Assert.ok(!Service.scheduler.isBlocked, "sync is not blocked.") - // and the user state should remain null. - Assert.deepEqual((yield fxaMigrator._queueCurrentUserState()), - null, - "still no user action necessary"); - // and our engines should be in the same enabled/disabled state as before. - Assert.ok(!Service.engineManager.get("addons").enabled, "addons is still disabled"); - Assert.ok(Service.engineManager.get("passwords").enabled, "passwords is still enabled"); - - // aaaand, we are done - clean up. - yield promiseStopServer(server); -}); - - -function run_test() { - initTestLogging(); - do_register_cleanup(() => { - fxaMigrator.finalize(); - Svc.Prefs.resetBranch(""); - }); - run_next_test(); -} diff --git a/services/sync/tests/unit/test_fxa_migration_sentinel.js b/services/sync/tests/unit/test_fxa_migration_sentinel.js deleted file mode 100644 index bed2dd756..000000000 --- a/services/sync/tests/unit/test_fxa_migration_sentinel.js +++ /dev/null @@ -1,150 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Test the reading and writing of the sync migration sentinel. -Cu.import("resource://gre/modules/Promise.jsm"); -Cu.import("resource://gre/modules/FxAccounts.jsm"); -Cu.import("resource://gre/modules/FxAccountsCommon.js"); - -Cu.import("resource://testing-common/services/sync/utils.js"); -Cu.import("resource://testing-common/services/common/logging.js"); - -Cu.import("resource://services-sync/record.js"); - -// Set our username pref early so sync initializes with the legacy provider. -Services.prefs.setCharPref("services.sync.username", "foo"); - -// Now import sync -Cu.import("resource://services-sync/service.js"); - -const USER = "foo"; -const PASSPHRASE = "abcdeabcdeabcdeabcdeabcdea"; - -function promiseStopServer(server) { - return new Promise((resolve, reject) => { - server.stop(resolve); - }); -} - -let numServerRequests = 0; - -// Helpers -function configureLegacySync() { - let contents = { - meta: {global: {}}, - crypto: {}, - }; - - setBasicCredentials(USER, "password", PASSPHRASE); - - numServerRequests = 0; - let server = new SyncServer({ - onRequest: () => { - ++numServerRequests - } - }); - server.registerUser(USER, "password"); - server.createContents(USER, contents); - server.start(); - - Service.serverURL = server.baseURI; - Service.clusterURL = server.baseURI; - Service.identity.username = USER; - Service._updateCachedURLs(); - - return server; -} - -// Test a simple round-trip of the get/set functions. -add_task(function *() { - // Arrange for a legacy sync user. - let server = configureLegacySync(); - - Assert.equal((yield Service.getFxAMigrationSentinel()), null, "no sentinel to start"); - - let sentinel = {foo: "bar"}; - yield Service.setFxAMigrationSentinel(sentinel); - - Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back"); - - yield promiseStopServer(server); -}); - -// Test the records are cached by the record manager. -add_task(function *() { - // Arrange for a legacy sync user. - let server = configureLegacySync(); - Service.login(); - - // Reset the request count here as the login would have made some. - numServerRequests = 0; - - Assert.equal((yield Service.getFxAMigrationSentinel()), null, "no sentinel to start"); - Assert.equal(numServerRequests, 1, "first fetch should hit the server"); - - let sentinel = {foo: "bar"}; - yield Service.setFxAMigrationSentinel(sentinel); - Assert.equal(numServerRequests, 2, "setting sentinel should hit the server"); - - Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back"); - Assert.equal(numServerRequests, 2, "second fetch should not should hit the server"); - - // Clobber the caches and ensure we still get the correct value back when we - // do hit the server. - Service.recordManager.clearCache(); - Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got the sentinel back"); - Assert.equal(numServerRequests, 3, "should have re-hit the server with empty caches"); - - yield promiseStopServer(server); -}); - -// Test the records are cached by a sync. -add_task(function* () { - let server = configureLegacySync(); - - // A first sync clobbers meta/global due to it being empty, so we first - // do a sync which forces a good set of data on the server. - Service.sync(); - - // Now create a sentinel exists on the server. It's encrypted, so we need to - // put an encrypted version. - let cryptoWrapper = new CryptoWrapper("meta", "fxa_credentials"); - let sentinel = {foo: "bar"}; - cryptoWrapper.cleartext = { - id: "fxa_credentials", - sentinel: sentinel, - deleted: false, - } - cryptoWrapper.encrypt(Service.identity.syncKeyBundle); - let payload = { - ciphertext: cryptoWrapper.ciphertext, - IV: cryptoWrapper.IV, - hmac: cryptoWrapper.hmac, - }; - - server.createContents(USER, { - meta: {fxa_credentials: payload}, - crypto: {}, - }); - - // Another sync - this will cause the encrypted record to be fetched. - Service.sync(); - // Reset the request count here as the sync will have made many! - numServerRequests = 0; - - // Asking for the sentinel should use the copy cached in the record manager. - Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got it"); - Assert.equal(numServerRequests, 0, "should not have hit the server"); - - // And asking for it again should work (we have to work around the fact the - // ciphertext is clobbered on first decrypt...) - Assert.deepEqual((yield Service.getFxAMigrationSentinel()), sentinel, "got it again"); - Assert.equal(numServerRequests, 0, "should not have hit the server"); - - yield promiseStopServer(server); -}); - -function run_test() { - initTestLogging(); - run_next_test(); -} diff --git a/services/sync/tests/unit/test_healthreport.js b/services/sync/tests/unit/test_healthreport.js deleted file mode 100644 index 486320b6a..000000000 --- a/services/sync/tests/unit/test_healthreport.js +++ /dev/null @@ -1,194 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://gre/modules/Metrics.jsm", this); -Cu.import("resource://gre/modules/Preferences.jsm", this); -Cu.import("resource://gre/modules/Promise.jsm", this); -Cu.import("resource://services-sync/main.js", this); -Cu.import("resource://services-sync/healthreport.jsm", this); -Cu.import("resource://testing-common/services/common/logging.js", this); -Cu.import("resource://testing-common/services/healthreport/utils.jsm", this); - -function run_test() { - initTestLogging(); - - run_next_test(); -} - -add_task(function test_constructor() { - let provider = new SyncProvider(); -}); - -// Provider can initialize and de-initialize properly. -add_task(function* test_init() { - let storage = yield Metrics.Storage("init"); - let provider = new SyncProvider(); - yield provider.init(storage); - yield provider.shutdown(); - yield storage.close(); -}); - -add_task(function* test_collect() { - let storage = yield Metrics.Storage("collect"); - let provider = new SyncProvider(); - yield provider.init(storage); - - // Initially nothing should be configured. - let now = new Date(); - yield provider.collectDailyData(); - - let m = provider.getMeasurement("sync", 1); - let values = yield m.getValues(); - Assert.equal(values.days.size, 1); - Assert.ok(values.days.hasDay(now)); - let day = values.days.getDay(now); - Assert.ok(day.has("enabled")); - Assert.ok(day.has("activeProtocol")); - Assert.ok(day.has("preferredProtocol")); - Assert.equal(day.get("enabled"), 0); - Assert.equal(day.get("preferredProtocol"), "1.5"); - Assert.equal(day.get("activeProtocol"), "1.5", - "Protocol without setup should be FX Accounts version."); - - // Now check for old Sync setup. - let branch = new Preferences("services.sync."); - branch.set("username", "foo"); - branch.reset("fxaccounts.enabled"); - yield provider.collectDailyData(); - values = yield m.getValues(); - Assert.equal(values.days.getDay(now).get("activeProtocol"), "1.1", - "Protocol with old Sync setup is correct."); - - Assert.equal(Weave.Status.__authManager, undefined, "Detect code changes"); - - // Let's enable Sync so we can get more useful data. - // We need to do this because the FHR probe only records more info if Sync - // is configured properly. - Weave.Service.identity.account = "johndoe"; - Weave.Service.identity.basicPassword = "ilovejane"; - Weave.Service.identity.syncKey = Weave.Utils.generatePassphrase(); - Weave.Service.clusterURL = "http://localhost/"; - Assert.equal(Weave.Status.checkSetup(), Weave.STATUS_OK); - - yield provider.collectDailyData(); - values = yield m.getValues(); - day = values.days.getDay(now); - Assert.equal(day.get("enabled"), 1); - - // An empty account should have 1 device: us. - let dm = provider.getMeasurement("devices", 1); - values = yield dm.getValues(); - Assert.ok(values.days.hasDay(now)); - day = values.days.getDay(now); - Assert.equal(day.size, 1); - let engine = Weave.Service.clientsEngine; - Assert.ok(engine); - Assert.ok(day.has(engine.localType)); - Assert.equal(day.get(engine.localType), 1); - - // Add some devices and ensure they show up. - engine._store._remoteClients["id1"] = {type: "mobile"}; - engine._store._remoteClients["id2"] = {type: "tablet"}; - engine._store._remoteClients["id3"] = {type: "mobile"}; - - yield provider.collectDailyData(); - values = yield dm.getValues(); - day = values.days.getDay(now); - - let expected = { - "foobar": 0, - "tablet": 1, - "mobile": 2, - "desktop": 0, - }; - - for (let type in expected) { - let count = expected[type]; - - if (engine.localType == type) { - count++; - } - - if (!count) { - Assert.ok(!day.has(type)); - } else { - Assert.ok(day.has(type)); - Assert.equal(day.get(type), count); - } - } - - engine._store._remoteClients = {}; - - yield provider.shutdown(); - yield storage.close(); -}); - -add_task(function* test_sync_events() { - let storage = yield Metrics.Storage("sync_events"); - let provider = new SyncProvider(); - yield provider.init(storage); - - let m = provider.getMeasurement("sync", 1); - - for (let i = 0; i < 5; i++) { - Services.obs.notifyObservers(null, "weave:service:sync:start", null); - } - - for (let i = 0; i < 3; i++) { - Services.obs.notifyObservers(null, "weave:service:sync:finish", null); - } - - for (let i = 0; i < 2; i++) { - Services.obs.notifyObservers(null, "weave:service:sync:error", null); - } - - // Wait for storage to complete. - yield m.storage.enqueueOperation(() => { - return Promise.resolve(); - }); - - let values = yield m.getValues(); - let now = new Date(); - Assert.ok(values.days.hasDay(now)); - let day = values.days.getDay(now); - - Assert.ok(day.has("syncStart")); - Assert.ok(day.has("syncSuccess")); - Assert.ok(day.has("syncError")); - Assert.equal(day.get("syncStart"), 5); - Assert.equal(day.get("syncSuccess"), 3); - Assert.equal(day.get("syncError"), 2); - - yield provider.shutdown(); - yield storage.close(); -}); - -add_task(function* test_healthreporter_json() { - let reporter = yield getHealthReporter("healthreporter_json"); - yield reporter.init(); - try { - yield reporter._providerManager.registerProvider(new SyncProvider()); - yield reporter.collectMeasurements(); - let payload = yield reporter.getJSONPayload(true); - let now = new Date(); - let today = reporter._formatDate(now); - - Assert.ok(today in payload.data.days); - let day = payload.data.days[today]; - - Assert.ok("org.mozilla.sync.sync" in day); - Assert.ok("org.mozilla.sync.devices" in day); - - let devices = day["org.mozilla.sync.devices"]; - let engine = Weave.Service.clientsEngine; - Assert.ok(engine); - let type = engine.localType; - Assert.ok(type); - Assert.ok(type in devices); - Assert.equal(devices[type], 1); - } finally { - reporter._shutdown(); - } -}); diff --git a/services/sync/tests/unit/test_healthreport_migration.js b/services/sync/tests/unit/test_healthreport_migration.js deleted file mode 100644 index 23f756748..000000000 --- a/services/sync/tests/unit/test_healthreport_migration.js +++ /dev/null @@ -1,155 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -"use strict"; - -Cu.import("resource://gre/modules/Metrics.jsm", this); -Cu.import("resource://gre/modules/Preferences.jsm", this); -Cu.import("resource://gre/modules/Promise.jsm", this); -Cu.import("resource://services-sync/healthreport.jsm", this); -Cu.import("resource://services-sync/FxaMigrator.jsm", this); -Cu.import("resource://testing-common/services/common/logging.js", this); -Cu.import("resource://testing-common/services/healthreport/utils.jsm", this); - - -function run_test() { - initTestLogging(); - - run_next_test(); -} - -add_task(function* test_no_data() { - let storage = yield Metrics.Storage("collect"); - let provider = new SyncProvider(); - yield provider.init(storage); - - try { - // Initially nothing should be configured. - let now = new Date(); - yield provider.collectDailyData(); - - let m = provider.getMeasurement("migration", 1); - let values = yield m.getValues(); - Assert.equal(values.days.size, 0); - Assert.ok(!values.days.hasDay(now)); - } finally { - yield provider.shutdown(); - yield storage.close(); - } -}); - -function checkCorrectStateRecorded(provider, state) { - // Wait for storage to complete. - yield m.storage.enqueueOperation(() => { - return Promise.resolve(); - }); - - let m = provider.getMeasurement("migration", 1); - let values = yield m.getValues(); - Assert.equal(values.days.size, 1); - Assert.ok(values.days.hasDay(now)); - let day = values.days.getDay(now); - - Assert.ok(day.has("state")); - Assert.equal(day.get("state"), state); -} - -add_task(function* test_state() { - let storage = yield Metrics.Storage("collect"); - let provider = new SyncProvider(); - yield provider.init(storage); - - try { - // Initially nothing should be configured. - let now = new Date(); - - // We record both a "user" and "internal" state in the same field. - // So simulate a "user" state first. - Services.obs.notifyObservers(null, "fxa-migration:state-changed", - fxaMigrator.STATE_USER_FXA_VERIFIED); - checkCorrectStateRecorded(provider, fxaMigrator.STATE_USER_FXA_VERIFIED); - - // And an internal state. - Services.obs.notifyObservers(null, "fxa-migration:internal-state-changed", - fxaMigrator.STATE_INTERNAL_WAITING_SYNC_COMPLETE); - checkCorrectStateRecorded(provider, fxaMigrator.STATE_INTERNAL_WAITING_SYNC_COMPLETE); - } finally { - yield provider.shutdown(); - yield storage.close(); - } -}); - -add_task(function* test_flags() { - let storage = yield Metrics.Storage("collect"); - let provider = new SyncProvider(); - yield provider.init(storage); - - try { - // Initially nothing should be configured. - let now = new Date(); - - let m = provider.getMeasurement("migration", 1); - - let record = function*(what) { - Services.obs.notifyObservers(null, "fxa-migration:internal-telemetry", what); - // Wait for storage to complete. - yield m.storage.enqueueOperation(Promise.resolve); - let values = yield m.getValues(); - Assert.equal(values.days.size, 1); - return values.days.getDay(now); - } - - let values = yield m.getValues(); - Assert.equal(values.days.size, 1); - let day = values.days.getDay(now); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED)); - - // let's send an unknown value to ensure our error mitigation works. - day = yield record("unknown"); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED)); - - // record an fxaMigrator.TELEMETRY_ACCEPTED state. - day = yield record(fxaMigrator.TELEMETRY_ACCEPTED); - Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED)); - Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 1); - - // and again - it should get 2. - day = yield record(fxaMigrator.TELEMETRY_ACCEPTED); - Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2); - - // record fxaMigrator.TELEMETRY_DECLINED - also a counter. - day = yield record(fxaMigrator.TELEMETRY_DECLINED); - Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED)); - Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2); - Assert.equal(day.get(fxaMigrator.TELEMETRY_DECLINED), 1); - - day = yield record(fxaMigrator.TELEMETRY_DECLINED); - Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(!day.has(fxaMigrator.TELEMETRY_UNLINKED)); - Assert.equal(day.get(fxaMigrator.TELEMETRY_ACCEPTED), 2); - Assert.equal(day.get(fxaMigrator.TELEMETRY_DECLINED), 2); - - // and fxaMigrator.TELEMETRY_UNLINKED - this is conceptually a "daily bool". - // (ie, it's DAILY_LAST_NUMERIC_FIELD and only ever has |1| written to it) - day = yield record(fxaMigrator.TELEMETRY_UNLINKED); - Assert.ok(day.has(fxaMigrator.TELEMETRY_ACCEPTED)); - Assert.ok(day.has(fxaMigrator.TELEMETRY_DECLINED)); - Assert.ok(day.has(fxaMigrator.TELEMETRY_UNLINKED)); - Assert.equal(day.get(fxaMigrator.TELEMETRY_UNLINKED), 1); - // and doing it again still leaves us with |1| - day = yield record(fxaMigrator.TELEMETRY_UNLINKED); - Assert.equal(day.get(fxaMigrator.TELEMETRY_UNLINKED), 1); - } finally { - yield provider.shutdown(); - yield storage.close(); - } -}); diff --git a/services/sync/tests/unit/xpcshell.ini b/services/sync/tests/unit/xpcshell.ini index dc33c0eb2..7e97835ac 100644 --- a/services/sync/tests/unit/xpcshell.ini +++ b/services/sync/tests/unit/xpcshell.ini @@ -168,15 +168,4 @@ skip-if = debug [test_tab_store.js] [test_tab_tracker.js] -[test_healthreport.js] -skip-if = ! healthreport - -[test_healthreport_migration.js] -skip-if = ! healthreport - [test_warn_on_truncated_response.js] - -# FxA migration -[test_block_sync.js] -[test_fxa_migration.js] -[test_fxa_migration_sentinel.js] |