public MockGlobalSessionCallback doTestSuccess(
      final boolean stageShouldBackoff, final boolean stageShouldAdvance)
      throws SyncConfigurationException, IllegalArgumentException, NonObjectJSONException,
          IOException, ParseException, CryptoException {
    MockServer server =
        new MockServer() {
          @Override
          public void handle(Request request, Response response) {
            if (stageShouldBackoff) {
              response.set("X-Weave-Backoff", Long.toString(TEST_BACKOFF_IN_SECONDS));
            }
            super.handle(request, response);
          }
        };

    final MockServerSyncStage stage =
        new MockServerSyncStage() {
          @Override
          public void execute() {
            // We should have installed our HTTP response observer before starting the sync.
            assertTrue(BaseResource.isHttpResponseObserver(session));

            doRequest();
            if (stageShouldAdvance) {
              session.advance();
              return;
            }
            session.abort(null, "Stage intentionally failed.");
          }
        };

    final MockGlobalSessionCallback callback = new MockGlobalSessionCallback(TEST_CLUSTER_URL);
    SyncConfiguration config =
        new SyncConfiguration(
            TEST_USERNAME,
            new BasicAuthHeaderProvider(TEST_USERNAME, TEST_PASSWORD),
            new MockSharedPreferences(),
            new KeyBundle(TEST_USERNAME, TEST_SYNC_KEY));
    final GlobalSession session =
        new MockGlobalSession(config, callback).withStage(Stage.syncBookmarks, stage);

    data.startHTTPServer(server);
    WaitHelper.getTestWaiter()
        .performWait(
            WaitHelper.onThreadRunnable(
                new Runnable() {
                  @Override
                  public void run() {
                    try {
                      session.start();
                    } catch (Exception e) {
                      final AssertionFailedError error = new AssertionFailedError();
                      error.initCause(e);
                      WaitHelper.getTestWaiter().performNotify(error);
                    }
                  }
                }));
    data.stopHTTPServer();

    // We should have uninstalled our HTTP response observer when the session is terminated.
    assertFalse(BaseResource.isHttpResponseObserver(session));

    return callback;
  }