function runAndAssert(useSetUp, useTearDown, runAsync) {
  const fakeExecutionTime = [100, 95, 98, 104, 130, 101, 96, 98, 90, 103];
  let count = 0;
  const testFunction = () => {
    mockClock.tick(fakeExecutionTime[count++]);
    if (runAsync) {
      return Deferred.succeed();
    }
  };

  let setUpCount = 0;
  const setUpFunction = () => {
    // Should have no effect on total time.
    mockClock.tick(7);
    setUpCount++;
    if (runAsync) {
      return Deferred.succeed();
    }
  };

  let tearDownCount = 0;
  const tearDownFunction = () => {
    // Should have no effect on total time.
    mockClock.tick(11);
    tearDownCount++;
    if (runAsync) {
      return Deferred.succeed();
    }
  };

  // Fast test function should complete successfully in under 5 seconds...
  const task = new PerformanceTimer.Task(testFunction);
  if (useSetUp) {
    task.withSetUp(setUpFunction);
  }
  if (useTearDown) {
    task.withTearDown(tearDownFunction);
  }
  if (runAsync) {
    let assertsRan = false;
    return timer.runAsyncTask(task)
        .then((results) => {
          /**
           * @suppress {checkTypes} suppression added to enable type checking
           */
          assertsRan = assertResults(
              results, useSetUp, useTearDown, setUpCount, tearDownCount,
              fakeExecutionTime);
        })
        .then(() => assertTrue(assertsRan));
  } else {
    const results = timer.runTask(task);
    assertResults(
        results, useSetUp, useTearDown, setUpCount, tearDownCount,
        fakeExecutionTime);
  }
}
@param {boolean} useSetUp
@param {boolean} useTearDown
@param {boolean} runAsync
@return {!Deferred|undefined} A deferred if any of the test functions was
    asynchronous, otherwise, undefined.
@suppress {checkTypes} suppression added to enable type checking