advance method

Future<void> advance(
  1. Duration duration
)

Moves time forward by duration, completing every delay that comes due.

Delays complete in due order, and the returned future settles only after the microtask queue has drained — so await clock.advance(...) leaves the system in the state it would be in after that much real time.

A delay scheduled by a completing delay is also honoured: the loop keeps going until nothing else is due, which is what makes a multi-step retry sequence testable with a single call.

Implementation

Future<void> advance(Duration duration) async {
  if (duration.isNegative) {
    throw ArgumentError.value(
      duration,
      'duration',
      'Time cannot move backwards on a FakeClock; that would make already '
          'completed delays un-complete.',
    );
  }
  final target = _now.add(duration);

  while (true) {
    _pending.sort((a, b) => a.dueAt.compareTo(b.dueAt));
    final index = _pending.indexWhere(
      (pending) => !pending.dueAt.isAfter(target),
    );
    if (index < 0) break;

    final due = _pending.removeAt(index);
    _now = due.dueAt;
    if (!due.completer.isCompleted) due.completer.complete();

    // Let whatever was waiting run before considering the next timer, so that
    // work scheduled by this delay is visible to the rest of the advance.
    await _drainMicrotasks();
  }

  _now = target;
  await _drainMicrotasks();
}