anchor.diff:              }
             }
   
  +          Function backoffWrapper(int callCount) {
  +            return expectAsync((int failedAttempts) {
  +              var exp = ResumableUploadOptions.ExponentialBackoff;
  +              Duration duration = exp(failedAttempts);
  +              expect(duration.inSeconds, equals(1 << (failedAttempts - 1)));
  +              return const Duration(milliseconds: 1);
  +            }, count: callCount);
  +          }
  +
             test('length-small-block', () {
               runTest(1, 10, [10], false);
             });
  
positive.code:           });
  
            test('stream-big-block-parts--with-server-error-recovery', () {
              var options = new ResumableUploadOptions(
                  chunkSize: 256 * 1024, numberOfAttempts: 4);
              runTest(1, 1024 * 1024,
                      [1,
                       256*1024-1,
  
negative.code:         if (attemptsLeft > 0 &&
              (status == 500 || (502 <= status && status < 504))) {
            return response.read().drain().then((_) {
              // Delay the next attempt. Default backoff function is exponential.
              int failedAttemts = _options.numberOfAttempts - attemptsLeft;
              var duration = _options.backoffFunction(failedAttemts);
              if (duration == null) {
                throw new common_external.DetailedApiRequestError(
                    status,
                    'Resumable upload: Uploading a chunk resulted in status '
                    '$status. Maximum number of retries reached.');
              }
  
              return new Future.delayed(duration).then((_) {
                return tryUpload(attemptsLeft - 1);
              });
            });
          } else if (!lastChunk && status != 308) {
              return response.read().drain().then((_) {
                throw new common_external.DetailedApiRequestError(
                    status,
                    'Resumable upload: Uploading a chunk resulted in status '
                    '$status instead of 308.');
              });
          } else if (lastChunk && status != 201 && status != 200) {
            return response.read().drain().then((_) {
              throw new common_external.DetailedApiRequestError(
                  status,
                  'Resumable upload: Uploading a chunk resulted in status '
                  '$status instead of 200 or 201.');
            });
          } else {
  