Small refactors in Invoker (#1052)

- Remove `removeAllOutstandingCallbacks` method. This never had any
  usage outside of `scheduled_test` which has been deprecated for a long
  time.
- Change some bare `Future` to `Future<void>`.
- Move and rename `OutstandingCallbackCounter` class - the
  implementation has no ties to the concept of callbacks, but that is
  how it is used.
- Use the modern syntax for function typed arguments.
- Add generics to `unclosable` to void throwing away potentially useful
  type information.
diff --git a/pkgs/test_api/lib/src/backend/invoker.dart b/pkgs/test_api/lib/src/backend/invoker.dart
index 100cd1f..5b44624 100644
--- a/pkgs/test_api/lib/src/backend/invoker.dart
+++ b/pkgs/test_api/lib/src/backend/invoker.dart
@@ -17,7 +17,6 @@
 import 'live_test_controller.dart';
 import 'message.dart';
 import 'metadata.dart';
-import 'outstanding_callback_counter.dart';
 import 'state.dart';
 import 'suite.dart';
 import 'suite_platform.dart';
@@ -97,19 +96,19 @@
   bool get closed => _closable && _onCloseCompleter.isCompleted;
 
   /// A future that completes once the test has been closed.
-  Future get onClose => _closable
+  Future<void> get onClose => _closable
       ? _onCloseCompleter.future
       // If we're in an unclosable block, return a future that will never
       // complete.
-      : Completer().future;
-  final _onCloseCompleter = Completer();
+      : Completer<void>().future;
+  final _onCloseCompleter = Completer<void>();
 
   /// The test being run.
   LocalTest get _test => liveTest.test as LocalTest;
 
   /// The outstanding callback counter for the current zone.
-  OutstandingCallbackCounter get _outstandingCallbacks {
-    var counter = Zone.current[_counterKey] as OutstandingCallbackCounter;
+  _AsyncCounter get _outstandingCallbacks {
+    var counter = Zone.current[_counterKey] as _AsyncCounter;
     if (counter != null) return counter;
     throw StateError("Can't add or remove outstanding callbacks outside "
         "of a test body.");
@@ -206,23 +205,16 @@
   /// Throws a [ClosedException] if this test has been closed.
   void addOutstandingCallback() {
     if (closed) throw ClosedException();
-    _outstandingCallbacks.addOutstandingCallback();
+    _outstandingCallbacks.increment();
   }
 
   /// Tells the invoker that a callback declared with [addOutstandingCallback]
   /// is no longer running.
   void removeOutstandingCallback() {
     heartbeat();
-    _outstandingCallbacks.removeOutstandingCallback();
+    _outstandingCallbacks.decrement();
   }
 
-  /// Removes all outstanding callbacks, for example when an error occurs.
-  ///
-  /// Future calls to [addOutstandingCallback] and [removeOutstandingCallback]
-  /// will be ignored.
-  void removeAllOutstandingCallbacks() =>
-      _outstandingCallbacks.removeAllOutstandingCallbacks();
-
   /// Runs [fn] and returns once all (registered) outstanding callbacks it
   /// transitively invokes have completed.
   ///
@@ -239,19 +231,19 @@
   /// If the test times out, the *most recent* call to
   /// [waitForOutstandingCallbacks] will treat that error as occurring within
   /// [fn]—that is, it will complete immediately.
-  Future waitForOutstandingCallbacks(fn()) {
+  Future<void> waitForOutstandingCallbacks(FutureOr<void> Function() fn) {
     heartbeat();
 
     Zone zone;
-    var counter = OutstandingCallbackCounter();
+    var counter = _AsyncCounter();
     runZoned(() async {
       zone = Zone.current;
       _outstandingCallbackZones.add(zone);
       await fn();
-      counter.removeOutstandingCallback();
+      counter.decrement();
     }, zoneValues: {_counterKey: counter});
 
-    return counter.noOutstandingCallbacks.whenComplete(() {
+    return counter.onZero.whenComplete(() {
       _outstandingCallbackZones.remove(zone);
     });
   }
@@ -261,7 +253,7 @@
   /// This is useful for running code that should be able to register callbacks
   /// and interact with the test framework normally even when the invoker is
   /// closed, for example cleanup code.
-  unclosable(fn()) {
+  T unclosable<T>(T Function() fn) {
     heartbeat();
 
     return runZoned(fn, zoneValues: {_closableKey: false});
@@ -345,7 +337,7 @@
     }
 
     _controller.addError(error, stackTrace);
-    zone.run(removeAllOutstandingCallbacks);
+    zone.run(() => _outstandingCallbacks.complete());
 
     if (!liveTest.test.metadata.chainStackTraces) {
       _printsOnFailure.add("Consider enabling the flag chain-stack-traces to "
@@ -378,7 +370,7 @@
   void _onRun() {
     _controller.setState(const State(Status.running, Result.success));
 
-    var outstandingCallbacksForBody = OutstandingCallbackCounter();
+    var outstandingCallbacksForBody = _AsyncCounter();
 
     _runCount++;
     Chain.capture(() {
@@ -402,7 +394,7 @@
             removeOutstandingCallback();
           }));
 
-          await _outstandingCallbacks.noOutstandingCallbacks;
+          await _outstandingCallbacks.onZero;
           if (_timeoutTimer != null) _timeoutTimer.cancel();
 
           if (liveTest.state.result != Result.success &&
@@ -431,7 +423,7 @@
   }
 
   /// Runs [callback], in a [Invoker.guard] context if [_guarded] is `true`.
-  void _guardIfGuarded(void callback()) {
+  void _guardIfGuarded(void Function() callback) {
     if (_guarded) {
       Invoker.guard(callback);
     } else {
@@ -443,9 +435,37 @@
   void _print(String text) => _controller.message(Message.print(text));
 
   /// Run [_tearDowns] in reverse order.
-  Future _runTearDowns() async {
+  Future<void> _runTearDowns() async {
     while (_tearDowns.isNotEmpty) {
       await errorsDontStopTest(_tearDowns.removeLast());
     }
   }
 }
+
+/// A manually incremented/decremented counter that completes a [Future] the
+/// first time it reaches zero or is forcefully completed.
+class _AsyncCounter {
+  var _count = 1;
+
+  /// A Future that completes the first time the counter reaches 0.
+  Future<void> get onZero => _completer.future;
+  final _completer = Completer<void>();
+
+  void increment() {
+    _count++;
+  }
+
+  void decrement() {
+    _count--;
+    if (_count != 0) return;
+    if (_completer.isCompleted) return;
+    _completer.complete();
+  }
+
+  /// Force [onZero] to complete.
+  ///
+  /// No effect if [onZero] has already completed.
+  void complete() {
+    if (!_completer.isCompleted) _completer.complete();
+  }
+}
diff --git a/pkgs/test_api/lib/src/backend/outstanding_callback_counter.dart b/pkgs/test_api/lib/src/backend/outstanding_callback_counter.dart
deleted file mode 100644
index 4f8e401..0000000
--- a/pkgs/test_api/lib/src/backend/outstanding_callback_counter.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-/// A class that counts outstanding callbacks for a test and fires a future once
-/// they reach zero.
-///
-/// The outstanding callback count automatically starts at 1.
-class OutstandingCallbackCounter {
-  /// The number of outstanding callbacks.
-  var _count = 1;
-
-  /// A future that fires when the oustanding callback count reaches 0.
-  Future get noOutstandingCallbacks => _completer.future;
-  final _completer = Completer();
-
-  /// Adds an outstanding callback.
-  void addOutstandingCallback() {
-    _count++;
-  }
-
-  /// Removes an outstanding callback.
-  void removeOutstandingCallback() {
-    _count--;
-    if (_count != 0) return;
-    if (_completer.isCompleted) return;
-    _completer.complete();
-  }
-
-  /// Removes all outstanding callbacks, forcing [noOutstandingCallbacks] to
-  /// fire.
-  ///
-  /// Future calls to [addOutstandingCallback] and [removeOutstandingCallback]
-  /// will be ignored.
-  void removeAllOutstandingCallbacks() {
-    if (!_completer.isCompleted) _completer.complete();
-  }
-}