Bug 1242975 - Make services/sync eslintable. r=markh
authorHector Zhao <bzhao@mozilla.com>
Tue, 26 Jan 2016 23:13:31 +0800
changeset 327108 c09055940ce92b4af917ff156fca0b67cfc36fa6
parent 327107 adf78202a5bb40a743cbf0ccf4da12083f2ed598
child 327109 ad4fae74b6a31041cd4586072df5baeaae216c2f
push id10194
push userdmitchell@mozilla.com
push dateFri, 29 Jan 2016 17:28:53 +0000
reviewersmarkh
bugs1242975
milestone47.0a1
Bug 1242975 - Make services/sync eslintable. r=markh
services/sync/modules-testing/utils.js
services/sync/modules/browserid_identity.js
services/sync/modules/engines.js
services/sync/modules/engines/bookmarks.js
services/sync/modules/engines/history.js
services/sync/modules/engines/passwords.js
services/sync/modules/identity.js
services/sync/modules/policies.js
services/sync/modules/record.js
services/sync/modules/resource.js
services/sync/modules/util.js
services/sync/tests/unit/test_bookmark_engine.js
services/sync/tests/unit/test_browserid_identity.js
services/sync/tests/unit/test_collections_recovery.js
services/sync/tests/unit/test_corrupt_keys.js
services/sync/tests/unit/test_errorhandler.js
services/sync/tests/unit/test_errorhandler_eol.js
services/sync/tests/unit/test_errorhandler_sync_checkServerError.js
services/sync/tests/unit/test_fxa_node_reassignment.js
services/sync/tests/unit/test_fxa_service_cluster.js
services/sync/tests/unit/test_interval_triggers.js
services/sync/tests/unit/test_node_reassignment.js
services/sync/tests/unit/test_service_startOver.js
services/sync/tests/unit/test_service_wipeServer.js
services/sync/tests/unit/test_syncscheduler.js
services/sync/tps/extensions/mozmill/resource/driver/controller.js
services/sync/tps/extensions/mozmill/resource/modules/assertions.js
services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
--- a/services/sync/modules-testing/utils.js
+++ b/services/sync/modules-testing/utils.js
@@ -311,25 +311,25 @@ this.encryptPayload = function encryptPa
 this.add_identity_test = function(test, testFunction) {
   function note(what) {
     let msg = "running test " + testFunction.name + " with " + what + " identity manager";
     test.do_print(msg);
   }
   let ns = {};
   Cu.import("resource://services-sync/service.js", ns);
   // one task for the "old" identity manager.
-  test.add_task(function() {
+  test.add_task(function* () {
     note("sync");
     let oldIdentity = Status._authManager;
     ensureLegacyIdentityManager();
     yield testFunction();
     Status.__authManager = ns.Service.identity = oldIdentity;
   });
   // another task for the FxAccounts identity manager.
-  test.add_task(function() {
+  test.add_task(function* () {
     note("FxAccounts");
     let oldIdentity = Status._authManager;
     Status.__authManager = ns.Service.identity = new BrowserIDManager();
     yield testFunction();
     Status.__authManager = ns.Service.identity = oldIdentity;
   });
 }
 
--- a/services/sync/modules/browserid_identity.js
+++ b/services/sync/modules/browserid_identity.js
@@ -689,17 +689,20 @@ this.BrowserIDManager.prototype = {
     let cb = Async.makeSpinningCallback();
     this._ensureValidToken().then(cb, cb);
     // Note that in failure states we return null, causing the request to be
     // made without authorization headers, thereby presumably causing a 401,
     // which causes Sync to log out. If we throw, this may not happen as
     // expected.
     try {
       cb.wait();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.error("Failed to fetch a token for authentication", ex);
       return null;
     }
     if (!this._token) {
       return null;
     }
     let credentials = {algorithm: "sha256",
                        id: this._token.id,
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -296,22 +296,26 @@ Store.prototype = {
    * @param  records Array of records to apply
    * @return Array of record IDs which did not apply cleanly
    */
   applyIncomingBatch: function (records) {
     let failed = [];
     for (let record of records) {
       try {
         this.applyIncoming(record);
-      } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) {
-        // This kind of exception should have a 'cause' attribute, which is an
-        // originating exception.
-        // ex.cause will carry its stack with it when rethrown.
-        throw ex.cause;
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (ex.code == Engine.prototype.eEngineAbortApplyIncoming) {
+          // This kind of exception should have a 'cause' attribute, which is an
+          // originating exception.
+          // ex.cause will carry its stack with it when rethrown.
+          throw ex.cause;
+        }
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.warn("Failed to apply incoming record " + record.id, ex);
         this.engine._noteApplyFailure();
         failed.push(record.id);
       }
     };
     return failed;
   },
 
@@ -985,17 +989,20 @@ SyncEngine.prototype = {
     // methods to signal that they would like processing of incoming records to
     // cease.
     let aborting = undefined;
 
     function doApplyBatch() {
       this._tracker.ignoreAll = true;
       try {
         failed = failed.concat(this._store.applyIncomingBatch(applyBatch));
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         // Catch any error that escapes from applyIncomingBatch. At present
         // those will all be abort events.
         this._log.warn("Got exception, aborting processIncoming", ex);
         aborting = ex;
       }
       this._tracker.ignoreAll = false;
       applyBatch = [];
     }
@@ -1033,27 +1040,33 @@ SyncEngine.prototype = {
       item.collection = self.name;
 
       // Remember which records were processed
       handled.push(item.id);
 
       try {
         try {
           item.decrypt(key);
-        } catch (ex if Utils.isHMACMismatch(ex)) {
+        } catch (ex) {
+          if (!Utils.isHMACMismatch(ex)) {
+            throw ex;
+          }
           let strategy = self.handleHMACMismatch(item, true);
           if (strategy == SyncEngine.kRecoveryStrategy.retry) {
             // You only get one retry.
             try {
               // Try decrypting again, typically because we've got new keys.
               self._log.info("Trying decrypt again...");
               key = self.service.collectionKeys.keyForCollection(self.name);
               item.decrypt(key);
               strategy = null;
-            } catch (ex if Utils.isHMACMismatch(ex)) {
+            } catch (ex) {
+              if (!Utils.isHMACMismatch(ex)) {
+                throw ex;
+              }
               strategy = self.handleHMACMismatch(item, false);
             }
           }
 
           switch (strategy) {
             case null:
               // Retry succeeded! No further handling.
               break;
@@ -1076,26 +1089,30 @@ SyncEngine.prototype = {
         self._noteApplyFailure();
         failed.push(item.id);
         return;
       }
 
       let shouldApply;
       try {
         shouldApply = self._reconcile(item);
-      } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) {
-        self._log.warn("Reconciliation failed: aborting incoming processing.");
-        self._noteApplyFailure();
-        failed.push(item.id);
-        aborting = ex.cause;
-      } catch (ex if !Async.isShutdownException(ex)) {
-        self._log.warn("Failed to reconcile incoming record " + item.id, ex);
-        self._noteApplyFailure();
-        failed.push(item.id);
-        return;
+      } catch (ex) {
+        if (ex.code == Engine.prototype.eEngineAbortApplyIncoming) {
+          self._log.warn("Reconciliation failed: aborting incoming processing.");
+          self._noteApplyFailure();
+          failed.push(item.id);
+          aborting = ex.cause;
+        } else if (!Async.isShutdownException(ex)) {
+          self._log.warn("Failed to reconcile incoming record " + item.id, ex);
+          self._noteApplyFailure();
+          failed.push(item.id);
+          return;
+        } else {
+          throw ex;
+        }
       }
 
       if (shouldApply) {
         count.applied++;
         applyBatch.push(item);
       } else {
         count.reconciled++;
         self._log.trace("Skipping reconciled incoming item " + item.id);
@@ -1466,17 +1483,20 @@ SyncEngine.prototype = {
         let ok = false;
         try {
           out = this._createRecord(id);
           if (this._log.level <= Log.Level.Trace)
             this._log.trace("Outgoing: " + out);
 
           out.encrypt(this.service.collectionKeys.keyForCollection(this.name));
           ok = true;
-        } catch (ex if !Async.isShutdownException(ex)) {
+        } catch (ex) {
+          if (Async.isShutdownException(ex)) {
+            throw ex;
+          }
           this._log.warn("Error creating record", ex);
         }
         if (ok) {
           postQueue.enqueue(out);
         }
         this._store._sleep(0);
       }
       postQueue.flush();
@@ -1552,17 +1572,20 @@ SyncEngine.prototype = {
       record.decrypt(key);
       canDecrypt = true;
     }.bind(this);
 
     // Any failure fetching/decrypting will just result in false
     try {
       this._log.trace("Trying to decrypt a record from the server..");
       test.get();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.debug("Failed test decrypt", ex);
     }
 
     return canDecrypt;
   },
 
   _resetClient: function () {
     this.resetLastSync();
--- a/services/sync/modules/engines/bookmarks.js
+++ b/services/sync/modules/engines/bookmarks.js
@@ -251,17 +251,20 @@ BookmarksEngine.prototype = {
       let stmt = this._store._getStmt(`
             SELECT h.url
             FROM moz_places h
             JOIN moz_bookmarks b ON h.id = b.fk
             WHERE b.id = :id`);
       stmt.params.id = id;
       let rows = Async.querySpinningly(stmt, ["url"]);
       url = rows.length == 0 ? "<not found>" : rows[0].url;
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       if (ex instanceof Ci.mozIStorageError) {
         url = `<failed: Storage error: ${ex.message} (${ex.result})>`;
       } else {
         url = `<failed: ${ex.toString()}>`;
       }
     }
     return url;
   },
@@ -409,17 +412,17 @@ BookmarksEngine.prototype = {
     this._log.trace("No dupe found for key " + key + "/" + altKey + ".");
     return undefined;
   },
 
   _syncStartup: function _syncStart() {
     SyncEngine.prototype._syncStartup.call(this);
 
     let cb = Async.makeSpinningCallback();
-    Task.spawn(function() {
+    Task.spawn(function* () {
       // For first-syncs, make a backup for the user to restore
       if (this.lastSync == 0) {
         this._log.debug("Bookmarks backup starting.");
         yield PlacesBackups.create(null, true);
         this._log.debug("Bookmarks backup done.");
       }
     }.bind(this)).then(
       cb, ex => {
@@ -435,17 +438,20 @@ BookmarksEngine.prototype = {
 
     this.__defineGetter__("_guidMap", function() {
       // Create a mapping of folder titles and separator positions to GUID.
       // We do this lazily so that we don't do any work unless we reconcile
       // incoming items.
       let guidMap;
       try {
         guidMap = this._buildGUIDMap();
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.warn("Error while building GUID map, skipping all other incoming items", ex);
         throw {code: Engine.prototype.eEngineAbortApplyIncoming,
                cause: ex};
       }
       delete this._guidMap;
       return this._guidMap = guidMap;
     });
 
@@ -1362,17 +1368,17 @@ BookmarksStore.prototype = {
       if (guid != "places" && guid != "tags")
         this._getChildren(guid, items);
     }
     return items;
   },
 
   wipe: function BStore_wipe() {
     let cb = Async.makeSpinningCallback();
-    Task.spawn(function() {
+    Task.spawn(function* () {
       // Save a backup before clearing out all bookmarks.
       yield PlacesBackups.create(null, true);
       for (let guid of kSpecialIds.guids)
         if (guid != "places") {
           let id = kSpecialIds.specialIdForGUID(guid);
           if (id)
             PlacesUtils.bookmarks.removeFolderChildren(id);
         }
--- a/services/sync/modules/engines/history.js
+++ b/services/sync/modules/engines/history.js
@@ -218,17 +218,20 @@ HistoryStore.prototype = {
         if (record.deleted) {
           // Consider using nsIBrowserHistory::removePages() here.
           this.remove(record);
           // No further processing needed. Remove it from the list.
           shouldApply = false;
         } else {
           shouldApply = this._recordToPlaceInfo(record);
         }
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         failed.push(record.id);
         shouldApply = false;
       }
 
       if (shouldApply) {
         k += 1;
       }
     }
--- a/services/sync/modules/engines/passwords.js
+++ b/services/sync/modules/engines/passwords.js
@@ -63,17 +63,20 @@ PasswordEngine.prototype = {
           }
         } else {
           this._log.debug("Didn't find any passwords to delete");
         }
         // If there were no ids to delete, or we succeeded, or got a 400,
         // record success.
         Svc.Prefs.set("deletePwdFxA", true);
         Svc.Prefs.reset("deletePwd"); // The old prefname we previously used.
-      } catch (ex if !Async.isShutdownException(ex)) {
+      } catch (ex) {
+        if (Async.isShutdownException(ex)) {
+          throw ex;
+        }
         this._log.debug("Password deletes failed", ex);
       }
     }
   },
 
   _findDupe: function (item) {
     let login = this._store._nsLoginInfoFromRecord(item);
     if (!login) {
--- a/services/sync/modules/identity.js
+++ b/services/sync/modules/identity.js
@@ -441,17 +441,20 @@ IdentityManager.prototype = {
    * allows us to avoid a network request for when we actually need the
    * migration info.
    */
   prefetchMigrationSentinel: function(service) {
     // Try and fetch the migration sentinel - it will end up in the recordManager
     // cache.
     try {
       service.recordManager.get(service.storageURL + "meta/fxa_credentials");
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.warn("Failed to pre-fetch the migration sentinel", ex);
     }
   },
 
   /**
    * Obtains the array of basic logins from nsiPasswordManager.
    */
   _getLogins: function _getLogins(realm) {
--- a/services/sync/modules/policies.js
+++ b/services/sync/modules/policies.js
@@ -234,17 +234,20 @@ SyncScheduler.prototype = {
          Services.prefs.savePrefFile(null);
          Svc.Idle.addIdleObserver(this, Svc.Prefs.get("scheduler.idleTime"));
          Svc.Obs.add("wake_notification", this);
          break;
       case "weave:service:start-over":
          this.setDefaults();
          try {
            Svc.Idle.removeIdleObserver(this, Svc.Prefs.get("scheduler.idleTime"));
-         } catch (ex if (ex.result == Cr.NS_ERROR_FAILURE)) {
+         } catch (ex) {
+           if (ex.result != Cr.NS_ERROR_FAILURE) {
+             throw ex;
+           }
            // In all likelihood we didn't have an idle observer registered yet.
            // It's all good.
          }
          break;
       case "idle":
         this._log.trace("We're idle.");
         this.idle = true;
         // Adjust the interval for future syncs. This won't actually have any
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -233,17 +233,20 @@ RecordManager.prototype = {
       // Don't parse and save the record on failure
       if (!this.response.success)
         return null;
 
       let record = new this._recordType(url);
       record.deserialize(this.response);
 
       return this.set(url, record);
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.debug("Failed to import record", ex);
       return null;
     }
   },
 
   get: function RecordMgr_get(url) {
     // Use a url string as the key to the hash
     let spec = url.spec ? url.spec : url;
--- a/services/sync/modules/resource.js
+++ b/services/sync/modules/resource.js
@@ -391,17 +391,20 @@ Resource.prototype = {
       else
         cb(ret);
     }
 
     // The channel listener might get a failure code
     try {
       this._doRequest(action, data, callback);
       return Async.waitForSyncCallback(cb);
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       // Combine the channel stack with this request stack.  Need to create
       // a new error object for that.
       let error = Error(ex.message);
       error.result = ex.result;
       let chanStack = [];
       if (ex.stack)
         chanStack = ex.stack.trim().split(/\n/).slice(1);
       let requestStack = error.stack.split(/\n/).slice(1);
@@ -544,17 +547,20 @@ ChannelListener.prototype = {
       this._data += siStream.read(count);
     } catch (ex) {
       this._log.warn("Exception thrown reading " + count + " bytes from " + siStream + ".");
       throw ex;
     }
 
     try {
       this._onProgress();
-    } catch (ex if !Async.isShutdownException(ex)) {
+    } catch (ex) {
+      if (Async.isShutdownException(ex)) {
+        throw ex;
+      }
       this._log.warn("Got exception calling onProgress handler during fetch of "
                      + req.URI.spec, ex);
       this._log.trace("Rethrowing; expect a failure code from the HTTP channel.");
       throw ex;
     }
 
     this.delayAbort();
   },
--- a/services/sync/modules/util.js
+++ b/services/sync/modules/util.js
@@ -331,21 +331,23 @@ this.Utils = {
     if (that._log) {
       that._log.trace("Loading json from disk: " + filePath);
     }
 
     let json;
 
     try {
       json = yield CommonUtils.readJSON(path);
-    } catch (e if e instanceof OS.File.Error && e.becauseNoSuchFile) {
-      // Ignore non-existent files.
     } catch (e) {
-      if (that._log) {
-        that._log.debug("Failed to load json", e);
+      if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
+        // Ignore non-existent files.
+      } else {
+        if (that._log) {
+          that._log.debug("Failed to load json", e);
+        }
       }
     }
 
     callback.call(that, json);
   }),
 
   /**
    * Save a json-able object to disk in the profile directory.
--- a/services/sync/tests/unit/test_bookmark_engine.js
+++ b/services/sync/tests/unit/test_bookmark_engine.js
@@ -162,17 +162,17 @@ add_test(function test_processIncoming_e
   } finally {
     store.wipe();
     Svc.Prefs.resetBranch("");
     Service.recordManager.clearCache();
     server.stop(run_next_test);
   }
 });
 
-add_task(function test_restorePromptsReupload() {
+add_task(function* test_restorePromptsReupload() {
   _("Ensure that restoring from a backup will reupload all records.");
   let engine = new BookmarksEngine(Service);
   let store  = engine._store;
   let server = serverForFoo(engine);
   new SyncTestingInfrastructure(server.server);
 
   let collection = server.user("foo").collection("bookmarks");
 
--- a/services/sync/tests/unit/test_browserid_identity.js
+++ b/services/sync/tests/unit/test_browserid_identity.js
@@ -71,27 +71,27 @@ function run_test() {
 add_test(function test_initial_state() {
     _("Verify initial state");
     do_check_false(!!browseridManager._token);
     do_check_false(browseridManager.hasValidToken());
     run_next_test();
   }
 );
 
-add_task(function test_initialializeWithCurrentIdentity() {
+add_task(function* test_initialializeWithCurrentIdentity() {
     _("Verify start after initializeWithCurrentIdentity");
     browseridManager.initializeWithCurrentIdentity();
     yield browseridManager.whenReadyToAuthenticate.promise;
     do_check_true(!!browseridManager._token);
     do_check_true(browseridManager.hasValidToken());
     do_check_eq(browseridManager.account, identityConfig.fxaccount.user.email);
   }
 );
 
-add_task(function test_initialializeWithAuthErrorAndDeletedAccount() {
+add_task(function* test_initialializeWithAuthErrorAndDeletedAccount() {
     _("Verify sync unpair after initializeWithCurrentIdentity with auth error + account deleted");
 
     browseridManager._fxaService.internal.initialize();
 
     let fetchTokenForUserCalled = false;
     let accountStatusCalled = false;
 
     let MockFxAccountsClient = function() {
@@ -122,17 +122,17 @@ add_task(function test_initialializeWith
     do_check_true(accountStatusCalled);
     do_check_false(browseridManager.account);
     do_check_false(browseridManager._token);
     do_check_false(browseridManager.hasValidToken());
     do_check_false(browseridManager.account);
     browseridManager._fetchTokenForUser = oldFetchTokenForUser;
 });
 
-add_task(function test_initialializeWithNoKeys() {
+add_task(function* test_initialializeWithNoKeys() {
     _("Verify start after initializeWithCurrentIdentity without kA, kB or keyFetchToken");
     let identityConfig = makeIdentityConfig();
     delete identityConfig.fxaccount.user.kA;
     delete identityConfig.fxaccount.user.kB;
     // there's no keyFetchToken by default, so the initialize should fail.
     configureFxAccountIdentity(browseridManager, identityConfig);
 
     yield browseridManager.initializeWithCurrentIdentity();
@@ -291,17 +291,17 @@ add_test(function test_RESTResourceAuthe
   // window.
   do_check_eq(getTimestamp(authHeader), now - 12 * HOUR_MS);
   do_check_true(
       (getTimestampDelta(authHeader, now) - 12 * HOUR_MS) < 2 * MINUTE_MS);
 
   run_next_test();
 });
 
-add_task(function test_ensureLoggedIn() {
+add_task(function* test_ensureLoggedIn() {
   configureFxAccountIdentity(browseridManager);
   yield browseridManager.initializeWithCurrentIdentity();
   yield browseridManager.whenReadyToAuthenticate.promise;
   Assert.equal(Status.login, LOGIN_SUCCEEDED, "original initialize worked");
   yield browseridManager.ensureLoggedIn();
   Assert.equal(Status.login, LOGIN_SUCCEEDED, "original ensureLoggedIn worked");
   Assert.ok(browseridManager._shouldHaveSyncKeyBundle,
             "_shouldHaveSyncKeyBundle should always be true after ensureLogin completes.");
@@ -389,17 +389,17 @@ add_test(function test_computeXClientSta
 
   let bidUser = new BrowserIDManager();
   let header = bidUser._computeXClientState(kB);
 
   do_check_eq(header, "6ae94683571c7a7c54dab4700aa3995f");
   run_next_test();
 });
 
-add_task(function test_getTokenErrors() {
+add_task(function* test_getTokenErrors() {
   _("BrowserIDManager correctly handles various failures to get a token.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   initializeIdentityWithTokenServerResponse({
     status: 401,
     headers: {"content-type": "application/json"},
     body: JSON.stringify({}),
   });
@@ -428,17 +428,17 @@ add_task(function test_getTokenErrors() 
   yield Assert.rejects(browseridManager.whenReadyToAuthenticate.promise,
                        "should reject due to non-JSON response");
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login state is LOGIN_FAILED_NETWORK_ERROR");
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for invalid responses");
 });
 
-add_task(function test_getTokenErrorWithRetry() {
+add_task(function* test_getTokenErrorWithRetry() {
   _("tokenserver sends an observer notification on various backoff headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a Retry-After header.");
   initializeIdentityWithTokenServerResponse({
     status: 503,
@@ -476,17 +476,17 @@ add_task(function test_getTokenErrorWith
 
   // The observer should have fired - check it got the value in the response.
   Assert.ok(Status.backoffInterval >= 200000);
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503/backoff response from FxA");
 });
 
-add_task(function test_getKeysErrorWithBackoff() {
+add_task(function* test_getKeysErrorWithBackoff() {
   _("Auth server (via hawk) sends an observer notification on backoff headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a X-Backoff header.");
 
   let config = makeIdentityConfig();
@@ -513,17 +513,17 @@ add_task(function test_getKeysErrorWithB
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login was rejected");
   // Sync will have the value in ms with some slop - so check it is at least that.
   Assert.ok(Status.backoffInterval >= 100000);
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getKeysErrorWithRetry() {
+add_task(function* test_getKeysErrorWithRetry() {
   _("Auth server (via hawk) sends an observer notification on retry headers.");
 
   // Set Sync's backoffInterval to zero - after we simulated the backoff header
   // it should reflect the value we sent.
   Status.backoffInterval = 0;
   _("Arrange for a 503 with a Retry-After header.");
 
   let config = makeIdentityConfig();
@@ -550,17 +550,17 @@ add_task(function test_getKeysErrorWithR
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login was rejected");
   // Sync will have the value in ms with some slop - so check it is at least that.
   Assert.ok(Status.backoffInterval >= 100000);
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getHAWKErrors() {
+add_task(function* test_getHAWKErrors() {
   _("BrowserIDManager correctly handles various HAWK failures.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   let config = makeIdentityConfig();
   yield initializeIdentityWithHAWKResponseFactory(config, function(method, data, uri) {
     Assert.equal(method, "post");
     Assert.equal(uri, "http://mockedserver:9999/certificate/sign")
     return {
@@ -589,17 +589,17 @@ add_task(function test_getHAWKErrors() {
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "login state is LOGIN_FAILED_NETWORK_ERROR");
 
   keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for invalid response from FxA");
 });
 
-add_task(function test_getGetKeysFailing401() {
+add_task(function* test_getGetKeysFailing401() {
   _("BrowserIDManager correctly handles 401 responses fetching keys.");
 
   _("Arrange for a 401 - Sync should reflect an auth error.");
   let config = makeIdentityConfig();
   // We want no kA or kB so we attempt to fetch them.
   delete config.fxaccount.user.kA;
   delete config.fxaccount.user.kB;
   config.fxaccount.user.keyFetchToken = "keyfetchtoken";
@@ -613,17 +613,17 @@ add_task(function test_getGetKeysFailing
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_LOGIN_REJECTED, "login was rejected");
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 1, "Should record key fetch errors for 401 from FxA");
 });
 
-add_task(function test_getGetKeysFailing503() {
+add_task(function* test_getGetKeysFailing503() {
   _("BrowserIDManager correctly handles 5XX responses fetching keys.");
 
   _("Arrange for a 503 - Sync should reflect a network error.");
   let config = makeIdentityConfig();
   // We want no kA or kB so we attempt to fetch them.
   delete config.fxaccount.user.kA;
   delete config.fxaccount.user.kB;
   config.fxaccount.user.keyFetchToken = "keyfetchtoken";
@@ -637,17 +637,17 @@ add_task(function test_getGetKeysFailing
     }
   });
   Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR, "state reflects network error");
 
   let keyFetchErrorCount = sumHistogram("WEAVE_FXA_KEY_FETCH_AUTH_ERRORS");
   Assert.equal(keyFetchErrorCount, 0, "Should not record key fetch errors for 503 from FxA");
 });
 
-add_task(function test_getKeysMissing() {
+add_task(function* test_getKeysMissing() {
   _("BrowserIDManager correctly handles getKeys succeeding but not returning keys.");
 
   let browseridManager = new BrowserIDManager();
   let identityConfig = makeIdentityConfig();
   // our mock identity config already has kA and kB - remove them or we never
   // try and fetch them.
   delete identityConfig.fxaccount.user.kA;
   delete identityConfig.fxaccount.user.kB;
--- a/services/sync/tests/unit/test_collections_recovery.js
+++ b/services/sync/tests/unit/test_collections_recovery.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Verify that we wipe the server if we have to regenerate keys.
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
-add_identity_test(this, function test_missing_crypto_collection() {
+add_identity_test(this, function* test_missing_crypto_collection() {
   let johnHelper = track_collections_helper();
   let johnU      = johnHelper.with_updated_collection;
   let johnColls  = johnHelper.collections;
 
   let empty = false;
   function maybe_empty(handler) {
     return function (request, response) {
       if (empty) {
--- a/services/sync/tests/unit/test_corrupt_keys.js
+++ b/services/sync/tests/unit/test_corrupt_keys.js
@@ -9,17 +9,17 @@ Cu.import("resource://services-sync/engi
 Cu.import("resource://services-sync/engines/history.js");
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/status.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 Cu.import("resource://gre/modules/Promise.jsm");
 
-add_task(function test_locally_changed_keys() {
+add_task(function* test_locally_changed_keys() {
   let passphrase = "abcdeabcdeabcdeabcdeabcdea";
 
   let hmacErrorCount = 0;
   function counting(f) {
     return function() {
       hmacErrorCount++;
       return f.call(this);
     };
--- a/services/sync/tests/unit/test_errorhandler.js
+++ b/services/sync/tests/unit/test_errorhandler.js
@@ -156,17 +156,17 @@ function generateAndUploadKeys() {
 
 function clean() {
   Service.startOver();
   Status.resetSync();
   Status.resetBackoff();
   errorHandler.didReportProlongedError = false;
 }
 
-add_identity_test(this, function test_401_logout() {
+add_identity_test(this, function* test_401_logout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
 
@@ -201,17 +201,17 @@ add_identity_test(this, function test_40
   Service._updateCachedURLs();
 
   _("Starting first sync.");
   Service.sync();
   _("First sync done.");
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_credentials_changed_logout() {
+add_identity_test(this, function* test_credentials_changed_logout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
 
@@ -451,17 +451,17 @@ add_identity_test(this, function test_sh
   Status.resetSync();
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.dontIgnoreErrors = true;
   Status.login = SERVER_MAINTENANCE;
   do_check_true(errorHandler.shouldReportError());
   do_check_false(errorHandler.didReportProlongedError);
 });
 
-add_identity_test(this, function test_shouldReportError_master_password() {
+add_identity_test(this, function* test_shouldReportError_master_password() {
   _("Test error ignored due to locked master password");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Monkey patch Service.verifyLogin to imitate
   // master password being locked.
   Service._verifyLogin = Service.verifyLogin;
   Service.verifyLogin = function () {
@@ -496,17 +496,17 @@ add_identity_test(this, function test_sh
   // 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;
   do_check_false(errorHandler.shouldReportError());
 });
 
 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
 // an fxaccounts environment?
-add_task(function test_login_syncAndReportErrors_non_network_error() {
+add_task(function* test_login_syncAndReportErrors_non_network_error() {
   // Test non-network errors are reported
   // when calling syncAndReportErrors
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
@@ -517,17 +517,17 @@ add_task(function test_login_syncAndRepo
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_sync_syncAndReportErrors_non_network_error() {
+add_identity_test(this, function* test_sync_syncAndReportErrors_non_network_error() {
   // Test non-network errors are reported
   // when calling syncAndReportErrors
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
@@ -546,17 +546,17 @@ add_identity_test(this, function test_sy
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
 // XXX - how to arrange for 'Service.identity.basicPassword = null;' in
 // an fxaccounts environment?
-add_task(function test_login_syncAndReportErrors_prolonged_non_network_error() {
+add_task(function* test_login_syncAndReportErrors_prolonged_non_network_error() {
   // Test prolonged, non-network errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
@@ -567,17 +567,17 @@ add_task(function test_login_syncAndRepo
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_sync_syncAndReportErrors_prolonged_non_network_error() {
+add_identity_test(this, function* test_sync_syncAndReportErrors_prolonged_non_network_error() {
   // Test prolonged, non-network errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
@@ -594,17 +594,17 @@ add_identity_test(this, function test_sy
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_syncAndReportErrors_network_error() {
+add_identity_test(this, function* test_login_syncAndReportErrors_network_error() {
   // Test network errors are reported when calling syncAndReportErrors.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -632,17 +632,17 @@ add_test(function test_sync_syncAndRepor
     clean();
     run_next_test();
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
 });
 
-add_identity_test(this, function test_login_syncAndReportErrors_prolonged_network_error() {
+add_identity_test(this, function* test_login_syncAndReportErrors_prolonged_network_error() {
   // Test prolonged, network errors are reported
   // when calling syncAndReportErrors.
   yield configureIdentity({username: "johndoe"});
 
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
@@ -672,17 +672,17 @@ add_test(function test_sync_syncAndRepor
     clean();
     run_next_test();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
 });
 
-add_task(function test_login_prolonged_non_network_error() {
+add_task(function* test_login_prolonged_non_network_error() {
   // Test prolonged, non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -693,17 +693,17 @@ add_task(function test_login_prolonged_n
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_prolonged_non_network_error() {
+add_task(function* test_sync_prolonged_non_network_error() {
   // Test prolonged, non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
@@ -720,17 +720,17 @@ add_task(function test_sync_prolonged_no
     server.stop(deferred.resolve);
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_prolonged_network_error() {
+add_identity_test(this, function* test_login_prolonged_network_error() {
   // Test prolonged, network errors are reported
   yield configureIdentity({username: "johndoe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -759,17 +759,17 @@ add_test(function test_sync_prolonged_ne
     clean();
     run_next_test();
   });
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
 });
 
-add_task(function test_login_non_network_error() {
+add_task(function* test_login_non_network_error() {
   // Test non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
   Service.identity.basicPassword = null;
 
   let deferred = Promise.defer();
   Svc.Obs.add("weave:ui:login:error", function onSyncError() {
     Svc.Obs.remove("weave:ui:login:error", onSyncError);
@@ -780,17 +780,17 @@ add_task(function test_login_non_network
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_non_network_error() {
+add_task(function* test_sync_non_network_error() {
   // Test non-network errors are reported
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // By calling sync, we ensure we're logged in.
   Service.sync();
   do_check_eq(Status.sync, SYNC_SUCCEEDED);
   do_check_true(Service.isLoggedIn);
@@ -807,17 +807,17 @@ add_task(function test_sync_non_network_
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_login_network_error() {
+add_identity_test(this, function* test_login_network_error() {
   yield configureIdentity({username: "johndoe"});
   Service.serverURL  = fakeServerUrl;
   Service.clusterURL = fakeServerUrl;
 
   let deferred = Promise.defer();
   // Test network errors are not reported.
   Svc.Obs.add("weave:ui:clear-error", function onClearError() {
     Svc.Obs.remove("weave:ui:clear-error", onClearError);
@@ -848,17 +848,17 @@ add_test(function test_sync_network_erro
     clean();
     run_next_test();
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
 });
 
-add_identity_test(this, function test_sync_server_maintenance_error() {
+add_identity_test(this, function* test_sync_server_maintenance_error() {
   // Test server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 503,
@@ -884,17 +884,17 @@ add_identity_test(this, function test_sy
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_server_maintenance_error() {
   // Test info/collections server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   Service.username = "broken.info";
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -928,17 +928,17 @@ add_identity_test(this, function test_in
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_server_maintenance_error() {
   // Test meta/global server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -971,17 +971,17 @@ add_identity_test(this, function test_me
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_crypto_keys_login_server_maintenance_error() {
+add_identity_test(this, function* test_crypto_keys_login_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are not reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1017,17 +1017,17 @@ add_identity_test(this, function test_cr
     server.stop(deferred.resolve);
   });
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_prolonged_server_maintenance_error() {
+add_task(function* test_sync_prolonged_server_maintenance_error() {
   // Test prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 503,
@@ -1046,17 +1046,17 @@ add_task(function test_sync_prolonged_se
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_info_collections_login_prolonged_server_maintenance_error(){
   // Test info/collections prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1082,17 +1082,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_meta_global_login_prolonged_server_maintenance_error(){
   // Test meta/global prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1118,17 +1118,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_download_crypto_keys_login_prolonged_server_maintenance_error(){
   // Test crypto/keys prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
   // Force re-download of keys
@@ -1156,17 +1156,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_upload_crypto_keys_login_prolonged_server_maintenance_error(){
   // Test crypto/keys prolonged server maintenance errors are reported.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
 
@@ -1192,17 +1192,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_wipeServer_login_prolonged_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping the server.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1229,17 +1229,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeRemote_prolonged_server_maintenance_error(){
+add_identity_test(this, function* test_wipeRemote_prolonged_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping all remote devices.
   let server = sync_httpd_setup();
 
   server.registerPathHandler("/1.1/broken.wipe/storage/catapult", service_unavailable);
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1273,17 +1273,17 @@ add_identity_test(this, function test_wi
   do_check_eq(Status.service, STATUS_OK);
 
   Svc.Prefs.set("firstSync", "wipeRemote");
   setLastSync(PROLONGED_ERROR_DURATION);
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_sync_syncAndReportErrors_server_maintenance_error() {
+add_task(function* test_sync_syncAndReportErrors_server_maintenance_error() {
   // Test server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
@@ -1303,17 +1303,17 @@ add_task(function test_sync_syncAndRepor
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_syncAndReportErrors_server_maintenance_error() {
   // Test info/collections server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1340,17 +1340,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_syncAndReportErrors_server_maintenance_error() {
   // Test meta/global server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1377,17 +1377,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1416,17 +1416,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1453,17 +1453,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
+add_identity_test(this, function* test_wipeServer_login_syncAndReportErrors_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1490,17 +1490,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
+add_identity_test(this, function* test_wipeRemote_syncAndReportErrors_server_maintenance_error(){
   // Test that we report prolonged server maintenance errors that occur whilst
   // wiping all remote devices.
   let server = sync_httpd_setup();
 
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
   generateAndUploadKeys();
@@ -1533,17 +1533,17 @@ add_identity_test(this, function test_wi
   do_check_eq(Status.service, STATUS_OK);
 
   Svc.Prefs.set("firstSync", "wipeRemote");
   setLastSync(NON_PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_task(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_task(function* test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test prolonged server maintenance errors are
   // reported when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
@@ -1565,17 +1565,17 @@ add_task(function test_sync_syncAndRepor
 
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test info/collections server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.info"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1604,17 +1604,17 @@ add_identity_test(this, function test_in
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test meta/global server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.meta"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1643,17 +1643,17 @@ add_identity_test(this, function test_me
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
   yield setUp(server);
 
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1684,17 +1684,17 @@ add_identity_test(this, function test_do
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.keys"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1723,17 +1723,17 @@ add_identity_test(this, function test_up
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
+add_identity_test(this, function* test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
   // Test crypto/keys server maintenance errors are reported
   // when calling syncAndReportErrors.
   let server = sync_httpd_setup();
 
   // Start off with an empty account, do not upload a key.
   yield configureIdentity({username: "broken.wipe"});
   Service.serverURL = server.baseURI + "/maintenance/";
   Service.clusterURL = server.baseURI + "/maintenance/";
@@ -1762,17 +1762,17 @@ add_identity_test(this, function test_wi
   do_check_false(Status.enforceBackoff);
   do_check_eq(Status.service, STATUS_OK);
 
   setLastSync(PROLONGED_ERROR_DURATION);
   errorHandler.syncAndReportErrors();
   yield deferred.promise;
 });
 
-add_task(function test_sync_engine_generic_fail() {
+add_task(function* test_sync_engine_generic_fail() {
   let server = sync_httpd_setup();
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.sync = function sync() {
     Svc.Obs.notify("weave:engine:sync:error", "", "catapult");
   };
 
@@ -1868,17 +1868,17 @@ add_test(function test_logs_on_login_err
     clean();
     run_next_test();
   });
   Svc.Obs.notify("weave:service:login:error", {});
 });
 
 // This test should be the last one since it monkeypatches the engine object
 // and we should only have one engine object throughout the file (bug 629664).
-add_task(function test_engine_applyFailed() {
+add_task(function* test_engine_applyFailed() {
   let server = sync_httpd_setup();
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   delete engine.exception;
   engine.sync = function sync() {
     Svc.Obs.notify("weave:engine:sync:applied", {newFailed:1}, "catapult");
   };
--- a/services/sync/tests/unit/test_errorhandler_eol.js
+++ b/services/sync/tests/unit/test_errorhandler_eol.js
@@ -38,17 +38,17 @@ function handler200(eolCode) {
 
 function sync_httpd_setup(infoHandler) {
   let handlers = {
     "/1.1/johndoe/info/collections": infoHandler,
   };
   return httpd_setup(handlers);
 }
 
-function setUp(server) {
+function* setUp(server) {
   yield configureIdentity({username: "johndoe"});
   Service.serverURL = server.baseURI + "/";
   Service.clusterURL = server.baseURI + "/";
   new FakeCryptoService();
 }
 
 function run_test() {
   run_next_test();
@@ -61,17 +61,17 @@ function do_check_soft_eol(eh, start) {
 }
 function do_check_hard_eol(eh, start) {
   // We subtract 1000 because the stored value is in second precision.
   do_check_true(eh.earliestNextAlert >= (start + eh.MINIMUM_ALERT_INTERVAL_MSEC - 1000));
   do_check_eq("hard-eol", eh.currentAlertMode);
   do_check_true(Status.eol);
 }
 
-add_identity_test(this, function test_200_hard() {
+add_identity_test(this, function* test_200_hard() {
   let eh = Service.errorHandler;
   let start = Date.now();
   let server = sync_httpd_setup(handler200("hard-eol"));
   yield setUp(server);
 
   let deferred = Promise.defer();
   let obs = function (subject, topic, data) {
     Svc.Obs.remove("weave:eol", obs);
@@ -83,17 +83,17 @@ add_identity_test(this, function test_20
   };
 
   Svc.Obs.add("weave:eol", obs);
   Service._fetchInfo();
   Service.scheduler.adjustSyncInterval();   // As if we failed or succeeded in syncing.
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_513_hard() {
+add_identity_test(this, function* test_513_hard() {
   let eh = Service.errorHandler;
   let start = Date.now();
   let server = sync_httpd_setup(handler513);
   yield setUp(server);
 
   let deferred = Promise.defer();
   let obs = function (subject, topic, data) {
     Svc.Obs.remove("weave:eol", obs);
@@ -109,17 +109,17 @@ add_identity_test(this, function test_51
     Service._fetchInfo();
     Service.scheduler.adjustSyncInterval();   // As if we failed or succeeded in syncing.
   } catch (ex) {
     // Because fetchInfo will fail on a 513.
   }
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_200_soft() {
+add_identity_test(this, function* test_200_soft() {
   let eh = Service.errorHandler;
   let start = Date.now();
   let server = sync_httpd_setup(handler200("soft-eol"));
   yield setUp(server);
 
   let deferred = Promise.defer();
   let obs = function (subject, topic, data) {
     Svc.Obs.remove("weave:eol", obs);
--- a/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js
+++ b/services/sync/tests/unit/test_errorhandler_sync_checkServerError.js
@@ -54,33 +54,33 @@ function sync_httpd_setup() {
     "/1.1/johndoe/info/collections":    collectionsHelper.handler,
     "/1.1/johndoe/storage/meta/global": upd("meta",    globalWBO.handler()),
     "/1.1/johndoe/storage/clients":     upd("clients", clientsColl.handler()),
     "/1.1/johndoe/storage/crypto/keys": upd("crypto",  keysWBO.handler())
   };
   return httpd_setup(handlers);
 }
 
-function setUp(server) {
+function* setUp(server) {
   yield configureIdentity({username: "johndoe"});
   Service.serverURL = server.baseURI + "/";
   Service.clusterURL = server.baseURI + "/";
   new FakeCryptoService();
 }
 
 function generateAndUploadKeys(server) {
   generateNewKeys(Service.collectionKeys);
   let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
   serverKeys.encrypt(Service.identity.syncKeyBundle);
   let res = Service.resource(server.baseURI + "/1.1/johndoe/storage/crypto/keys");
   return serverKeys.upload(res).success;
 }
 
 
-add_identity_test(this, function test_backoff500() {
+add_identity_test(this, function* test_backoff500() {
   _("Test: HTTP 500 sets backoff status.");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 500};
 
@@ -97,17 +97,17 @@ add_identity_test(this, function test_ba
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
   } finally {
     Status.resetBackoff();
     Service.startOver();
   }
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_backoff503() {
+add_identity_test(this, function* test_backoff503() {
   _("Test: HTTP 503 with Retry-After header leads to backoff notification and sets backoff status.");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   const BACKOFF = 42;
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 503,
@@ -133,17 +133,17 @@ add_identity_test(this, function test_ba
   } finally {
     Status.resetBackoff();
     Status.resetSync();
     Service.startOver();
   }
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_overQuota() {
+add_identity_test(this, function* test_overQuota() {
   _("Test: HTTP 400 with body error code 14 means over quota.");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 400,
                       toString() {
@@ -162,17 +162,17 @@ add_identity_test(this, function test_ov
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
   } finally {
     Status.resetSync();
     Service.startOver();
   }
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_service_networkError() {
+add_identity_test(this, function* test_service_networkError() {
   _("Test: Connection refused error from Service.sync() leads to the right status code.");
   let server = sync_httpd_setup();
   yield setUp(server);
   let deferred = Promise.defer();
   server.stop(() => {
     // Provoke connection refused.
     Service.clusterURL = "http://localhost:12345/";
 
@@ -188,17 +188,17 @@ add_identity_test(this, function test_se
       Status.resetSync();
       Service.startOver();
     }
     deferred.resolve();
   });
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_service_offline() {
+add_identity_test(this, function* test_service_offline() {
   _("Test: Wanting to sync in offline mode leads to the right status code but does not increment the ignorable error count.");
   let server = sync_httpd_setup();
   yield setUp(server);
   let deferred = Promise.defer();
   server.stop(() => {
     Services.io.offline = true;
     Services.prefs.setBoolPref("network.dns.offline-localhost", false);
 
@@ -216,17 +216,17 @@ add_identity_test(this, function test_se
     }
     Services.io.offline = false;
     Services.prefs.clearUserPref("network.dns.offline-localhost");
     deferred.resolve();
   });
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_engine_networkError() {
+add_identity_test(this, function* test_engine_networkError() {
   _("Test: Network related exceptions from engine.sync() lead to the right status code.");
   let server = sync_httpd_setup();
   yield setUp(server);
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = Components.Exception("NS_ERROR_UNKNOWN_HOST",
                                           Cr.NS_ERROR_UNKNOWN_HOST);
@@ -243,17 +243,17 @@ add_identity_test(this, function test_en
     do_check_eq(Status.service, SYNC_FAILED_PARTIAL);
   } finally {
     Status.resetSync();
     Service.startOver();
   }
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_resource_timeout() {
+add_identity_test(this, function* test_resource_timeout() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   let engine = engineManager.get("catapult");
   engine.enabled = true;
   // Resource throws this when it encounters a timeout.
   engine.exception = Components.Exception("Aborting due to channel inactivity.",
                                           Cr.NS_ERROR_NET_TIMEOUT);
--- a/services/sync/tests/unit/test_fxa_node_reassignment.js
+++ b/services/sync/tests/unit/test_fxa_node_reassignment.js
@@ -88,31 +88,32 @@ function prepareServer(cbAfterTokenFetch
     Service.clusterURL = config.fxaccount.token.endpoint;
     return server;
   });
 }
 
 function getReassigned() {
   try {
     return Services.prefs.getBoolPref("services.sync.lastSyncReassigned");
-  } catch (ex if (ex.result == Cr.NS_ERROR_UNEXPECTED)) {
-    return false;
   } catch (ex) {
+    if (ex.result == Cr.NS_ERROR_UNEXPECTED) {
+      return false;
+    }
     do_throw("Got exception retrieving lastSyncReassigned: " +
              Log.exceptionStr(ex));
   }
 }
 
 /**
  * Make a test request to `url`, then watch the result of two syncs
  * to ensure that a node request was made.
  * Runs `between` between the two. This can be used to undo deliberate failure
  * setup, detach observers, etc.
  */
-function syncAndExpectNodeReassignment(server, firstNotification, between,
+function* syncAndExpectNodeReassignment(server, firstNotification, between,
                                        secondNotification, url) {
   _("Starting syncAndExpectNodeReassignment\n");
   let deferred = Promise.defer();
   function onwards() {
     let numTokenRequestsBefore;
     function onFirstSync() {
       _("First sync completed.");
       Svc.Obs.remove(firstNotification, onFirstSync);
@@ -150,17 +151,17 @@ function syncAndExpectNodeReassignment(s
   let request = new RESTRequest(url);
   request.get(function () {
     do_check_eq(request.response.status, 401);
     Utils.nextTick(onwards);
   });
   yield deferred.promise;
 }
 
-add_task(function test_momentary_401_engine() {
+add_task(function* test_momentary_401_engine() {
   _("Test a failure for engine URLs that's resolved by reassignment.");
   let server = yield prepareServer();
   let john   = server.user("johndoe");
 
   _("Enabling the Rotary engine.");
   let engine = Service.engineManager.get("rotary");
   engine.enabled = true;
 
@@ -202,17 +203,17 @@ add_task(function test_momentary_401_eng
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:sync:finish",
                                       between,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "rotary");
 });
 
 // This test ends up being a failing info fetch *after we're already logged in*.
-add_task(function test_momentary_401_info_collections_loggedin() {
+add_task(function* test_momentary_401_info_collections_loggedin() {
   _("Test a failure for info/collections after login that's resolved by reassignment.");
   let server = yield prepareServer();
 
   _("First sync to prepare server contents.");
   Service.sync();
 
   _("Arrange for info/collections to return a 401.");
   let oldHandler = server.toplevelHandlers.info;
@@ -230,17 +231,17 @@ add_task(function test_momentary_401_inf
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.infoURL);
 });
 
 // This test ends up being a failing info fetch *before we're logged in*.
 // In this case we expect to recover during the login phase - so the first
 // sync succeeds.
-add_task(function test_momentary_401_info_collections_loggedout() {
+add_task(function* test_momentary_401_info_collections_loggedout() {
   _("Test a failure for info/collections before login that's resolved by reassignment.");
 
   let oldHandler;
   let sawTokenFetch = false;
 
   function afterTokenFetch() {
     // After a single token fetch, we undo our evil handleReassign hack, so
     // the next /info request returns the collection instead of a 401
@@ -264,17 +265,17 @@ add_task(function test_momentary_401_inf
   // and we are done.
   Service.startOver();
   let deferred = Promise.defer();
   server.stop(deferred.resolve);
   yield deferred.promise;
 });
 
 // This test ends up being a failing meta/global fetch *after we're already logged in*.
-add_task(function test_momentary_401_storage_loggedin() {
+add_task(function* test_momentary_401_storage_loggedin() {
   _("Test a failure for any storage URL after login that's resolved by" +
     "reassignment.");
   let server = yield prepareServer();
 
   _("First sync to prepare server contents.");
   Service.sync();
 
   _("Arrange for meta/global to return a 401.");
@@ -291,17 +292,17 @@ add_task(function test_momentary_401_sto
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:sync:error",
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "meta/global");
 });
 
 // This test ends up being a failing meta/global fetch *before we've logged in*.
-add_task(function test_momentary_401_storage_loggedout() {
+add_task(function* test_momentary_401_storage_loggedout() {
   _("Test a failure for any storage URL before login, not just engine parts. " +
     "Resolved by reassignment.");
   let server = yield prepareServer();
 
   // Return a 401 for all storage requests.
   let oldHandler = server.toplevelHandlers.storage;
   server.toplevelHandlers.storage = handleReassign;
 
@@ -313,9 +314,8 @@ add_task(function test_momentary_401_sto
   do_check_false(Service.isLoggedIn, "already logged in");
 
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:login:error",
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "meta/global");
 });
-
--- a/services/sync/tests/unit/test_fxa_service_cluster.js
+++ b/services/sync/tests/unit/test_fxa_service_cluster.js
@@ -1,17 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Cu.import("resource://services-sync/service.js");
 Cu.import("resource://services-sync/util.js");
 Cu.import("resource://testing-common/services/sync/fxa_utils.js");
 Cu.import("resource://testing-common/services/sync/utils.js");
 
-add_task(function test_findCluster() {
+add_task(function* test_findCluster() {
   _("Test FxA _findCluster()");
 
   _("_findCluster() throws on 500 errors.");
   initializeIdentityWithTokenServerResponse({
     status: 500,
     headers: [],
     body: "",
   });
--- a/services/sync/tests/unit/test_interval_triggers.js
+++ b/services/sync/tests/unit/test_interval_triggers.js
@@ -36,17 +36,17 @@ function sync_httpd_setup() {
     "/1.1/johndoe/storage/meta/global": upd("meta", global.handler()),
     "/1.1/johndoe/info/collections": collectionsHelper.handler,
     "/1.1/johndoe/storage/crypto/keys":
       upd("crypto", (new ServerWBO("keys")).handler()),
     "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler())
   });
 }
 
-function setUp(server) {
+function* setUp(server) {
   yield configureIdentity({username: "johndoe"});
   Service.serverURL = server.baseURI + "/";
   Service.clusterURL = server.baseURI + "/";
   generateNewKeys(Service.collectionKeys);
   let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
   serverKeys.encrypt(Service.identity.syncKeyBundle);
   serverKeys.upload(Service.resource(Service.cryptoKeysURL));
 }
@@ -55,17 +55,17 @@ function run_test() {
   initTestLogging("Trace");
 
   Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
   Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
 
   run_next_test();
 }
 
-add_identity_test(this, function test_successful_sync_adjustSyncInterval() {
+add_identity_test(this, function* test_successful_sync_adjustSyncInterval() {
   _("Test successful sync calling adjustSyncInterval");
   let syncSuccesses = 0;
   function onSyncFinish() {
     _("Sync success.");
     syncSuccesses++;
   };
   Svc.Obs.add("weave:service:sync:finish", onSyncFinish);
 
@@ -154,17 +154,17 @@ add_identity_test(this, function test_su
   do_check_false(scheduler.hasIncomingItems); //gets reset to false
   do_check_eq(scheduler.syncInterval, scheduler.immediateInterval);
 
   Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
   Service.startOver();
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_unsuccessful_sync_adjustSyncInterval() {
+add_identity_test(this, function* test_unsuccessful_sync_adjustSyncInterval() {
   _("Test unsuccessful sync calling adjustSyncInterval");
 
   let syncFailures = 0;
   function onSyncError() {
     _("Sync error.");
     syncFailures++;
   }
   Svc.Obs.add("weave:service:sync:error", onSyncError);
@@ -259,17 +259,17 @@ add_identity_test(this, function test_un
   do_check_false(scheduler.hasIncomingItems); //gets reset to false
   do_check_eq(scheduler.syncInterval, scheduler.immediateInterval);
 
   Service.startOver();
   Svc.Obs.remove("weave:service:sync:error", onSyncError);
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_back_triggers_sync() {
+add_identity_test(this, function* test_back_triggers_sync() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Single device: no sync triggered.
   scheduler.idle = true;
   scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
   do_check_false(scheduler.idle);
 
@@ -291,17 +291,17 @@ add_identity_test(this, function test_ba
   });
 
   scheduler.idle = true;
   scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
   do_check_false(scheduler.idle);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_adjust_interval_on_sync_error() {
+add_identity_test(this, function* test_adjust_interval_on_sync_error() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   let syncFailures = 0;
   function onSyncError() {
     _("Sync error.");
     syncFailures++;
   }
@@ -322,17 +322,17 @@ add_identity_test(this, function test_ad
   do_check_true(scheduler.numClients > 1);
   do_check_eq(scheduler.syncInterval, scheduler.activeInterval);
 
   Svc.Obs.remove("weave:service:sync:error", onSyncError);
   Service.startOver();
   yield promiseStopServer(server);
 });
 
-add_identity_test(this, function test_bug671378_scenario() {
+add_identity_test(this, function* test_bug671378_scenario() {
   // Test scenario similar to bug 671378. This bug appeared when a score
   // update occurred that wasn't large enough to trigger a sync so
   // scheduleNextSync() was called without a time interval parameter,
   // setting nextSync to a non-zero value and preventing the timer from
   // being adjusted in the next call to scheduleNextSync().
   let server = sync_httpd_setup();
   yield setUp(server);
 
--- a/services/sync/tests/unit/test_node_reassignment.js
+++ b/services/sync/tests/unit/test_node_reassignment.js
@@ -87,31 +87,32 @@ function prepareServer() {
     deferred.resolve(server);
   });
   return deferred.promise;
 }
 
 function getReassigned() {
   try {
     return Services.prefs.getBoolPref("services.sync.lastSyncReassigned");
-  } catch (ex if (ex.result == Cr.NS_ERROR_UNEXPECTED)) {
-    return false;
   } catch (ex) {
+    if (ex.result == Cr.NS_ERROR_UNEXPECTED) {
+      return false;
+    }
     do_throw("Got exception retrieving lastSyncReassigned: " +
              Log.exceptionStr(ex));
   }
 }
 
 /**
  * Make a test request to `url`, then watch the result of two syncs
  * to ensure that a node request was made.
  * Runs `between` between the two. This can be used to undo deliberate failure
  * setup, detach observers, etc.
  */
-function syncAndExpectNodeReassignment(server, firstNotification, between,
+function* syncAndExpectNodeReassignment(server, firstNotification, between,
                                        secondNotification, url) {
   let deferred = Promise.defer();
   function onwards() {
     let nodeFetched = false;
     function onFirstSync() {
       _("First sync completed.");
       Svc.Obs.remove(firstNotification, onFirstSync);
       Svc.Obs.add(secondNotification, onSecondSync);
@@ -155,17 +156,17 @@ function syncAndExpectNodeReassignment(s
   let request = new RESTRequest(url);
   request.get(function () {
     do_check_eq(request.response.status, 401);
     Utils.nextTick(onwards);
   });
   yield deferred.promise;
 }
 
-add_task(function test_momentary_401_engine() {
+add_task(function* test_momentary_401_engine() {
   _("Test a failure for engine URLs that's resolved by reassignment.");
   let server = yield prepareServer();
   let john   = server.user("johndoe");
 
   _("Enabling the Rotary engine.");
   let engine = Service.engineManager.get("rotary");
   engine.enabled = true;
 
@@ -207,17 +208,17 @@ add_task(function test_momentary_401_eng
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:sync:finish",
                                       between,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "rotary");
 });
 
 // This test ends up being a failing fetch *after we're already logged in*.
-add_task(function test_momentary_401_info_collections() {
+add_task(function* test_momentary_401_info_collections() {
   _("Test a failure for info/collections that's resolved by reassignment.");
   let server = yield prepareServer();
 
   _("First sync to prepare server contents.");
   Service.sync();
 
   // Return a 401 for info requests, particularly info/collections.
   let oldHandler = server.toplevelHandlers.info;
@@ -230,17 +231,17 @@ add_task(function test_momentary_401_inf
 
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:sync:error",
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.infoURL);
 });
 
-add_task(function test_momentary_401_storage_loggedin() {
+add_task(function* test_momentary_401_storage_loggedin() {
   _("Test a failure for any storage URL, not just engine parts. " +
     "Resolved by reassignment.");
   let server = yield prepareServer();
 
   _("Performing initial sync to ensure we are logged in.")
   Service.sync();
 
   // Return a 401 for all storage requests.
@@ -255,17 +256,17 @@ add_task(function test_momentary_401_sto
   do_check_true(Service.isLoggedIn, "already logged in");
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:sync:error",
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "meta/global");
 });
 
-add_task(function test_momentary_401_storage_loggedout() {
+add_task(function* test_momentary_401_storage_loggedout() {
   _("Test a failure for any storage URL, not just engine parts. " +
     "Resolved by reassignment.");
   let server = yield prepareServer();
 
   // Return a 401 for all storage requests.
   let oldHandler = server.toplevelHandlers.storage;
   server.toplevelHandlers.storage = handleReassign;
 
@@ -277,17 +278,17 @@ add_task(function test_momentary_401_sto
   do_check_false(Service.isLoggedIn, "not already logged in");
   yield syncAndExpectNodeReassignment(server,
                                       "weave:service:login:error",
                                       undo,
                                       "weave:service:sync:finish",
                                       Service.storageURL + "meta/global");
 });
 
-add_task(function test_loop_avoidance_storage() {
+add_task(function* test_loop_avoidance_storage() {
   _("Test that a repeated failure doesn't result in a sync loop " +
     "if node reassignment cannot resolve the failure.");
 
   let server = yield prepareServer();
 
   // Return a 401 for all storage requests.
   let oldHandler = server.toplevelHandlers.storage;
   server.toplevelHandlers.storage = handleReassign;
@@ -377,17 +378,17 @@ add_task(function test_loop_avoidance_st
 
   Svc.Obs.add(firstNotification, onFirstSync);
 
   now = Date.now();
   Service.sync();
   yield deferred.promise;
 });
 
-add_task(function test_loop_avoidance_engine() {
+add_task(function* test_loop_avoidance_engine() {
   _("Test that a repeated 401 in an engine doesn't result in a sync loop " +
     "if node reassignment cannot resolve the failure.");
   let server = yield prepareServer();
   let john   = server.user("johndoe");
 
   _("Enabling the Rotary engine.");
   let engine = Service.engineManager.get("rotary");
   engine.enabled = true;
--- a/services/sync/tests/unit/test_service_startOver.js
+++ b/services/sync/tests/unit/test_service_startOver.js
@@ -23,17 +23,17 @@ BlaEngine.prototype = {
 Service.engineManager.register(BlaEngine);
 
 
 function run_test() {
   initTestLogging("Trace");
   run_next_test();
 }
 
-add_identity_test(this, function test_resetLocalData() {
+add_identity_test(this, function* test_resetLocalData() {
   yield configureIdentity();
   Service.status.enforceBackoff = true;
   Service.status.backoffInterval = 42;
   Service.status.minimumNextSync = 23;
   Service.persistLogin();
 
   // Verify set up.
   do_check_eq(Service.status.checkSetup(), STATUS_OK);
--- a/services/sync/tests/unit/test_service_wipeServer.js
+++ b/services/sync/tests/unit/test_service_wipeServer.js
@@ -26,17 +26,17 @@ FakeCollection.prototype = {
       }
       response.setHeader("X-Weave-Timestamp", timestamp);
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.bodyOutputStream.write(body, body.length);
     };
   }
 };
 
-function setUpTestFixtures(server) {
+function* setUpTestFixtures(server) {
   let cryptoService = new FakeCryptoService();
 
   Service.serverURL = server.baseURI + "/";
   Service.clusterURL = server.baseURI + "/";
 
   yield configureIdentity(identityConfig);
 }
 
@@ -47,17 +47,17 @@ function run_test() {
 }
 
 function promiseStopServer(server) {
   let deferred = Promise.defer();
   server.stop(deferred.resolve);
   return deferred.promise;
 }
 
-add_identity_test(this, function test_wipeServer_list_success() {
+add_identity_test(this, function* test_wipeServer_list_success() {
   _("Service.wipeServer() deletes collections given as argument.");
 
   let steam_coll = new FakeCollection();
   let diesel_coll = new FakeCollection();
 
   let server = httpd_setup({
     "/1.1/johndoe/storage/steam": steam_coll.handler(),
     "/1.1/johndoe/storage/diesel": diesel_coll.handler(),
@@ -81,17 +81,17 @@ add_identity_test(this, function test_wi
     do_check_true(diesel_coll.deleted);
 
   } finally {
     yield promiseStopServer(server);
     Svc.Prefs.resetBranch("");
   }
 });
 
-add_identity_test(this, function test_wipeServer_list_503() {
+add_identity_test(this, function* test_wipeServer_list_503() {
   _("Service.wipeServer() deletes collections given as argument.");
 
   let steam_coll = new FakeCollection();
   let diesel_coll = new FakeCollection();
 
   let server = httpd_setup({
     "/1.1/johndoe/storage/steam": steam_coll.handler(),
     "/1.1/johndoe/storage/petrol": httpd_handler(503, "Service Unavailable"),
@@ -122,17 +122,17 @@ add_identity_test(this, function test_wi
     do_check_false(diesel_coll.deleted);
 
   } finally {
     yield promiseStopServer(server);
     Svc.Prefs.resetBranch("");
   }
 });
 
-add_identity_test(this, function test_wipeServer_all_success() {
+add_identity_test(this, function* test_wipeServer_all_success() {
   _("Service.wipeServer() deletes all the things.");
 
   /**
    * Handle the bulk DELETE request sent by wipeServer.
    */
   let deleted = false;
   let serverTimestamp;
   function storageHandler(request, response) {
@@ -152,17 +152,17 @@ add_identity_test(this, function test_wi
   let returnedTimestamp = Service.wipeServer();
   do_check_true(deleted);
   do_check_eq(returnedTimestamp, serverTimestamp);
 
   yield promiseStopServer(server);
   Svc.Prefs.resetBranch("");
 });
 
-add_identity_test(this, function test_wipeServer_all_404() {
+add_identity_test(this, function* test_wipeServer_all_404() {
   _("Service.wipeServer() accepts a 404.");
 
   /**
    * Handle the bulk DELETE request sent by wipeServer. Returns a 404.
    */
   let deleted = false;
   let serverTimestamp;
   function storageHandler(request, response) {
@@ -184,17 +184,17 @@ add_identity_test(this, function test_wi
   let returnedTimestamp = Service.wipeServer();
   do_check_true(deleted);
   do_check_eq(returnedTimestamp, serverTimestamp);
 
   yield promiseStopServer(server);
   Svc.Prefs.resetBranch("");
 });
 
-add_identity_test(this, function test_wipeServer_all_503() {
+add_identity_test(this, function* test_wipeServer_all_503() {
   _("Service.wipeServer() throws if it encounters a non-200/404 response.");
 
   /**
    * Handle the bulk DELETE request sent by wipeServer. Returns a 503.
    */
   function storageHandler(request, response) {
     do_check_eq("DELETE", request.method);
     do_check_true(request.hasHeader("X-Confirm-Delete"));
@@ -216,17 +216,17 @@ add_identity_test(this, function test_wi
     error = ex;
   }
   do_check_eq(error.status, 503);
 
   yield promiseStopServer(server);
   Svc.Prefs.resetBranch("");
 });
 
-add_identity_test(this, function test_wipeServer_all_connectionRefused() {
+add_identity_test(this, function* test_wipeServer_all_connectionRefused() {
   _("Service.wipeServer() throws if it encounters a network problem.");
   let server = httpd_setup({});
   yield setUpTestFixtures(server);
 
   Service.serverURL = "http://localhost:4352/";
   Service.clusterURL = "http://localhost:4352/";
 
   _("Try deletion.");
--- a/services/sync/tests/unit/test_syncscheduler.js
+++ b/services/sync/tests/unit/test_syncscheduler.js
@@ -151,17 +151,17 @@ add_test(function test_prefAttributes() 
   do_check_eq(scheduler.activeInterval, 18000);
   do_check_eq(scheduler.immediateInterval, 31415000);
 
   Svc.Prefs.resetBranch("");
   scheduler.setDefaults();
   run_next_test();
 });
 
-add_identity_test(this, function test_updateClientMode() {
+add_identity_test(this, function* test_updateClientMode() {
   _("Test updateClientMode adjusts scheduling attributes based on # of clients appropriately");
   do_check_eq(scheduler.syncThreshold, SINGLE_USER_THRESHOLD);
   do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
   do_check_false(scheduler.numClients > 1);
   do_check_false(scheduler.idle);
 
   // Trigger a change in interval & threshold by adding a client.
   clientsEngine._store.create({id: "foo", cleartext: "bar"});
@@ -181,17 +181,17 @@ add_identity_test(this, function test_up
   do_check_eq(scheduler.syncThreshold, SINGLE_USER_THRESHOLD);
   do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
   do_check_false(scheduler.numClients > 1);
   do_check_false(scheduler.idle);
 
   yield cleanUpAndGo();
 });
 
-add_identity_test(this, function test_masterpassword_locked_retry_interval() {
+add_identity_test(this, function* test_masterpassword_locked_retry_interval() {
   _("Test Status.login = MASTER_PASSWORD_LOCKED results in reschedule at MASTER_PASSWORD interval");
   let loginFailed = false;
   Svc.Obs.add("weave:service:login:error", function onLoginError() {
     Svc.Obs.remove("weave:service:login:error", onLoginError);
     loginFailed = true;
   });
 
   let rescheduleInterval = false;
@@ -218,17 +218,17 @@ add_identity_test(this, function test_ma
   do_check_true(rescheduleInterval);
 
   Service.verifyLogin = oldVerifyLogin;
   SyncScheduler.prototype.scheduleAtInterval = oldScheduleAtInterval;
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_calculateBackoff() {
+add_identity_test(this, function* test_calculateBackoff() {
   do_check_eq(Status.backoffInterval, 0);
 
   // Test no interval larger than the maximum backoff is used if
   // Status.backoffInterval is smaller.
   Status.backoffInterval = 5;
   let backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL,
                                                Status.backoffInterval);
 
@@ -240,32 +240,32 @@ add_identity_test(this, function test_ca
   backoffInterval = Utils.calculateBackoff(50, MAXIMUM_BACKOFF_INTERVAL,
                                            Status.backoffInterval);
 
   do_check_eq(backoffInterval, MAXIMUM_BACKOFF_INTERVAL + 10);
 
   yield cleanUpAndGo();
 });
 
-add_identity_test(this, function test_scheduleNextSync_nowOrPast() {
+add_identity_test(this, function* test_scheduleNextSync_nowOrPast() {
   let deferred = Promise.defer();
   Svc.Obs.add("weave:service:sync:finish", function onSyncFinish() {
     Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
     cleanUpAndGo(server).then(deferred.resolve);
   });
 
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // We're late for a sync...
   scheduler.scheduleNextSync(-1);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_scheduleNextSync_future_noBackoff() {
+add_identity_test(this, function* test_scheduleNextSync_future_noBackoff() {
   _("scheduleNextSync() uses the current syncInterval if no interval is provided.");
   // Test backoffInterval is 0 as expected.
   do_check_eq(Status.backoffInterval, 0);
 
   _("Test setting sync interval when nextSync == 0");
   scheduler.nextSync = 0;
   scheduler.scheduleNextSync();
 
@@ -304,17 +304,17 @@ add_identity_test(this, function test_sc
   // Request a sync at the smallest possible interval (0 triggers now).
   scheduler.scheduleNextSync(1);
   do_check_true(scheduler.nextSync <= Date.now() + 1);
   do_check_eq(scheduler.syncTimer.delay, 1);
 
   yield cleanUpAndGo();
 });
 
-add_identity_test(this, function test_scheduleNextSync_future_backoff() {
+add_identity_test(this, function* test_scheduleNextSync_future_backoff() {
  _("scheduleNextSync() will honour backoff in all scheduling requests.");
   // Let's take a backoff interval that's bigger than the default sync interval.
   const BACKOFF = 7337;
   Status.backoffInterval = scheduler.syncInterval + BACKOFF;
 
   _("Test setting sync interval when nextSync == 0");
   scheduler.nextSync = 0;
   scheduler.scheduleNextSync();
@@ -354,17 +354,17 @@ add_identity_test(this, function test_sc
   // Request a sync at the smallest possible interval (0 triggers now).
   scheduler.scheduleNextSync(1);
   do_check_true(scheduler.nextSync <= Date.now() + Status.backoffInterval);
   do_check_eq(scheduler.syncTimer.delay, Status.backoffInterval);
 
   yield cleanUpAndGo();
 });
 
-add_identity_test(this, function test_handleSyncError() {
+add_identity_test(this, function* test_handleSyncError() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Force sync to fail.
   Svc.Prefs.set("firstSync", "notReady");
 
   _("Ensure expected initial environment.");
   do_check_eq(scheduler._syncErrors, 0);
@@ -420,17 +420,17 @@ add_identity_test(this, function test_ha
     Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
     cleanUpAndGo(server).then(deferred.resolve);
   });
   Svc.Prefs.set("firstSync", "wipeRemote");
   scheduler.scheduleNextSync(-1);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_client_sync_finish_updateClientMode() {
+add_identity_test(this, function* test_client_sync_finish_updateClientMode() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Confirm defaults.
   do_check_eq(scheduler.syncThreshold, SINGLE_USER_THRESHOLD);
   do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
   do_check_false(scheduler.idle);
 
@@ -454,33 +454,33 @@ add_identity_test(this, function test_cl
   do_check_eq(scheduler.syncThreshold, SINGLE_USER_THRESHOLD);
   do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
   do_check_false(scheduler.numClients > 1);
   do_check_false(scheduler.idle);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_autoconnect_nextSync_past() {
+add_identity_test(this, function* test_autoconnect_nextSync_past() {
   let deferred = Promise.defer();
   // nextSync will be 0 by default, so it's way in the past.
 
   Svc.Obs.add("weave:service:sync:finish", function onSyncFinish() {
     Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
     cleanUpAndGo(server).then(deferred.resolve);
   });
 
   let server = sync_httpd_setup();
   yield setUp(server);
 
   scheduler.delayedAutoConnect(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_autoconnect_nextSync_future() {
+add_identity_test(this, function* test_autoconnect_nextSync_future() {
   let deferred = Promise.defer();
   let previousSync = Date.now() + scheduler.syncInterval / 2;
   scheduler.nextSync = previousSync;
   // nextSync rounds to the nearest second.
   let expectedSync = scheduler.nextSync;
   let expectedInterval = expectedSync - Date.now() - 1000;
 
   // Ensure we don't actually try to sync (or log in for that matter).
@@ -499,17 +499,17 @@ add_identity_test(this, function test_au
 
   yield configureIdentity({username: "johndoe"});
   scheduler.delayedAutoConnect(0);
   yield deferred.promise;
 });
 
 // XXX - this test can't be run with the browserid identity as it relies
 // on the syncKey getter behaving in a certain way...
-add_task(function test_autoconnect_mp_locked() {
+add_task(function* test_autoconnect_mp_locked() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Pretend user did not unlock master password.
   let origLocked = Utils.mpLocked;
   Utils.mpLocked = () => true;
 
   let origGetter = Service.identity.__lookupGetter__("syncKey");
@@ -536,17 +536,17 @@ add_task(function test_autoconnect_mp_lo
       cleanUpAndGo(server).then(deferred.resolve);
     });
   });
 
   scheduler.delayedAutoConnect(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_no_autoconnect_during_wizard() {
+add_identity_test(this, function* test_no_autoconnect_during_wizard() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Simulate the Sync setup wizard.
   Svc.Prefs.set("firstSync", "notReady");
 
   // Ensure we don't actually try to sync (or log in for that matter).
   function onLoginStart() {
@@ -559,17 +559,17 @@ add_identity_test(this, function test_no
     Svc.Obs.remove("weave:service:login:start", onLoginStart);
     cleanUpAndGo(server).then(deferred.resolve);
   });
 
   scheduler.delayedAutoConnect(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_no_autoconnect_status_not_ok() {
+add_identity_test(this, function* test_no_autoconnect_status_not_ok() {
   let server = sync_httpd_setup();
 
   // Ensure we don't actually try to sync (or log in for that matter).
   function onLoginStart() {
     do_throw("Should not get here!");
   }
   Svc.Obs.add("weave:service:login:start", onLoginStart);
 
@@ -582,17 +582,17 @@ add_identity_test(this, function test_no
 
     cleanUpAndGo(server).then(deferred.resolve);
   });
 
   scheduler.delayedAutoConnect(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_autoconnectDelay_pref() {
+add_identity_test(this, function* test_autoconnectDelay_pref() {
   let deferred = Promise.defer();
   Svc.Obs.add("weave:service:sync:finish", function onSyncFinish() {
     Svc.Obs.remove("weave:service:sync:finish", onSyncFinish);
     cleanUpAndGo(server).then(deferred.resolve);
   });
 
   Svc.Prefs.set("autoconnectDelay", 1);
 
@@ -602,17 +602,17 @@ add_identity_test(this, function test_au
   Svc.Obs.notify("weave:service:ready");
 
   // autoconnectDelay pref is multiplied by 1000.
   do_check_eq(scheduler._autoTimer.delay, 1000);
   do_check_eq(Status.service, STATUS_OK);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_idle_adjustSyncInterval() {
+add_identity_test(this, function* test_idle_adjustSyncInterval() {
   // Confirm defaults.
   do_check_eq(scheduler.idle, false);
 
   // Single device: nothing changes.
   scheduler.observe(null, "idle", Svc.Prefs.get("scheduler.idleTime"));
   do_check_eq(scheduler.idle, true);
   do_check_eq(scheduler.syncInterval, scheduler.singleDeviceInterval);
 
@@ -622,17 +622,17 @@ add_identity_test(this, function test_id
   scheduler.updateClientMode();
   scheduler.observe(null, "idle", Svc.Prefs.get("scheduler.idleTime"));
   do_check_eq(scheduler.idle, true);
   do_check_eq(scheduler.syncInterval, scheduler.idleInterval);
 
   yield cleanUpAndGo();
 });
 
-add_identity_test(this, function test_back_triggersSync() {
+add_identity_test(this, function* test_back_triggersSync() {
   // Confirm defaults.
   do_check_false(scheduler.idle);
   do_check_eq(Status.backoffInterval, 0);
 
   // Set up: Define 2 clients and put the system in idle.
   scheduler.numClients = 2;
   scheduler.observe(null, "idle", Svc.Prefs.get("scheduler.idleTime"));
   do_check_true(scheduler.idle);
@@ -645,17 +645,17 @@ add_identity_test(this, function test_ba
     cleanUpAndGo().then(deferred.resolve);
   });
 
   // Send an 'active' event to trigger sync soonish.
   scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_active_triggersSync_observesBackoff() {
+add_identity_test(this, function* test_active_triggersSync_observesBackoff() {
   // Confirm defaults.
   do_check_false(scheduler.idle);
 
   // Set up: Set backoff, define 2 clients and put the system in idle.
   const BACKOFF = 7337;
   Status.backoffInterval = scheduler.idleInterval + BACKOFF;
   scheduler.numClients = 2;
   scheduler.observe(null, "idle", Svc.Prefs.get("scheduler.idleTime"));
@@ -676,17 +676,17 @@ add_identity_test(this, function test_ac
     cleanUpAndGo().then(deferred.resolve);
   }, IDLE_OBSERVER_BACK_DELAY * 1.5, {}, "timer");
 
   // Send an 'active' event to try to trigger sync soonish.
   scheduler.observe(null, "active", Svc.Prefs.get("scheduler.idleTime"));
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_back_debouncing() {
+add_identity_test(this, function* test_back_debouncing() {
   _("Ensure spurious back-then-idle events, as observed on OS X, don't trigger a sync.");
 
   // Confirm defaults.
   do_check_eq(scheduler.idle, false);
 
   // Set up: Define 2 clients and put the system in idle.
   scheduler.numClients = 2;
   scheduler.observe(null, "idle", Svc.Prefs.get("scheduler.idleTime"));
@@ -704,32 +704,32 @@ add_identity_test(this, function test_ba
   let deferred = Promise.defer();
   timer = Utils.namedTimer(function () {
     Svc.Obs.remove("weave:service:login:start", onLoginStart);
     cleanUpAndGo().then(deferred.resolve);
   }, IDLE_OBSERVER_BACK_DELAY * 1.5, {}, "timer");
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_no_sync_node() {
+add_identity_test(this, function* test_no_sync_node() {
   // Test when Status.sync == NO_SYNC_NODE_FOUND
   // it is not overwritten on sync:finish
   let server = sync_httpd_setup();
   yield setUp(server);
 
   Service.serverURL = server.baseURI + "/";
 
   Service.sync();
   do_check_eq(Status.sync, NO_SYNC_NODE_FOUND);
   do_check_eq(scheduler.syncTimer.delay, NO_SYNC_NODE_INTERVAL);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_sync_failed_partial_500s() {
+add_identity_test(this, function* test_sync_failed_partial_500s() {
   _("Test a 5xx status calls handleSyncError.");
   scheduler._syncErrors = MAX_ERROR_COUNT_BEFORE_BACKOFF;
   let server = sync_httpd_setup();
 
   let engine = Service.engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 500};
 
@@ -746,17 +746,17 @@ add_identity_test(this, function test_sy
   do_check_true(Status.enforceBackoff);
   do_check_eq(scheduler._syncErrors, 4);
   do_check_true(scheduler.nextSync <= (Date.now() + maxInterval));
   do_check_true(scheduler.syncTimer.delay <= maxInterval);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_sync_failed_partial_400s() {
+add_identity_test(this, function* test_sync_failed_partial_400s() {
   _("Test a non-5xx status doesn't call handleSyncError.");
   scheduler._syncErrors = MAX_ERROR_COUNT_BEFORE_BACKOFF;
   let server = sync_httpd_setup();
 
   let engine = Service.engineManager.get("catapult");
   engine.enabled = true;
   engine.exception = {status: 400};
 
@@ -776,17 +776,17 @@ add_identity_test(this, function test_sy
   do_check_false(Status.enforceBackoff);
   do_check_eq(scheduler._syncErrors, 0);
   do_check_true(scheduler.nextSync <= (Date.now() + scheduler.activeInterval));
   do_check_true(scheduler.syncTimer.delay <= scheduler.activeInterval);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_sync_X_Weave_Backoff() {
+add_identity_test(this, function* test_sync_X_Weave_Backoff() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Use an odd value on purpose so that it doesn't happen to coincide with one
   // of the sync intervals.
   const BACKOFF = 7337;
 
   // Extend info/collections so that we can put it into server maintenance mode.
@@ -831,17 +831,17 @@ add_identity_test(this, function test_sy
 
   // Verify that the next sync is actually going to wait that long.
   do_check_true(scheduler.nextSync >= Date.now() + minimumExpectedDelay);
   do_check_true(scheduler.syncTimer.delay >= minimumExpectedDelay);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_sync_503_Retry_After() {
+add_identity_test(this, function* test_sync_503_Retry_After() {
   let server = sync_httpd_setup();
   yield setUp(server);
 
   // Use an odd value on purpose so that it doesn't happen to coincide with one
   // of the sync intervals.
   const BACKOFF = 7337;
 
   // Extend info/collections so that we can put it into server maintenance mode.
@@ -890,17 +890,17 @@ add_identity_test(this, function test_sy
 
   // Verify that the next sync is actually going to wait that long.
   do_check_true(scheduler.nextSync >= Date.now() + minimumExpectedDelay);
   do_check_true(scheduler.syncTimer.delay >= minimumExpectedDelay);
 
   yield cleanUpAndGo(server);
 });
 
-add_identity_test(this, function test_loginError_recoverable_reschedules() {
+add_identity_test(this, function* test_loginError_recoverable_reschedules() {
   _("Verify that a recoverable login error schedules a new sync.");
   yield configureIdentity({username: "johndoe"});
   Service.serverURL = "http://localhost:1234/";
   Service.clusterURL = Service.serverURL;
   Service.persistLogin();
   Status.resetSync(); // reset Status.login
 
   let deferred = Promise.defer();
@@ -934,17 +934,17 @@ add_identity_test(this, function test_lo
   do_check_eq(scheduler.syncTimer, null);
   do_check_eq(Status.checkSetup(), STATUS_OK);
   do_check_eq(Status.login, LOGIN_SUCCEEDED);
 
   scheduler.scheduleNextSync(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_loginError_fatal_clearsTriggers() {
+add_identity_test(this, function* test_loginError_fatal_clearsTriggers() {
   _("Verify that a fatal login error clears sync triggers.");
   yield configureIdentity({username: "johndoe"});
 
   let server = httpd_setup({
     "/1.1/johndoe/info/collections": httpd_handler(401, "Unauthorized")
   });
 
   Service.serverURL = server.baseURI + "/";
@@ -981,17 +981,17 @@ add_identity_test(this, function test_lo
   do_check_eq(scheduler.syncTimer, null);
   do_check_eq(Status.checkSetup(), STATUS_OK);
   do_check_eq(Status.login, LOGIN_SUCCEEDED);
 
   scheduler.scheduleNextSync(0);
   yield deferred.promise;
 });
 
-add_identity_test(this, function test_proper_interval_on_only_failing() {
+add_identity_test(this, function* test_proper_interval_on_only_failing() {
   _("Ensure proper behavior when only failed records are applied.");
 
   // If an engine reports that no records succeeded, we shouldn't decrease the
   // sync interval.
   do_check_false(scheduler.hasIncomingItems);
   const INTERVAL = 10000000;
   scheduler.syncInterval = INTERVAL;
 
--- a/services/sync/tps/extensions/mozmill/resource/driver/controller.js
+++ b/services/sync/tps/extensions/mozmill/resource/driver/controller.js
@@ -972,17 +972,20 @@ function browserAdditions (controller) {
     win = win || this.browserObject.selectedBrowser.contentWindow;
 
     // Wait until the content in the tab has been loaded
     try {
       this.waitFor(function () {
         return windows.map.hasPageLoaded(utils.getWindowId(win));
       }, "Timeout", timeout, aInterval);
     }
-    catch (ex if ex instanceof errors.TimeoutError) {
+    catch (ex) {
+      if (!ex instanceof errors.TimeoutError) {
+        throw ex;
+      }
       timed_out = true;
     }
     finally {
       state = 'URI=' + win.document.location.href +
               ', readyState=' + win.document.readyState;
       message = "controller.waitForPageLoad(" + state + ")";
 
       if (timed_out) {
--- a/services/sync/tps/extensions/mozmill/resource/modules/assertions.js
+++ b/services/sync/tps/extensions/mozmill/resource/modules/assertions.js
@@ -653,15 +653,18 @@ Expect.prototype._logFail = function Exp
  */
 Expect.prototype.waitFor = function Expect_waitFor(aCallback, aMessage, aTimeout, aInterval, aThisObject) {
   let condition = true;
   let message = aMessage;
 
   try {
     Assert.prototype.waitFor.apply(this, arguments);
   }
-  catch (ex if ex instanceof errors.AssertionError) {
+  catch (ex) {
+    if (!ex instanceof errors.AssertionError) {
+      throw ex;
+    }
     message = ex.message;
     condition = false;
   }
 
   return this._test(condition, message);
 }
--- a/services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
+++ b/services/sync/tps/extensions/mozmill/resource/stdlib/securable-module.js
@@ -316,17 +316,20 @@
          baseURI = ios.newURI(base, null, null);
        var newURI = ios.newURI(path, null, baseURI);
        var channel = NetUtil.newChannel({
           uri: newURI,
           loadUsingSystemPrincipal: true
        });
        try {
          channel.open2().close();
-       } catch (e if e.result == Cr.NS_ERROR_FILE_NOT_FOUND) {
+       } catch (e) {
+         if (e.result != Cr.NS_ERROR_FILE_NOT_FOUND) {
+           throw e;
+         }
          return null;
        }
        return newURI.spec;
      },
      getFile: function getFile(path) {
        var channel = NetUtil.newChannel({
          uri: path,
          loadUsingSystemPrincipal: true