services/sync/tests/unit/test_errorhandler.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* Any copyright is dedicated to the Public Domain.
     2    http://creativecommons.org/publicdomain/zero/1.0/ */
     4 Cu.import("resource://services-sync/engines/clients.js");
     5 Cu.import("resource://services-sync/constants.js");
     6 Cu.import("resource://services-sync/engines.js");
     7 Cu.import("resource://services-sync/keys.js");
     8 Cu.import("resource://services-sync/policies.js");
     9 Cu.import("resource://services-sync/service.js");
    10 Cu.import("resource://services-sync/status.js");
    11 Cu.import("resource://services-sync/util.js");
    12 Cu.import("resource://testing-common/services/sync/utils.js");
    13 Cu.import("resource://gre/modules/FileUtils.jsm");
    15 const FAKE_SERVER_URL = "http://dummy:9000/";
    16 const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
    17 const LOG_PREFIX_SUCCESS = "success-";
    18 const LOG_PREFIX_ERROR   = "error-";
    20 const PROLONGED_ERROR_DURATION =
    21   (Svc.Prefs.get('errorhandler.networkFailureReportTimeout') * 2) * 1000;
    23 const NON_PROLONGED_ERROR_DURATION =
    24   (Svc.Prefs.get('errorhandler.networkFailureReportTimeout') / 2) * 1000;
    26 Service.engineManager.clear();
    28 function setLastSync(lastSyncValue) {
    29   Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString());
    30 }
    32 function CatapultEngine() {
    33   SyncEngine.call(this, "Catapult", Service);
    34 }
    35 CatapultEngine.prototype = {
    36   __proto__: SyncEngine.prototype,
    37   exception: null, // tests fill this in
    38   _sync: function _sync() {
    39     if (this.exception) {
    40       throw this.exception;
    41     }
    42   }
    43 };
    45 let engineManager = Service.engineManager;
    46 engineManager.register(CatapultEngine);
    48 // This relies on Service/ErrorHandler being a singleton. Fixing this will take
    49 // a lot of work.
    50 let errorHandler = Service.errorHandler;
    52 function run_test() {
    53   initTestLogging("Trace");
    55   Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
    56   Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
    57   Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace;
    59   ensureLegacyIdentityManager();
    61   run_next_test();
    62 }
    64 function generateCredentialsChangedFailure() {
    65   // Make sync fail due to changed credentials. We simply re-encrypt
    66   // the keys with a different Sync Key, without changing the local one.
    67   let newSyncKeyBundle = new SyncKeyBundle("johndoe", "23456234562345623456234562");
    68   let keys = Service.collectionKeys.asWBO();
    69   keys.encrypt(newSyncKeyBundle);
    70   keys.upload(Service.resource(Service.cryptoKeysURL));
    71 }
    73 function service_unavailable(request, response) {
    74   let body = "Service Unavailable";
    75   response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
    76   response.setHeader("Retry-After", "42");
    77   response.bodyOutputStream.write(body, body.length);
    78 }
    80 function sync_httpd_setup() {
    81   let global = new ServerWBO("global", {
    82     syncID: Service.syncID,
    83     storageVersion: STORAGE_VERSION,
    84     engines: {clients: {version: Service.clientsEngine.version,
    85                         syncID: Service.clientsEngine.syncID},
    86               catapult: {version: engineManager.get("catapult").version,
    87                          syncID: engineManager.get("catapult").syncID}}
    88   });
    89   let clientsColl = new ServerCollection({}, true);
    91   // Tracking info/collections.
    92   let collectionsHelper = track_collections_helper();
    93   let upd = collectionsHelper.with_updated_collection;
    95   let handler_401 = httpd_handler(401, "Unauthorized");
    96   return httpd_setup({
    97     // Normal server behaviour.
    98     "/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
    99     "/1.1/johndoe/info/collections": collectionsHelper.handler,
   100     "/1.1/johndoe/storage/crypto/keys":
   101       upd("crypto", (new ServerWBO("keys")).handler()),
   102     "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
   104     // Credentials are wrong or node reallocated.
   105     "/1.1/janedoe/storage/meta/global": handler_401,
   106     "/1.1/janedoe/info/collections": handler_401,
   108     // Maintenance or overloaded (503 + Retry-After) at info/collections.
   109     "/maintenance/1.1/broken.info/info/collections": service_unavailable,
   111     // Maintenance or overloaded (503 + Retry-After) at meta/global.
   112     "/maintenance/1.1/broken.meta/storage/meta/global": service_unavailable,
   113     "/maintenance/1.1/broken.meta/info/collections": collectionsHelper.handler,
   115     // Maintenance or overloaded (503 + Retry-After) at crypto/keys.
   116     "/maintenance/1.1/broken.keys/storage/meta/global": upd("meta", global.handler()),
   117     "/maintenance/1.1/broken.keys/info/collections": collectionsHelper.handler,
   118     "/maintenance/1.1/broken.keys/storage/crypto/keys": service_unavailable,
   120     // Maintenance or overloaded (503 + Retry-After) at wiping collection.
   121     "/maintenance/1.1/broken.wipe/info/collections": collectionsHelper.handler,
   122     "/maintenance/1.1/broken.wipe/storage/meta/global": upd("meta", global.handler()),
   123     "/maintenance/1.1/broken.wipe/storage/crypto/keys":
   124       upd("crypto", (new ServerWBO("keys")).handler()),
   125     "/maintenance/1.1/broken.wipe/storage": service_unavailable,
   126     "/maintenance/1.1/broken.wipe/storage/clients": upd("clients", clientsColl.handler()),
   127     "/maintenance/1.1/broken.wipe/storage/catapult": service_unavailable
   128   });
   129 }
   131 function setUp(server) {
   132   return configureIdentity({username: "johndoe"}).then(
   133     () => {
   134       Service.serverURL  = server.baseURI + "/";
   135       Service.clusterURL = server.baseURI + "/";
   136     }
   137   ).then(
   138     () => generateAndUploadKeys()
   139   );
   140 }
   142 function generateAndUploadKeys() {
   143   generateNewKeys(Service.collectionKeys);
   144   let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
   145   serverKeys.encrypt(Service.identity.syncKeyBundle);
   146   return serverKeys.upload(Service.resource(Service.cryptoKeysURL)).success;
   147 }
   149 function clean() {
   150   Service.startOver();
   151   Status.resetSync();
   152   Status.resetBackoff();
   153   errorHandler.didReportProlongedError = false;
   154 }
   156 add_identity_test(this, function test_401_logout() {
   157   let server = sync_httpd_setup();
   158   yield setUp(server);
   160   // By calling sync, we ensure we're logged in.
   161   Service.sync();
   162   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   163   do_check_true(Service.isLoggedIn);
   165   let deferred = Promise.defer();
   166   Svc.Obs.add("weave:service:sync:error", onSyncError);
   167   function onSyncError() {
   168     _("Got weave:service:sync:error in first sync.");
   169     Svc.Obs.remove("weave:service:sync:error", onSyncError);
   171     // Wait for the automatic next sync.
   172     function onLoginError() {
   173       _("Got weave:service:login:error in second sync.");
   174       Svc.Obs.remove("weave:service:login:error", onLoginError);
   176       do_check_eq(Status.login, LOGIN_FAILED_LOGIN_REJECTED);
   177       do_check_false(Service.isLoggedIn);
   179       // Clean up.
   180       Utils.nextTick(function () {
   181         Service.startOver();
   182         server.stop(deferred.resolve);
   183       });
   184     }
   185     Svc.Obs.add("weave:service:login:error", onLoginError);
   186   }
   188   // Make sync fail due to login rejected.
   189   yield configureIdentity({username: "janedoe"});
   190   Service._updateCachedURLs();
   192   _("Starting first sync.");
   193   Service.sync();
   194   _("First sync done.");
   195   yield deferred.promise;
   196 });
   198 add_identity_test(this, function test_credentials_changed_logout() {
   199   let server = sync_httpd_setup();
   200   yield setUp(server);
   202   // By calling sync, we ensure we're logged in.
   203   Service.sync();
   204   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   205   do_check_true(Service.isLoggedIn);
   207   generateCredentialsChangedFailure();
   208   Service.sync();
   210   do_check_eq(Status.sync, CREDENTIALS_CHANGED);
   211   do_check_false(Service.isLoggedIn);
   213   // Clean up.
   214   Service.startOver();
   215   let deferred = Promise.defer();
   216   server.stop(deferred.resolve);
   217   yield deferred.promise;
   218 });
   220 add_identity_test(this, function test_no_lastSync_pref() {
   221   // Test reported error.
   222   Status.resetSync();
   223   errorHandler.dontIgnoreErrors = true;
   224   Status.sync = CREDENTIALS_CHANGED;
   225   do_check_true(errorHandler.shouldReportError());
   227   // Test unreported error.
   228   Status.resetSync();
   229   errorHandler.dontIgnoreErrors = true;
   230   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   231   do_check_true(errorHandler.shouldReportError());
   233 });
   235 add_identity_test(this, function test_shouldReportError() {
   236   Status.login = MASTER_PASSWORD_LOCKED;
   237   do_check_false(errorHandler.shouldReportError());
   239   // Give ourselves a clusterURL so that the temporary 401 no-error situation
   240   // doesn't come into play.
   241   Service.serverURL  = FAKE_SERVER_URL;
   242   Service.clusterURL = FAKE_SERVER_URL;
   244   // Test dontIgnoreErrors, non-network, non-prolonged, login error reported
   245   Status.resetSync();
   246   setLastSync(NON_PROLONGED_ERROR_DURATION);
   247   errorHandler.dontIgnoreErrors = true;
   248   Status.login = LOGIN_FAILED_NO_PASSWORD;
   249   do_check_true(errorHandler.shouldReportError());
   251   // Test dontIgnoreErrors, non-network, non-prolonged, sync error reported
   252   Status.resetSync();
   253   setLastSync(NON_PROLONGED_ERROR_DURATION);
   254   errorHandler.dontIgnoreErrors = true;
   255   Status.sync = CREDENTIALS_CHANGED;
   256   do_check_true(errorHandler.shouldReportError());
   258   // Test dontIgnoreErrors, non-network, prolonged, login error reported
   259   Status.resetSync();
   260   setLastSync(PROLONGED_ERROR_DURATION);
   261   errorHandler.dontIgnoreErrors = true;
   262   Status.login = LOGIN_FAILED_NO_PASSWORD;
   263   do_check_true(errorHandler.shouldReportError());
   265   // Test dontIgnoreErrors, non-network, prolonged, sync error reported
   266   Status.resetSync();
   267   setLastSync(PROLONGED_ERROR_DURATION);
   268   errorHandler.dontIgnoreErrors = true;
   269   Status.sync = CREDENTIALS_CHANGED;
   270   do_check_true(errorHandler.shouldReportError());
   272   // Test dontIgnoreErrors, network, non-prolonged, login error reported
   273   Status.resetSync();
   274   setLastSync(NON_PROLONGED_ERROR_DURATION);
   275   errorHandler.dontIgnoreErrors = true;
   276   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   277   do_check_true(errorHandler.shouldReportError());
   279   // Test dontIgnoreErrors, network, non-prolonged, sync error reported
   280   Status.resetSync();
   281   setLastSync(NON_PROLONGED_ERROR_DURATION);
   282   errorHandler.dontIgnoreErrors = true;
   283   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   284   do_check_true(errorHandler.shouldReportError());
   286   // Test dontIgnoreErrors, network, prolonged, login error reported
   287   Status.resetSync();
   288   setLastSync(PROLONGED_ERROR_DURATION);
   289   errorHandler.dontIgnoreErrors = true;
   290   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   291   do_check_true(errorHandler.shouldReportError());
   293   // Test dontIgnoreErrors, network, prolonged, sync error reported
   294   Status.resetSync();
   295   setLastSync(PROLONGED_ERROR_DURATION);
   296   errorHandler.dontIgnoreErrors = true;
   297   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   298   do_check_true(errorHandler.shouldReportError());
   300   // Test non-network, prolonged, login error reported
   301   do_check_false(errorHandler.didReportProlongedError);
   302   Status.resetSync();
   303   setLastSync(PROLONGED_ERROR_DURATION);
   304   errorHandler.dontIgnoreErrors = false;
   305   Status.login = LOGIN_FAILED_NO_PASSWORD;
   306   do_check_true(errorHandler.shouldReportError());
   307   do_check_true(errorHandler.didReportProlongedError);
   309   // Second time with prolonged error and without resetting
   310   // didReportProlongedError, sync error should not be reported.
   311   Status.resetSync();
   312   setLastSync(PROLONGED_ERROR_DURATION);
   313   errorHandler.dontIgnoreErrors = false;
   314   Status.login = LOGIN_FAILED_NO_PASSWORD;
   315   do_check_false(errorHandler.shouldReportError());
   316   do_check_true(errorHandler.didReportProlongedError);
   318   // Test non-network, prolonged, sync error reported
   319   Status.resetSync();
   320   setLastSync(PROLONGED_ERROR_DURATION);
   321   errorHandler.dontIgnoreErrors = false;
   322   errorHandler.didReportProlongedError = false;
   323   Status.sync = CREDENTIALS_CHANGED;
   324   do_check_true(errorHandler.shouldReportError());
   325   do_check_true(errorHandler.didReportProlongedError);
   326   errorHandler.didReportProlongedError = false;
   328   // Test network, prolonged, login error reported
   329   Status.resetSync();
   330   setLastSync(PROLONGED_ERROR_DURATION);
   331   errorHandler.dontIgnoreErrors = false;
   332   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   333   do_check_true(errorHandler.shouldReportError());
   334   do_check_true(errorHandler.didReportProlongedError);
   335   errorHandler.didReportProlongedError = false;
   337   // Test network, prolonged, sync error reported
   338   Status.resetSync();
   339   setLastSync(PROLONGED_ERROR_DURATION);
   340   errorHandler.dontIgnoreErrors = false;
   341   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   342   do_check_true(errorHandler.shouldReportError());
   343   do_check_true(errorHandler.didReportProlongedError);
   344   errorHandler.didReportProlongedError = false;
   346   // Test non-network, non-prolonged, login error reported
   347   Status.resetSync();
   348   setLastSync(NON_PROLONGED_ERROR_DURATION);
   349   errorHandler.dontIgnoreErrors = false;
   350   Status.login = LOGIN_FAILED_NO_PASSWORD;
   351   do_check_true(errorHandler.shouldReportError());
   352   do_check_false(errorHandler.didReportProlongedError);
   354   // Test non-network, non-prolonged, sync error reported
   355   Status.resetSync();
   356   setLastSync(NON_PROLONGED_ERROR_DURATION);
   357   errorHandler.dontIgnoreErrors = false;
   358   Status.sync = CREDENTIALS_CHANGED;
   359   do_check_true(errorHandler.shouldReportError());
   360   do_check_false(errorHandler.didReportProlongedError);
   362   // Test network, non-prolonged, login error reported
   363   Status.resetSync();
   364   setLastSync(NON_PROLONGED_ERROR_DURATION);
   365   errorHandler.dontIgnoreErrors = false;
   366   Status.login = LOGIN_FAILED_NETWORK_ERROR;
   367   do_check_false(errorHandler.shouldReportError());
   368   do_check_false(errorHandler.didReportProlongedError);
   370   // Test network, non-prolonged, sync error reported
   371   Status.resetSync();
   372   setLastSync(NON_PROLONGED_ERROR_DURATION);
   373   errorHandler.dontIgnoreErrors = false;
   374   Status.sync = LOGIN_FAILED_NETWORK_ERROR;
   375   do_check_false(errorHandler.shouldReportError());
   376   do_check_false(errorHandler.didReportProlongedError);
   378   // Test server maintenance, sync errors are not reported
   379   Status.resetSync();
   380   setLastSync(NON_PROLONGED_ERROR_DURATION);
   381   errorHandler.dontIgnoreErrors = false;
   382   Status.sync = SERVER_MAINTENANCE;
   383   do_check_false(errorHandler.shouldReportError());
   384   do_check_false(errorHandler.didReportProlongedError);
   386   // Test server maintenance, login errors are not reported
   387   Status.resetSync();
   388   setLastSync(NON_PROLONGED_ERROR_DURATION);
   389   errorHandler.dontIgnoreErrors = false;
   390   Status.login = SERVER_MAINTENANCE;
   391   do_check_false(errorHandler.shouldReportError());
   392   do_check_false(errorHandler.didReportProlongedError);
   394   // Test prolonged, server maintenance, sync errors are reported
   395   Status.resetSync();
   396   setLastSync(PROLONGED_ERROR_DURATION);
   397   errorHandler.dontIgnoreErrors = false;
   398   Status.sync = SERVER_MAINTENANCE;
   399   do_check_true(errorHandler.shouldReportError());
   400   do_check_true(errorHandler.didReportProlongedError);
   401   errorHandler.didReportProlongedError = false;
   403   // Test prolonged, server maintenance, login errors are reported
   404   Status.resetSync();
   405   setLastSync(PROLONGED_ERROR_DURATION);
   406   errorHandler.dontIgnoreErrors = false;
   407   Status.login = SERVER_MAINTENANCE;
   408   do_check_true(errorHandler.shouldReportError());
   409   do_check_true(errorHandler.didReportProlongedError);
   410   errorHandler.didReportProlongedError = false;
   412   // Test dontIgnoreErrors, server maintenance, sync errors are reported
   413   Status.resetSync();
   414   setLastSync(NON_PROLONGED_ERROR_DURATION);
   415   errorHandler.dontIgnoreErrors = true;
   416   Status.sync = SERVER_MAINTENANCE;
   417   do_check_true(errorHandler.shouldReportError());
   418   // dontIgnoreErrors means we don't set didReportProlongedError
   419   do_check_false(errorHandler.didReportProlongedError);
   421   // Test dontIgnoreErrors, server maintenance, login errors are reported
   422   Status.resetSync();
   423   setLastSync(NON_PROLONGED_ERROR_DURATION);
   424   errorHandler.dontIgnoreErrors = true;
   425   Status.login = SERVER_MAINTENANCE;
   426   do_check_true(errorHandler.shouldReportError());
   427   do_check_false(errorHandler.didReportProlongedError);
   429   // Test dontIgnoreErrors, prolonged, server maintenance,
   430   // sync errors are reported
   431   Status.resetSync();
   432   setLastSync(PROLONGED_ERROR_DURATION);
   433   errorHandler.dontIgnoreErrors = true;
   434   Status.sync = SERVER_MAINTENANCE;
   435   do_check_true(errorHandler.shouldReportError());
   436   do_check_false(errorHandler.didReportProlongedError);
   438   // Test dontIgnoreErrors, prolonged, server maintenance,
   439   // login errors are reported
   440   Status.resetSync();
   441   setLastSync(PROLONGED_ERROR_DURATION);
   442   errorHandler.dontIgnoreErrors = true;
   443   Status.login = SERVER_MAINTENANCE;
   444   do_check_true(errorHandler.shouldReportError());
   445   do_check_false(errorHandler.didReportProlongedError);
   446 });
   448 add_identity_test(this, function test_shouldReportError_master_password() {
   449   _("Test error ignored due to locked master password");
   450   let server = sync_httpd_setup();
   451   yield setUp(server);
   453   // Monkey patch Service.verifyLogin to imitate
   454   // master password being locked.
   455   Service._verifyLogin = Service.verifyLogin;
   456   Service.verifyLogin = function () {
   457     Status.login = MASTER_PASSWORD_LOCKED;
   458     return false;
   459   };
   461   setLastSync(NON_PROLONGED_ERROR_DURATION);
   462   Service.sync();
   463   do_check_false(errorHandler.shouldReportError());
   465   // Clean up.
   466   Service.verifyLogin = Service._verifyLogin;
   467   clean();
   468   let deferred = Promise.defer();
   469   server.stop(deferred.resolve);
   470   yield deferred.promise;
   471 });
   473 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
   474 // an fxaccounts environment?
   475 add_task(function test_login_syncAndReportErrors_non_network_error() {
   476   // Test non-network errors are reported
   477   // when calling syncAndReportErrors
   478   let server = sync_httpd_setup();
   479   yield setUp(server);
   480   Service.identity.basicPassword = null;
   482   let deferred = Promise.defer();
   483   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   484     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   485     do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
   487     clean();
   488     server.stop(deferred.resolve);
   489   });
   491   setLastSync(NON_PROLONGED_ERROR_DURATION);
   492   errorHandler.syncAndReportErrors();
   493   yield deferred.promise;
   494 });
   496 add_identity_test(this, function test_sync_syncAndReportErrors_non_network_error() {
   497   // Test non-network errors are reported
   498   // when calling syncAndReportErrors
   499   let server = sync_httpd_setup();
   500   yield setUp(server);
   502   // By calling sync, we ensure we're logged in.
   503   Service.sync();
   504   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   505   do_check_true(Service.isLoggedIn);
   507   generateCredentialsChangedFailure();
   509   let deferred = Promise.defer();
   510   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   511     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   512     do_check_eq(Status.sync, CREDENTIALS_CHANGED);
   514     clean();
   515     server.stop(deferred.resolve);
   516   });
   518   setLastSync(NON_PROLONGED_ERROR_DURATION);
   519   errorHandler.syncAndReportErrors();
   520   yield deferred.promise;
   521 });
   523 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
   524 // an fxaccounts environment?
   525 add_task(function test_login_syncAndReportErrors_prolonged_non_network_error() {
   526   // Test prolonged, non-network errors are
   527   // reported when calling syncAndReportErrors.
   528   let server = sync_httpd_setup();
   529   yield setUp(server);
   530   Service.identity.basicPassword = null;
   532   let deferred = Promise.defer();
   533   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   534     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   535     do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
   537     clean();
   538     server.stop(deferred.resolve);
   539   });
   541   setLastSync(PROLONGED_ERROR_DURATION);
   542   errorHandler.syncAndReportErrors();
   543   yield deferred.promise;
   544 });
   546 add_identity_test(this, function test_sync_syncAndReportErrors_prolonged_non_network_error() {
   547   // Test prolonged, non-network errors are
   548   // reported when calling syncAndReportErrors.
   549   let server = sync_httpd_setup();
   550   yield setUp(server);
   552   // By calling sync, we ensure we're logged in.
   553   Service.sync();
   554   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   555   do_check_true(Service.isLoggedIn);
   557   generateCredentialsChangedFailure();
   559   let deferred = Promise.defer();
   560   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   561     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   562     do_check_eq(Status.sync, CREDENTIALS_CHANGED);
   564     clean();
   565     server.stop(deferred.resolve);
   566   });
   568   setLastSync(PROLONGED_ERROR_DURATION);
   569   errorHandler.syncAndReportErrors();
   570   yield deferred.promise;
   571 });
   573 add_identity_test(this, function test_login_syncAndReportErrors_network_error() {
   574   // Test network errors are reported when calling syncAndReportErrors.
   575   yield configureIdentity({username: "broken.wipe"});
   576   Service.serverURL  = FAKE_SERVER_URL;
   577   Service.clusterURL = FAKE_SERVER_URL;
   579   let deferred = Promise.defer();
   580   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   581     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   582     do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
   584     clean();
   585     deferred.resolve();
   586   });
   588   setLastSync(NON_PROLONGED_ERROR_DURATION);
   589   errorHandler.syncAndReportErrors();
   590   yield deferred.promise;
   591 });
   594 add_test(function test_sync_syncAndReportErrors_network_error() {
   595   // Test network errors are reported when calling syncAndReportErrors.
   596   Services.io.offline = true;
   598   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   599     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   600     do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
   602     Services.io.offline = false;
   603     clean();
   604     run_next_test();
   605   });
   607   setLastSync(NON_PROLONGED_ERROR_DURATION);
   608   errorHandler.syncAndReportErrors();
   609 });
   611 add_identity_test(this, function test_login_syncAndReportErrors_prolonged_network_error() {
   612   // Test prolonged, network errors are reported
   613   // when calling syncAndReportErrors.
   614   yield configureIdentity({username: "johndoe"});
   616   Service.serverURL  = FAKE_SERVER_URL;
   617   Service.clusterURL = FAKE_SERVER_URL;
   619   let deferred = Promise.defer();
   620   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   621     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   622     do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
   624     clean();
   625     deferred.resolve();
   626   });
   628   setLastSync(PROLONGED_ERROR_DURATION);
   629   errorHandler.syncAndReportErrors();
   630   yield deferred.promise;
   631 });
   633 add_test(function test_sync_syncAndReportErrors_prolonged_network_error() {
   634   // Test prolonged, network errors are reported
   635   // when calling syncAndReportErrors.
   636   Services.io.offline = true;
   638   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   639     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   640     do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
   642     Services.io.offline = false;
   643     clean();
   644     run_next_test();
   645   });
   647   setLastSync(PROLONGED_ERROR_DURATION);
   648   errorHandler.syncAndReportErrors();
   649 });
   651 add_task(function test_login_prolonged_non_network_error() {
   652   // Test prolonged, non-network errors are reported
   653   let server = sync_httpd_setup();
   654   yield setUp(server);
   655   Service.identity.basicPassword = null;
   657   let deferred = Promise.defer();
   658   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   659     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   660     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
   661     do_check_true(errorHandler.didReportProlongedError);
   663     clean();
   664     server.stop(deferred.resolve);
   665   });
   667   setLastSync(PROLONGED_ERROR_DURATION);
   668   Service.sync();
   669   yield deferred.promise;
   670 });
   672 add_task(function test_sync_prolonged_non_network_error() {
   673   // Test prolonged, non-network errors are reported
   674   let server = sync_httpd_setup();
   675   yield setUp(server);
   677   // By calling sync, we ensure we're logged in.
   678   Service.sync();
   679   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   680   do_check_true(Service.isLoggedIn);
   682   generateCredentialsChangedFailure();
   684   let deferred = Promise.defer();
   685   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   686     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   687     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
   688     do_check_true(errorHandler.didReportProlongedError);
   690     clean();
   691     server.stop(deferred.resolve);
   692   });
   694   setLastSync(PROLONGED_ERROR_DURATION);
   695   Service.sync();
   696   yield deferred.promise;
   697 });
   699 add_identity_test(this, function test_login_prolonged_network_error() {
   700   // Test prolonged, network errors are reported
   701   yield configureIdentity({username: "johndoe"});
   702   Service.serverURL  = FAKE_SERVER_URL;
   703   Service.clusterURL = FAKE_SERVER_URL;
   705   let deferred = Promise.defer();
   706   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   707     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   708     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
   709     do_check_true(errorHandler.didReportProlongedError);
   711     clean();
   712     deferred.resolve();
   713   });
   715   setLastSync(PROLONGED_ERROR_DURATION);
   716   Service.sync();
   717   yield deferred.promise;
   718 });
   720 add_test(function test_sync_prolonged_network_error() {
   721   // Test prolonged, network errors are reported
   722   Services.io.offline = true;
   724   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   725     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   726     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
   727     do_check_true(errorHandler.didReportProlongedError);
   729     Services.io.offline = false;
   730     clean();
   731     run_next_test();
   732   });
   734   setLastSync(PROLONGED_ERROR_DURATION);
   735   Service.sync();
   736 });
   738 add_task(function test_login_non_network_error() {
   739   // Test non-network errors are reported
   740   let server = sync_httpd_setup();
   741   yield setUp(server);
   742   Service.identity.basicPassword = null;
   744   let deferred = Promise.defer();
   745   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
   746     Svc.Obs.remove("weave:ui:login:error", onSyncError);
   747     do_check_eq(Status.login, LOGIN_FAILED_NO_PASSWORD);
   748     do_check_false(errorHandler.didReportProlongedError);
   750     clean();
   751     server.stop(deferred.resolve);
   752   });
   754   setLastSync(NON_PROLONGED_ERROR_DURATION);
   755   Service.sync();
   756   yield deferred.promise;
   757 });
   759 add_task(function test_sync_non_network_error() {
   760   // Test non-network errors are reported
   761   let server = sync_httpd_setup();
   762   yield setUp(server);
   764   // By calling sync, we ensure we're logged in.
   765   Service.sync();
   766   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   767   do_check_true(Service.isLoggedIn);
   769   generateCredentialsChangedFailure();
   771   let deferred = Promise.defer();
   772   Svc.Obs.add("weave:ui:sync:error", function onSyncError() {
   773     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   774     do_check_eq(Status.sync, CREDENTIALS_CHANGED);
   775     do_check_false(errorHandler.didReportProlongedError);
   777     clean();
   778     server.stop(deferred.resolve);
   779   });
   781   setLastSync(NON_PROLONGED_ERROR_DURATION);
   782   Service.sync();
   783   yield deferred.promise;
   784 });
   786 add_identity_test(this, function test_login_network_error() {
   787   yield configureIdentity({username: "johndoe"});
   788   Service.serverURL  = FAKE_SERVER_URL;
   789   Service.clusterURL = FAKE_SERVER_URL;
   791   let deferred = Promise.defer();
   792   // Test network errors are not reported.
   793   Svc.Obs.add("weave:ui:clear-error", function onClearError() {
   794     Svc.Obs.remove("weave:ui:clear-error", onClearError);
   796     do_check_eq(Status.login, LOGIN_FAILED_NETWORK_ERROR);
   797     do_check_false(errorHandler.didReportProlongedError);
   799     Services.io.offline = false;
   800     clean();
   801     deferred.resolve()
   802   });
   804   setLastSync(NON_PROLONGED_ERROR_DURATION);
   805   Service.sync();
   806   yield deferred.promise;
   807 });
   809 add_test(function test_sync_network_error() {
   810   // Test network errors are not reported.
   811   Services.io.offline = true;
   813   Svc.Obs.add("weave:ui:sync:finish", function onUIUpdate() {
   814     Svc.Obs.remove("weave:ui:sync:finish", onUIUpdate);
   815     do_check_eq(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
   816     do_check_false(errorHandler.didReportProlongedError);
   818     Services.io.offline = false;
   819     clean();
   820     run_next_test();
   821   });
   823   setLastSync(NON_PROLONGED_ERROR_DURATION);
   824   Service.sync();
   825 });
   827 add_identity_test(this, function test_sync_server_maintenance_error() {
   828   // Test server maintenance errors are not reported.
   829   let server = sync_httpd_setup();
   830   yield setUp(server);
   832   const BACKOFF = 42;
   833   let engine = engineManager.get("catapult");
   834   engine.enabled = true;
   835   engine.exception = {status: 503,
   836                       headers: {"retry-after": BACKOFF}};
   838   function onSyncError() {
   839     do_throw("Shouldn't get here!");
   840   }
   841   Svc.Obs.add("weave:ui:sync:error", onSyncError);
   843   do_check_eq(Status.service, STATUS_OK);
   845   let deferred = Promise.defer();
   846   Svc.Obs.add("weave:ui:sync:finish", function onSyncFinish() {
   847     Svc.Obs.remove("weave:ui:sync:finish", onSyncFinish);
   849     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
   850     do_check_eq(Status.sync, SERVER_MAINTENANCE);
   851     do_check_false(errorHandler.didReportProlongedError);
   853     Svc.Obs.remove("weave:ui:sync:error", onSyncError);
   854     clean();
   855     server.stop(deferred.resolve);
   856   });
   858   setLastSync(NON_PROLONGED_ERROR_DURATION);
   859   Service.sync();
   860   yield deferred.promise;
   861 });
   863 add_identity_test(this, function test_info_collections_login_server_maintenance_error() {
   864   // Test info/collections server maintenance errors are not reported.
   865   let server = sync_httpd_setup();
   866   yield setUp(server);
   868   Service.username = "broken.info";
   869   yield configureIdentity({username: "broken.info"});
   870   Service.serverURL = server.baseURI + "/maintenance/";
   871   Service.clusterURL = server.baseURI + "/maintenance/";
   873   let backoffInterval;
   874   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
   875     Svc.Obs.remove("weave:service:backoff:interval", observe);
   876     backoffInterval = subject;
   877   });
   879   function onUIUpdate() {
   880     do_throw("Shouldn't experience UI update!");
   881   }
   882   Svc.Obs.add("weave:ui:login:error", onUIUpdate);
   884   do_check_false(Status.enforceBackoff);
   885   do_check_eq(Status.service, STATUS_OK);
   887   let deferred = Promise.defer();
   888   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
   889     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
   891     do_check_true(Status.enforceBackoff);
   892     do_check_eq(backoffInterval, 42);
   893     do_check_eq(Status.service, LOGIN_FAILED);
   894     do_check_eq(Status.login, SERVER_MAINTENANCE);
   895     do_check_false(errorHandler.didReportProlongedError);
   897     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
   898     clean();
   899     server.stop(deferred.resolve);
   900   });
   902   setLastSync(NON_PROLONGED_ERROR_DURATION);
   903   Service.sync();
   904   yield deferred.promise;
   905 });
   907 add_identity_test(this, function test_meta_global_login_server_maintenance_error() {
   908   // Test meta/global server maintenance errors are not reported.
   909   let server = sync_httpd_setup();
   910   yield setUp(server);
   912   yield configureIdentity({username: "broken.meta"});
   913   Service.serverURL = server.baseURI + "/maintenance/";
   914   Service.clusterURL = server.baseURI + "/maintenance/";
   916   let backoffInterval;
   917   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
   918     Svc.Obs.remove("weave:service:backoff:interval", observe);
   919     backoffInterval = subject;
   920   });
   922   function onUIUpdate() {
   923     do_throw("Shouldn't get here!");
   924   }
   925   Svc.Obs.add("weave:ui:login:error", onUIUpdate);
   927   do_check_false(Status.enforceBackoff);
   928   do_check_eq(Status.service, STATUS_OK);
   930   let deferred = Promise.defer();
   931   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
   932     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
   934     do_check_true(Status.enforceBackoff);
   935     do_check_eq(backoffInterval, 42);
   936     do_check_eq(Status.service, LOGIN_FAILED);
   937     do_check_eq(Status.login, SERVER_MAINTENANCE);
   938     do_check_false(errorHandler.didReportProlongedError);
   940     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
   941     clean();
   942     server.stop(deferred.resolve);
   943   });
   945   setLastSync(NON_PROLONGED_ERROR_DURATION);
   946   Service.sync();
   947   yield deferred.promise;
   948 });
   950 add_identity_test(this, function test_crypto_keys_login_server_maintenance_error() {
   951   // Test crypto/keys server maintenance errors are not reported.
   952   let server = sync_httpd_setup();
   953   yield setUp(server);
   955   yield configureIdentity({username: "broken.keys"});
   956   Service.serverURL = server.baseURI + "/maintenance/";
   957   Service.clusterURL = server.baseURI + "/maintenance/";
   959   // Force re-download of keys
   960   Service.collectionKeys.clear();
   962   let backoffInterval;
   963   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
   964     Svc.Obs.remove("weave:service:backoff:interval", observe);
   965     backoffInterval = subject;
   966   });
   968   function onUIUpdate() {
   969     do_throw("Shouldn't get here!");
   970   }
   971   Svc.Obs.add("weave:ui:login:error", onUIUpdate);
   973   do_check_false(Status.enforceBackoff);
   974   do_check_eq(Status.service, STATUS_OK);
   976   let deferred = Promise.defer();
   977   Svc.Obs.add("weave:ui:clear-error", function onLoginFinish() {
   978     Svc.Obs.remove("weave:ui:clear-error", onLoginFinish);
   980     do_check_true(Status.enforceBackoff);
   981     do_check_eq(backoffInterval, 42);
   982     do_check_eq(Status.service, LOGIN_FAILED);
   983     do_check_eq(Status.login, SERVER_MAINTENANCE);
   984     do_check_false(errorHandler.didReportProlongedError);
   986     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
   987     clean();
   988     server.stop(deferred.resolve);
   989   });
   991   setLastSync(NON_PROLONGED_ERROR_DURATION);
   992   Service.sync();
   993   yield deferred.promise;
   994 });
   996 add_task(function test_sync_prolonged_server_maintenance_error() {
   997   // Test prolonged server maintenance errors are reported.
   998   let server = sync_httpd_setup();
   999   yield setUp(server);
  1001   const BACKOFF = 42;
  1002   let engine = engineManager.get("catapult");
  1003   engine.enabled = true;
  1004   engine.exception = {status: 503,
  1005                       headers: {"retry-after": BACKOFF}};
  1007   let deferred = Promise.defer();
  1008   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
  1009     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
  1010     do_check_eq(Status.service, SYNC_FAILED);
  1011     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1012     do_check_true(errorHandler.didReportProlongedError);
  1014     clean();
  1015     server.stop(deferred.resolve);
  1016   });
  1018   do_check_eq(Status.service, STATUS_OK);
  1020   setLastSync(PROLONGED_ERROR_DURATION);
  1021   Service.sync();
  1022   yield deferred.promise;
  1023 });
  1025 add_identity_test(this, function test_info_collections_login_prolonged_server_maintenance_error(){
  1026   // Test info/collections prolonged server maintenance errors are reported.
  1027   let server = sync_httpd_setup();
  1028   yield setUp(server);
  1030   yield configureIdentity({username: "broken.info"});
  1031   Service.serverURL = server.baseURI + "/maintenance/";
  1032   Service.clusterURL = server.baseURI + "/maintenance/";
  1034   let backoffInterval;
  1035   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1036     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1037     backoffInterval = subject;
  1038   });
  1040   let deferred = Promise.defer();
  1041   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1042     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1043     do_check_true(Status.enforceBackoff);
  1044     do_check_eq(backoffInterval, 42);
  1045     do_check_eq(Status.service, SYNC_FAILED);
  1046     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1047     do_check_true(errorHandler.didReportProlongedError);
  1049     clean();
  1050     server.stop(deferred.resolve);
  1051   });
  1053   do_check_false(Status.enforceBackoff);
  1054   do_check_eq(Status.service, STATUS_OK);
  1056   setLastSync(PROLONGED_ERROR_DURATION);
  1057   Service.sync();
  1058   yield deferred.promise;
  1059 });
  1061 add_identity_test(this, function test_meta_global_login_prolonged_server_maintenance_error(){
  1062   // Test meta/global prolonged server maintenance errors are reported.
  1063   let server = sync_httpd_setup();
  1064   yield setUp(server);
  1066   yield configureIdentity({username: "broken.meta"});
  1067   Service.serverURL = server.baseURI + "/maintenance/";
  1068   Service.clusterURL = server.baseURI + "/maintenance/";
  1070   let backoffInterval;
  1071   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1072     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1073     backoffInterval = subject;
  1074   });
  1076   let deferred = Promise.defer();
  1077   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1078     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1079     do_check_true(Status.enforceBackoff);
  1080     do_check_eq(backoffInterval, 42);
  1081     do_check_eq(Status.service, SYNC_FAILED);
  1082     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1083     do_check_true(errorHandler.didReportProlongedError);
  1085     clean();
  1086     server.stop(deferred.resolve);
  1087   });
  1089   do_check_false(Status.enforceBackoff);
  1090   do_check_eq(Status.service, STATUS_OK);
  1092   setLastSync(PROLONGED_ERROR_DURATION);
  1093   Service.sync();
  1094   yield deferred.promise;
  1095 });
  1097 add_identity_test(this, function test_download_crypto_keys_login_prolonged_server_maintenance_error(){
  1098   // Test crypto/keys prolonged server maintenance errors are reported.
  1099   let server = sync_httpd_setup();
  1100   yield setUp(server);
  1102   yield configureIdentity({username: "broken.keys"});
  1103   Service.serverURL = server.baseURI + "/maintenance/";
  1104   Service.clusterURL = server.baseURI + "/maintenance/";
  1105   // Force re-download of keys
  1106   Service.collectionKeys.clear();
  1108   let backoffInterval;
  1109   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1110     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1111     backoffInterval = subject;
  1112   });
  1114   let deferred = Promise.defer();
  1115   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1116     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1117     do_check_true(Status.enforceBackoff);
  1118     do_check_eq(backoffInterval, 42);
  1119     do_check_eq(Status.service, SYNC_FAILED);
  1120     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1121     do_check_true(errorHandler.didReportProlongedError);
  1123     clean();
  1124     server.stop(deferred.resolve);
  1125   });
  1127   do_check_false(Status.enforceBackoff);
  1128   do_check_eq(Status.service, STATUS_OK);
  1130   setLastSync(PROLONGED_ERROR_DURATION);
  1131   Service.sync();
  1132   yield deferred.promise;
  1133 });
  1135 add_identity_test(this, function test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
  1136   // Test crypto/keys prolonged server maintenance errors are reported.
  1137   let server = sync_httpd_setup();
  1139   // Start off with an empty account, do not upload a key.
  1140   yield configureIdentity({username: "broken.keys"});
  1141   Service.serverURL = server.baseURI + "/maintenance/";
  1142   Service.clusterURL = server.baseURI + "/maintenance/";
  1144   let backoffInterval;
  1145   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1146     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1147     backoffInterval = subject;
  1148   });
  1150   let deferred = Promise.defer();
  1151   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1152     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1153     do_check_true(Status.enforceBackoff);
  1154     do_check_eq(backoffInterval, 42);
  1155     do_check_eq(Status.service, SYNC_FAILED);
  1156     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1157     do_check_true(errorHandler.didReportProlongedError);
  1159     clean();
  1160     server.stop(deferred.resolve);
  1161   });
  1163   do_check_false(Status.enforceBackoff);
  1164   do_check_eq(Status.service, STATUS_OK);
  1166   setLastSync(PROLONGED_ERROR_DURATION);
  1167   Service.sync();
  1168   yield deferred.promise;
  1169 });
  1171 add_identity_test(this, function test_wipeServer_login_prolonged_server_maintenance_error(){
  1172   // Test that we report prolonged server maintenance errors that occur whilst
  1173   // wiping the server.
  1174   let server = sync_httpd_setup();
  1176   // Start off with an empty account, do not upload a key.
  1177   yield configureIdentity({username: "broken.wipe"});
  1178   Service.serverURL = server.baseURI + "/maintenance/";
  1179   Service.clusterURL = server.baseURI + "/maintenance/";
  1181   let backoffInterval;
  1182   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1183     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1184     backoffInterval = subject;
  1185   });
  1187   let deferred = Promise.defer();
  1188   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1189     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1190     do_check_true(Status.enforceBackoff);
  1191     do_check_eq(backoffInterval, 42);
  1192     do_check_eq(Status.service, SYNC_FAILED);
  1193     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1194     do_check_true(errorHandler.didReportProlongedError);
  1196     clean();
  1197     server.stop(deferred.resolve);
  1198   });
  1200   do_check_false(Status.enforceBackoff);
  1201   do_check_eq(Status.service, STATUS_OK);
  1203   setLastSync(PROLONGED_ERROR_DURATION);
  1204   Service.sync();
  1205   yield deferred.promise;
  1206 });
  1208 add_identity_test(this, function test_wipeRemote_prolonged_server_maintenance_error(){
  1209   // Test that we report prolonged server maintenance errors that occur whilst
  1210   // wiping all remote devices.
  1211   let server = sync_httpd_setup();
  1213   server.registerPathHandler("/1.1/broken.wipe/storage/catapult", service_unavailable);
  1214   yield configureIdentity({username: "broken.wipe"});
  1215   Service.serverURL = server.baseURI + "/maintenance/";
  1216   Service.clusterURL = server.baseURI + "/maintenance/";
  1217   generateAndUploadKeys();
  1219   let engine = engineManager.get("catapult");
  1220   engine.exception = null;
  1221   engine.enabled = true;
  1223   let backoffInterval;
  1224   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1225     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1226     backoffInterval = subject;
  1227   });
  1229   let deferred = Promise.defer();
  1230   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
  1231     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
  1232     do_check_true(Status.enforceBackoff);
  1233     do_check_eq(backoffInterval, 42);
  1234     do_check_eq(Status.service, SYNC_FAILED);
  1235     do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE);
  1236     do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
  1237     do_check_true(errorHandler.didReportProlongedError);
  1239     clean();
  1240     server.stop(deferred.resolve);
  1241   });
  1243   do_check_false(Status.enforceBackoff);
  1244   do_check_eq(Status.service, STATUS_OK);
  1246   Svc.Prefs.set("firstSync", "wipeRemote");
  1247   setLastSync(PROLONGED_ERROR_DURATION);
  1248   Service.sync();
  1249   yield deferred.promise;
  1250 });
  1252 add_task(function test_sync_syncAndReportErrors_server_maintenance_error() {
  1253   // Test server maintenance errors are reported
  1254   // when calling syncAndReportErrors.
  1255   let server = sync_httpd_setup();
  1256   yield setUp(server);
  1258   const BACKOFF = 42;
  1259   let engine = engineManager.get("catapult");
  1260   engine.enabled = true;
  1261   engine.exception = {status: 503,
  1262                       headers: {"retry-after": BACKOFF}};
  1264   let deferred = Promise.defer();
  1265   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
  1266     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
  1267     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
  1268     do_check_eq(Status.sync, SERVER_MAINTENANCE);
  1269     do_check_false(errorHandler.didReportProlongedError);
  1271     clean();
  1272     server.stop(deferred.resolve);
  1273   });
  1275   do_check_eq(Status.service, STATUS_OK);
  1277   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1278   errorHandler.syncAndReportErrors();
  1279   yield deferred.promise;
  1280 });
  1282 add_identity_test(this, function test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
  1283   // Test info/collections server maintenance errors are reported
  1284   // when calling syncAndReportErrors.
  1285   let server = sync_httpd_setup();
  1286   yield setUp(server);
  1288   yield configureIdentity({username: "broken.info"});
  1289   Service.serverURL = server.baseURI + "/maintenance/";
  1290   Service.clusterURL = server.baseURI + "/maintenance/";
  1292   let backoffInterval;
  1293   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1294     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1295     backoffInterval = subject;
  1296   });
  1298   let deferred = Promise.defer();
  1299   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1300     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1301     do_check_true(Status.enforceBackoff);
  1302     do_check_eq(backoffInterval, 42);
  1303     do_check_eq(Status.service, LOGIN_FAILED);
  1304     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1305     do_check_false(errorHandler.didReportProlongedError);
  1307     clean();
  1308     server.stop(deferred.resolve);
  1309   });
  1311   do_check_false(Status.enforceBackoff);
  1312   do_check_eq(Status.service, STATUS_OK);
  1314   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1315   errorHandler.syncAndReportErrors();
  1316   yield deferred.promise;
  1317 });
  1319 add_identity_test(this, function test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
  1320   // Test meta/global server maintenance errors are reported
  1321   // when calling syncAndReportErrors.
  1322   let server = sync_httpd_setup();
  1323   yield setUp(server);
  1325   yield configureIdentity({username: "broken.meta"});
  1326   Service.serverURL = server.baseURI + "/maintenance/";
  1327   Service.clusterURL = server.baseURI + "/maintenance/";
  1329   let backoffInterval;
  1330   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1331     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1332     backoffInterval = subject;
  1333   });
  1335   let deferred = Promise.defer();
  1336   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1337     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1338     do_check_true(Status.enforceBackoff);
  1339     do_check_eq(backoffInterval, 42);
  1340     do_check_eq(Status.service, LOGIN_FAILED);
  1341     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1342     do_check_false(errorHandler.didReportProlongedError);
  1344     clean();
  1345     server.stop(deferred.resolve);
  1346   });
  1348   do_check_false(Status.enforceBackoff);
  1349   do_check_eq(Status.service, STATUS_OK);
  1351   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1352   errorHandler.syncAndReportErrors();
  1353   yield deferred.promise;
  1354 });
  1356 add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
  1357   // Test crypto/keys server maintenance errors are reported
  1358   // when calling syncAndReportErrors.
  1359   let server = sync_httpd_setup();
  1360   yield setUp(server);
  1362   yield configureIdentity({username: "broken.keys"});
  1363   Service.serverURL = server.baseURI + "/maintenance/";
  1364   Service.clusterURL = server.baseURI + "/maintenance/";
  1365   // Force re-download of keys
  1366   Service.collectionKeys.clear();
  1368   let backoffInterval;
  1369   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1370     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1371     backoffInterval = subject;
  1372   });
  1374   let deferred = Promise.defer();
  1375   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1376     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1377     do_check_true(Status.enforceBackoff);
  1378     do_check_eq(backoffInterval, 42);
  1379     do_check_eq(Status.service, LOGIN_FAILED);
  1380     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1381     do_check_false(errorHandler.didReportProlongedError);
  1383     clean();
  1384     server.stop(deferred.resolve);
  1385   });
  1387   do_check_false(Status.enforceBackoff);
  1388   do_check_eq(Status.service, STATUS_OK);
  1390   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1391   errorHandler.syncAndReportErrors();
  1392   yield deferred.promise;
  1393 });
  1395 add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
  1396   // Test crypto/keys server maintenance errors are reported
  1397   // when calling syncAndReportErrors.
  1398   let server = sync_httpd_setup();
  1400   // Start off with an empty account, do not upload a key.
  1401   yield configureIdentity({username: "broken.keys"});
  1402   Service.serverURL = server.baseURI + "/maintenance/";
  1403   Service.clusterURL = server.baseURI + "/maintenance/";
  1405   let backoffInterval;
  1406   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1407     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1408     backoffInterval = subject;
  1409   });
  1411   let deferred = Promise.defer();
  1412   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1413     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1414     do_check_true(Status.enforceBackoff);
  1415     do_check_eq(backoffInterval, 42);
  1416     do_check_eq(Status.service, LOGIN_FAILED);
  1417     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1418     do_check_false(errorHandler.didReportProlongedError);
  1420     clean();
  1421     server.stop(deferred.resolve);
  1422   });
  1424   do_check_false(Status.enforceBackoff);
  1425   do_check_eq(Status.service, STATUS_OK);
  1427   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1428   errorHandler.syncAndReportErrors();
  1429   yield deferred.promise;
  1430 });
  1432 add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
  1433   // Test crypto/keys server maintenance errors are reported
  1434   // when calling syncAndReportErrors.
  1435   let server = sync_httpd_setup();
  1437   // Start off with an empty account, do not upload a key.
  1438   yield configureIdentity({username: "broken.wipe"});
  1439   Service.serverURL = server.baseURI + "/maintenance/";
  1440   Service.clusterURL = server.baseURI + "/maintenance/";
  1442   let backoffInterval;
  1443   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1444     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1445     backoffInterval = subject;
  1446   });
  1448   let deferred = Promise.defer();
  1449   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1450     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1451     do_check_true(Status.enforceBackoff);
  1452     do_check_eq(backoffInterval, 42);
  1453     do_check_eq(Status.service, LOGIN_FAILED);
  1454     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1455     do_check_false(errorHandler.didReportProlongedError);
  1457     clean();
  1458     server.stop(deferred.resolve);
  1459   });
  1461   do_check_false(Status.enforceBackoff);
  1462   do_check_eq(Status.service, STATUS_OK);
  1464   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1465   errorHandler.syncAndReportErrors();
  1466   yield deferred.promise;
  1467 });
  1469 add_identity_test(this, function test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
  1470   // Test that we report prolonged server maintenance errors that occur whilst
  1471   // wiping all remote devices.
  1472   let server = sync_httpd_setup();
  1474   yield configureIdentity({username: "broken.wipe"});
  1475   Service.serverURL = server.baseURI + "/maintenance/";
  1476   Service.clusterURL = server.baseURI + "/maintenance/";
  1477   generateAndUploadKeys();
  1479   let engine = engineManager.get("catapult");
  1480   engine.exception = null;
  1481   engine.enabled = true;
  1483   let backoffInterval;
  1484   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1485     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1486     backoffInterval = subject;
  1487   });
  1489   let deferred = Promise.defer();
  1490   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
  1491     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
  1492     do_check_true(Status.enforceBackoff);
  1493     do_check_eq(backoffInterval, 42);
  1494     do_check_eq(Status.service, SYNC_FAILED);
  1495     do_check_eq(Status.sync, SERVER_MAINTENANCE);
  1496     do_check_eq(Svc.Prefs.get("firstSync"), "wipeRemote");
  1497     do_check_false(errorHandler.didReportProlongedError);
  1499     clean();
  1500     server.stop(deferred.resolve);
  1501   });
  1503   do_check_false(Status.enforceBackoff);
  1504   do_check_eq(Status.service, STATUS_OK);
  1506   Svc.Prefs.set("firstSync", "wipeRemote");
  1507   setLastSync(NON_PROLONGED_ERROR_DURATION);
  1508   errorHandler.syncAndReportErrors();
  1509   yield deferred.promise;
  1510 });
  1512 add_task(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
  1513   // Test prolonged server maintenance errors are
  1514   // reported when calling syncAndReportErrors.
  1515   let server = sync_httpd_setup();
  1516   yield setUp(server);
  1518   const BACKOFF = 42;
  1519   let engine = engineManager.get("catapult");
  1520   engine.enabled = true;
  1521   engine.exception = {status: 503,
  1522                       headers: {"retry-after": BACKOFF}};
  1524   let deferred = Promise.defer();
  1525   Svc.Obs.add("weave:ui:sync:error", function onUIUpdate() {
  1526     Svc.Obs.remove("weave:ui:sync:error", onUIUpdate);
  1527     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
  1528     do_check_eq(Status.sync, SERVER_MAINTENANCE);
  1529     // syncAndReportErrors means dontIgnoreErrors, which means
  1530     // didReportProlongedError not touched.
  1531     do_check_false(errorHandler.didReportProlongedError);
  1533     clean();
  1534     server.stop(deferred.resolve);
  1535   });
  1537   do_check_eq(Status.service, STATUS_OK);
  1539   setLastSync(PROLONGED_ERROR_DURATION);
  1540   errorHandler.syncAndReportErrors();
  1541   yield deferred.promise;
  1542 });
  1544 add_identity_test(this, function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
  1545   // Test info/collections server maintenance errors are reported
  1546   // when calling syncAndReportErrors.
  1547   let server = sync_httpd_setup();
  1548   yield setUp(server);
  1550   yield configureIdentity({username: "broken.info"});
  1551   Service.serverURL = server.baseURI + "/maintenance/";
  1552   Service.clusterURL = server.baseURI + "/maintenance/";
  1554   let backoffInterval;
  1555   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1556     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1557     backoffInterval = subject;
  1558   });
  1560   let deferred = Promise.defer();
  1561   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1562     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1563     do_check_true(Status.enforceBackoff);
  1564     do_check_eq(backoffInterval, 42);
  1565     do_check_eq(Status.service, LOGIN_FAILED);
  1566     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1567     // syncAndReportErrors means dontIgnoreErrors, which means
  1568     // didReportProlongedError not touched.
  1569     do_check_false(errorHandler.didReportProlongedError);
  1571     clean();
  1572     server.stop(deferred.resolve);
  1573   });
  1575   do_check_false(Status.enforceBackoff);
  1576   do_check_eq(Status.service, STATUS_OK);
  1578   setLastSync(PROLONGED_ERROR_DURATION);
  1579   errorHandler.syncAndReportErrors();
  1580   yield deferred.promise;
  1581 });
  1583 add_identity_test(this, function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
  1584   // Test meta/global server maintenance errors are reported
  1585   // when calling syncAndReportErrors.
  1586   let server = sync_httpd_setup();
  1587   yield setUp(server);
  1589   yield configureIdentity({username: "broken.meta"});
  1590   Service.serverURL = server.baseURI + "/maintenance/";
  1591   Service.clusterURL = server.baseURI + "/maintenance/";
  1593   let backoffInterval;
  1594   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1595     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1596     backoffInterval = subject;
  1597   });
  1599   let deferred = Promise.defer();
  1600   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1601     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1602     do_check_true(Status.enforceBackoff);
  1603     do_check_eq(backoffInterval, 42);
  1604     do_check_eq(Status.service, LOGIN_FAILED);
  1605     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1606     // syncAndReportErrors means dontIgnoreErrors, which means
  1607     // didReportProlongedError not touched.
  1608     do_check_false(errorHandler.didReportProlongedError);
  1610     clean();
  1611     server.stop(deferred.resolve);
  1612   });
  1614   do_check_false(Status.enforceBackoff);
  1615   do_check_eq(Status.service, STATUS_OK);
  1617   setLastSync(PROLONGED_ERROR_DURATION);
  1618   errorHandler.syncAndReportErrors();
  1619   yield deferred.promise;
  1620 });
  1622 add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
  1623   // Test crypto/keys server maintenance errors are reported
  1624   // when calling syncAndReportErrors.
  1625   let server = sync_httpd_setup();
  1626   yield setUp(server);
  1628   yield configureIdentity({username: "broken.keys"});
  1629   Service.serverURL = server.baseURI + "/maintenance/";
  1630   Service.clusterURL = server.baseURI + "/maintenance/";
  1631   // Force re-download of keys
  1632   Service.collectionKeys.clear();
  1634   let backoffInterval;
  1635   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1636     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1637     backoffInterval = subject;
  1638   });
  1640   let deferred = Promise.defer();
  1641   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1642     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1643     do_check_true(Status.enforceBackoff);
  1644     do_check_eq(backoffInterval, 42);
  1645     do_check_eq(Status.service, LOGIN_FAILED);
  1646     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1647     // syncAndReportErrors means dontIgnoreErrors, which means
  1648     // didReportProlongedError not touched.
  1649     do_check_false(errorHandler.didReportProlongedError);
  1651     clean();
  1652     server.stop(deferred.resolve);
  1653   });
  1655   do_check_false(Status.enforceBackoff);
  1656   do_check_eq(Status.service, STATUS_OK);
  1658   setLastSync(PROLONGED_ERROR_DURATION);
  1659   errorHandler.syncAndReportErrors();
  1660   yield deferred.promise;
  1661 });
  1663 add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
  1664   // Test crypto/keys server maintenance errors are reported
  1665   // when calling syncAndReportErrors.
  1666   let server = sync_httpd_setup();
  1668   // Start off with an empty account, do not upload a key.
  1669   yield configureIdentity({username: "broken.keys"});
  1670   Service.serverURL = server.baseURI + "/maintenance/";
  1671   Service.clusterURL = server.baseURI + "/maintenance/";
  1673   let backoffInterval;
  1674   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1675     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1676     backoffInterval = subject;
  1677   });
  1679   let deferred = Promise.defer();
  1680   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1681     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1682     do_check_true(Status.enforceBackoff);
  1683     do_check_eq(backoffInterval, 42);
  1684     do_check_eq(Status.service, LOGIN_FAILED);
  1685     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1686     // syncAndReportErrors means dontIgnoreErrors, which means
  1687     // didReportProlongedError not touched.
  1688     do_check_false(errorHandler.didReportProlongedError);
  1690     clean();
  1691     server.stop(deferred.resolve);
  1692   });
  1694   do_check_false(Status.enforceBackoff);
  1695   do_check_eq(Status.service, STATUS_OK);
  1697   setLastSync(PROLONGED_ERROR_DURATION);
  1698   errorHandler.syncAndReportErrors();
  1699   yield deferred.promise;
  1700 });
  1702 add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
  1703   // Test crypto/keys server maintenance errors are reported
  1704   // when calling syncAndReportErrors.
  1705   let server = sync_httpd_setup();
  1707   // Start off with an empty account, do not upload a key.
  1708   yield configureIdentity({username: "broken.wipe"});
  1709   Service.serverURL = server.baseURI + "/maintenance/";
  1710   Service.clusterURL = server.baseURI + "/maintenance/";
  1712   let backoffInterval;
  1713   Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
  1714     Svc.Obs.remove("weave:service:backoff:interval", observe);
  1715     backoffInterval = subject;
  1716   });
  1718   let deferred = Promise.defer();
  1719   Svc.Obs.add("weave:ui:login:error", function onUIUpdate() {
  1720     Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
  1721     do_check_true(Status.enforceBackoff);
  1722     do_check_eq(backoffInterval, 42);
  1723     do_check_eq(Status.service, LOGIN_FAILED);
  1724     do_check_eq(Status.login, SERVER_MAINTENANCE);
  1725     // syncAndReportErrors means dontIgnoreErrors, which means
  1726     // didReportProlongedError not touched.
  1727     do_check_false(errorHandler.didReportProlongedError);
  1729     clean();
  1730     server.stop(deferred.resolve);
  1731   });
  1733   do_check_false(Status.enforceBackoff);
  1734   do_check_eq(Status.service, STATUS_OK);
  1736   setLastSync(PROLONGED_ERROR_DURATION);
  1737   errorHandler.syncAndReportErrors();
  1738   yield deferred.promise;
  1739 });
  1741 add_task(function test_sync_engine_generic_fail() {
  1742   let server = sync_httpd_setup();
  1744   let engine = engineManager.get("catapult");
  1745   engine.enabled = true;
  1746   engine.sync = function sync() {
  1747     Svc.Obs.notify("weave:engine:sync:error", "", "catapult");
  1748   };
  1750   let log = Log.repository.getLogger("Sync.ErrorHandler");
  1751   Svc.Prefs.set("log.appender.file.logOnError", true);
  1753   do_check_eq(Status.engines["catapult"], undefined);
  1755   let deferred = Promise.defer();
  1756   // Don't wait for reset-file-log until the sync is underway.
  1757   // This avoids us catching a delayed notification from an earlier test.
  1758   Svc.Obs.add("weave:engine:sync:finish", function onEngineFinish() {
  1759     Svc.Obs.remove("weave:engine:sync:finish", onEngineFinish);
  1761     log.info("Adding reset-file-log observer.");
  1762     Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
  1763       Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
  1765       // Put these checks here, not after sync(), so that we aren't racing the
  1766       // log handler... which resets everything just a few lines below!
  1767       _("Status.engines: " + JSON.stringify(Status.engines));
  1768       do_check_eq(Status.engines["catapult"], ENGINE_UNKNOWN_FAIL);
  1769       do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
  1771       // Test Error log was written on SYNC_FAILED_PARTIAL.
  1772       let entries = logsdir.directoryEntries;
  1773       do_check_true(entries.hasMoreElements());
  1774       let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
  1775       do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
  1776                   LOG_PREFIX_ERROR);
  1778       clean();
  1779       server.stop(deferred.resolve);
  1780     });
  1781   });
  1783   do_check_true(yield setUp(server));
  1784   Service.sync();
  1785   yield deferred.promise;
  1786 });
  1788 add_test(function test_logs_on_sync_error_despite_shouldReportError() {
  1789   _("Ensure that an error is still logged when weave:service:sync:error " +
  1790     "is notified, despite shouldReportError returning false.");
  1792   let log = Log.repository.getLogger("Sync.ErrorHandler");
  1793   Svc.Prefs.set("log.appender.file.logOnError", true);
  1794   log.info("TESTING");
  1796   // Ensure that we report no error.
  1797   Status.login = MASTER_PASSWORD_LOCKED;
  1798   do_check_false(errorHandler.shouldReportError());
  1800   Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
  1801     Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
  1803     // Test that error log was written.
  1804     let entries = logsdir.directoryEntries;
  1805     do_check_true(entries.hasMoreElements());
  1806     let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
  1807     do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
  1808                 LOG_PREFIX_ERROR);
  1810     clean();
  1811     run_next_test();
  1812   });
  1813   Svc.Obs.notify("weave:service:sync:error", {});
  1814 });
  1816 add_test(function test_logs_on_login_error_despite_shouldReportError() {
  1817   _("Ensure that an error is still logged when weave:service:login:error " +
  1818     "is notified, despite shouldReportError returning false.");
  1820   let log = Log.repository.getLogger("Sync.ErrorHandler");
  1821   Svc.Prefs.set("log.appender.file.logOnError", true);
  1822   log.info("TESTING");
  1824   // Ensure that we report no error.
  1825   Status.login = MASTER_PASSWORD_LOCKED;
  1826   do_check_false(errorHandler.shouldReportError());
  1828   Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
  1829     Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
  1831     // Test that error log was written.
  1832     let entries = logsdir.directoryEntries;
  1833     do_check_true(entries.hasMoreElements());
  1834     let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
  1835     do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
  1836                 LOG_PREFIX_ERROR);
  1838     clean();
  1839     run_next_test();
  1840   });
  1841   Svc.Obs.notify("weave:service:login:error", {});
  1842 });
  1844 // This test should be the last one since it monkeypatches the engine object
  1845 // and we should only have one engine object throughout the file (bug 629664).
  1846 add_task(function test_engine_applyFailed() {
  1847   let server = sync_httpd_setup();
  1849   let engine = engineManager.get("catapult");
  1850   engine.enabled = true;
  1851   delete engine.exception;
  1852   engine.sync = function sync() {
  1853     Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
  1854   };
  1856   let log = Log.repository.getLogger("Sync.ErrorHandler");
  1857   Svc.Prefs.set("log.appender.file.logOnError", true);
  1859   let deferred = Promise.defer();
  1860   Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
  1861     Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
  1863     do_check_eq(Status.engines["catapult"], ENGINE_APPLY_FAIL);
  1864     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
  1866     // Test Error log was written on SYNC_FAILED_PARTIAL.
  1867     let entries = logsdir.directoryEntries;
  1868     do_check_true(entries.hasMoreElements());
  1869     let logfile = entries.getNext().QueryInterface(Ci.nsILocalFile);
  1870     do_check_eq(logfile.leafName.slice(0, LOG_PREFIX_ERROR.length),
  1871                 LOG_PREFIX_ERROR);
  1873     clean();
  1874     server.stop(deferred.resolve);
  1875   });
  1877   do_check_eq(Status.engines["catapult"], undefined);
  1878   do_check_true(yield setUp(server));
  1879   Service.sync();
  1880   yield deferred.promise;
  1881 });

mercurial