diff --git a/browser/base/content/browser-sync.js b/browser/base/content/browser-sync.js index 59d03b2ee69c..10878c070f66 100644 --- a/browser/base/content/browser-sync.js +++ b/browser/base/content/browser-sync.js @@ -565,7 +565,7 @@ var gSync = { const state = UIState.get(); if (state.status == UIState.STATUS_SIGNED_IN) { this.updateSyncStatus({ syncing: true }); - setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0); + Services.tm.dispatchToMainThread(() => Weave.Service.sync()); } }, diff --git a/services/sync/modules/constants.js b/services/sync/modules/constants.js index 69b65fcaca30..61a04f3785c7 100644 --- a/services/sync/modules/constants.js +++ b/services/sync/modules/constants.js @@ -106,7 +106,6 @@ CREDENTIALS_CHANGED: "error.sync.reason.credentials_changed", ABORT_SYNC_COMMAND: "aborting sync, process commands said so", NO_SYNC_NODE_FOUND: "error.sync.reason.no_node_found", OVER_QUOTA: "error.sync.reason.over_quota", -PROLONGED_SYNC_FAILURE: "error.sync.prolonged_failure", SERVER_MAINTENANCE: "error.sync.reason.serverMaintenance", RESPONSE_OVER_QUOTA: "14", diff --git a/services/sync/modules/policies.js b/services/sync/modules/policies.js index 9a24d5062774..1ccb2cb34dde 100644 --- a/services/sync/modules/policies.js +++ b/services/sync/modules/policies.js @@ -654,19 +654,7 @@ function ErrorHandler(service) { this.init(); } ErrorHandler.prototype = { - /** - * Flag that turns on error reporting for all errors, incl. network errors. - */ - dontIgnoreErrors: false, - - /** - * Flag that indicates if we have already reported a prolonged failure. - * Once set, we don't report it again, meaning this error is only reported - * one per run. - */ - didReportProlongedError: false, - - init: function init() { + init() { Svc.Obs.add("weave:engine:sync:applied", this); Svc.Obs.add("weave:engine:sync:error", this); Svc.Obs.add("weave:service:login:error", this); @@ -692,7 +680,7 @@ ErrorHandler.prototype = { this._logManager = new LogManager(Svc.Prefs, logs, "sync"); }, - observe: function observe(subject, topic, data) { + observe(subject, topic, data) { this._log.trace("Handling " + topic); switch (topic) { case "weave:engine:sync:applied": @@ -723,14 +711,6 @@ ErrorHandler.prototype = { case "weave:service:login:error": this._log.error("Sync encountered a login error"); this.resetFileLog(); - - if (this.shouldReportError()) { - this.notifyOnNextTick("weave:ui:login:error"); - } else { - this.notifyOnNextTick("weave:ui:clear-error"); - } - - this.dontIgnoreErrors = false; break; case "weave:service:sync:error": { if (Status.sync == CREDENTIALS_CHANGED) { @@ -749,14 +729,6 @@ ErrorHandler.prototype = { // Not a shutdown related exception... this._log.error("Sync encountered an error", exception); this.resetFileLog(); - - if (this.shouldReportError()) { - this.notifyOnNextTick("weave:ui:sync:error"); - } else { - this.notifyOnNextTick("weave:ui:sync:finish"); - } - - this.dontIgnoreErrors = false; break; } case "weave:service:sync:finish": @@ -775,18 +747,8 @@ ErrorHandler.prototype = { if (Status.service == SYNC_FAILED_PARTIAL) { this._log.error("Some engines did not sync correctly."); - this.resetFileLog(); - - if (this.shouldReportError()) { - this.dontIgnoreErrors = false; - this.notifyOnNextTick("weave:ui:sync:error"); - break; - } - } else { - this.resetFileLog(); } - this.dontIgnoreErrors = false; - this.notifyOnNextTick("weave:ui:sync:finish"); + this.resetFileLog(); break; case "weave:service:start-over:finish": // ensure we capture any logs between the last sync and the reset completing. @@ -795,27 +757,6 @@ ErrorHandler.prototype = { } }, - notifyOnNextTick: function notifyOnNextTick(topic) { - CommonUtils.nextTick(function() { - this._log.trace("Notifying " + topic + - ". Status.login is " + Status.login + - ". Status.sync is " + Status.sync); - Svc.Obs.notify(topic); - }, this); - }, - - /** - * Trigger a sync and don't muffle any errors, particularly network errors. - */ - syncAndReportErrors: function syncAndReportErrors() { - this._log.debug("Beginning user-triggered sync."); - - this.dontIgnoreErrors = true; - CommonUtils.nextTick(() => { - this.service.sync({why: "user"}); - }, this); - }, - async _dumpAddons() { // Just dump the items that sync may be concerned with. Specifically, // active extensions that are not hidden. @@ -837,108 +778,16 @@ ErrorHandler.prototype = { * Generate a log file for the sync that just completed * and refresh the input & output streams. */ - resetFileLog: function resetFileLog() { - let onComplete = logType => { - Svc.Obs.notify("weave:service:reset-file-log"); - this._log.trace("Notified: " + Date.now()); - if (logType == this._logManager.ERROR_LOG_WRITTEN) { - Cu.reportError("Sync encountered an error - see about:sync-log for the log file."); - } - }; - + async resetFileLog() { // If we're writing an error log, dump extensions that may be causing problems. - let beforeResetLog; if (this._logManager.sawError) { - beforeResetLog = this._dumpAddons(); - } else { - beforeResetLog = Promise.resolve(); + await this._dumpAddons(); } - // Note we do not return the promise here - the caller doesn't need to wait - // for this to complete. - beforeResetLog - .then(() => this._logManager.resetFileLog()) - .then(onComplete, onComplete); - }, - - /** - * Translates server error codes to meaningful strings. - * - * @param code - * server error code as an integer - */ - errorStr: function errorStr(code) { - switch (code.toString()) { - case "1": - return "illegal-method"; - case "2": - return "invalid-captcha"; - case "3": - return "invalid-username"; - case "4": - return "cannot-overwrite-resource"; - case "5": - return "userid-mismatch"; - case "6": - return "json-parse-failure"; - case "7": - return "invalid-password"; - case "8": - return "invalid-record"; - case "9": - return "weak-password"; - default: - return "generic-server-error"; + const logType = await this._logManager.resetFileLog(); + if (logType == this._logManager.ERROR_LOG_WRITTEN) { + Cu.reportError("Sync encountered an error - see about:sync-log for the log file."); } - }, - - // A function to indicate if Sync errors should be "reported" - which in this - // context really means "should be notify observers of an error" - but note - // that since bug 1180587, no one is going to surface an error to the user. - shouldReportError: function shouldReportError() { - if (Status.login == MASTER_PASSWORD_LOCKED) { - this._log.trace("shouldReportError: false (master password locked)."); - return false; - } - - if (this.dontIgnoreErrors) { - return true; - } - - if (Status.login == LOGIN_FAILED_LOGIN_REJECTED) { - // An explicit LOGIN_REJECTED state is always reported (bug 1081158) - this._log.trace("shouldReportError: true (login was rejected)"); - return true; - } - - let lastSync = Svc.Prefs.get("lastSync"); - if (lastSync && ((Date.now() - Date.parse(lastSync)) > - Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 1000)) { - Status.sync = PROLONGED_SYNC_FAILURE; - if (this.didReportProlongedError) { - this._log.trace("shouldReportError: false (prolonged sync failure, but" + - " we've already reported it)."); - return false; - } - this._log.trace("shouldReportError: true (first prolonged sync failure)."); - this.didReportProlongedError = true; - return true; - } - - // We got a 401 mid-sync. Wait for the next sync before actually handling - // an error. This assumes that we'll get a 401 again on a login fetch in - // order to report the error. - if (!this.service.clusterURL) { - this._log.trace("shouldReportError: false (no cluster URL; " + - "possible node reassignment)."); - return false; - } - - - let result = (![Status.login, Status.sync].includes(SERVER_MAINTENANCE) && - ![Status.login, Status.sync].includes(LOGIN_FAILED_NETWORK_ERROR)); - this._log.trace("shouldReportError: ${result} due to login=${login}, sync=${sync}", - {result, login: Status.login, sync: Status.sync}); - return result; + Svc.Obs.notify("weave:service:reset-file-log"); }, /** diff --git a/services/sync/services-sync.js b/services/sync/services-sync.js index 8ad7c5201e5a..5f3ca3899422 100644 --- a/services/sync/services-sync.js +++ b/services/sync/services-sync.js @@ -14,8 +14,6 @@ pref("services.sync.scheduler.idleTime", 300); // 5 minutes pref("services.sync.scheduler.fxa.singleDeviceInterval", 3600); // 1 hour -pref("services.sync.errorhandler.networkFailureReportTimeout", 1209600); // 2 weeks - // Note that new engines are typically added with a default of disabled, so // when an existing sync user gets the Firefox upgrade that supports the engine // it starts as disabled until the user has explicitly opted in. diff --git a/services/sync/tests/unit/test_errorhandler_1.js b/services/sync/tests/unit/test_errorhandler_1.js index 049f1293226a..cf70676be929 100644 --- a/services/sync/tests/unit/test_errorhandler_1.js +++ b/services/sync/tests/unit/test_errorhandler_1.js @@ -12,8 +12,9 @@ ChromeUtils.import("resource://services-sync/util.js"); ChromeUtils.import("resource://gre/modules/FileUtils.jsm"); ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); -var fakeServer = new SyncServer(); +const fakeServer = new SyncServer(); fakeServer.start(); +const fakeServerUrl = "http://localhost:" + fakeServer.port; registerCleanupFunction(function() { return promiseStopServer(fakeServer).finally(() => { @@ -21,25 +22,7 @@ registerCleanupFunction(function() { }); }); -var fakeServerUrl = "http://localhost:" + fakeServer.port; - -const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true); - -const PROLONGED_ERROR_DURATION = - (Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000; - -const NON_PROLONGED_ERROR_DURATION = - (Svc.Prefs.get("errorhandler.networkFailureReportTimeout") / 2) * 1000; - -function setLastSync(lastSyncValue) { - Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString()); -} - -// This relies on Service/ErrorHandler being a singleton. Fixing this will take -// a lot of work. -let errorHandler = Service.errorHandler; let engine; - add_task(async function setup() { await Service.engineManager.clear(); await Service.engineManager.register(EHTestsCommon.CatapultEngine); @@ -52,7 +35,6 @@ async function clean() { await promiseLogReset; Status.resetSync(); Status.resetBackoff(); - errorHandler.didReportProlongedError = false; // Move log levels back to trace (startOver will have reversed this), sicne syncTestLogging(); } @@ -130,259 +112,27 @@ add_task(async function test_credentials_changed_logout() { await promiseStopServer(server); }); -add_task(function test_no_lastSync_pref() { - syncTestLogging(); - // Test reported error. - Status.resetSync(); - errorHandler.dontIgnoreErrors = true; - Status.sync = CREDENTIALS_CHANGED; - Assert.ok(errorHandler.shouldReportError()); - - // Test unreported error. - Status.resetSync(); - errorHandler.dontIgnoreErrors = true; - Status.login = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - -}); - -add_task(function test_shouldReportError() { - Status.login = MASTER_PASSWORD_LOCKED; - Assert.ok(!errorHandler.shouldReportError()); - - // Give ourselves a clusterURL so that the temporary 401 no-error situation - // doesn't come into play. - Service.clusterURL = fakeServerUrl; - - // Test dontIgnoreErrors, non-network, non-prolonged, sync error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = CREDENTIALS_CHANGED; - Assert.ok(errorHandler.shouldReportError()); - - // Test dontIgnoreErrors, non-network, prolonged, sync error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = CREDENTIALS_CHANGED; - Assert.ok(errorHandler.shouldReportError()); - - // Test dontIgnoreErrors, network, non-prolonged, login error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.login = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - - // Test dontIgnoreErrors, network, non-prolonged, sync error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - - // Test dontIgnoreErrors, network, prolonged, login error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.login = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - - // Test dontIgnoreErrors, network, prolonged, sync error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - - // Test non-network, prolonged, sync error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - errorHandler.didReportProlongedError = false; - Status.sync = CREDENTIALS_CHANGED; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(errorHandler.didReportProlongedError); - errorHandler.didReportProlongedError = false; - - // Test network, prolonged, login error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.login = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(errorHandler.didReportProlongedError); - errorHandler.didReportProlongedError = false; - - // Test network, prolonged, sync error reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.sync = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(errorHandler.didReportProlongedError); - errorHandler.didReportProlongedError = false; - - // Test non-network, non-prolonged, sync error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.sync = CREDENTIALS_CHANGED; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test network, non-prolonged, login error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.login = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(!errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test network, non-prolonged, sync error reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.sync = LOGIN_FAILED_NETWORK_ERROR; - Assert.ok(!errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test server maintenance, sync errors are not reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.sync = SERVER_MAINTENANCE; - Assert.ok(!errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test server maintenance, login errors are not reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.login = SERVER_MAINTENANCE; - Assert.ok(!errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test prolonged, server maintenance, sync errors are reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.sync = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(errorHandler.didReportProlongedError); - errorHandler.didReportProlongedError = false; - - // Test prolonged, server maintenance, login errors are reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = false; - Status.login = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(errorHandler.didReportProlongedError); - errorHandler.didReportProlongedError = false; - - // Test dontIgnoreErrors, server maintenance, sync errors are reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - // dontIgnoreErrors means we don't set didReportProlongedError - Assert.ok(!errorHandler.didReportProlongedError); - - // Test dontIgnoreErrors, server maintenance, login errors are reported - Status.resetSync(); - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.login = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test dontIgnoreErrors, prolonged, server maintenance, - // sync errors are reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.sync = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); - - // Test dontIgnoreErrors, prolonged, server maintenance, - // login errors are reported - Status.resetSync(); - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.dontIgnoreErrors = true; - Status.login = SERVER_MAINTENANCE; - Assert.ok(errorHandler.shouldReportError()); - Assert.ok(!errorHandler.didReportProlongedError); -}); - -add_task(async function test_shouldReportError_master_password() { - _("Test error ignored due to locked master password"); - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - // Monkey patch Service.verifyLogin to imitate - // master password being locked. - Service._verifyLogin = Service.verifyLogin; - Service.verifyLogin = async function() { - Status.login = MASTER_PASSWORD_LOCKED; - return false; - }; - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await Service.sync(); - Assert.ok(!errorHandler.shouldReportError()); - - // Clean up. - Service.verifyLogin = Service._verifyLogin; - await clean(); - await promiseStopServer(server); -}); - -// Test that even if we don't have a cluster URL, a login failure due to -// authentication errors is always reported. -add_task(function test_shouldReportLoginFailureWithNoCluster() { - // Ensure no clusterURL - any error not specific to login should not be reported. - Service.clusterURL = ""; - - // Test explicit "login rejected" state. - Status.resetSync(); - // If we have a LOGIN_REJECTED state, we always report the error. - Status.login = LOGIN_FAILED_LOGIN_REJECTED; - Assert.ok(errorHandler.shouldReportError()); - // But any other status with a missing clusterURL is treated as a mid-sync - // 401 (ie, should be treated as a node reassignment) - Status.login = LOGIN_SUCCEEDED; - Assert.ok(!errorHandler.shouldReportError()); -}); - -add_task(async function test_login_syncAndReportErrors_non_network_error() { +add_task(async function test_login_non_network_error() { enableValidationPrefs(); // Test non-network errors are reported - // when calling syncAndReportErrors + // when calling sync let server = await EHTestsCommon.sync_httpd_setup(); await EHTestsCommon.setUp(server); Service.identity._syncKeyBundle = null; - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseObserved; + await Service.sync(); Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE); await clean(); await promiseStopServer(server); }); -add_task(async function test_sync_syncAndReportErrors_non_network_error() { +add_task(async function test_sync_non_network_error() { enableValidationPrefs(); // Test non-network errors are reported - // when calling syncAndReportErrors + // when calling sync let server = await EHTestsCommon.sync_httpd_setup(); await EHTestsCommon.setUp(server); @@ -393,16 +143,12 @@ add_task(async function test_sync_syncAndReportErrors_non_network_error() { await EHTestsCommon.generateCredentialsChangedFailure(); - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - let ping = await wait_for_ping(() => errorHandler.syncAndReportErrors(), true); + let ping = await sync_and_validate_telem(true); equal(ping.status.sync, CREDENTIALS_CHANGED); deepEqual(ping.failureReason, { name: "unexpectederror", error: "Error: Aborting sync, remote setup failed" }); - await promiseObserved; Assert.equal(Status.sync, CREDENTIALS_CHANGED); // If we clean this tick, telemetry won't get the right error @@ -411,219 +157,33 @@ add_task(async function test_sync_syncAndReportErrors_non_network_error() { await promiseStopServer(server); }); -add_task(async function test_login_syncAndReportErrors_prolonged_non_network_error() { +add_task(async function test_login_sync_network_error() { enableValidationPrefs(); - // Test prolonged, non-network errors are - // reported when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - Service.identity._syncKeyBundle = null; - - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseObserved; - Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_sync_syncAndReportErrors_prolonged_non_network_error() { - enableValidationPrefs(); - - // Test prolonged, non-network errors are - // reported when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - // By calling sync, we ensure we're logged in. - await Service.sync(); - Assert.equal(Status.sync, SYNC_SUCCEEDED); - Assert.ok(Service.isLoggedIn); - - await EHTestsCommon.generateCredentialsChangedFailure(); - - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - let ping = await wait_for_ping(() => errorHandler.syncAndReportErrors(), true); - equal(ping.status.sync, CREDENTIALS_CHANGED); - deepEqual(ping.failureReason, { - name: "unexpectederror", - error: "Error: Aborting sync, remote setup failed" - }); - await promiseObserved; - - Assert.equal(Status.sync, CREDENTIALS_CHANGED); - // If we clean this tick, telemetry won't get the right error - await Async.promiseYield(); - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_login_syncAndReportErrors_network_error() { - enableValidationPrefs(); - - // Test network errors are reported when calling syncAndReportErrors. + // Test network errors are reported when calling sync. await configureIdentity({username: "broken.wipe"}); Service.clusterURL = fakeServerUrl; - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseObserved; - + await Service.sync(); Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR); await clean(); }); -add_task(async function test_sync_syncAndReportErrors_network_error() { +add_task(async function test_sync_network_error() { enableValidationPrefs(); - // Test network errors are reported when calling syncAndReportErrors. + // Test network errors are reported when calling sync. Services.io.offline = true; - let promiseUISyncError = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseUISyncError; + await Service.sync(); Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR); Services.io.offline = false; await clean(); }); -add_task(async function test_login_syncAndReportErrors_prolonged_network_error() { - enableValidationPrefs(); - - // Test prolonged, network errors are reported - // when calling syncAndReportErrors. - await configureIdentity({username: "johndoe"}); - - Service.clusterURL = fakeServerUrl; - - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseObserved; - Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR); - - await clean(); -}); - -add_task(async function test_sync_syncAndReportErrors_prolonged_network_error() { - enableValidationPrefs(); - - // Test prolonged, network errors are reported - // when calling syncAndReportErrors. - Services.io.offline = true; - - let promiseUISyncError = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - errorHandler.syncAndReportErrors(); - await promiseUISyncError; - Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR); - - Services.io.offline = false; - await clean(); -}); - -add_task(async function test_login_prolonged_non_network_error() { - enableValidationPrefs(); - - // Test prolonged, non-network errors are reported - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - Service.identity._syncKeyBundle = null; - - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - await Service.sync(); - await promiseObserved; - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_sync_prolonged_non_network_error() { - enableValidationPrefs(); - - // Test prolonged, non-network errors are reported - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - // By calling sync, we ensure we're logged in. - await Service.sync(); - Assert.equal(Status.sync, SYNC_SUCCEEDED); - Assert.ok(Service.isLoggedIn); - - await EHTestsCommon.generateCredentialsChangedFailure(); - - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - - let ping = await sync_and_validate_telem(true); - equal(ping.status.sync, PROLONGED_SYNC_FAILURE); - deepEqual(ping.failureReason, { - name: "unexpectederror", - error: "Error: Aborting sync, remote setup failed" - }); - await promiseObserved; - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_login_prolonged_network_error() { - enableValidationPrefs(); - - // Test prolonged, network errors are reported - await configureIdentity({username: "johndoe"}); - Service.clusterURL = fakeServerUrl; - - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - await Service.sync(); - await promiseObserved; - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); - - await clean(); -}); - -add_task(async function test_sync_prolonged_network_error() { - enableValidationPrefs(); - - // Test prolonged, network errors are reported - Services.io.offline = true; - - let promiseUISyncError = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(PROLONGED_ERROR_DURATION); - await Service.sync(); - await promiseUISyncError; - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); - - Services.io.offline = false; - await clean(); -}); - add_task(async function test_login_non_network_error() { enableValidationPrefs(); @@ -632,13 +192,8 @@ add_task(async function test_login_non_network_error() { await EHTestsCommon.setUp(server); Service.identity._syncKeyBundle = null; - let promiseObserved = promiseOneObserver("weave:ui:login:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseObserved; Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE); - Assert.ok(!errorHandler.didReportProlongedError); await clean(); await promiseStopServer(server); @@ -658,13 +213,8 @@ add_task(async function test_sync_non_network_error() { await EHTestsCommon.generateCredentialsChangedFailure(); - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseObserved; Assert.equal(Status.sync, CREDENTIALS_CHANGED); - Assert.ok(!errorHandler.didReportProlongedError); await clean(); await promiseStopServer(server); @@ -676,14 +226,10 @@ add_task(async function test_login_network_error() { await configureIdentity({username: "johndoe"}); Service.clusterURL = fakeServerUrl; - let promiseObserved = promiseOneObserver("weave:ui:clear-error"); // Test network errors are not reported. - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseObserved; Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR); - Assert.ok(!errorHandler.didReportProlongedError); Services.io.offline = false; await clean(); @@ -695,13 +241,8 @@ add_task(async function test_sync_network_error() { // Test network errors are not reported. Services.io.offline = true; - let promiseSyncFinished = promiseOneObserver("weave:ui:sync:finish"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseSyncFinished; Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR); - Assert.ok(!errorHandler.didReportProlongedError); Services.io.offline = false; await clean(); @@ -719,24 +260,14 @@ add_task(async function test_sync_server_maintenance_error() { engine.exception = {status: 503, headers: {"retry-after": BACKOFF}}; - function onSyncError() { - do_throw("Shouldn't get here!"); - } - Svc.Obs.add("weave:ui:sync:error", onSyncError); - Assert.equal(Status.service, STATUS_OK); - let promiseObserved = promiseOneObserver("weave:ui:sync:finish"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); let ping = await sync_and_validate_telem(true); equal(ping.status.sync, SERVER_MAINTENANCE); deepEqual(ping.engines.find(e => e.failureReason).failureReason, { name: "httperror", code: 503 }); - await promiseObserved; Assert.equal(Status.service, SYNC_FAILED_PARTIAL); Assert.equal(Status.sync, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); await clean(); await promiseStopServer(server); @@ -757,27 +288,16 @@ add_task(async function test_info_collections_login_server_maintenance_error() { backoffInterval = subject; }); - function onUIUpdate() { - do_throw("Shouldn't experience UI update!"); - } - Svc.Obs.add("weave:ui:login:error", onUIUpdate); - Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - let promiseObserved = promiseOneObserver("weave:ui:clear-error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseObserved; Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); Assert.equal(Status.service, LOGIN_FAILED); Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - Svc.Obs.remove("weave:ui:login:error", onUIUpdate); await clean(); await promiseStopServer(server); }); @@ -797,27 +317,16 @@ add_task(async function test_meta_global_login_server_maintenance_error() { backoffInterval = subject; }); - function onUIUpdate() { - do_throw("Shouldn't get here!"); - } - Svc.Obs.add("weave:ui:login:error", onUIUpdate); - Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - let promiseObserved = promiseOneObserver("weave:ui:clear-error"); - - setLastSync(NON_PROLONGED_ERROR_DURATION); await Service.sync(); - await promiseObserved; Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); Assert.equal(Status.service, LOGIN_FAILED); Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - Svc.Obs.remove("weave:ui:login:error", onUIUpdate); await clean(); await promiseStopServer(server); }); diff --git a/services/sync/tests/unit/test_errorhandler_2.js b/services/sync/tests/unit/test_errorhandler_2.js index a55c8c155d34..d6df38d94d86 100644 --- a/services/sync/tests/unit/test_errorhandler_2.js +++ b/services/sync/tests/unit/test_errorhandler_2.js @@ -12,15 +12,16 @@ ChromeUtils.import("resource://services-sync/util.js"); ChromeUtils.import("resource://gre/modules/FileUtils.jsm"); ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); -var fakeServer = new SyncServer(); +const fakeServer = new SyncServer(); fakeServer.start(); +const fakeServerUrl = "http://localhost:" + fakeServer.port; registerCleanupFunction(function() { - return promiseStopServer(fakeServer); + return promiseStopServer(fakeServer).finally(() => { + Svc.Prefs.resetBranch(""); + }); }); -var fakeServerUrl = "http://localhost:" + fakeServer.port; - const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true); function removeLogFiles() { @@ -40,38 +41,7 @@ function getLogFiles() { return result; } -const PROLONGED_ERROR_DURATION = - (Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000; - -const NON_PROLONGED_ERROR_DURATION = - (Svc.Prefs.get("errorhandler.networkFailureReportTimeout") / 2) * 1000; - -function setLastSync(lastSyncValue) { - Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString()); -} - -// This relies on Service/ErrorHandler being a singleton. Fixing this will take -// a lot of work. -var errorHandler = Service.errorHandler; let engine; - -async function syncAndWait(topic) { - let promise1 = promiseOneObserver(topic); - // also wait for the log file to be written - let promise2 = promiseOneObserver("weave:service:reset-file-log"); - await Service.sync(); - await promise1; - await promise2; -} - -async function syncAndReportErrorsAndWait(topic) { - let promise1 = promiseOneObserver(topic); - // also wait for the log file to be written - let promise2 = promiseOneObserver("weave:service:reset-file-log"); - errorHandler.syncAndReportErrors(); - await promise1; - await promise2; -} add_task(async function setup() { await Service.engineManager.clear(); await Service.engineManager.register(EHTestsCommon.CatapultEngine); @@ -84,7 +54,6 @@ async function clean() { await promiseLogReset; Status.resetSync(); Status.resetBackoff(); - errorHandler.didReportProlongedError = false; removeLogFiles(); // Move log levels back to trace (startOver will have reversed this), sicne syncTestLogging(); @@ -109,24 +78,34 @@ add_task(async function test_crypto_keys_login_server_maintenance_error() { backoffInterval = subject; }); - function onUIUpdate() { - do_throw("Shouldn't get here!"); - } - Svc.Obs.add("weave:ui:login:error", onUIUpdate); - Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:clear-error"); + await Service.sync(); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); Assert.equal(Status.service, LOGIN_FAILED); Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - Svc.Obs.remove("weave:ui:login:error", onUIUpdate); + await clean(); + await promiseStopServer(server); +}); + +add_task(async function test_sync_server_maintenance_error() { + enableValidationPrefs(); + + let server = await EHTestsCommon.sync_httpd_setup(); + await EHTestsCommon.setUp(server); + + await configureIdentity({username: "johndoe"}, server); + + Assert.equal(Status.service, STATUS_OK); + Assert.equal(Status.sync, SYNC_SUCCEEDED); + + Assert.equal(Status.service, SYNC_FAILED_PARTIAL); + Assert.equal(Status.sync, SERVER_MAINTENANCE); + await clean(); await promiseStopServer(server); }); @@ -166,10 +145,9 @@ add_task(async function test_lastSync_not_updated_on_complete_failure() { await promiseStopServer(server); }); -add_task(async function test_info_collections_login_prolonged_server_maintenance_error() { +add_task(async function test_info_collections_login_server_maintenance_error() { enableValidationPrefs(); - // Test info/collections prolonged server maintenance errors are reported. let server = await EHTestsCommon.sync_httpd_setup(); await EHTestsCommon.setUp(server); @@ -184,23 +162,20 @@ add_task(async function test_info_collections_login_prolonged_server_maintenance Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:login:error"); + await Service.sync(); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); + Assert.equal(Status.service, LOGIN_FAILED); + Assert.equal(Status.login, SERVER_MAINTENANCE); await clean(); await promiseStopServer(server); }); -add_task(async function test_meta_global_login_prolonged_server_maintenance_error() { +add_task(async function test_meta_global_login_server_maintenance_error() { enableValidationPrefs(); - // Test meta/global prolonged server maintenance errors are reported. let server = await EHTestsCommon.sync_httpd_setup(); await EHTestsCommon.setUp(server); @@ -215,23 +190,20 @@ add_task(async function test_meta_global_login_prolonged_server_maintenance_erro Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:login:error"); + await Service.sync(); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); + Assert.equal(Status.service, LOGIN_FAILED); + Assert.equal(Status.login, SERVER_MAINTENANCE); await clean(); await promiseStopServer(server); }); -add_task(async function test_download_crypto_keys_login_prolonged_server_maintenance_error() { +add_task(async function test_download_crypto_keys_login_server_maintenance_error() { enableValidationPrefs(); - // Test crypto/keys prolonged server maintenance errors are reported. let server = await EHTestsCommon.sync_httpd_setup(); await EHTestsCommon.setUp(server); @@ -248,22 +220,20 @@ add_task(async function test_download_crypto_keys_login_prolonged_server_mainten Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:login:error"); + await Service.sync(); + Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); + Assert.equal(Status.service, LOGIN_FAILED); + Assert.equal(Status.login, SERVER_MAINTENANCE); await clean(); await promiseStopServer(server); }); -add_task(async function test_upload_crypto_keys_login_prolonged_server_maintenance_error() { +add_task(async function test_upload_crypto_keys_login_server_maintenance_error() { enableValidationPrefs(); - // Test crypto/keys prolonged server maintenance errors are reported. let server = await EHTestsCommon.sync_httpd_setup(); // Start off with an empty account, do not upload a key. @@ -278,24 +248,20 @@ add_task(async function test_upload_crypto_keys_login_prolonged_server_maintenan Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:login:error"); + await Service.sync(); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); + Assert.equal(Status.service, LOGIN_FAILED); + Assert.equal(Status.login, SERVER_MAINTENANCE); await clean(); await promiseStopServer(server); }); -add_task(async function test_wipeServer_login_prolonged_server_maintenance_error() { +add_task(async function test_wipeServer_login_server_maintenance_error() { enableValidationPrefs(); - // Test that we report prolonged server maintenance errors that occur whilst - // wiping the server. let server = await EHTestsCommon.sync_httpd_setup(); // Start off with an empty account, do not upload a key. @@ -310,27 +276,22 @@ add_task(async function test_wipeServer_login_prolonged_server_maintenance_error Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndWait("weave:ui:login:error"); + await Service.sync(); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.ok(errorHandler.didReportProlongedError); + Assert.equal(Status.service, LOGIN_FAILED); + Assert.equal(Status.login, SERVER_MAINTENANCE); await clean(); await promiseStopServer(server); }); -add_task(async function test_wipeRemote_prolonged_server_maintenance_error() { +add_task(async function test_wipeRemote_server_maintenance_error() { enableValidationPrefs(); - // Test that we report prolonged server maintenance errors that occur whilst - // wiping all remote devices. let server = await EHTestsCommon.sync_httpd_setup(); - server.registerPathHandler("/1.1/broken.wipe/storage/catapult", EHTestsCommon.service_unavailable); await configureIdentity({username: "broken.wipe"}, server); await EHTestsCommon.generateAndUploadKeys(); @@ -343,447 +304,18 @@ add_task(async function test_wipeRemote_prolonged_server_maintenance_error() { backoffInterval = subject; }); - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - Assert.ok(!Status.enforceBackoff); Assert.equal(Status.service, STATUS_OK); Svc.Prefs.set("firstSync", "wipeRemote"); - setLastSync(PROLONGED_ERROR_DURATION); let ping = await sync_and_validate_telem(true); deepEqual(ping.failureReason, { name: "httperror", code: 503 }); - await promiseObserved; - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, SYNC_FAILED); - Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE); - Assert.equal(Svc.Prefs.get("firstSync"), "wipeRemote"); - Assert.ok(errorHandler.didReportProlongedError); - await promiseStopServer(server); - await clean(); -}); - -add_task(async function test_sync_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - const BACKOFF = 42; - engine.enabled = true; - engine.exception = {status: 503, - headers: {"retry-after": BACKOFF}}; - - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:sync:error"); - - Assert.equal(Status.service, SYNC_FAILED_PARTIAL); - Assert.equal(Status.sync, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_info_collections_login_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test info/collections server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.info"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_meta_global_login_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test meta/global server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.meta"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.keys"}, server); - // Force re-download of keys - Service.collectionKeys.clear(); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - - // Start off with an empty account, do not upload a key. - await configureIdentity({username: "broken.keys"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_wipeServer_login_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - - // Start off with an empty account, do not upload a key. - await configureIdentity({username: "broken.wipe"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_wipeRemote_syncAndReportErrors_server_maintenance_error() { - enableValidationPrefs(); - - // Test that we report prolonged server maintenance errors that occur whilst - // wiping all remote devices. - let server = await EHTestsCommon.sync_httpd_setup(); - - await configureIdentity({username: "broken.wipe"}, server); - await EHTestsCommon.generateAndUploadKeys(); - - engine.exception = null; - engine.enabled = true; - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - Svc.Prefs.set("firstSync", "wipeRemote"); - setLastSync(NON_PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:sync:error"); Assert.ok(Status.enforceBackoff); Assert.equal(backoffInterval, 42); Assert.equal(Status.service, SYNC_FAILED); Assert.equal(Status.sync, SERVER_MAINTENANCE); Assert.equal(Svc.Prefs.get("firstSync"), "wipeRemote"); - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test prolonged server maintenance errors are - // reported when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - const BACKOFF = 42; - engine.enabled = true; - engine.exception = {status: 503, - headers: {"retry-after": BACKOFF}}; - - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:sync:error"); - - Assert.equal(Status.service, SYNC_FAILED_PARTIAL); - Assert.equal(Status.sync, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test info/collections server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.info"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test meta/global server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.meta"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - await EHTestsCommon.setUp(server); - - await configureIdentity({username: "broken.keys"}, server); - // Force re-download of keys - Service.collectionKeys.clear(); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - - // Start off with an empty account, do not upload a key. - await configureIdentity({username: "broken.keys"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); - - await clean(); - await promiseStopServer(server); -}); - -add_task(async function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() { - enableValidationPrefs(); - - // Test crypto/keys server maintenance errors are reported - // when calling syncAndReportErrors. - let server = await EHTestsCommon.sync_httpd_setup(); - - // Start off with an empty account, do not upload a key. - await configureIdentity({username: "broken.wipe"}, server); - - let backoffInterval; - Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { - Svc.Obs.remove("weave:service:backoff:interval", observe); - backoffInterval = subject; - }); - - Assert.ok(!Status.enforceBackoff); - Assert.equal(Status.service, STATUS_OK); - - setLastSync(PROLONGED_ERROR_DURATION); - await syncAndReportErrorsAndWait("weave:ui:login:error"); - - Assert.ok(Status.enforceBackoff); - Assert.equal(backoffInterval, 42); - Assert.equal(Status.service, LOGIN_FAILED); - Assert.equal(Status.login, SERVER_MAINTENANCE); - // syncAndReportErrors means dontIgnoreErrors, which means - // didReportProlongedError not touched. - Assert.ok(!errorHandler.didReportProlongedError); await clean(); await promiseStopServer(server); @@ -845,19 +377,14 @@ add_task(async function test_sync_engine_generic_fail() { await promiseStopServer(server); }); -add_task(async function test_logs_on_sync_error_despite_shouldReportError() { +add_task(async function test_logs_on_sync_error() { enableValidationPrefs(); - _("Ensure that an error is still logged when weave:service:sync:error " + - "is notified, despite shouldReportError returning false."); - let log = Log.repository.getLogger("Sync.ErrorHandler"); Svc.Prefs.set("log.appender.file.logOnError", true); log.info("TESTING"); - // Ensure that we report no error. Status.login = MASTER_PASSWORD_LOCKED; - Assert.ok(!errorHandler.shouldReportError()); let promiseObserved = promiseOneObserver("weave:service:reset-file-log"); Svc.Obs.notify("weave:service:sync:error", {}); @@ -871,19 +398,14 @@ add_task(async function test_logs_on_sync_error_despite_shouldReportError() { await clean(); }); -add_task(async function test_logs_on_login_error_despite_shouldReportError() { +add_task(async function test_logs_on_login_error() { enableValidationPrefs(); - _("Ensure that an error is still logged when weave:service:login:error " + - "is notified, despite shouldReportError returning false."); - let log = Log.repository.getLogger("Sync.ErrorHandler"); Svc.Prefs.set("log.appender.file.logOnError", true); log.info("TESTING"); - // Ensure that we report no error. Status.login = MASTER_PASSWORD_LOCKED; - Assert.ok(!errorHandler.shouldReportError()); let promiseObserved = promiseOneObserver("weave:service:reset-file-log"); Svc.Obs.notify("weave:service:login:error", {}); diff --git a/services/sync/tests/unit/test_errorhandler_filelog.js b/services/sync/tests/unit/test_errorhandler_filelog.js index b7a1d549242e..90c638293c0b 100644 --- a/services/sync/tests/unit/test_errorhandler_filelog.js +++ b/services/sync/tests/unit/test_errorhandler_filelog.js @@ -18,15 +18,8 @@ const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true); const CLEANUP_DELAY = 2000; const DELAY_BUFFER = 500; // Buffer for timers on different OS platforms. -const PROLONGED_ERROR_DURATION = - (Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000; - var errorHandler = Service.errorHandler; -function setLastSync(lastSyncValue) { - Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString()); -} - function run_test() { validate_all_future_pings(); run_next_test(); @@ -142,8 +135,7 @@ add_test(function test_sync_error_logOnError_false() { run_next_test(); }); - // Fake an unsuccessful sync due to prolonged failure. - setLastSync(PROLONGED_ERROR_DURATION); + // Fake an unsuccessful sync. Svc.Obs.notify("weave:service:sync:error"); }); @@ -183,8 +175,7 @@ add_test(function test_sync_error_logOnError_true() { }); }); - // Fake an unsuccessful sync due to prolonged failure. - setLastSync(PROLONGED_ERROR_DURATION); + // Fake an unsuccessful sync. Svc.Obs.notify("weave:service:sync:error"); }); @@ -203,8 +194,7 @@ add_test(function test_login_error_logOnError_false() { run_next_test(); }); - // Fake an unsuccessful login due to prolonged failure. - setLastSync(PROLONGED_ERROR_DURATION); + // Fake an unsuccessful login. Svc.Obs.notify("weave:service:login:error"); }); @@ -244,8 +234,7 @@ add_test(function test_login_error_logOnError_true() { }); }); - // Fake an unsuccessful login due to prolonged failure. - setLastSync(PROLONGED_ERROR_DURATION); + // Fake an unsuccessful login. Svc.Obs.notify("weave:service:login:error"); }); @@ -353,8 +342,7 @@ add_test(function test_errorLog_dumpAddons() { }); }); - // Fake an unsuccessful sync due to prolonged failure. - setLastSync(PROLONGED_ERROR_DURATION); + // Fake an unsuccessful sync. Svc.Obs.notify("weave:service:sync:error"); }); diff --git a/services/sync/tests/unit/test_fxa_node_reassignment.js b/services/sync/tests/unit/test_fxa_node_reassignment.js index 14ca7a59f4a6..304a438b49a0 100644 --- a/services/sync/tests/unit/test_fxa_node_reassignment.js +++ b/services/sync/tests/unit/test_fxa_node_reassignment.js @@ -25,13 +25,6 @@ add_task(async function setup() { // Setup the FxA identity manager and cluster manager. Status.__authManager = Service.identity = new BrowserIDManager(); - - // None of the failures in this file should result in a UI error. - function onUIError() { - do_throw("Errors should not be presented in the UI."); - } - Svc.Obs.add("weave:ui:login:error", onUIError); - Svc.Obs.add("weave:ui:sync:error", onUIError); }); diff --git a/services/sync/tests/unit/test_node_reassignment.js b/services/sync/tests/unit/test_node_reassignment.js index caaed668d079..d5cf23d5afae 100644 --- a/services/sync/tests/unit/test_node_reassignment.js +++ b/services/sync/tests/unit/test_node_reassignment.js @@ -16,13 +16,6 @@ ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm"); add_task(async function setup() { validate_all_future_pings(); - - // None of the failures in this file should result in a UI error. - function onUIError() { - do_throw("Errors should not be presented in the UI."); - } - Svc.Obs.add("weave:ui:login:error", onUIError); - Svc.Obs.add("weave:ui:sync:error", onUIError); }); /** diff --git a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js index da2e642b664f..3eade27318a3 100644 --- a/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js +++ b/services/sync/tests/unit/test_service_sync_updateEnabledEngines.js @@ -220,11 +220,8 @@ add_task(async function test_disabledLocally_wipe503() { Service._ignorePrefObserver = false; engine.enabled = false; - let promiseObserved = promiseOneObserver("weave:ui:sync:error"); - _("Sync."); - Service.errorHandler.syncAndReportErrors(); - await promiseObserved; + await Service.sync(); Assert.equal(Service.status.sync, SERVER_MAINTENANCE); await Service.startOver(); diff --git a/tools/lint/eslint/modules.json b/tools/lint/eslint/modules.json index faf2b2386ce2..6191bb653fb9 100644 --- a/tools/lint/eslint/modules.json +++ b/tools/lint/eslint/modules.json @@ -29,7 +29,7 @@ "collection_repair.js": ["getRepairRequestor", "getAllRepairRequestors", "CollectionRepairRequestor", "getRepairResponder", "CollectionRepairResponder"], "collection_validator.js": ["CollectionValidator", "CollectionProblemData"], "Console.jsm": ["console", "ConsoleAPI"], - "constants.js": ["WEAVE_VERSION", "SYNC_API_VERSION", "STORAGE_VERSION", "PREFS_BRANCH", "DEFAULT_KEYBUNDLE_NAME", "SYNC_KEY_ENCODED_LENGTH", "SYNC_KEY_DECODED_LENGTH", "NO_SYNC_NODE_INTERVAL", "MAX_ERROR_COUNT_BEFORE_BACKOFF", "MINIMUM_BACKOFF_INTERVAL", "MAXIMUM_BACKOFF_INTERVAL", "HMAC_EVENT_INTERVAL", "MASTER_PASSWORD_LOCKED_RETRY_INTERVAL", "DEFAULT_GUID_FETCH_BATCH_SIZE", "DEFAULT_DOWNLOAD_BATCH_SIZE", "SINGLE_USER_THRESHOLD", "MULTI_DEVICE_THRESHOLD", "SCORE_INCREMENT_SMALL", "SCORE_INCREMENT_MEDIUM", "SCORE_INCREMENT_XLARGE", "SCORE_UPDATE_DELAY", "IDLE_OBSERVER_BACK_DELAY", "URI_LENGTH_MAX", "MAX_HISTORY_UPLOAD", "MAX_HISTORY_DOWNLOAD", "STATUS_OK", "SYNC_FAILED", "LOGIN_FAILED", "SYNC_FAILED_PARTIAL", "CLIENT_NOT_CONFIGURED", "STATUS_DISABLED", "MASTER_PASSWORD_LOCKED", "LOGIN_SUCCEEDED", "SYNC_SUCCEEDED", "ENGINE_SUCCEEDED", "LOGIN_FAILED_NO_USERNAME", "LOGIN_FAILED_NO_PASSPHRASE", "LOGIN_FAILED_NETWORK_ERROR", "LOGIN_FAILED_SERVER_ERROR", "LOGIN_FAILED_INVALID_PASSPHRASE", "LOGIN_FAILED_LOGIN_REJECTED", "METARECORD_DOWNLOAD_FAIL", "VERSION_OUT_OF_DATE", "CREDENTIALS_CHANGED", "ABORT_SYNC_COMMAND", "NO_SYNC_NODE_FOUND", "OVER_QUOTA", "PROLONGED_SYNC_FAILURE", "SERVER_MAINTENANCE", "RESPONSE_OVER_QUOTA", "ENGINE_UPLOAD_FAIL", "ENGINE_DOWNLOAD_FAIL", "ENGINE_UNKNOWN_FAIL", "ENGINE_APPLY_FAIL", "ENGINE_BATCH_INTERRUPTED", "kSyncMasterPasswordLocked", "kSyncWeaveDisabled", "kSyncNetworkOffline", "kSyncBackoffNotMet", "kFirstSyncChoiceNotMade", "kSyncNotConfigured", "kFirefoxShuttingDown", "DEVICE_TYPE_DESKTOP", "DEVICE_TYPE_MOBILE", "SQLITE_MAX_VARIABLE_NUMBER"], + "constants.js": ["WEAVE_VERSION", "SYNC_API_VERSION", "STORAGE_VERSION", "PREFS_BRANCH", "DEFAULT_KEYBUNDLE_NAME", "SYNC_KEY_ENCODED_LENGTH", "SYNC_KEY_DECODED_LENGTH", "NO_SYNC_NODE_INTERVAL", "MAX_ERROR_COUNT_BEFORE_BACKOFF", "MINIMUM_BACKOFF_INTERVAL", "MAXIMUM_BACKOFF_INTERVAL", "HMAC_EVENT_INTERVAL", "MASTER_PASSWORD_LOCKED_RETRY_INTERVAL", "DEFAULT_GUID_FETCH_BATCH_SIZE", "DEFAULT_DOWNLOAD_BATCH_SIZE", "SINGLE_USER_THRESHOLD", "MULTI_DEVICE_THRESHOLD", "SCORE_INCREMENT_SMALL", "SCORE_INCREMENT_MEDIUM", "SCORE_INCREMENT_XLARGE", "SCORE_UPDATE_DELAY", "IDLE_OBSERVER_BACK_DELAY", "URI_LENGTH_MAX", "MAX_HISTORY_UPLOAD", "MAX_HISTORY_DOWNLOAD", "STATUS_OK", "SYNC_FAILED", "LOGIN_FAILED", "SYNC_FAILED_PARTIAL", "CLIENT_NOT_CONFIGURED", "STATUS_DISABLED", "MASTER_PASSWORD_LOCKED", "LOGIN_SUCCEEDED", "SYNC_SUCCEEDED", "ENGINE_SUCCEEDED", "LOGIN_FAILED_NO_USERNAME", "LOGIN_FAILED_NO_PASSPHRASE", "LOGIN_FAILED_NETWORK_ERROR", "LOGIN_FAILED_SERVER_ERROR", "LOGIN_FAILED_INVALID_PASSPHRASE", "LOGIN_FAILED_LOGIN_REJECTED", "METARECORD_DOWNLOAD_FAIL", "VERSION_OUT_OF_DATE", "CREDENTIALS_CHANGED", "ABORT_SYNC_COMMAND", "NO_SYNC_NODE_FOUND", "OVER_QUOTA", "SERVER_MAINTENANCE", "RESPONSE_OVER_QUOTA", "ENGINE_UPLOAD_FAIL", "ENGINE_DOWNLOAD_FAIL", "ENGINE_UNKNOWN_FAIL", "ENGINE_APPLY_FAIL", "ENGINE_BATCH_INTERRUPTED", "kSyncMasterPasswordLocked", "kSyncWeaveDisabled", "kSyncNetworkOffline", "kSyncBackoffNotMet", "kFirstSyncChoiceNotMade", "kSyncNotConfigured", "kFirefoxShuttingDown", "DEVICE_TYPE_DESKTOP", "DEVICE_TYPE_MOBILE", "SQLITE_MAX_VARIABLE_NUMBER"], "Constants.jsm": ["Roles", "Events", "Relations", "Filters", "States", "Prefilters"], "ContactDB.jsm": ["ContactDB", "DB_NAME", "STORE_NAME", "SAVED_GETALL_STORE_NAME", "REVISION_STORE", "DB_VERSION"], "content-server.jsm": ["init"],