Catch the test_runner codebase up to somewhat modern practices.

- Run dartfmt --fix. This converts JavaDoc comments to "///", removes
  "new" and extraneous "const", and a couple of other things.
- Fix SCREAMING_CAPS constants to lowerCamelCase.
- Use collection literals where possible.
- Use UI-as-code in a couple of places where it seemed obvious.
- Use "var" for more local variables.
- Use "const" instead of "final" when possible.
- Make members private when possible. Deleted a few that then became
  obviously unused.
- ".length > 0" -> ".isNotEmpty".

There are no meaningful changes.

Change-Id: Ic6c5a74b2af9b3ebcbe881dbed69f65488bdef09
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/105880
Commit-Queue: Bob Nystrom <rnystrom@google.com>
Reviewed-by: William Hesse <whesse@google.com>
diff --git a/pkg/test_runner/bin/http_server.dart b/pkg/test_runner/bin/http_server.dart
index 298e914..881dd35 100644
--- a/pkg/test_runner/bin/http_server.dart
+++ b/pkg/test_runner/bin/http_server.dart
@@ -8,7 +8,7 @@
 import 'package:test_runner/src/vendored_pkg/args/args.dart';
 
 void main(List<String> arguments) {
-  var parser = new ArgParser();
+  var parser = ArgParser();
   parser.addOption('port',
       abbr: 'p',
       help: 'The main server port we wish to respond to requests.',
@@ -33,7 +33,7 @@
   if (args['help'] as bool) {
     print(parser.getUsage());
   } else {
-    var servers = new TestingServers(
+    var servers = TestingServers(
         args['build-directory'] as String,
         args['csp'] as bool,
         Runtime.find(args['runtime'] as String),
diff --git a/pkg/test_runner/bin/launch_browser.dart b/pkg/test_runner/bin/launch_browser.dart
index 91dfd9e..1924521 100644
--- a/pkg/test_runner/bin/launch_browser.dart
+++ b/pkg/test_runner/bin/launch_browser.dart
@@ -2,13 +2,11 @@
 // 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.
 
-/**
- * Simple command line interface to launching browsers.
- * Uses the browser_controller framework.
- * The usage is:
- *   DARTBIN launch_browser.dart BROWSER_NAME URL
- * DARTBIN should be the checked in stable binary.
- */
+/// Simple command line interface to launching browsers.
+/// Uses the browser_controller framework.
+/// The usage is:
+///   DARTBIN launch_browser.dart BROWSER_NAME URL
+/// DARTBIN should be the checked in stable binary.
 
 import 'package:test_runner/src/browser_controller.dart';
 import 'package:test_runner/src/configuration.dart';
@@ -16,7 +14,7 @@
 void printHelp() {
   print("Usage pattern:");
   print("launch_browser.dart browser url");
-  print("Supported browsers: ${Browser.SUPPORTED_BROWSERS}");
+  print("Supported browsers: ${Browser.supportedBrowsers}");
 }
 
 void main(List<String> arguments) {
@@ -34,10 +32,10 @@
   }
 
   var runtime = Runtime.find(name);
-  var configuration = new TestConfiguration(
-      configuration: new Configuration(
+  var configuration = TestConfiguration(
+      configuration: Configuration(
           "dummy configuration", null, null, null, runtime, null));
   var executable = configuration.browserLocation;
-  var browser = new Browser.byRuntime(runtime, executable);
+  var browser = Browser.byRuntime(runtime, executable);
   browser.start(arguments[1]);
 }
diff --git a/pkg/test_runner/bin/package_testing_support.dart b/pkg/test_runner/bin/package_testing_support.dart
index ce9f760..0f01485 100644
--- a/pkg/test_runner/bin/package_testing_support.dart
+++ b/pkg/test_runner/bin/package_testing_support.dart
@@ -11,7 +11,7 @@
   Repository.uri = Uri.base;
   var configurations = <TestConfiguration>[];
   for (var argument in arguments) {
-    configurations.addAll(new OptionsParser().parse(argument.split(" ")));
+    configurations.addAll(OptionsParser().parse(argument.split(" ")));
   }
   testConfigurations(configurations);
 }
diff --git a/pkg/test_runner/bin/test_runner.dart b/pkg/test_runner/bin/test_runner.dart
index 2dbad82..491e10b 100644
--- a/pkg/test_runner/bin/test_runner.dart
+++ b/pkg/test_runner/bin/test_runner.dart
@@ -27,7 +27,7 @@
 /// Runs all of the tests specified by the given command line [arguments].
 void main(List<String> arguments) {
   // Parse the command line arguments to a configuration.
-  var parser = new OptionsParser();
+  var parser = OptionsParser();
   var configurations = parser.parse(arguments);
   if (configurations == null || configurations.isEmpty) return;
 
diff --git a/pkg/test_runner/lib/src/android.dart b/pkg/test_runner/lib/src/android.dart
index 20e5fca..ab133aa 100644
--- a/pkg/test_runner/lib/src/android.dart
+++ b/pkg/test_runner/lib/src/android.dart
@@ -1,9 +1,6 @@
 // Copyright (c) 2013, 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.
-
-library android;
-
 import "dart:async";
 import "dart:convert" show LineSplitter, utf8;
 import "dart:core";
@@ -30,18 +27,16 @@
           "stderr:\n  ${stderr.trim()}\n"
           "exitCode: $exitCode\n"
           "timedOut: $timedOut";
-      throw new Exception(error);
+      throw Exception(error);
     }
   }
 }
 
-/**
- * [_executeCommand] will write [stdin] to the standard input of the created
- * process and will return a tuple (stdout, stderr).
- *
- * If the exit code of the process was nonzero it will complete with an error.
- * If starting the process failed, it will complete with an error as well.
- */
+/// [_executeCommand] will write [stdin] to the standard input of the created
+/// process and will return a tuple (stdout, stderr).
+///
+/// If the exit code of the process was nonzero it will complete with an error.
+/// If starting the process failed, it will complete with an error as well.
 Future<AdbCommandResult> _executeCommand(String executable, List<String> args,
     {String stdin, Duration timeout}) {
   Future<String> getOutput(Stream<List<int>> stream) {
@@ -61,7 +56,7 @@
     Timer timer;
     bool timedOut = false;
     if (timeout != null) {
-      timer = new Timer(timeout, () {
+      timer = Timer(timeout, () {
         timedOut = true;
         process.kill(ProcessSignal.sigterm);
         timer = null;
@@ -76,40 +71,36 @@
     if (timer != null) timer.cancel();
 
     String command = "$executable ${args.join(' ')}";
-    return new AdbCommandResult(command, results[0] as String,
-        results[1] as String, results[2] as int, timedOut);
+    return AdbCommandResult(command, results[0] as String, results[1] as String,
+        results[2] as int, timedOut);
   });
 }
 
-/**
- * Helper class to loop through all adb ports.
- *
- * The ports come in pairs:
- *  - even number: console connection
- *  - odd number: adb connection
- * Note that this code doesn't check if the ports are used.
- */
+/// Helper class to loop through all adb ports.
+///
+/// The ports come in pairs:
+///  - even number: console connection
+///  - odd number: adb connection
+/// Note that this code doesn't check if the ports are used.
 class AdbServerPortPool {
-  static int MIN_PORT = 5554;
-  static int MAX_PORT = 5584;
+  static const _minPort = 5554;
+  static const _maxPort = 5584;
 
-  static int _nextPort = MIN_PORT;
+  static int _nextPort = _minPort;
 
   static int next() {
     var port = _nextPort;
-    if (port > MAX_PORT) {
-      throw new Exception("All ports are used.");
-    }
+    if (port > _maxPort) throw Exception("All ports are used.");
+
     _nextPort += 2;
     return port;
   }
 }
 
-/**
- * Represents the interface to the emulator.
- * New emulators can be launched by calling the static [launchNewEmulator]
- * method.
- */
+/// Represents the interface to the emulator.
+///
+/// New emulators can be launched by calling the static [launchNewEmulator]
+/// method.
 class AndroidEmulator {
   int _port;
   Process _emulatorProcess;
@@ -123,14 +114,14 @@
     var portNumber = AdbServerPortPool.next();
     var args = ['-avd', '$avdName', '-port', "$portNumber" /*, '-gpu', 'on'*/];
     return Process.start("emulator64-arm", args).then((Process process) {
-      var adbDevice = new AdbDevice('emulator-$portNumber');
-      return new AndroidEmulator._private(portNumber, adbDevice, process);
+      var adbDevice = AdbDevice('emulator-$portNumber');
+      return AndroidEmulator._private(portNumber, adbDevice, process);
     });
   }
 
   AndroidEmulator._private(this._port, this._adbDevice, this._emulatorProcess) {
     Stream<String> getLines(Stream s) {
-      return s.transform(utf8.decoder).transform(new LineSplitter());
+      return s.transform(utf8.decoder).transform(LineSplitter());
     }
 
     getLines(_emulatorProcess.stdout).listen((line) {
@@ -145,7 +136,7 @@
   }
 
   Future<bool> kill() {
-    var completer = new Completer<bool>();
+    var completer = Completer<bool>();
     if (_emulatorProcess.kill()) {
       _emulatorProcess.exitCode.then((exitCode) {
         // TODO: Should we use exitCode to do something clever?
@@ -163,9 +154,7 @@
   }
 }
 
-/**
- * Helper class to create avd device configurations.
- */
+/// Helper class to create avd device configurations.
 class AndroidHelper {
   static Future createAvd(String name, String target) async {
     var args = [
@@ -186,29 +175,23 @@
   }
 }
 
-/**
- * Used for communicating with an emulator or with a real device.
- */
+/// Used for communicating with an emulator or with a real device.
 class AdbDevice {
-  static const _adbServerStartupTime = const Duration(seconds: 3);
+  static const _adbServerStartupTime = Duration(seconds: 3);
   String _deviceId;
-  Map<String, String> _cachedData = new Map<String, String>();
+  Map<String, String> _cachedData = {};
 
   String get deviceId => _deviceId;
 
   AdbDevice(this._deviceId);
 
-  /**
-   * Blocks execution until the device is online
-   */
+  /// Blocks execution until the device is online.
   Future waitForDevice() {
     return _adbCommand(['wait-for-device']);
   }
 
-  /**
-   * Polls the 'sys.boot_completed' property. Returns as soon as the property is
-   * 1.
-   */
+  /// Polls the 'sys.boot_completed' property. Returns as soon as the property
+  /// is 1.
   Future<Null> waitForBootCompleted() async {
     while (true) {
       try {
@@ -216,71 +199,57 @@
             await _adbCommand(['shell', 'getprop', 'sys.boot_completed']);
         if (result.stdout.trim() == '1') return;
       } catch (_) {}
-      await new Future<Null>.delayed(const Duration(seconds: 2));
+      await Future<Null>.delayed(const Duration(seconds: 2));
     }
   }
 
-  /**
-   * Put adb in root mode.
-   */
+  /// Put adb in root mode.
   Future<bool> adbRoot() {
-    var adbRootCompleter = new Completer<bool>();
+    var adbRootCompleter = Completer<bool>();
     _adbCommand(['root']).then((_) {
       // TODO: Figure out a way to wait until the adb daemon was restarted in
       // 'root mode' on the device.
-      new Timer(_adbServerStartupTime, () => adbRootCompleter.complete(true));
+      Timer(_adbServerStartupTime, () => adbRootCompleter.complete(true));
     }).catchError((error) => adbRootCompleter.completeError(error));
     return adbRootCompleter.future;
   }
 
-  /**
-   * Download data form the device.
-   */
+  /// Download data from the device.
   Future pullData(Path remote, Path local) {
     return _adbCommand(['pull', '$remote', '$local']);
   }
 
-  /**
-   * Upload data to the device.
-   */
+  /// Upload data to the device.
   Future pushData(Path local, Path remote) {
     return _adbCommand(['push', '$local', '$remote']);
   }
 
-  /**
-   * Upload data to the device, unless [local] is the same as the most recently
-   * used source for [remote].
-   */
+  /// Upload data to the device, unless [local] is the same as the most recently
+  /// used source for [remote].
   Future<AdbCommandResult> pushCachedData(String local, String remote) {
     if (_cachedData[remote] == local) {
-      return new Future.value(
-          new AdbCommandResult("Skipped cached push", "", "", 0, false));
+      return Future.value(
+          AdbCommandResult("Skipped cached push", "", "", 0, false));
     }
     _cachedData[remote] = local;
     return _adbCommand(['push', local, remote]);
   }
 
-  /**
-   * Change permission of directory recursively.
-   */
+  /// Change permission of directory recursively.
   Future chmod(String mode, Path directory) {
     var arguments = ['shell', 'chmod', '-R', mode, '$directory'];
     return _adbCommand(arguments);
   }
 
-  /**
-   * Install an application on the device.
-   */
+  /// Install an application on the device.
   Future installApk(Path filename) {
     return _adbCommand(
         ['install', '-i', 'com.google.android.feedback', '-r', '$filename']);
   }
 
-  /**
-   * Start the given intent on the device.
-   */
+  /// Start the given intent on the device.
   Future startActivity(Intent intent) {
-    var arguments = [
+    return _adbCommand([
       'shell',
       'am',
       'start',
@@ -288,35 +257,24 @@
       '-a',
       intent.action,
       '-n',
-      "${intent.package}/${intent.activity}"
-    ];
-    if (intent.dataUri != null) {
-      arguments.addAll(['-d', intent.dataUri]);
-    }
-    return _adbCommand(arguments);
+      "${intent.package}/${intent.activity}",
+      if (intent.dataUri != null) ...['-d', intent.dataUri]
+    ]);
   }
 
-  /**
-   * Force to stop everything associated with [package].
-   */
+  /// Force to stop everything associated with [package].
   Future forceStop(String package) {
-    var arguments = ['shell', 'am', 'force-stop', package];
-    return _adbCommand(arguments);
+    return _adbCommand(['shell', 'am', 'force-stop', package]);
   }
 
-  /**
-   * Set system property name to value.
-   */
+  /// Set system property name to value.
   Future setProp(String name, String value) {
     return _adbCommand(['shell', 'setprop', name, value]);
   }
 
-  /**
-   * Kill all background processes.
-   */
+  /// Kill all background processes.
   Future killAll() {
-    var arguments = ['shell', 'am', 'kill-all'];
-    return _adbCommand(arguments);
+    return _adbCommand(['shell', 'am', 'kill-all']);
   }
 
   Future<AdbCommandResult> runAdbCommand(List<String> adbArgs,
@@ -327,28 +285,27 @@
 
   Future<AdbCommandResult> runAdbShellCommand(List<String> shellArgs,
       {Duration timeout}) async {
-    const MARKER = 'AdbShellExitCode: ';
+    const marker = 'AdbShellExitCode: ';
 
     // The exitcode of 'adb shell ...' can be 0 even though the command failed
     // with a non-zero exit code. We therefore explicitly print it to stdout and
     // search for it.
 
-    var args = ['shell', "${shellArgs.join(' ')} ; echo $MARKER \$?"];
-    AdbCommandResult result = await _executeCommand(
-        "adb", _deviceSpecificArgs(args),
+    var args = ['shell', "${shellArgs.join(' ')} ; echo $marker \$?"];
+    var result = await _executeCommand("adb", _deviceSpecificArgs(args),
         timeout: timeout);
-    int exitCode = result.exitCode;
+    var exitCode = result.exitCode;
     var lines = result.stdout
         .split('\n')
-        .where((line) => line.trim().length > 0)
+        .where((line) => line.trim().isNotEmpty)
         .toList();
-    if (lines.length > 0) {
-      int index = lines.last.indexOf(MARKER);
+    if (lines.isNotEmpty) {
+      int index = lines.last.indexOf(marker);
       if (index >= 0) {
         exitCode =
-            int.parse(lines.last.substring(index + MARKER.length).trim());
+            int.parse(lines.last.substring(index + marker.length).trim());
         if (exitCode > 128 && exitCode <= 128 + 31) {
-          // Return negative exit codes for signals 1..31 (128+N for signal N)
+          // Return negative exit codes for signals 1..31 (128+N for signal N).
           exitCode = 128 - exitCode;
         }
       } else {
@@ -369,7 +326,7 @@
         assert(result.exitCode != 0);
       }
     }
-    return new AdbCommandResult(result.command, result.stdout, result.stderr,
+    return AdbCommandResult(result.command, result.stdout, result.stderr,
         exitCode, result.timedOut);
   }
 
@@ -389,17 +346,15 @@
   }
 }
 
-/**
- * Helper to list all adb devices available.
- */
+/// Helper to list all adb devices available.
 class AdbHelper {
   static RegExp _deviceLineRegexp =
-      new RegExp(r'^([a-zA-Z0-9_-]+)[ \t]+device$', multiLine: true);
+      RegExp(r'^([a-zA-Z0-9_-]+)[ \t]+device$', multiLine: true);
 
   static Future<List<String>> listDevices() {
     return Process.run('adb', ['devices']).then((ProcessResult result) {
       if (result.exitCode != 0) {
-        throw new Exception("Could not list devices [stdout: ${result.stdout},"
+        throw Exception("Could not list devices [stdout: ${result.stdout},"
             "stderr: ${result.stderr}]");
       }
       return _deviceLineRegexp
@@ -410,9 +365,7 @@
   }
 }
 
-/**
- * Represents an android intent.
- */
+/// Represents an android intent.
 class Intent {
   String action;
   String package;
@@ -422,12 +375,10 @@
   Intent(this.action, this.package, this.activity, [this.dataUri]);
 }
 
-/**
- * Discovers all available devices and supports acquire/release.
- */
+/// Discovers all available devices and supports acquire/release.
 class AdbDevicePool {
-  final Queue<AdbDevice> _idleDevices = new Queue<AdbDevice>();
-  final Queue<Completer> _waiter = new Queue<Completer>();
+  final Queue<AdbDevice> _idleDevices = Queue();
+  final Queue<Completer<AdbDevice>> _waiter = Queue();
 
   AdbDevicePool(List<AdbDevice> idleDevices) {
     _idleDevices.addAll(idleDevices);
@@ -435,28 +386,28 @@
 
   static Future<AdbDevicePool> create() async {
     var names = await AdbHelper.listDevices();
-    var devices = names.map((id) => new AdbDevice(id)).toList();
+    var devices = names.map((id) => AdbDevice(id)).toList();
     if (devices.length == 0) {
-      throw new Exception('No android devices found. '
+      throw Exception('No android devices found. '
           'Please make sure "adb devices" shows your device!');
     }
     print("Found ${devices.length} Android devices.");
-    return new AdbDevicePool(devices);
+    return AdbDevicePool(devices);
   }
 
   Future<AdbDevice> acquireDevice() async {
-    if (_idleDevices.length > 0) {
+    if (_idleDevices.isNotEmpty) {
       return _idleDevices.removeFirst();
     } else {
-      var completer = new Completer<AdbDevice>();
+      var completer = Completer<AdbDevice>();
       _waiter.add(completer);
       return completer.future;
     }
   }
 
   void releaseDevice(AdbDevice device) {
-    if (_waiter.length > 0) {
-      Completer completer = _waiter.removeFirst();
+    if (_waiter.isNotEmpty) {
+      var completer = _waiter.removeFirst();
       completer.complete(device);
     } else {
       _idleDevices.add(device);
diff --git a/pkg/test_runner/lib/src/browser_controller.dart b/pkg/test_runner/lib/src/browser_controller.dart
index c29fe62..dd67eef 100644
--- a/pkg/test_runner/lib/src/browser_controller.dart
+++ b/pkg/test_runner/lib/src/browser_controller.dart
@@ -14,59 +14,55 @@
 import 'reset_safari.dart';
 import 'utils.dart';
 
-typedef void BrowserDoneCallback(BrowserTestOutput output);
-typedef void TestChangedCallback(String browserId, String output, int testId);
-typedef BrowserTest NextTestCallback(String browserId);
+typedef BrowserDoneCallback = void Function(BrowserTestOutput output);
+typedef TestChangedCallback = void Function(
+    String browserId, String output, int testId);
+typedef NextTestCallback = BrowserTest Function(String browserId);
 
 class BrowserOutput {
-  final StringBuffer stdout = new StringBuffer();
-  final StringBuffer stderr = new StringBuffer();
-  final StringBuffer eventLog = new StringBuffer();
+  final StringBuffer stdout = StringBuffer();
+  final StringBuffer stderr = StringBuffer();
+  final StringBuffer eventLog = StringBuffer();
 }
 
-/** Class describing the interface for communicating with browsers. */
+/// Class describing the interface for communicating with browsers.
 abstract class Browser {
-  BrowserOutput _allBrowserOutput = new BrowserOutput();
-  BrowserOutput _testBrowserOutput = new BrowserOutput();
+  BrowserOutput _allBrowserOutput = BrowserOutput();
+  BrowserOutput _testBrowserOutput = BrowserOutput();
 
-  // This is called after the process is closed, before the done future
-  // is completed.
-  // Subclasses can use this to cleanup any browser specific resources
-  // (temp directories, profiles, etc). The function is expected to do
-  // it's work synchronously.
+  /// This is called after the process is closed, before the done future
+  /// is completed.
+  ///
+  /// Subclasses can use this to cleanup any browser specific resources
+  /// (temp directories, profiles, etc). The function is expected to do
+  /// it's work synchronously.
   Function _cleanup;
 
-  /** The version of the browser - normally set when starting a browser */
+  /// The version of the browser - normally set when starting a browser
   String version = "";
 
-  // The path to the browser executable.
+  /// The path to the browser executable.
   String _binary;
 
-  /**
-   * The underlying process - don't mess directly with this if you don't
-   * know what you are doing (this is an interactive process that needs
-   * special treatment to not leak).
-   */
+  /// The underlying process - don't mess directly with this if you don't
+  /// know what you are doing (this is an interactive process that needs
+  /// special treatment to not leak).
   Process process;
 
   Function logger;
 
-  /**
-   * Id of the browser
-   */
+  /// Id of the browser.
   String id;
 
-  /**
-   * Reset the browser to a known configuration on start-up.
-   * Browser specific implementations are free to ignore this.
-   */
+  /// Reset the browser to a known configuration on start-up.
+  /// Browser specific implementations are free to ignore this.
   static bool resetBrowserConfiguration = false;
 
-  /** Print everything (stdout, stderr, usageLog) whenever we add to it */
+  /// Print everything (stdout, stderr, usageLog) whenever we add to it
   bool debugPrint = false;
 
-  // This future returns when the process exits. It is also the return value
-  // of close()
+  /// This future returns when the process exits. It is also the return value
+  /// of close()
   Future done;
 
   Browser();
@@ -76,18 +72,18 @@
     Browser browser;
     switch (runtime) {
       case Runtime.firefox:
-        browser = new Firefox();
+        browser = Firefox();
         break;
       case Runtime.chrome:
-        browser = new Chrome();
+        browser = Chrome();
         break;
       case Runtime.safari:
-        browser = new Safari();
+        browser = Safari();
         break;
       case Runtime.ie9:
       case Runtime.ie10:
       case Runtime.ie11:
-        browser = new IE();
+        browser = IE();
         break;
       default:
         throw "unreachable";
@@ -97,7 +93,7 @@
     return browser;
   }
 
-  static const List<String> SUPPORTED_BROWSERS = const [
+  static const List<String> supportedBrowsers = [
     'safari',
     'ff',
     'firefox',
@@ -113,11 +109,11 @@
 
   // TODO(kustermann): add standard support for chrome on android
   static bool supportedBrowser(String name) {
-    return SUPPORTED_BROWSERS.contains(name);
+    return supportedBrowsers.contains(name);
   }
 
   void _logEvent(String event) {
-    String toLog = "$this ($id) - $event \n";
+    var toLog = "$this ($id) - $event \n";
     if (debugPrint) print("usageLog: $toLog");
     if (logger != null) logger(toLog);
 
@@ -150,14 +146,12 @@
       return done;
     } else {
       _logEvent("The process is already dead.");
-      return new Future.value(true);
+      return Future.value(true);
     }
   }
 
-  /**
-   * Start the browser using the supplied argument.
-   * This sets up the error handling and usage logging.
-   */
+  /// Start the browser using the supplied argument.
+  /// This sets up the error handling and usage logging.
   Future<bool> startBrowserProcess(String command, List<String> arguments,
       {Map<String, String> environment}) {
     return Process.start(command, arguments, environment: environment)
@@ -166,14 +160,14 @@
       process = startedProcess;
       // Used to notify when exiting, and as a return value on calls to
       // close().
-      var doneCompleter = new Completer<bool>();
+      var doneCompleter = Completer<bool>();
       done = doneCompleter.future;
 
-      Completer stdoutDone = new Completer<Null>();
-      Completer stderrDone = new Completer<Null>();
+      var stdoutDone = Completer<Null>();
+      var stderrDone = Completer<Null>();
 
-      bool stdoutIsDone = false;
-      bool stderrIsDone = false;
+      var stdoutIsDone = false;
+      var stderrIsDone = false;
       StreamSubscription stdoutSubscription;
       StreamSubscription stderrSubscription;
 
@@ -226,9 +220,8 @@
         _logEvent("Browser closed with exitcode $exitCode");
 
         if (!stdoutIsDone || !stderrIsDone) {
-          watchdogTimer = new Timer(MAX_STDIO_DELAY, () {
-            DebugLogger.warning(
-                "$MAX_STDIO_DELAY_PASSED_MESSAGE (browser: $this)");
+          watchdogTimer = Timer(maxStdioDelay, () {
+            DebugLogger.warning("$maxStdioDelayPassedMessage (browser: $this)");
             watchdogTimer = null;
             stdoutSubscription.cancel();
             stderrSubscription.cancel();
@@ -253,26 +246,20 @@
     });
   }
 
-  /**
-   * Get the output that was written so far to stdout/stderr/eventLog.
-   */
+  /// Get the output that was written so far to stdout/stderr/eventLog.
   BrowserOutput get allBrowserOutput => _allBrowserOutput;
   BrowserOutput get testBrowserOutput => _testBrowserOutput;
 
   void resetTestBrowserOutput() {
-    _testBrowserOutput = new BrowserOutput();
+    _testBrowserOutput = BrowserOutput();
   }
 
-  /**
-   * Add useful info about the browser to the _testBrowserOutput.stdout,
-   * where it will be reported for failing tests.  Used to report which
-   * android device a failing test is running on.
-   */
+  /// Add useful info about the browser to the _testBrowserOutput.stdout,
+  /// where it will be reported for failing tests.  Used to report which
+  /// android device a failing test is running on.
   void logBrowserInfoToTestBrowserOutput() {}
 
-  String toString();
-
-  /** Starts the browser loading the given url */
+  /// Starts the browser loading the given url
   Future<bool> start(String url);
 
   /// Called when the driver page is requested, that is, when the browser first
@@ -280,13 +267,11 @@
   /// browser process has started and opened its first window.
   ///
   /// This is used by [Safari] to ensure the browser window has focus.
-  Future<Null> onDriverPageRequested() => new Future<Null>.value();
+  Future<Null> onDriverPageRequested() => Future.value();
 }
 
 class Safari extends Browser {
-  /**
-   * We get the safari version by parsing a version file
-   */
+  /// We get the safari version by parsing a version file
   static const String versionFile =
       "/Applications/Safari.app/Contents/version.plist";
 
@@ -297,17 +282,17 @@
   Future<bool> resetConfiguration() async {
     if (!Browser.resetBrowserConfiguration) return true;
 
-    var completer = new Completer<Null>();
+    var completer = Completer<Null>();
     handleUncaughtError(error, StackTrace stackTrace) {
       if (!completer.isCompleted) {
         completer.completeError(error, stackTrace);
       } else {
-        throw new AsyncError(error, stackTrace);
+        throw AsyncError(error, stackTrace);
       }
     }
 
-    Zone parent = Zone.current;
-    ZoneSpecification specification = new ZoneSpecification(
+    var parent = Zone.current;
+    var specification = ZoneSpecification(
         print: (Zone self, ZoneDelegate delegate, Zone zone, String line) {
       delegate.run(parent, () {
         _logEvent(line);
@@ -315,7 +300,7 @@
     });
     Future zoneWrapper() {
       Uri safariUri = Uri.base.resolve(safariBundleLocation);
-      return new Future(() => killAndResetSafari(bundle: safariUri))
+      return Future(() => killAndResetSafari(bundle: safariUri))
           .then(completer.complete);
     }
 
@@ -335,28 +320,25 @@
   }
 
   Future<String> getVersion() {
-    /**
-     * Example of the file:
-     * <?xml version="1.0" encoding="UTF-8"?>
-     * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-     * <plist version="1.0">
-     * <dict>
-     *	     <key>BuildVersion</key>
-     * 	     <string>2</string>
-     * 	     <key>CFBundleShortVersionString</key>
-     * 	     <string>6.0.4</string>
-     * 	     <key>CFBundleVersion</key>
-     * 	     <string>8536.29.13</string>
-     * 	     <key>ProjectName</key>
-     * 	     <string>WebBrowser</string>
-     * 	     <key>SourceVersion</key>
-     * 	     <string>7536029013000000</string>
-     * </dict>
-     * </plist>
-     */
-    File f = new File(versionFile);
-    return f.readAsLines().then((content) {
-      bool versionOnNextLine = false;
+    // Example of the file:
+    // <?xml version="1.0" encoding="UTF-8"?>
+    // <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+    // <plist version="1.0">
+    // <dict>
+    // 	     <key>BuildVersion</key>
+    // 	     <string>2</string>
+    // 	     <key>CFBundleShortVersionString</key>
+    // 	     <string>6.0.4</string>
+    // 	     <key>CFBundleVersion</key>
+    // 	     <string>8536.29.13</string>
+    // 	     <key>ProjectName</key>
+    // 	     <string>WebBrowser</string>
+    // 	     <key>SourceVersion</key>
+    // 	     <string>7536029013000000</string>
+    // </dict>
+    // </plist>
+    return File(versionFile).readAsLines().then((content) {
+      var versionOnNextLine = false;
       for (var line in content) {
         if (versionOnNextLine) return line;
         if (line.contains("CFBundleShortVersionString")) {
@@ -368,7 +350,7 @@
   }
 
   Future<Null> _createLaunchHTML(String path, String url) async {
-    var file = new File("$path/launch.html");
+    var file = File("$path/launch.html");
     var randomFile = await file.open(mode: FileMode.write);
     var content = '<script language="JavaScript">location = "$url"</script>';
     await randomFile.writeString(content);
@@ -444,7 +426,7 @@
       _version = "Can't get version on windows";
       // We still validate that the binary exists so that we can give good
       // feedback.
-      return new File(_binary).exists().then((exists) {
+      return File(_binary).exists().then((exists) {
         if (!exists) {
           _logEvent("Chrome binary not available.");
           _logEvent("Make sure $_binary is a valid program for running chrome");
@@ -478,7 +460,7 @@
             _logEvent(
                 "Error: failed to delete Chrome user-data-dir ${userDir.path}"
                 ", will try again in 40 seconds: $e");
-            new Timer(new Duration(seconds: 40), () {
+            Timer(Duration(seconds: 40), () {
               try {
                 userDir.deleteSync(recursive: true);
               } catch (e) {
@@ -556,7 +538,7 @@
     }
 
     var localAppData = Platform.environment['LOCALAPPDATA'];
-    Directory dir = new Directory("$localAppData\\Microsoft\\"
+    Directory dir = Directory("$localAppData\\Microsoft\\"
         "Internet Explorer\\Recovery");
     return dir.delete(recursive: true).then((_) {
       return true;
@@ -594,22 +576,20 @@
   AndroidChrome(this._adbDevice);
 
   Future<bool> start(String url) {
-    var chromeIntent =
-        new Intent(viewAction, chromePackage, chromeActivity, url);
+    var chromeIntent = Intent(viewAction, chromePackage, chromeActivity, url);
     var turnScreenOnIntent =
-        new Intent(mainAction, turnScreenOnPackage, turnScreenOnActivity);
+        Intent(mainAction, turnScreenOnPackage, turnScreenOnActivity);
 
-    var testing_resources_dir =
-        new Path('third_party/android_testing_resources');
-    if (!new Directory(testing_resources_dir.toNativePath()).existsSync()) {
-      DebugLogger.error("$testing_resources_dir doesn't exist. Exiting now.");
+    var testingResourcesDir = Path('third_party/android_testing_resources');
+    if (!Directory(testingResourcesDir.toNativePath()).existsSync()) {
+      DebugLogger.error("$testingResourcesDir doesn't exist. Exiting now.");
       exit(1);
     }
 
-    var chromeAPK = testing_resources_dir.append('com.android.chrome-1.apk');
-    var turnScreenOnAPK = testing_resources_dir.append('TurnScreenOn.apk');
-    var chromeConfDir = testing_resources_dir.append('chrome_configuration');
-    var chromeConfDirRemote = new Path('/data/user/0/com.android.chrome/');
+    var chromeAPK = testingResourcesDir.append('com.android.chrome-1.apk');
+    var turnScreenOnAPK = testingResourcesDir.append('TurnScreenOn.apk');
+    var chromeConfDir = testingResourcesDir.append('chrome_configuration');
+    var chromeConfDirRemote = Path('/data/user/0/com.android.chrome/');
 
     return _adbDevice.waitForBootCompleted().then((_) {
       return _adbDevice.forceStop(chromeIntent.package);
@@ -638,7 +618,7 @@
         return _adbDevice.killAll().then((_) => true);
       });
     }
-    return new Future.value(true);
+    return Future.value(true);
   }
 
   void logBrowserInfoToTestBrowserOutput() {
@@ -658,7 +638,7 @@
       'user_pref("dom.max_script_run_time", 0);';
 
   void _createPreferenceFile(String path) {
-    var file = new File("$path/user.js");
+    var file = File("$path/user.js");
     var randomFile = file.openSync(mode: FileMode.write);
     randomFile.writeStringSync(enablePopUp);
     randomFile.writeStringSync(disableDefaultCheck);
@@ -673,7 +653,7 @@
       if (versionResult.exitCode != 0) {
         _logEvent("Failed to firefox get version");
         _logEvent("Make sure $_binary is a valid program for running firefox");
-        return new Future.value(false);
+        return Future.value(false);
       }
       version = versionResult.stdout as String;
       _logEvent("Got version: $version");
@@ -690,7 +670,7 @@
           "-new-instance",
           url
         ];
-        var environment = new Map<String, String>.from(Platform.environment);
+        var environment = Map<String, String>.from(Platform.environment);
         environment["MOZ_CRASHREPORTER_DISABLE"] = "1";
         return startBrowserProcess(_binary, args, environment: environment);
       });
@@ -703,9 +683,7 @@
   String toString() => "Firefox";
 }
 
-/**
- * Describes the current state of a browser used for testing.
- */
+/// Describes the current state of a browser used for testing.
 class BrowserStatus {
   Browser browser;
   BrowserTest currentTest;
@@ -716,14 +694,12 @@
   BrowserTest lastTest;
   bool timeout = false;
   Timer nextTestTimeout;
-  Stopwatch timeSinceRestart = new Stopwatch()..start();
+  Stopwatch timeSinceRestart = Stopwatch()..start();
 
   BrowserStatus(Browser this.browser);
 }
 
-/**
- * Describes a single test to be run in the browser.
- */
+/// Describes a single test to be run in the browser.
 class BrowserTest {
   // TODO(ricow): Add timeout callback instead of the string passing hack.
   BrowserDoneCallback doneCallback;
@@ -763,7 +739,7 @@
 
   BrowserTestOutput(this.delayUntilTestStarted, this.duration,
       this.lastKnownMessage, this.browserOutput,
-      {this.didTimeout: false});
+      {this.didTimeout = false});
 }
 
 /// Encapsulates all the functionality for running tests in browsers.
@@ -776,12 +752,12 @@
 /// driver page to the browsers, serves tests, and receives results and
 /// requests back from the browsers.
 class BrowserTestRunner {
-  static const int MAX_NEXT_TEST_TIMEOUTS = 10;
-  static const Duration NEXT_TEST_TIMEOUT = const Duration(seconds: 120);
-  static const Duration RESTART_BROWSER_INTERVAL = const Duration(seconds: 60);
+  static const int _maxNextTestTimeouts = 10;
+  static const Duration _nextTestTimeout = Duration(seconds: 120);
+  static const Duration _restartBrowserInterval = Duration(seconds: 60);
 
   /// If the queue was recently empty, don't start another browser.
-  static const Duration MIN_NONEMPTY_QUEUE_TIME = const Duration(seconds: 1);
+  static const Duration _minNonemptyQueueTime = Duration(seconds: 1);
 
   final TestConfiguration configuration;
   final BrowserTestingServer testingServer;
@@ -789,7 +765,8 @@
   final String localIp;
   int maxNumBrowsers;
   int numBrowsers = 0;
-  // Used to send back logs from the browser (start, stop etc)
+
+  /// Used to send back logs from the browser (start, stop etc.).
   Function logger;
 
   int browserIdCounter = 1;
@@ -797,7 +774,7 @@
   bool testingServerStarted = false;
   bool underTermination = false;
   int numBrowserGetTestTimeouts = 0;
-  DateTime lastEmptyTestQueueTime = new DateTime.now();
+  DateTime lastEmptyTestQueueTime = DateTime.now();
   String _currentStartingBrowserId;
   List<BrowserTest> testQueue = [];
   Map<String, BrowserStatus> browserStatus = {};
@@ -805,26 +782,26 @@
   Map<String, AdbDevice> adbDeviceMapping = {};
   List<AdbDevice> idleAdbDevices;
 
-  // This cache is used to guarantee that we never see double reporting.
-  // If we do we need to provide developers with this information.
-  // We don't add urls to the cache until we have run it.
+  /// This cache is used to guarantee that we never see double reporting.
+  /// If we do we need to provide developers with this information.
+  /// We don't add urls to the cache until we have run it.
   Map<int, String> testCache = {};
 
   Map<int, String> doubleReportingOutputs = {};
   List<String> timedOut = [];
 
-  // We will start a new browser when the test queue hasn't been empty
-  // recently, we have fewer than maxNumBrowsers browsers, and there is
-  // no other browser instance currently starting up.
+  /// We will start a new browser when the test queue hasn't been empty
+  /// recently, we have fewer than maxNumBrowsers browsers, and there is
+  /// no other browser instance currently starting up.
   bool get queueWasEmptyRecently {
     return testQueue.isEmpty ||
-        new DateTime.now().difference(lastEmptyTestQueueTime) <
-            MIN_NONEMPTY_QUEUE_TIME;
+        DateTime.now().difference(lastEmptyTestQueueTime) <
+            _minNonemptyQueueTime;
   }
 
-  // While a browser is starting, but has not requested its first test, its
-  // browserId is stored in _currentStartingBrowserId.
-  // When no browser is currently starting, _currentStartingBrowserId is null.
+  /// While a browser is starting, but has not requested its first test, its
+  /// browserId is stored in _currentStartingBrowserId.
+  /// When no browser is currently starting, _currentStartingBrowserId is null.
   bool get aBrowserIsCurrentlyStarting => _currentStartingBrowserId != null;
   void markCurrentlyStarting(String id) {
     _currentStartingBrowserId = id;
@@ -838,7 +815,7 @@
       TestConfiguration configuration, String localIp, this.maxNumBrowsers)
       : configuration = configuration,
         localIp = localIp,
-        testingServer = new BrowserTestingServer(configuration, localIp,
+        testingServer = BrowserTestingServer(configuration, localIp,
             Browser.requiresFocus(configuration.runtime.name)) {
     testingServer.testRunner = this;
   }
@@ -852,7 +829,7 @@
       ..nextTestCallBack = getNextTest;
     if (configuration.runtime == Runtime.chromeOnAndroid) {
       var idbNames = await AdbHelper.listDevices();
-      idleAdbDevices = new List.from(idbNames.map((id) => new AdbDevice(id)));
+      idleAdbDevices = List.from(idbNames.map((id) => AdbDevice(id)));
       maxNumBrowsers = min(maxNumBrowsers, idleAdbDevices.length);
     }
     testingServerStarted = true;
@@ -861,6 +838,7 @@
 
   /// requestBrowser() is called whenever we might want to start an additional
   /// browser instance.
+  ///
   /// It is called when starting the BrowserTestRunner, and whenever a browser
   /// is killed, whenever a new test is enqueued, or whenever a browser
   /// finishes a test.
@@ -885,17 +863,17 @@
     if (configuration.runtime == Runtime.chromeOnAndroid) {
       AdbDevice device = idleAdbDevices.removeLast();
       adbDeviceMapping[id] = device;
-      browser = new AndroidChrome(device);
+      browser = AndroidChrome(device);
     } else {
       var path = configuration.browserLocation;
-      browser = new Browser.byRuntime(
+      browser = Browser.byRuntime(
           configuration.runtime, path, configuration.isChecked);
       browser.logger = logger;
     }
 
     browser.id = id;
     markCurrentlyStarting(id);
-    var status = new BrowserStatus(browser);
+    var status = BrowserStatus(browser);
     browserStatus[id] = status;
     numBrowsers++;
     status.nextTestTimeout = createNextTestTimer(status);
@@ -928,7 +906,7 @@
       testCache[testId] = status.currentTest.url;
 
       // Report that the test is finished now
-      var browserTestOutput = new BrowserTestOutput(
+      var browserTestOutput = BrowserTestOutput(
           status.currentTest.delayUntilTestStarted,
           status.currentTest.stopwatch.elapsed,
           output,
@@ -987,7 +965,7 @@
     await status.browser.close();
     var lastKnownMessage =
         'Dom could not be fetched, since the test timed out.';
-    if (status.currentTest.lastKnownMessage.length > 0) {
+    if (status.currentTest.lastKnownMessage.isNotEmpty) {
       lastKnownMessage = status.currentTest.lastKnownMessage;
     }
     if (status.lastTest != null) {
@@ -996,7 +974,7 @@
     // Wait until the browser is closed before reporting the test as timeout.
     // This will enable us to capture stdout/stderr from the browser
     // (which might provide us with information about what went wrong).
-    var browserTestOutput = new BrowserTestOutput(
+    var browserTestOutput = BrowserTestOutput(
         status.currentTest.delayUntilTestStarted,
         status.currentTest.stopwatch.elapsed,
         lastKnownMessage,
@@ -1041,7 +1019,7 @@
     // had flaky timeouts, and this may help.
     if ((configuration.runtime == Runtime.ie10 ||
             configuration.runtime == Runtime.ie11) &&
-        status.timeSinceRestart.elapsed > RESTART_BROWSER_INTERVAL) {
+        status.timeSinceRestart.elapsed > _restartBrowserInterval) {
       var id = status.browser.id;
       // Reset stopwatch so we don't trigger again before restarting.
       status.timeout = true;
@@ -1058,7 +1036,7 @@
     BrowserTest test = testQueue.removeLast();
     // If our queue isn't empty, try starting more browsers
     if (testQueue.isEmpty) {
-      lastEmptyTestQueueTime = new DateTime.now();
+      lastEmptyTestQueueTime = DateTime.now();
     } else {
       requestBrowser();
     }
@@ -1079,7 +1057,7 @@
     }
 
     status.currentTest.timeoutTimer = createTimeoutTimer(test, status);
-    status.currentTest.stopwatch = new Stopwatch()..start();
+    status.currentTest.stopwatch = Stopwatch()..start();
 
     // Reset the test specific output information (stdout, stderr) on the
     // browser, since a new test is being started.
@@ -1090,7 +1068,7 @@
 
   /// Creates a timer that is active while a test is running on a browser.
   Timer createTimeoutTimer(BrowserTest test, BrowserStatus status) {
-    return new Timer(new Duration(seconds: test.timeout), () {
+    return Timer(Duration(seconds: test.timeout), () {
       handleTimeout(status);
     });
   }
@@ -1098,7 +1076,7 @@
   /// Creates a timer that is active while no test is running on the
   /// browser. It has finished one test, and it has not requested a new test.
   Timer createNextTestTimer(BrowserStatus status) {
-    return new Timer(BrowserTestRunner.NEXT_TEST_TIMEOUT, () {
+    return Timer(BrowserTestRunner._nextTestTimeout, () {
       handleNextTestTimeout(status);
     });
   }
@@ -1108,7 +1086,7 @@
         "Browser timed out before getting next test. Restarting");
     if (status.timeout) return;
     numBrowserGetTestTimeouts++;
-    if (numBrowserGetTestTimeouts >= MAX_NEXT_TEST_TIMEOUTS) {
+    if (numBrowserGetTestTimeouts >= _maxNextTestTimeouts) {
       DebugLogger.error(
           "Too many browser timeouts before getting next test. Terminating");
       terminate().then((_) => exit(1));
@@ -1169,21 +1147,20 @@
   }
 }
 
+/// Interface of the testing server:
+///
+/// GET /driver/BROWSER_ID -- This will get the driver page to fetch
+///                           and run tests ...
+/// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
+/// where url is the test to run, and id is the id of the test.
+/// If there are currently no available tests the waitSignal is send
+/// back. If we are in the process of terminating the terminateSignal
+/// is send back and the browser will stop requesting new tasks.
+/// POST /report/BROWSER_ID?id=NUM -- sends back the dom of the executed
+///                                   test
 class BrowserTestingServer {
   final TestConfiguration configuration;
 
-  /// Interface of the testing server:
-  ///
-  /// GET /driver/BROWSER_ID -- This will get the driver page to fetch
-  ///                           and run tests ...
-  /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
-  /// where url is the test to run, and id is the id of the test.
-  /// If there are currently no available tests the waitSignal is send
-  /// back. If we are in the process of terminating the terminateSignal
-  /// is send back and the browser will stop requesting new tasks.
-  /// POST /report/BROWSER_ID?id=NUM -- sends back the dom of the executed
-  ///                                   test
-
   final String localIp;
   final bool requiresFocus;
   BrowserTestRunner testRunner;
@@ -1216,11 +1193,11 @@
   void setupErrorServer(HttpServer server) {
     errorReportingServer = server;
     void errorReportingHandler(HttpRequest request) {
-      StringBuffer buffer = new StringBuffer();
+      var buffer = StringBuffer();
       request.transform(utf8.decoder).listen((data) {
         buffer.write(data);
       }, onDone: () {
-        String back = buffer.toString();
+        var back = buffer.toString();
         request.response.headers.set("Access-Control-Allow-Origin", "*");
         request.response.done.catchError((error) {
           DebugLogger.error("Error getting error from browser"
@@ -1278,15 +1255,15 @@
         textResponse = getDriverPage(browserId(request, driverPath));
         request.response.headers.set('Content-Type', 'text/html');
       } else if (request.uri.path.startsWith(nextTestPath)) {
-        textResponse = new Future<String>.value(
-            getNextTest(browserId(request, nextTestPath)));
+        textResponse =
+            Future.value(getNextTest(browserId(request, nextTestPath)));
         request.response.headers.set('Content-Type', 'text/plain');
       } else {
-        textResponse = new Future<String>.value("");
+        textResponse = Future.value("");
       }
       request.response.done.catchError((error) async {
         if (!underTermination) {
-          String text = await textResponse;
+          var text = await textResponse;
           print("URI ${request.uri}");
           print("text $text");
           throw "Error returning content to browser: $error";
@@ -1307,11 +1284,11 @@
 
   void handleReport(HttpRequest request, String browserId, int testId,
       {bool isStatusUpdate}) {
-    StringBuffer buffer = new StringBuffer();
+    var buffer = StringBuffer();
     request.transform(utf8.decoder).listen((data) {
       buffer.write(data);
     }, onDone: () {
-      String back = buffer.toString();
+      var back = buffer.toString();
       request.response.close();
       if (isStatusUpdate) {
         testStatusUpdateCallBack(browserId, back, testId);
@@ -1325,14 +1302,14 @@
   }
 
   void handleStarted(HttpRequest request, String browserId, int testId) {
-    StringBuffer buffer = new StringBuffer();
+    var buffer = StringBuffer();
     // If an error occurs while receiving the data from the request stream,
     // we don't handle it specially. We can safely ignore it, since the started
     // events are not crucial.
     request.transform(utf8.decoder).listen((data) {
       buffer.write(data);
     }, onDone: () {
-      String back = buffer.toString();
+      var back = buffer.toString();
       request.response.close();
       testStartedCallBack(browserId, back, testId);
     }, onError: (error) {
@@ -1365,7 +1342,7 @@
     await testRunner.browserStatus[browserId].browser.onDriverPageRequested();
     var errorReportingUrl =
         "http://$localIp:${errorReportingServer.port}/$browserId";
-    String driverContent = """
+    var driverContent = """
 <!DOCTYPE html><html>
 <head>
   <title>Driving page</title>
diff --git a/pkg/test_runner/lib/src/co19_test_config.dart b/pkg/test_runner/lib/src/co19_test_config.dart
index e736dec..f2c1fc8 100644
--- a/pkg/test_runner/lib/src/co19_test_config.dart
+++ b/pkg/test_runner/lib/src/co19_test_config.dart
@@ -7,10 +7,10 @@
 import 'test_suite.dart';
 
 class Co19TestSuite extends StandardTestSuite {
-  RegExp _testRegExp = new RegExp(r"t[0-9]{2}.dart$");
+  static final _testRegExp = RegExp(r"t[0-9]{2}.dart$");
 
   Co19TestSuite(TestConfiguration configuration, String selector)
-      : super(configuration, selector, new Path("tests/$selector/src"), [
+      : super(configuration, selector, Path("tests/$selector/src"), [
           "tests/$selector/$selector-co19.status",
           "tests/$selector/$selector-analyzer.status",
           "tests/$selector/$selector-runtime.status",
diff --git a/pkg/test_runner/lib/src/command.dart b/pkg/test_runner/lib/src/command.dart
index dc620c3..e6ea871 100644
--- a/pkg/test_runner/lib/src/command.dart
+++ b/pkg/test_runner/lib/src/command.dart
@@ -18,7 +18,7 @@
 class Command {
   static Command browserTest(String url, TestConfiguration configuration,
       {bool retry}) {
-    return new BrowserTestCommand._(url, configuration, retry);
+    return BrowserTestCommand._(url, configuration, retry);
   }
 
   static Command compilation(
@@ -28,9 +28,9 @@
       String executable,
       List<String> arguments,
       Map<String, String> environment,
-      {bool alwaysCompile: false,
+      {bool alwaysCompile = false,
       String workingDirectory}) {
-    return new CompilationCommand._(displayName, outputFile, alwaysCompile,
+    return CompilationCommand._(displayName, outputFile, alwaysCompile,
         bootstrapDependencies, executable, arguments, environment,
         workingDirectory: workingDirectory);
   }
@@ -43,36 +43,35 @@
       List<String> arguments,
       Map<String, String> environment,
       List<String> batchArgs) {
-    return new VMKernelCompilationCommand._(outputFile, neverSkipCompilation,
+    return VMKernelCompilationCommand._(outputFile, neverSkipCompilation,
         bootstrapDependencies, executable, arguments, environment, batchArgs);
   }
 
   static Command analysis(String executable, List<String> arguments,
       Map<String, String> environmentOverrides) {
-    return new AnalysisCommand._(executable, arguments, environmentOverrides);
+    return AnalysisCommand._(executable, arguments, environmentOverrides);
   }
 
   static Command compareAnalyzerCfe(String executable, List<String> arguments,
       Map<String, String> environmentOverrides) {
-    return new CompareAnalyzerCfeCommand._(
+    return CompareAnalyzerCfeCommand._(
         executable, arguments, environmentOverrides);
   }
 
   static Command specParse(String executable, List<String> arguments,
       Map<String, String> environmentOverrides) {
-    return new SpecParseCommand._(executable, arguments, environmentOverrides);
+    return SpecParseCommand._(executable, arguments, environmentOverrides);
   }
 
   static Command vm(String executable, List<String> arguments,
       Map<String, String> environmentOverrides) {
-    return new VmCommand._(executable, arguments, environmentOverrides);
+    return VmCommand._(executable, arguments, environmentOverrides);
   }
 
   static Command vmBatch(String executable, String tester,
       List<String> arguments, Map<String, String> environmentOverrides,
-      {bool checked: true}) {
-    return new VmBatchCommand._(
-        executable, tester, arguments, environmentOverrides,
+      {bool checked = true}) {
+    return VmBatchCommand._(executable, tester, arguments, environmentOverrides,
         checked: checked);
   }
 
@@ -83,37 +82,36 @@
       List<String> arguments,
       bool useBlobs,
       bool useElf) {
-    return new AdbPrecompilationCommand._(precompiledRunner, processTest,
+    return AdbPrecompilationCommand._(precompiledRunner, processTest,
         testDirectory, arguments, useBlobs, useElf);
   }
 
   static Command adbDartk(String precompiledRunner, String processTest,
       String script, List<String> arguments, List<String> extraLibraries) {
-    return new AdbDartkCommand._(
+    return AdbDartkCommand._(
         precompiledRunner, processTest, script, arguments, extraLibraries);
   }
 
   static Command jsCommandLine(
       String displayName, String executable, List<String> arguments,
       [Map<String, String> environment]) {
-    return new JSCommandlineCommand._(
+    return JSCommandlineCommand._(
         displayName, executable, arguments, environment);
   }
 
   static Command process(
       String displayName, String executable, List<String> arguments,
       [Map<String, String> environment, String workingDirectory]) {
-    return new ProcessCommand._(
+    return ProcessCommand._(
         displayName, executable, arguments, environment, workingDirectory);
   }
 
   static Command copy(String sourceDirectory, String destinationDirectory) {
-    return new CleanDirectoryCopyCommand._(
-        sourceDirectory, destinationDirectory);
+    return CleanDirectoryCopyCommand._(sourceDirectory, destinationDirectory);
   }
 
   static Command makeSymlink(String link, String target) {
-    return new MakeSymlinkCommand._(link, target);
+    return MakeSymlinkCommand._(link, target);
   }
 
   static Command fasta(
@@ -124,7 +122,7 @@
       List<String> arguments,
       Map<String, String> environment,
       Uri workingDirectory) {
-    return new FastaCompilationCommand._(
+    return FastaCompilationCommand._(
         compilerLocation,
         outputFile.toFilePath(),
         bootstrapDependencies,
@@ -163,7 +161,7 @@
 
   int get hashCode {
     if (_cachedHashCode == null) {
-      var builder = new HashCodeBuilder();
+      var builder = HashCodeBuilder();
       _buildHashCode(builder);
       _cachedHashCode = builder.value;
     }
@@ -234,7 +232,7 @@
       deepJsonCompare(environmentOverrides, other.environmentOverrides);
 
   String get reproductionCommand {
-    var env = new StringBuffer();
+    var env = StringBuffer();
     environmentOverrides?.forEach((key, value) =>
         (io.Platform.operatingSystem == 'windows')
             ? env.write('set $key=${escapeCommandLineArgument(value)} & ')
@@ -292,7 +290,7 @@
   bool get outputIsUpToDate {
     if (_alwaysCompile) return false;
 
-    var file = new io.File(new Path("$outputFile.deps").toNativePath());
+    var file = io.File(Path("$outputFile.deps").toNativePath());
     if (!file.existsSync()) return false;
 
     var lines = file.readAsLinesSync();
@@ -306,7 +304,7 @@
 
     dependencies.addAll(_bootstrapDependencies);
     var jsOutputLastModified = TestUtils.lastModifiedCache
-        .getLastModified(new Uri(scheme: 'file', path: outputFile));
+        .getLastModified(Uri(scheme: 'file', path: outputFile));
     if (jsOutputLastModified == null) return false;
 
     for (var dependency in dependencies) {
@@ -374,12 +372,12 @@
     String relativizeAndEscape(String argument) {
       if (workingDirectory != null) {
         argument = argument.replaceAll(
-            workingDirectory, new Uri.directory(".").toFilePath());
+            workingDirectory, Uri.directory(".").toFilePath());
       }
       return escapeCommandLineArgument(argument);
     }
 
-    StringBuffer buffer = new StringBuffer();
+    StringBuffer buffer = StringBuffer();
     if (workingDirectory != null && !io.Platform.isWindows) {
       buffer.write("(cd ");
       buffer.write(escapeCommandLineArgument(workingDirectory));
@@ -561,7 +559,7 @@
 
   VmBatchCommand._(String executable, String dartFile, List<String> arguments,
       Map<String, String> environmentOverrides,
-      {this.checked: true, int index = 0})
+      {this.checked = true, int index = 0})
       : this.dartFile = dartFile,
         super._('vm-batch', executable, arguments, environmentOverrides, null,
             index);
@@ -705,24 +703,24 @@
       "Copying '$_sourceDirectory' to '$_destinationDirectory'.";
 
   Future<ScriptCommandOutput> run() {
-    var watch = new Stopwatch()..start();
+    var watch = Stopwatch()..start();
 
-    var destination = new io.Directory(_destinationDirectory);
+    var destination = io.Directory(_destinationDirectory);
 
     return destination.exists().then((bool exists) {
       Future cleanDirectoryFuture;
       if (exists) {
         cleanDirectoryFuture = TestUtils.deleteDirectory(_destinationDirectory);
       } else {
-        cleanDirectoryFuture = new Future.value(null);
+        cleanDirectoryFuture = Future.value(null);
       }
       return cleanDirectoryFuture.then((_) {
         return TestUtils.copyDirectory(_sourceDirectory, _destinationDirectory);
       });
     }).then((_) {
-      return new ScriptCommandOutput(this, Expectation.pass, "", watch.elapsed);
+      return ScriptCommandOutput(this, Expectation.pass, "", watch.elapsed);
     }).catchError((error) {
-      return new ScriptCommandOutput(
+      return ScriptCommandOutput(
           this, Expectation.fail, "An error occured: $error.", watch.elapsed);
     });
   }
@@ -754,21 +752,21 @@
       "Make symbolic link '$_link' (target: $_target)'.";
 
   Future<ScriptCommandOutput> run() {
-    var watch = new Stopwatch()..start();
-    var targetFile = new io.Directory(_target);
+    var watch = Stopwatch()..start();
+    var targetFile = io.Directory(_target);
     return targetFile.exists().then((bool targetExists) {
       if (!targetExists) {
-        throw new Exception("Target '$_target' does not exist");
+        throw Exception("Target '$_target' does not exist");
       }
-      var link = new io.Link(_link);
+      var link = io.Link(_link);
 
       return link.exists().then((bool exists) {
         if (exists) link.deleteSync();
       }).then((_) => link.create(_target));
     }).then((_) {
-      return new ScriptCommandOutput(this, Expectation.pass, "", watch.elapsed);
+      return ScriptCommandOutput(this, Expectation.pass, "", watch.elapsed);
     }).catchError((error) {
-      return new ScriptCommandOutput(
+      return ScriptCommandOutput(
           this, Expectation.fail, "An error occured: $error.", watch.elapsed);
     });
   }
diff --git a/pkg/test_runner/lib/src/command_output.dart b/pkg/test_runner/lib/src/command_output.dart
index 8f1fb1e..f3be68f 100644
--- a/pkg/test_runner/lib/src/command_output.dart
+++ b/pkg/test_runner/lib/src/command_output.dart
@@ -12,6 +12,7 @@
 import 'browser_controller.dart';
 import 'command.dart';
 import 'configuration.dart';
+import 'process_queue.dart';
 import 'test_progress.dart';
 import 'test_case.dart';
 import 'utils.dart';
@@ -149,7 +150,7 @@
 }
 
 class BrowserTestJsonResult {
-  static const _allowedTypes = const [
+  static const _allowedTypes = [
     'sync_exception',
     'window_onerror',
     'script_onerror',
@@ -211,7 +212,7 @@
           dom = '$dom\n';
         }
 
-        return new BrowserTestJsonResult(
+        return BrowserTestJsonResult(
             _getOutcome(messagesByType), dom, events as List<dynamic>);
       }
     } catch (error) {
@@ -311,7 +312,7 @@
       }
     }
 
-    return new BrowserCommandOutput._internal(command, result, outcome,
+    return BrowserCommandOutput._internal(command, result, outcome,
         parsedResult, encodeUtf8(""), encodeUtf8(stderr));
   }
 
@@ -528,7 +529,7 @@
     // Parse a line delimited by the | character using \ as an escape character
     // like:  FOO|BAR|FOO\|BAR|FOO\\BAZ as 4 fields: FOO BAR FOO|BAR FOO\BAZ
     List<String> splitMachineError(String line) {
-      var field = new StringBuffer();
+      var field = StringBuffer();
       var result = <String>[];
       var escaped = false;
       for (var i = 0; i < line.length; i++) {
@@ -540,7 +541,7 @@
         escaped = false;
         if (c == '|') {
           result.add(field.toString());
-          field = new StringBuffer();
+          field = StringBuffer();
           continue;
         }
         field.write(c);
@@ -1022,40 +1023,40 @@
     List<int> stdout, List<int> stderr, Duration time, bool compilationSkipped,
     [int pid = 0]) {
   if (command is AnalysisCommand) {
-    return new AnalysisCommandOutput(
+    return AnalysisCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is CompareAnalyzerCfeCommand) {
-    return new CompareAnalyzerCfeCommandOutput(
+    return CompareAnalyzerCfeCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is SpecParseCommand) {
-    return new SpecParseCommandOutput(
+    return SpecParseCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is VmCommand) {
-    return new VMCommandOutput(
+    return VMCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, pid);
   } else if (command is VMKernelCompilationCommand) {
-    return new VMKernelCompilationCommandOutput(
+    return VMKernelCompilationCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is AdbPrecompilationCommand) {
-    return new VMCommandOutput(
+    return VMCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, pid);
   } else if (command is CompilationCommand) {
     if (command.displayName == 'precompiler' ||
         command.displayName == 'app_jit') {
-      return new VMCommandOutput(
+      return VMCommandOutput(
           command, exitCode, timedOut, stdout, stderr, time, pid);
     } else if (command.displayName == 'dartdevc') {
-      return new DevCompilerCommandOutput(command, exitCode, timedOut, stdout,
+      return DevCompilerCommandOutput(command, exitCode, timedOut, stdout,
           stderr, time, compilationSkipped, pid);
     }
-    return new CompilationCommandOutput(
+    return CompilationCommandOutput(
         command, exitCode, timedOut, stdout, stderr, time, compilationSkipped);
   } else if (command is JSCommandlineCommand) {
-    return new JSCommandLineOutput(
+    return JSCommandLineOutput(
         command, exitCode, timedOut, stdout, stderr, time);
   }
 
-  return new CommandOutput(command, exitCode, timedOut, stdout, stderr, time,
+  return CommandOutput(command, exitCode, timedOut, stdout, stderr, time,
       compilationSkipped, pid);
 }
 
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index e591dbd..eb8fb4e 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -53,29 +53,28 @@
   factory CompilerConfiguration(TestConfiguration configuration) {
     switch (configuration.compiler) {
       case Compiler.dart2analyzer:
-        return new AnalyzerCompilerConfiguration(configuration);
+        return AnalyzerCompilerConfiguration(configuration);
 
       case Compiler.compareAnalyzerCfe:
-        return new CompareAnalyzerCfeCompilerConfiguration(configuration);
+        return CompareAnalyzerCfeCompilerConfiguration(configuration);
 
       case Compiler.dart2js:
-        return new Dart2jsCompilerConfiguration(configuration);
+        return Dart2jsCompilerConfiguration(configuration);
 
       case Compiler.dartdevc:
-        return new DevCompilerConfiguration(configuration);
+        return DevCompilerConfiguration(configuration);
 
       case Compiler.dartdevk:
-        return new DevCompilerConfiguration(configuration);
+        return DevCompilerConfiguration(configuration);
 
       case Compiler.appJit:
-        return new AppJitCompilerConfiguration(configuration,
-            previewDart2: false);
+        return AppJitCompilerConfiguration(configuration, previewDart2: false);
 
       case Compiler.appJitk:
-        return new AppJitCompilerConfiguration(configuration);
+        return AppJitCompilerConfiguration(configuration);
 
       case Compiler.precompiler:
-        return new PrecompilerCompilerConfiguration(configuration,
+        return PrecompilerCompilerConfiguration(configuration,
             previewDart2: false);
 
       case Compiler.dartk:
@@ -83,24 +82,24 @@
             configuration.architecture == Architecture.simarm ||
             configuration.architecture == Architecture.simarm64 ||
             configuration.system == System.android) {
-          return new VMKernelCompilerConfiguration(configuration);
+          return VMKernelCompilerConfiguration(configuration);
         }
-        return new NoneCompilerConfiguration(configuration);
+        return NoneCompilerConfiguration(configuration);
 
       case Compiler.dartkb:
-        return new VMKernelCompilerConfiguration(configuration);
+        return VMKernelCompilerConfiguration(configuration);
 
       case Compiler.dartkp:
-        return new PrecompilerCompilerConfiguration(configuration);
+        return PrecompilerCompilerConfiguration(configuration);
 
       case Compiler.specParser:
-        return new SpecParserCompilerConfiguration(configuration);
+        return SpecParserCompilerConfiguration(configuration);
 
       case Compiler.fasta:
-        return new FastaCompilerConfiguration(configuration);
+        return FastaCompilerConfiguration(configuration);
 
       case Compiler.none:
-        return new NoneCompilerConfiguration(configuration);
+        return NoneCompilerConfiguration(configuration);
     }
 
     throw "unreachable";
@@ -134,7 +133,7 @@
       String tempDir,
       List<String> arguments,
       Map<String, String> environmentOverrides) {
-    return new CommandArtifact([], null, null);
+    return CommandArtifact([], null, null);
   }
 
   List<String> computeCompilerArguments(
@@ -224,7 +223,7 @@
     final commands = <Command>[
       computeCompileToKernelCommand(tempDir, arguments, environmentOverrides),
     ];
-    return new CommandArtifact(commands, tempKernelFile(tempDir),
+    return CommandArtifact(commands, tempKernelFile(tempDir),
         'application/kernel-ir-fully-linked');
   }
 
@@ -274,7 +273,7 @@
   }
 }
 
-typedef List<String> CompilerArgumentsFunction(
+typedef CompilerArgumentsFunction = List<String> Function(
     List<String> globalArguments, String previousCompilerOutput);
 
 class PipelineCommand {
@@ -285,7 +284,7 @@
 
   factory PipelineCommand.runWithGlobalArguments(
       CompilerConfiguration configuration) {
-    return new PipelineCommand._(configuration,
+    return PipelineCommand._(configuration,
         (List<String> globalArguments, String previousOutput) {
       assert(previousOutput == null);
       return globalArguments;
@@ -294,7 +293,7 @@
 
   factory PipelineCommand.runWithDartOrKernelFile(
       CompilerConfiguration configuration) {
-    return new PipelineCommand._(configuration,
+    return PipelineCommand._(configuration,
         (List<String> globalArguments, String previousOutput) {
       var filtered = globalArguments
           .where((name) => name.endsWith('.dart') || name.endsWith('.dill'))
@@ -306,7 +305,7 @@
 
   factory PipelineCommand.runWithPreviousKernelOutput(
       CompilerConfiguration configuration) {
-    return new PipelineCommand._(configuration,
+    return PipelineCommand._(configuration,
         (List<String> globalArguments, String previousOutput) {
       assert(previousOutput.endsWith('.dill'));
       return _replaceDartFiles(globalArguments, previousOutput);
@@ -349,8 +348,7 @@
       allCommands.addAll(artifact.commands);
     }
 
-    return new CommandArtifact(
-        allCommands, artifact.filename, artifact.mimeType);
+    return CommandArtifact(allCommands, artifact.filename, artifact.mimeType);
   }
 
   List<String> computeCompilerArguments(
@@ -438,7 +436,7 @@
         _configuration.buildDirectory,
         () => [
               Uri.base
-                  .resolveUri(new Uri.directory(_configuration.buildDirectory))
+                  .resolveUri(Uri.directory(_configuration.buildDirectory))
                   .resolve('dart-sdk/bin/snapshots/dart2js.dart.snapshot')
             ]);
   }
@@ -480,7 +478,7 @@
     // TODO(athom): input filename extraction is copied from DDC. Maybe this
     // should be passed to computeCompilationArtifact, instead?
     var inputFile = arguments.last;
-    var inputFilename = (new Uri.file(inputFile)).pathSegments.last;
+    var inputFilename = (Uri.file(inputFile)).pathSegments.last;
     var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
     var babel = _configuration.babel;
     var babelOut = out;
@@ -494,7 +492,7 @@
       commands.add(computeBabelCommand(out, babelOut, babel));
     }
 
-    return new CommandArtifact(commands, babelOut, 'application/javascript');
+    return CommandArtifact(commands, babelOut, 'application/javascript');
   }
 
   List<String> computeRuntimeArguments(
@@ -506,8 +504,8 @@
       List<String> originalArguments,
       CommandArtifact artifact) {
     Uri sdk = _useSdk
-        ? new Uri.directory(_configuration.buildDirectory).resolve('dart-sdk/')
-        : new Uri.directory(Repository.dir.toNativePath()).resolve('sdk/');
+        ? Uri.directory(_configuration.buildDirectory).resolve('dart-sdk/')
+        : Uri.directory(Repository.dir.toNativePath()).resolve('sdk/');
     Uri preambleDir = sdk.resolve('lib/_internal/js_runtime/lib/preambles/');
     return runtimeConfiguration.dart2jsPreambles(preambleDir)
       ..add(artifact.filename);
@@ -589,7 +587,7 @@
       // at the built summary file location.
       var sdkSummaryFile =
           useDillFormat ? 'kernel/ddc_sdk.dill' : 'ddc_sdk.sum';
-      var sdkSummary = new Path(_configuration.buildDirectory)
+      var sdkSummary = Path(_configuration.buildDirectory)
           .append("/gen/utils/dartdevc/$sdkSummaryFile")
           .absolute
           .toNativePath();
@@ -600,7 +598,7 @@
     if (!useKernel) {
       // TODO(jmesserly): library-root needs to be removed.
       args.addAll(
-          ["--library-root", new Path(inputFile).directoryPath.toNativePath()]);
+          ["--library-root", Path(inputFile).directoryPath.toNativePath()]);
     }
 
     args.addAll([
@@ -622,15 +620,14 @@
       // Since the summaries for the packages are not near the tests, we give
       // dartdevc explicit module paths for each one. When the test is run, we
       // will tell require.js where to find each package's compiled JS.
-      var summary = new Path(_configuration.buildDirectory)
+      var summary = Path(_configuration.buildDirectory)
           .append("/gen/utils/dartdevc/$pkgDir/$package.$pkgExtension")
           .absolute
           .toNativePath();
       args.add("$summary=$package");
     }
 
-    var inputDir =
-        new Path(inputFile).append("..").canonicalize().toNativePath();
+    var inputDir = Path(inputFile).append("..").canonicalize().toNativePath();
     var displayName = useKernel ? 'dartdevk' : 'dartdevc';
     return Command.compilation(displayName, outputFile, bootstrapDependencies(),
         computeCompilerPath(), args, environment,
@@ -646,10 +643,10 @@
     // computeCompilerArguments() to here seems hacky. Is there a cleaner way?
     var sharedOptions = arguments.sublist(0, arguments.length - 1);
     var inputFile = arguments.last;
-    var inputFilename = (new Uri.file(inputFile)).pathSegments.last;
+    var inputFilename = (Uri.file(inputFile)).pathSegments.last;
     var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
 
-    return new CommandArtifact(
+    return CommandArtifact(
         [_createCommand(inputFile, outputFile, sharedOptions, environment)],
         outputFile,
         "application/javascript");
@@ -669,7 +666,7 @@
   bool get _isAot => true;
 
   PrecompilerCompilerConfiguration(TestConfiguration configuration,
-      {this.previewDart2: true})
+      {this.previewDart2 = true})
       : super._subclass(configuration);
 
   int get timeoutMultiplier {
@@ -703,7 +700,7 @@
       }
     }
 
-    return new CommandArtifact(
+    return CommandArtifact(
         commands, '$tempDir', 'application/dart-precompiled');
   }
 
@@ -913,7 +910,7 @@
   final bool previewDart2;
 
   AppJitCompilerConfiguration(TestConfiguration configuration,
-      {this.previewDart2: true})
+      {this.previewDart2 = true})
       : super._subclass(configuration);
 
   int get timeoutMultiplier {
@@ -926,7 +923,7 @@
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
     var snapshot = "$tempDir/out.jitsnapshot";
-    return new CommandArtifact(
+    return CommandArtifact(
         [computeCompilationCommand(tempDir, arguments, environmentOverrides)],
         snapshot,
         'application/dart-snapshot');
@@ -1013,7 +1010,7 @@
       List<String> arguments, Map<String, String> environmentOverrides) {
     arguments = arguments.toList();
     if (!previewDart2) {
-      throw new ArgumentError('--no-preview-dart-2 not supported');
+      throw ArgumentError('--no-preview-dart-2 not supported');
     }
     if (_configuration.useAnalyzerCfe) {
       arguments.add('--use-cfe');
@@ -1023,7 +1020,7 @@
     }
 
     // Since this is not a real compilation, no artifacts are produced.
-    return new CommandArtifact([
+    return CommandArtifact([
       Command.analysis(computeCompilerPath(), arguments, environmentOverrides)
     ], null, null);
   }
@@ -1059,11 +1056,11 @@
       List<String> arguments, Map<String, String> environmentOverrides) {
     arguments = arguments.toList();
     if (!previewDart2) {
-      throw new ArgumentError('--no-preview-dart-2 not supported');
+      throw ArgumentError('--no-preview-dart-2 not supported');
     }
 
     // Since this is not a real compilation, no artifacts are produced.
-    return new CommandArtifact([
+    return CommandArtifact([
       Command.compareAnalyzerCfe(
           computeCompilerPath(), arguments, environmentOverrides)
     ], null, null);
@@ -1093,7 +1090,7 @@
     arguments = arguments.toList();
 
     // Since this is not a real compilation, no artifacts are produced.
-    return new CommandArtifact([
+    return CommandArtifact([
       Command.specParse(computeCompilerPath(), arguments, environmentOverrides)
     ], null, null);
   }
@@ -1112,7 +1109,7 @@
 
 abstract class VMKernelCompilerMixin {
   static final noCausalAsyncStacksRegExp =
-      new RegExp('--no[_-]causal[_-]async[_-]stacks');
+      RegExp('--no[_-]causal[_-]async[_-]stacks');
 
   TestConfiguration get _configuration;
 
@@ -1127,7 +1124,7 @@
   List<Uri> bootstrapDependencies();
 
   String tempKernelFile(String tempDir) =>
-      new Path('$tempDir/out.dill').toNativePath();
+      Path('$tempDir/out.dill').toNativePath();
 
   Command computeCompileToKernelCommand(String tempDir, List<String> arguments,
       Map<String, String> environmentOverrides) {
@@ -1202,7 +1199,7 @@
 
   factory FastaCompilerConfiguration(TestConfiguration configuration) {
     var buildDirectory =
-        Uri.base.resolveUri(new Uri.directory(configuration.buildDirectory));
+        Uri.base.resolveUri(Uri.directory(configuration.buildDirectory));
 
     var dillDir = buildDirectory;
     if (configuration.useSdk) {
@@ -1214,7 +1211,7 @@
 
     var vmExecutable = buildDirectory
         .resolve(configuration.useSdk ? "dart-sdk/bin/dart" : "dart");
-    return new FastaCompilerConfiguration._(
+    return FastaCompilerConfiguration._(
         platformDill, vmExecutable, configuration);
   }
 
@@ -1232,7 +1229,7 @@
   CommandArtifact computeCompilationArtifact(String tempDir,
       List<String> arguments, Map<String, String> environmentOverrides) {
     var output =
-        Uri.base.resolveUri(new Uri.directory(tempDir)).resolve("out.dill");
+        Uri.base.resolveUri(Uri.directory(tempDir)).resolve("out.dill");
     var outputFileName = output.toFilePath();
 
     var compilerArguments = <String>['--verify'];
@@ -1244,7 +1241,7 @@
         ["-o", outputFileName, "--platform", _platformDill.toFilePath()]);
     compilerArguments.addAll(arguments);
 
-    return new CommandArtifact([
+    return CommandArtifact([
       Command.fasta(
           _compilerLocation,
           output,
@@ -1264,7 +1261,7 @@
       List<String> dart2jsOptions,
       List<String> ddcOptions,
       List<String> args) {
-    List<String> arguments = new List<String>.from(sharedOptions);
+    List<String> arguments = List<String>.from(sharedOptions);
     arguments.addAll(_configuration.sharedOptions);
     for (String argument in args) {
       if (argument == "--ignore-unrecognized-flags") continue;
diff --git a/pkg/test_runner/lib/src/configuration.dart b/pkg/test_runner/lib/src/configuration.dart
index 5c9d514..e37b2f3 100644
--- a/pkg/test_runner/lib/src/configuration.dart
+++ b/pkg/test_runner/lib/src/configuration.dart
@@ -173,7 +173,7 @@
 
   TestingServers get servers {
     if (_servers == null) {
-      throw new StateError("Servers have not been started yet.");
+      throw StateError("Servers have not been started yet.");
     }
     return _servers;
   }
@@ -255,7 +255,7 @@
 
   String get windowsSdkPath {
     if (!Platform.isWindows) {
-      throw new StateError(
+      throw StateError(
           "Should not use windowsSdkPath when not running on Windows.");
     }
 
@@ -263,8 +263,8 @@
       // When running tests on Windows, use cdb from depot_tools to dump
       // stack traces of tests timing out.
       try {
-        var path = new Path("build/win_toolchain.json").toNativePath();
-        var text = new File(path).readAsStringSync();
+        var path = Path("build/win_toolchain.json").toNativePath();
+        var text = File(path).readAsStringSync();
         _windowsSdkPath = jsonDecode(text)['win_sdk'] as String;
       } on dynamic {
         // Ignore errors here. If win_sdk is not found, stack trace dumping
@@ -293,29 +293,29 @@
 
     if (location != null) return location;
 
-    const locations = const {
-      Runtime.firefox: const {
+    const locations = {
+      Runtime.firefox: {
         System.win: 'C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe',
         System.linux: 'firefox',
         System.mac: '/Applications/Firefox.app/Contents/MacOS/firefox'
       },
-      Runtime.chrome: const {
+      Runtime.chrome: {
         System.win:
             'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
         System.mac:
             '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
         System.linux: 'google-chrome'
       },
-      Runtime.safari: const {
+      Runtime.safari: {
         System.mac: '/Applications/Safari.app/Contents/MacOS/Safari'
       },
-      Runtime.ie9: const {
+      Runtime.ie9: {
         System.win: 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
       },
-      Runtime.ie10: const {
+      Runtime.ie10: {
         System.win: 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
       },
-      Runtime.ie11: const {
+      Runtime.ie11: {
         System.win: 'C:\\Program Files\\Internet Explorer\\iexplore.exe'
       }
     };
@@ -332,12 +332,12 @@
   RuntimeConfiguration _runtimeConfiguration;
 
   RuntimeConfiguration get runtimeConfiguration =>
-      _runtimeConfiguration ??= new RuntimeConfiguration(this);
+      _runtimeConfiguration ??= RuntimeConfiguration(this);
 
   CompilerConfiguration _compilerConfiguration;
 
   CompilerConfiguration get compilerConfiguration =>
-      _compilerConfiguration ??= new CompilerConfiguration(this);
+      _compilerConfiguration ??= CompilerConfiguration(this);
 
   /// Determines if this configuration has a compatible compiler and runtime
   /// and other valid fields.
@@ -377,7 +377,7 @@
   /// server for cross-domain tests can be found by calling
   /// `getCrossOriginPortNumber()`.
   Future startServers() {
-    _servers = new TestingServers(
+    _servers = TestingServers(
         buildDirectory, isCsp, runtime, null, packageRoot, packages);
     var future = servers.startServers(localIP,
         port: testServerPort, crossOriginPort: testServerCrossOriginPort);
@@ -414,8 +414,8 @@
     var normal = '$modeName$os$arch';
     var cross = '$modeName${os}X$arch';
     var outDir = system.outputDirectory;
-    var normalDir = new Directory(new Path('$outDir$normal').toNativePath());
-    var crossDir = new Directory(new Path('$outDir$cross').toNativePath());
+    var normalDir = Directory(Path('$outDir$normal').toNativePath());
+    var crossDir = Directory(Path('$outDir$cross').toNativePath());
 
     if (normalDir.existsSync() && crossDir.existsSync()) {
       throw "You can't have both $normalDir and $crossDir. We don't know which"
@@ -468,18 +468,18 @@
 }
 
 class Progress {
-  static const compact = const Progress._('compact');
-  static const color = const Progress._('color');
-  static const line = const Progress._('line');
-  static const verbose = const Progress._('verbose');
-  static const silent = const Progress._('silent');
-  static const status = const Progress._('status');
-  static const buildbot = const Progress._('buildbot');
-  static const diff = const Progress._('diff');
+  static const compact = Progress._('compact');
+  static const color = Progress._('color');
+  static const line = Progress._('line');
+  static const verbose = Progress._('verbose');
+  static const silent = Progress._('silent');
+  static const status = Progress._('status');
+  static const buildbot = Progress._('buildbot');
+  static const diff = Progress._('diff');
 
   static final List<String> names = _all.keys.toList();
 
-  static final _all = new Map<String, Progress>.fromIterable(
+  static final _all = Map<String, Progress>.fromIterable(
       [compact, color, line, verbose, silent, status, buildbot, diff],
       key: (progress) => (progress as Progress).name);
 
@@ -487,7 +487,7 @@
     var progress = _all[name];
     if (progress != null) return progress;
 
-    throw new ArgumentError('Unknown progress type "$name".');
+    throw ArgumentError('Unknown progress type "$name".');
   }
 
   final String name;
diff --git a/pkg/test_runner/lib/src/dependency_graph.dart b/pkg/test_runner/lib/src/dependency_graph.dart
index 1b6cb0e..bf89d9e 100644
--- a/pkg/test_runner/lib/src/dependency_graph.dart
+++ b/pkg/test_runner/lib/src/dependency_graph.dart
@@ -12,7 +12,7 @@
 /// The graph exposes a few broadcast streams that can be subscribed to in
 /// order to be notified of modifications to the graph.
 class Graph<T> {
-  final _nodes = new Set<Node<T>>();
+  final _nodes = <Node<T>>{};
   final _stateCounts = <NodeState, int>{};
   bool _isSealed = false;
 
@@ -29,11 +29,11 @@
   final StreamController<Null> _sealedController;
 
   factory Graph() {
-    var added = new StreamController<Node<T>>();
-    var changed = new StreamController<StateChangedEvent<T>>();
-    var sealed = new StreamController<Null>();
+    var added = StreamController<Node<T>>();
+    var changed = StreamController<StateChangedEvent<T>>();
+    var sealed = StreamController<Null>();
 
-    return new Graph._(
+    return Graph._(
         added,
         added.stream.asBroadcastStream(),
         changed,
@@ -74,7 +74,7 @@
       {bool timingDependency = false}) {
     assert(!_isSealed);
 
-    var node = new Node._(userData, timingDependency);
+    var node = Node._(userData, timingDependency);
     _nodes.add(node);
 
     for (var dependency in dependencies) {
@@ -99,8 +99,7 @@
     _stateCounts.putIfAbsent(state, () => 0);
     _stateCounts[state] += 1;
 
-    _emitEvent(
-        _changedController, new StateChangedEvent(node, fromState, state));
+    _emitEvent(_changedController, StateChangedEvent(node, fromState, state));
   }
 
   /// We emit events asynchronously so the graph can be build up in small
@@ -117,8 +116,8 @@
   final T data;
   final bool timingDependency;
   NodeState _state = NodeState.initialized;
-  final Set<Node<T>> _dependencies = new Set();
-  final Set<Node<T>> _neededFor = new Set();
+  final Set<Node<T>> _dependencies = {};
+  final Set<Node<T>> _neededFor = {};
 
   Node._(this.data, this.timingDependency);
 
@@ -128,13 +127,13 @@
 }
 
 class NodeState {
-  static const initialized = const NodeState._("Initialized");
-  static const waiting = const NodeState._("Waiting");
-  static const enqueuing = const NodeState._("Enqueuing");
-  static const processing = const NodeState._("Running");
-  static const successful = const NodeState._("Successful");
-  static const failed = const NodeState._("Failed");
-  static const unableToRun = const NodeState._("UnableToRun");
+  static const initialized = NodeState._("Initialized");
+  static const waiting = NodeState._("Waiting");
+  static const enqueuing = NodeState._("Enqueuing");
+  static const processing = NodeState._("Running");
+  static const successful = NodeState._("Successful");
+  static const failed = NodeState._("Failed");
+  static const unableToRun = NodeState._("UnableToRun");
 
   final String name;
 
diff --git a/pkg/test_runner/lib/src/environment.dart b/pkg/test_runner/lib/src/environment.dart
index 5245977..b028db0 100644
--- a/pkg/test_runner/lib/src/environment.dart
+++ b/pkg/test_runner/lib/src/environment.dart
@@ -6,38 +6,37 @@
 
 import 'configuration.dart';
 
-typedef String _LookUpFunction(TestConfiguration configuration);
-typedef bool _BoolLookUpFunction(TestConfiguration configuration);
+typedef _LookUpFunction = String Function(TestConfiguration configuration);
+typedef _BoolLookUpFunction = bool Function(TestConfiguration configuration);
 
 // TODO(29756): Instead of synthesized negated variables like "unchecked",
 // consider adding support for "!" to status expressions.
 final _variables = {
-  "analyzer": new _Variable.bool((c) => c.compiler == Compiler.dart2analyzer),
-  "analyzer_use_fasta_parser":
-      new _Variable.bool((c) => c.useAnalyzerFastaParser),
-  "arch": new _Variable((c) => c.architecture.name, Architecture.names),
-  "browser": new _Variable.bool((c) => c.runtime.isBrowser),
-  "builder_tag": new _Variable((c) => c.builderTag ?? "", const []),
-  "checked": new _Variable.bool((c) => c.isChecked),
-  "compiler": new _Variable((c) => c.compiler.name, Compiler.names),
-  "csp": new _Variable.bool((c) => c.isCsp),
-  "enable_asserts": new _Variable.bool((c) => c.useEnableAsserts),
-  "fasta": new _Variable.bool((c) => c.usesFasta),
-  "host_checked": new _Variable.bool((c) => c.isHostChecked),
-  "host_unchecked": new _Variable.bool((c) => !c.isHostChecked),
-  "hot_reload": new _Variable.bool((c) => c.hotReload),
-  "hot_reload_rollback": new _Variable.bool((c) => c.hotReloadRollback),
-  "ie": new _Variable.bool((c) => c.runtime.isIE),
-  "jscl": new _Variable.bool((c) => c.runtime.isJSCommandLine),
-  "minified": new _Variable.bool((c) => c.isMinified),
-  "mode": new _Variable((c) => c.mode.name, Mode.names),
-  "no_preview_dart_2": new _Variable.bool((c) => c.noPreviewDart2),
-  "preview_dart_2": new _Variable.bool((c) => !c.noPreviewDart2),
-  "runtime": new _Variable(_runtimeName, _runtimeNames),
-  "spec_parser": new _Variable.bool((c) => c.compiler == Compiler.specParser),
-  "strong": new _Variable.bool((c) => !c.noPreviewDart2),
-  "system": new _Variable(_systemName, _systemNames),
-  "use_sdk": new _Variable.bool((c) => c.useSdk)
+  "analyzer": _Variable.bool((c) => c.compiler == Compiler.dart2analyzer),
+  "analyzer_use_fasta_parser": _Variable.bool((c) => c.useAnalyzerFastaParser),
+  "arch": _Variable((c) => c.architecture.name, Architecture.names),
+  "browser": _Variable.bool((c) => c.runtime.isBrowser),
+  "builder_tag": _Variable((c) => c.builderTag ?? "", const []),
+  "checked": _Variable.bool((c) => c.isChecked),
+  "compiler": _Variable((c) => c.compiler.name, Compiler.names),
+  "csp": _Variable.bool((c) => c.isCsp),
+  "enable_asserts": _Variable.bool((c) => c.useEnableAsserts),
+  "fasta": _Variable.bool((c) => c.usesFasta),
+  "host_checked": _Variable.bool((c) => c.isHostChecked),
+  "host_unchecked": _Variable.bool((c) => !c.isHostChecked),
+  "hot_reload": _Variable.bool((c) => c.hotReload),
+  "hot_reload_rollback": _Variable.bool((c) => c.hotReloadRollback),
+  "ie": _Variable.bool((c) => c.runtime.isIE),
+  "jscl": _Variable.bool((c) => c.runtime.isJSCommandLine),
+  "minified": _Variable.bool((c) => c.isMinified),
+  "mode": _Variable((c) => c.mode.name, Mode.names),
+  "no_preview_dart_2": _Variable.bool((c) => c.noPreviewDart2),
+  "preview_dart_2": _Variable.bool((c) => !c.noPreviewDart2),
+  "runtime": _Variable(_runtimeName, _runtimeNames),
+  "spec_parser": _Variable.bool((c) => c.compiler == Compiler.specParser),
+  "strong": _Variable.bool((c) => !c.noPreviewDart2),
+  "system": _Variable(_systemName, _systemNames),
+  "use_sdk": _Variable.bool((c) => c.useSdk)
 };
 
 /// Gets the name of the runtime as it appears in status files.
@@ -103,7 +102,7 @@
     if (variable == null) {
       // This shouldn't happen since we validate variables before evaluating
       // expressions.
-      throw new ArgumentError('Unknown variable "$variable".');
+      throw ArgumentError('Unknown variable "$variable".');
     }
 
     return variable.lookUp(_configuration);
diff --git a/pkg/test_runner/lib/src/expectation_set.dart b/pkg/test_runner/lib/src/expectation_set.dart
index 4e83724..40f84af 100644
--- a/pkg/test_runner/lib/src/expectation_set.dart
+++ b/pkg/test_runner/lib/src/expectation_set.dart
@@ -27,16 +27,16 @@
   final Map<String, RegExp> _globCache = {};
 
   /// The root of the expectation tree.
-  final _PathNode _tree = new _PathNode();
+  final _PathNode _tree = _PathNode();
 
   /// Reads the expectations defined by the status files at [statusFilePaths]
   /// when in [configuration].
   ExpectationSet.read(
       List<String> statusFilePaths, TestConfiguration configuration) {
     try {
-      var environment = new ConfigurationEnvironment(configuration);
+      var environment = ConfigurationEnvironment(configuration);
       for (var path in statusFilePaths) {
-        var file = new StatusFile.read(path);
+        var file = StatusFile.read(path);
         file.validate(environment);
         for (var section in file.sections) {
           if (section.isEnabled(environment)) {
@@ -60,11 +60,11 @@
     for (var part in entry.path.split('/')) {
       if (part.contains("*")) {
         var regExp = _globCache.putIfAbsent(part, () {
-          return new RegExp("^" + part.replaceAll("*", ".*") + r"$");
+          return RegExp("^" + part.replaceAll("*", ".*") + r"$");
         });
-        tree = tree.regExpChildren.putIfAbsent(regExp, () => new _PathNode());
+        tree = tree.regExpChildren.putIfAbsent(regExp, () => _PathNode());
       } else {
-        tree = tree.stringChildren.putIfAbsent(part, () => new _PathNode());
+        tree = tree.stringChildren.putIfAbsent(part, () => _PathNode());
       }
     }
 
@@ -80,7 +80,7 @@
   /// checks that the anchored regular expression "^$keyComponent\$" matches
   /// the corresponding filename component.
   Set<Expectation> expectations(String path) {
-    var result = new Set<Expectation>();
+    var result = <Expectation>{};
     _tree.walk(path.split('/'), 0, result);
 
     // If no status files modified the expectation, default to the test passing.
@@ -105,7 +105,7 @@
 
   /// The test expectatations that any test within this directory should
   /// include.
-  final Set<Expectation> expectations = new Set();
+  final Set<Expectation> expectations = {};
 
   /// Walks the list of path [parts], starting at [index] adding any
   /// expectations to [result] from this node and any of its matching children.
diff --git a/pkg/test_runner/lib/src/multitest.dart b/pkg/test_runner/lib/src/multitest.dart
index bc6567d..987af25 100644
--- a/pkg/test_runner/lib/src/multitest.dart
+++ b/pkg/test_runner/lib/src/multitest.dart
@@ -77,7 +77,7 @@
 import "utils.dart";
 
 /// Until legacy multitests are ported we need to support both /// and //#
-final _multitestMarker = new RegExp(r"//[/#]");
+final _multitestMarker = RegExp(r"//[/#]");
 
 final _multitestOutcomes = [
   'ok',
@@ -92,7 +92,7 @@
 
 void extractTestsFromMultitest(Path filePath, Map<String, String> tests,
     Map<String, Set<String>> outcomes) {
-  var contents = new File(filePath.toNativePath()).readAsStringSync();
+  var contents = File(filePath.toNativePath()).readAsStringSync();
 
   var firstNewline = contents.indexOf('\n');
   var lineSeparator =
@@ -105,8 +105,8 @@
   var testsAsLines = <String, List<String>>{};
 
   // Add the default case with key "none".
-  testsAsLines['none'] = <String>[];
-  outcomes['none'] = new Set<String>();
+  testsAsLines['none'] = [];
+  outcomes['none'] = {};
 
   var lineCount = 0;
   for (var line in lines) {
@@ -114,12 +114,12 @@
     var annotation = _Annotation.tryParse(line);
     if (annotation != null) {
       testsAsLines.putIfAbsent(
-          annotation.key, () => new List<String>.from(testsAsLines["none"]));
+          annotation.key, () => List<String>.from(testsAsLines["none"]));
       // Add line to test with annotation.key as key, empty line to the rest.
       for (var key in testsAsLines.keys) {
         testsAsLines[key].add(annotation.key == key ? line : "");
       }
-      outcomes.putIfAbsent(annotation.key, () => new Set<String>());
+      outcomes.putIfAbsent(annotation.key, () => <String>{});
       if (annotation.rest != 'continued') {
         for (var nextOutcome in annotation.outcomes) {
           if (_multitestOutcomes.contains(nextOutcome)) {
@@ -165,8 +165,7 @@
 Future doMultitest(Path filePath, String outputDir, Path suiteDir,
     CreateTest doTest, bool hotReload) {
   void writeFile(String filepath, String content) {
-    final File file = new File(filepath);
-
+    var file = File(filepath);
     if (file.existsSync()) {
       var oldContent = file.readAsStringSync();
       if (oldContent == content) {
@@ -190,7 +189,7 @@
   var importsToCopy = _findAllRelativeImports(filePath);
   var futureCopies = <Future>[];
   for (var relativeImport in importsToCopy) {
-    var importPath = new Path(relativeImport);
+    var importPath = Path(relativeImport);
     // Make sure the target directory exists.
     var importDir = importPath.directoryPath;
     if (!importDir.isEmpty) {
@@ -249,12 +248,12 @@
         .split(_multitestMarker)[1]
         .split(':')
         .map((s) => s.trim())
-        .where((s) => s.length > 0)
+        .where((s) => s.isNotEmpty)
         .toList();
 
     if (parts.length <= 1) return null;
 
-    return new _Annotation._(parts[0], parts[1]);
+    return _Annotation._(parts[0], parts[1]);
   }
 
   final String key;
@@ -272,9 +271,9 @@
 /// Finds all relative imports and copies them into the directory with the
 /// generated tests.
 Set<String> _findAllRelativeImports(Path topLibrary) {
-  var found = new Set<String>();
+  var found = <String>{};
   var libraryDir = topLibrary.directoryPath;
-  var relativeImportRegExp = new RegExp(
+  var relativeImportRegExp = RegExp(
       '^(?:@.*\\s+)?' // Allow for a meta-data annotation.
       '(import|part)'
       '\\s+["\']'
@@ -283,7 +282,7 @@
       '["\']');
 
   processFile(Path filePath) {
-    var file = new File(filePath.toNativePath());
+    var file = File(filePath.toNativePath());
     for (var line in file.readAsLinesSync()) {
       var match = relativeImportRegExp.firstMatch(line);
       if (match == null) continue;
@@ -327,10 +326,10 @@
 Path _createMultitestDirectory(
     String outputDir, Path suiteDir, Path sourceDir) {
   var relative = sourceDir.relativeTo(suiteDir);
-  var path = new Path(outputDir)
+  var path = Path(outputDir)
       .append('generated_tests')
       .append(_suiteNameFromPath(suiteDir))
       .join(relative);
   TestUtils.mkdirRecursive(Path.workingDirectory, path);
-  return new Path(new File(path.toNativePath()).absolute.path);
+  return Path(File(path.toNativePath()).absolute.path);
 }
diff --git a/pkg/test_runner/lib/src/options.dart b/pkg/test_runner/lib/src/options.dart
index 1dc983a..59f4f59 100644
--- a/pkg/test_runner/lib/src/options.dart
+++ b/pkg/test_runner/lib/src/options.dart
@@ -12,7 +12,7 @@
 import 'repository.dart';
 import 'utils.dart';
 
-const _defaultTestSelectors = const [
+const _defaultTestSelectors = [
   'samples',
   'standalone',
   'standalone_2',
@@ -82,9 +82,9 @@
 /// Parses command line arguments and produces a test runner configuration.
 class OptionsParser {
   static final List<_Option> _options = [
-    new _Option('mode', 'Mode in which to run the tests.',
+    _Option('mode', 'Mode in which to run the tests.',
         abbr: 'm', values: ['all']..addAll(Mode.names)),
-    new _Option(
+    _Option(
         'compiler',
         '''How the Dart code should be compiled or statically processed.
 
@@ -102,7 +102,7 @@
 spec_parser:   Parse Dart code using the specification parser.''',
         abbr: 'c',
         values: Compiler.names),
-    new _Option(
+    _Option(
         'runtime',
         '''Where the tests should be run.
 vm:               Run Dart code on the standalone Dart VM.
@@ -126,7 +126,7 @@
 none:             No runtime, compile only.''',
         abbr: 'r',
         values: Runtime.names),
-    new _Option(
+    _Option(
         'arch',
         '''The architecture to run tests for.
 
@@ -140,54 +140,51 @@
         values: ['all']..addAll(Architecture.names),
         defaultsTo: Architecture.x64.name,
         hide: true),
-    new _Option('system', 'The operating system to run tests on.',
+    _Option('system', 'The operating system to run tests on.',
         abbr: 's',
         values: System.names,
         defaultsTo: Platform.operatingSystem,
         hide: true),
-    new _Option(
+    _Option(
         'named_configuration',
         '''The named test configuration that supplies the values for all
 test options, specifying how tests should be run.''',
         abbr: 'n',
         hide: true),
-    new _Option.bool('strong', 'Deprecated, no-op.', hide: true),
+    _Option.bool('strong', 'Deprecated, no-op.', hide: true),
     // TODO(sigmund): rename flag once we migrate all dart2js bots to the test
     // matrix.
-    new _Option.bool('host_checked', 'Run compiler with assertions enabled.',
+    _Option.bool('host_checked', 'Run compiler with assertions enabled.',
         hide: true),
-    new _Option.bool('minified', 'Enable minification in the compiler.',
+    _Option.bool('minified', 'Enable minification in the compiler.',
         hide: true),
-    new _Option.bool(
-        'csp', 'Run tests under Content Security Policy restrictions.',
+    _Option.bool('csp', 'Run tests under Content Security Policy restrictions.',
         hide: true),
-    new _Option.bool('fast_tests',
+    _Option.bool('fast_tests',
         'Only run tests that are not marked `Slow` or `Timeout`.'),
-    new _Option.bool('enable_asserts',
+    _Option.bool('enable_asserts',
         'Pass the --enable-asserts flag to dart2js or to the vm.'),
-    new _Option.bool('no_preview_dart_2',
+    _Option.bool('no_preview_dart_2',
         'Enable legacy Dart 1 behavior for some runtimes and compilers.',
         hide: true),
-    new _Option.bool('use_cfe', 'Pass the --use-cfe flag to analyzer',
-        hide: true),
-    new _Option.bool('analyzer_use_fasta_parser',
+    _Option.bool('use_cfe', 'Pass the --use-cfe flag to analyzer', hide: true),
+    _Option.bool('analyzer_use_fasta_parser',
         'Pass the --use-fasta-parser flag to analyzer',
         hide: true),
 
-    new _Option.bool('hot_reload', 'Run hot reload stress tests.', hide: true),
-    new _Option.bool(
-        'hot_reload_rollback', 'Run hot reload rollback stress tests.',
+    _Option.bool('hot_reload', 'Run hot reload stress tests.', hide: true),
+    _Option.bool('hot_reload_rollback', 'Run hot reload rollback stress tests.',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'use_blobs', 'Use mmap instead of shared libraries for precompilation.',
         hide: true),
-    new _Option.bool('use_elf',
+    _Option.bool('use_elf',
         'Directly generate an ELF shared libraries for precompilation.',
         hide: true),
-    new _Option.bool('keep_generated_files', 'Keep any generated files.',
+    _Option.bool('keep_generated_files', 'Keep any generated files.',
         abbr: 'k'),
-    new _Option.int('timeout', 'Timeout in seconds.', abbr: 't'),
-    new _Option(
+    _Option.int('timeout', 'Timeout in seconds.', abbr: 't'),
+    _Option(
         'progress',
         '''Progress indication mode.
 
@@ -196,130 +193,126 @@
         abbr: 'p',
         values: Progress.names,
         defaultsTo: Progress.compact.name),
-    new _Option('step_name', 'Step name for use by -pbuildbot.', hide: true),
-    new _Option.bool('report',
+    _Option('step_name', 'Step name for use by -pbuildbot.', hide: true),
+    _Option.bool('report',
         'Print a summary report of the number of tests, by expectation.',
         hide: true),
-    new _Option.int('tasks', 'The number of parallel tasks to run.',
+    _Option.int('tasks', 'The number of parallel tasks to run.',
         abbr: 'j', defaultsTo: Platform.numberOfProcessors),
-    new _Option.int('shards',
+    _Option.int('shards',
         'The number of instances that the tests will be sharded over.',
         defaultsTo: 1, hide: true),
-    new _Option.int(
+    _Option.int(
         'shard', 'The index of this instance when running in sharded mode.',
         defaultsTo: 1, hide: true),
-    new _Option.bool('help', 'Print list of options.', abbr: 'h'),
-    new _Option.int('repeat', 'How many times each test is run', defaultsTo: 1),
-    new _Option.bool('verbose', 'Verbose output.', abbr: 'v'),
-    new _Option.bool('verify-ir', 'Verify kernel IR.', hide: true),
-    new _Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
+    _Option.bool('help', 'Print list of options.', abbr: 'h'),
+    _Option.int('repeat', 'How many times each test is run', defaultsTo: 1),
+    _Option.bool('verbose', 'Verbose output.', abbr: 'v'),
+    _Option.bool('verify-ir', 'Verify kernel IR.', hide: true),
+    _Option.bool('no-tree-shake', 'Disable kernel IR tree shaking.',
         hide: true),
-    new _Option.bool('list', 'List tests only, do not run them.'),
-    new _Option.bool('list-configurations', 'Output list of configurations.'),
-    new _Option.bool('list_status_files',
+    _Option.bool('list', 'List tests only, do not run them.'),
+    _Option.bool('list-configurations', 'Output list of configurations.'),
+    _Option.bool('list_status_files',
         'List status files for test-suites. Do not run any test suites.',
         hide: true),
-    new _Option.bool(
-        'clean_exit', 'Exit 0 if tests ran and results were output.',
+    _Option.bool('clean_exit', 'Exit 0 if tests ran and results were output.',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'silent_failures',
         "Don't complain about failing tests. This is useful when in "
             "combination with --write-results.",
         hide: true),
-    new _Option.bool('report_in_json',
+    _Option.bool('report_in_json',
         'When listing with --list, output result summary in JSON.',
         hide: true),
-    new _Option.bool('time', 'Print timing information after running tests.'),
-    new _Option('dart', 'Path to dart executable.', hide: true),
-    new _Option('gen-snapshot', 'Path to gen_snapshot executable.', hide: true),
-    new _Option('firefox', 'Path to firefox browser executable.', hide: true),
-    new _Option('chrome', 'Path to chrome browser executable.', hide: true),
-    new _Option('safari', 'Path to safari browser executable.', hide: true),
-    new _Option.bool('use_sdk', '''Use compiler or runtime from the SDK.'''),
+    _Option.bool('time', 'Print timing information after running tests.'),
+    _Option('dart', 'Path to dart executable.', hide: true),
+    _Option('gen-snapshot', 'Path to gen_snapshot executable.', hide: true),
+    _Option('firefox', 'Path to firefox browser executable.', hide: true),
+    _Option('chrome', 'Path to chrome browser executable.', hide: true),
+    _Option('safari', 'Path to safari browser executable.', hide: true),
+    _Option.bool('use_sdk', '''Use compiler or runtime from the SDK.'''),
     // TODO(rnystrom): This does not appear to be used. Remove?
-    new _Option('build_directory',
+    _Option('build_directory',
         'The name of the build directory, where products are placed.',
         hide: true),
-    new _Option('output_directory',
+    _Option('output_directory',
         'The name of the output directory for storing log files.',
         defaultsTo: "logs", hide: true),
-    new _Option.bool('noBatch', 'Do not run tests in batch mode.', hide: true),
-    new _Option.bool('dart2js_batch', 'Run dart2js tests in batch mode.',
+    _Option.bool('noBatch', 'Do not run tests in batch mode.', hide: true),
+    _Option.bool('dart2js_batch', 'Run dart2js tests in batch mode.',
         hide: true),
-    new _Option.bool('write_debug_log',
+    _Option.bool('write_debug_log',
         'Don\'t write debug messages to stdout but rather to a logfile.',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'write_results',
         'Write results to a "${TestUtils.resultsFileName}" json file '
             'located at the debug_output_directory.',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'write_logs',
         'Include the stdout and stderr of tests that don\'t match expectations '
             'in the "${TestUtils.logsFileName}" file',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'reset_browser_configuration',
         '''Browser specific reset of configuration.
 
 Warning: Using this option may remove your bookmarks and other
 settings.''',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'copy_coredumps',
         '''If we see a crash that we did not expect, copy the core dumps to
 "/tmp".''',
         hide: true),
-    new _Option(
+    _Option(
         'local_ip',
         '''IP address the HTTP servers should listen on. This address is also
 used for browsers to connect to.''',
         defaultsTo: '127.0.0.1',
         hide: true),
-    new _Option.int('test_server_port', 'Port for test http server.',
+    _Option.int('test_server_port', 'Port for test http server.',
         defaultsTo: 0, hide: true),
-    new _Option.int('test_server_cross_origin_port',
+    _Option.int('test_server_cross_origin_port',
         'Port for test http server cross origin.',
         defaultsTo: 0, hide: true),
-    new _Option.int('test_driver_port', 'Port for http test driver server.',
+    _Option.int('test_driver_port', 'Port for http test driver server.',
         defaultsTo: 0, hide: true),
-    new _Option.int(
+    _Option.int(
         'test_driver_error_port', 'Port for http test driver server errors.',
         defaultsTo: 0, hide: true),
-    new _Option('test_list', 'File containing a list of tests to be executed',
+    _Option('test_list', 'File containing a list of tests to be executed',
         hide: true),
-    new _Option('tests', 'A newline separated list of tests to be executed'),
-    new _Option(
+    _Option('tests', 'A newline separated list of tests to be executed'),
+    _Option(
         'builder_tag',
         '''Machine specific options that is not captured by the regular test
 options. Used to be able to make sane updates to the status files.''',
         hide: true),
-    new _Option('vm_options', 'Extra options to send to the VM when running.',
+    _Option('vm_options', 'Extra options to send to the VM when running.',
         hide: true),
-    new _Option(
-        'dart2js_options', 'Extra options for dart2js compilation step.',
+    _Option('dart2js_options', 'Extra options for dart2js compilation step.',
         hide: true),
-    new _Option('shared_options', 'Extra shared options.', hide: true),
-    new _Option(
+    _Option('shared_options', 'Extra shared options.', hide: true),
+    _Option(
         'babel',
         '''Transforms dart2js output with Babel. The value must be
 Babel options JSON.''',
         hide: true),
-    new _Option(
-        'suite_dir', 'Additional directory to add to the testing matrix.',
+    _Option('suite_dir', 'Additional directory to add to the testing matrix.',
         hide: true),
-    new _Option('package_root', 'The package root to use for testing.',
+    _Option('package_root', 'The package root to use for testing.', hide: true),
+    _Option('packages', 'The package spec file to use for testing.',
         hide: true),
-    new _Option('packages', 'The package spec file to use for testing.',
-        hide: true),
-    new _Option(
+    _Option(
         'exclude_suite',
         '''Exclude suites from default selector, only works when no selector
 has been specified on the command line.''',
         hide: true),
-    new _Option.bool(
+    _Option.bool(
         'skip_compilation',
         '''
 Skip the compilation step, using the compilation artifacts left in
@@ -328,7 +321,7 @@
 dirty offline testing when not making changes that affect the
 compiler.''',
         hide: true),
-    new _Option.bool('print_passing_stdout',
+    _Option.bool('print_passing_stdout',
         'Print the stdout of passing, as well as failing, tests.',
         hide: true)
   ];
@@ -583,8 +576,7 @@
         // observatory_ui, and remove observatory_ui from the original
         // selectors. The only mutable value in the map is the selectors, so a
         // shallow copy is safe.
-        var observatoryConfiguration =
-            new Map<String, dynamic>.from(configuration);
+        var observatoryConfiguration = Map<String, dynamic>.from(configuration);
         var observatorySelectors = {
           'observatory_ui': selectors['observatory_ui']
         };
@@ -688,8 +680,8 @@
             var namedConfiguration =
                 getNamedConfiguration(data["named_configuration"] as String);
             var innerConfiguration = namedConfiguration ??
-                new Configuration("custom configuration", architecture,
-                    compiler, mode, runtime, system,
+                Configuration("custom configuration", architecture, compiler,
+                    mode, runtime, system,
                     timeout: data["timeout"] as int,
                     enableAsserts: data["enable_asserts"] as bool,
                     useAnalyzerCfe: data["use_cfe"] as bool,
@@ -708,7 +700,7 @@
                     babel: data['babel'] as String,
                     builderTag: data["builder_tag"] as String,
                     previewDart2: true);
-            var configuration = new TestConfiguration(
+            var configuration = TestConfiguration(
                 configuration: innerConfiguration,
                 progress: Progress.find(data["progress"] as String),
                 selectors: selectors,
@@ -817,7 +809,7 @@
         _fail("Error: '$suite/$pattern'.  Only one test selection"
             " pattern is allowed to start with '$suite/'");
       }
-      selectorMap[suite] = new RegExp(pattern);
+      selectorMap[suite] = RegExp(pattern);
     }
 
     return selectorMap;
@@ -825,7 +817,7 @@
 
   /// Print out usage information.
   void _printHelp({bool verbose}) {
-    var buffer = new StringBuffer();
+    var buffer = StringBuffer();
 
     buffer.writeln('''The Dart SDK's internal test runner.
 
diff --git a/pkg/test_runner/lib/src/output_log.dart b/pkg/test_runner/lib/src/output_log.dart
new file mode 100644
index 0000000..54d9aff
--- /dev/null
+++ b/pkg/test_runner/lib/src/output_log.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2019, 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';
+import 'dart:convert';
+import 'dart:io';
+
+/// An OutputLog records the output from a test, but truncates it if
+/// it is longer than [_maxHead] characters, and just keeps the head and
+/// the last [_tailLength] characters of the output.
+class OutputLog implements StreamConsumer<List<int>> {
+  static const _maxHead = 500 * 1024;
+  static const _tailLength = 10 * 1024;
+
+  List<int> _head = [];
+  List<int> _tail;
+  List<int> complete;
+  bool _dataDropped = false;
+  StreamSubscription _subscription;
+
+  bool _hasNonUtf8 = false;
+  bool get hasNonUtf8 => _hasNonUtf8;
+
+  void add(List<int> data) {
+    if (complete != null) {
+      throw StateError("Cannot add to OutputLog after calling toList");
+    }
+    if (_tail == null) {
+      _head.addAll(data);
+      if (_head.length > _maxHead) {
+        _tail = _head.sublist(_maxHead);
+        _head.length = _maxHead;
+      }
+    } else {
+      _tail.addAll(data);
+    }
+    if (_tail != null && _tail.length > 2 * _tailLength) {
+      _tail = _truncatedTail();
+      _dataDropped = true;
+    }
+  }
+
+  List<int> _truncatedTail() => _tail.length > _tailLength
+      ? _tail.sublist(_tail.length - _tailLength)
+      : _tail;
+
+  void _checkUtf8(List<int> data) {
+    try {
+      utf8.decode(data, allowMalformed: false);
+    } on FormatException {
+      _hasNonUtf8 = true;
+      var malformed = utf8.decode(data, allowMalformed: true);
+      data
+        ..clear()
+        ..addAll(utf8.encode(malformed))
+        ..addAll("""
+*****************************************************************************
+test.dart: The output of this test contained non-UTF8 formatted data.
+*****************************************************************************
+"""
+            .codeUnits);
+    }
+  }
+
+  List<int> toList() {
+    if (complete == null) {
+      complete = _head;
+      if (_dataDropped) {
+        complete.addAll("""
+*****************************************************************************
+test.dart: Data was removed due to excessive length. If you need the limit to
+be increased, please contact dart-engprod or file an issue.
+*****************************************************************************
+"""
+            .codeUnits);
+        complete.addAll(_truncatedTail());
+      } else if (_tail != null) {
+        complete.addAll(_tail);
+      }
+      _head = null;
+      _tail = null;
+      _checkUtf8(complete);
+    }
+    return complete;
+  }
+
+  @override
+  Future addStream(Stream<List<int>> stream) {
+    _subscription = stream.listen(this.add);
+    return _subscription.asFuture();
+  }
+
+  @override
+  Future close() {
+    toList();
+    return _subscription?.cancel();
+  }
+
+  Future cancel() {
+    return _subscription?.cancel();
+  }
+}
+
+/// An [OutputLog] that tees the output to a file as well.
+class FileOutputLog extends OutputLog {
+  File _outputFile;
+  IOSink _sink;
+
+  FileOutputLog(this._outputFile);
+
+  @override
+  void add(List<int> data) {
+    super.add(data);
+    _sink ??= _outputFile.openWrite();
+    _sink.add(data);
+  }
+
+  @override
+  Future close() {
+    return Future.wait([
+      super.close(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
+
+  @override
+  Future cancel() {
+    return Future.wait([
+      super.cancel(),
+      if (_sink != null) _sink.flush().whenComplete(_sink.close)
+    ]);
+  }
+}
diff --git a/pkg/test_runner/lib/src/path.dart b/pkg/test_runner/lib/src/path.dart
index 555b549..9152d14 100644
--- a/pkg/test_runner/lib/src/path.dart
+++ b/pkg/test_runner/lib/src/path.dart
@@ -6,7 +6,7 @@
 
 // TODO: Remove this class, and use the URI class for all path manipulation.
 class Path {
-  static Path workingDirectory = new Path(Directory.current.path);
+  static Path workingDirectory = Path(Directory.current.path);
 
   final String _path;
   final bool isWindowsShare;
@@ -67,7 +67,7 @@
     // Throws exception if an impossible case is reached.
     if (base.isAbsolute != isAbsolute ||
         base.isWindowsShare != isWindowsShare) {
-      throw new ArgumentError("Invalid case of Path.relativeTo(base):\n"
+      throw ArgumentError("Invalid case of Path.relativeTo(base):\n"
           "  Path and base must both be relative, or both absolute.\n"
           "  Arguments: $_path.relativeTo($base)");
     }
@@ -87,22 +87,22 @@
           if (basePath[1] != _path[1]) {
             // Replace the drive letter in basePath with that from _path.
             basePath = '/${_path[1]}:/${basePath.substring(4)}';
-            base = new Path(basePath);
+            base = Path(basePath);
           }
         } else {
-          throw new ArgumentError("Invalid case of Path.relativeTo(base):\n"
+          throw ArgumentError("Invalid case of Path.relativeTo(base):\n"
               "  Base path and target path are on different Windows drives.\n"
               "  Arguments: $_path.relativeTo($base)");
         }
       } else if (baseHasDrive != pathHasDrive) {
-        throw new ArgumentError("Invalid case of Path.relativeTo(base):\n"
+        throw ArgumentError("Invalid case of Path.relativeTo(base):\n"
             "  Base path must start with a drive letter if and "
             "only if target path does.\n"
             "  Arguments: $_path.relativeTo($base)");
       }
     }
     if (_path.startsWith(basePath)) {
-      if (_path == basePath) return new Path('.');
+      if (_path == basePath) return Path('.');
       // There must be a '/' at the end of the match, or immediately after.
       int matchEnd = basePath.length;
       if (_path[matchEnd - 1] == '/' || _path[matchEnd] == '/') {
@@ -110,7 +110,7 @@
         while (matchEnd < _path.length && _path[matchEnd] == '/') {
           matchEnd++;
         }
-        return new Path(_path.substring(matchEnd)).canonicalize();
+        return Path(_path.substring(matchEnd)).canonicalize();
       }
     }
 
@@ -127,10 +127,10 @@
     while (common < length && pathSegments[common] == baseSegments[common]) {
       common++;
     }
-    final segments = new List<String>();
+    final segments = List<String>();
 
     if (common < baseSegments.length && baseSegments[common] == '..') {
-      throw new ArgumentError("Invalid case of Path.relativeTo(base):\n"
+      throw ArgumentError("Invalid case of Path.relativeTo(base):\n"
           "  Base path has more '..'s than path does.\n"
           "  Arguments: $_path.relativeTo($base)");
     }
@@ -146,22 +146,21 @@
     if (hasTrailingSeparator) {
       segments.add('');
     }
-    return new Path(segments.join('/'));
+    return Path(segments.join('/'));
   }
 
   Path join(Path further) {
     if (further.isAbsolute) {
-      throw new ArgumentError(
-          "Path.join called with absolute Path as argument.");
+      throw ArgumentError("Path.join called with absolute Path as argument.");
     }
     if (isEmpty) {
       return further.canonicalize();
     }
     if (hasTrailingSeparator) {
-      var joined = new Path._internal('$_path${further}', isWindowsShare);
+      var joined = Path._internal('$_path${further}', isWindowsShare);
       return joined.canonicalize();
     }
-    var joined = new Path._internal('$_path/${further}', isWindowsShare);
+    var joined = Path._internal('$_path/${further}', isWindowsShare);
     return joined.canonicalize();
   }
 
@@ -250,7 +249,7 @@
         segmentsToJoin.add('');
       }
     }
-    return new Path._internal(segmentsToJoin.join('/'), isWindowsShare);
+    return Path._internal(segmentsToJoin.join('/'), isWindowsShare);
   }
 
   String toNativePath() {
@@ -281,11 +280,11 @@
 
   Path append(String finalSegment) {
     if (isEmpty) {
-      return new Path._internal(finalSegment, isWindowsShare);
+      return Path._internal(finalSegment, isWindowsShare);
     } else if (hasTrailingSeparator) {
-      return new Path._internal('$_path$finalSegment', isWindowsShare);
+      return Path._internal('$_path$finalSegment', isWindowsShare);
     } else {
-      return new Path._internal('$_path/$finalSegment', isWindowsShare);
+      return Path._internal('$_path/$finalSegment', isWindowsShare);
     }
   }
 
@@ -304,10 +303,10 @@
 
   Path get directoryPath {
     int pos = _path.lastIndexOf('/');
-    if (pos < 0) return new Path('');
+    if (pos < 0) return Path('');
     while (pos > 0 && _path[pos - 1] == '/') --pos;
     var dirPath = (pos > 0) ? _path.substring(0, pos) : '/';
-    return new Path._internal(dirPath, isWindowsShare);
+    return Path._internal(dirPath, isWindowsShare);
   }
 
   String get filename {
diff --git a/pkg/test_runner/lib/src/process_queue.dart b/pkg/test_runner/lib/src/process_queue.dart
new file mode 100644
index 0000000..0d5c77c
--- /dev/null
+++ b/pkg/test_runner/lib/src/process_queue.dart
@@ -0,0 +1,1191 @@
+// Copyright (c) 2019, 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';
+import 'dart:collection';
+import 'dart:convert';
+// We need to use the 'io' prefix here, otherwise io.exitCode will shadow
+// CommandOutput.exitCode in subclasses of CommandOutput.
+import 'dart:io' as io;
+import 'dart:math' as math;
+
+import 'android.dart';
+import 'browser_controller.dart';
+import 'command.dart';
+import 'command_output.dart';
+import 'configuration.dart';
+import 'dependency_graph.dart';
+import 'output_log.dart';
+import 'runtime_configuration.dart';
+import 'test_case.dart';
+import 'test_progress.dart';
+import 'test_suite.dart';
+import 'utils.dart';
+
+const unhandledCompilerExceptionExitCode = 253;
+const parseFailExitCode = 245;
+
+const _cannotOpenDisplayMessage = 'Gtk-WARNING **: cannot open display';
+const _failedToRunCommandMessage = 'Failed to run command. return code=1';
+
+typedef _StepFunction = Future<AdbCommandResult> Function();
+
+class ProcessQueue {
+  TestConfiguration _globalConfiguration;
+
+  Function _allDone;
+  final Graph<Command> _graph = Graph();
+  List<EventListener> _eventListener;
+
+  ProcessQueue(
+      this._globalConfiguration,
+      int maxProcesses,
+      int maxBrowserProcesses,
+      DateTime startTime,
+      List<TestSuite> testSuites,
+      this._eventListener,
+      this._allDone,
+      [bool verbose = false,
+      AdbDevicePool adbDevicePool]) {
+    void setupForListing(TestCaseEnqueuer testCaseEnqueuer) {
+      _graph.sealed.listen((_) {
+        var testCases = testCaseEnqueuer.remainingTestCases.toList();
+        testCases.sort((a, b) => a.displayName.compareTo(b.displayName));
+
+        print("\nGenerating all matching test cases ....\n");
+
+        for (TestCase testCase in testCases) {
+          eventFinishedTestCase(testCase);
+          var outcomes = testCase.expectedOutcomes.map((o) => '$o').toList()
+            ..sort();
+          print("${testCase.displayName}   "
+              "Expectations: ${outcomes.join(', ')}   "
+              "Configuration: '${testCase.configurationString}'");
+        }
+        eventAllTestsKnown();
+      });
+    }
+
+    TestCaseEnqueuer testCaseEnqueuer;
+    CommandQueue commandQueue;
+
+    void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) {
+      Timer _debugTimer;
+      // If we haven't seen a single test finishing during a 10 minute period
+      // something is definitely wrong, so we dump the debugging information.
+      final debugTimerDuration = const Duration(minutes: 10);
+
+      void cancelDebugTimer() {
+        if (_debugTimer != null) {
+          _debugTimer.cancel();
+        }
+      }
+
+      void resetDebugTimer() {
+        cancelDebugTimer();
+        _debugTimer = Timer(debugTimerDuration, () {
+          print("The debug timer of test.dart expired. Please report this issue"
+              " to whesse@ and provide the following information:");
+          print("");
+          print("Graph is sealed: ${_graph.isSealed}");
+          print("");
+          _graph.dumpCounts();
+          print("");
+          var unfinishedNodeStates = [
+            NodeState.initialized,
+            NodeState.waiting,
+            NodeState.enqueuing,
+            NodeState.processing
+          ];
+
+          for (var nodeState in unfinishedNodeStates) {
+            if (_graph.stateCount(nodeState) > 0) {
+              print("Commands in state '$nodeState':");
+              print("=================================");
+              print("");
+              for (var node in _graph.nodes) {
+                if (node.state == nodeState) {
+                  var command = node.data;
+                  var testCases = testCaseEnqueuer.command2testCases[command];
+                  print("  Command: $command");
+                  for (var testCase in testCases) {
+                    print("    Enqueued by: ${testCase.configurationString} "
+                        "-- ${testCase.displayName}");
+                  }
+                  print("");
+                }
+              }
+              print("");
+              print("");
+            }
+          }
+
+          if (commandQueue != null) {
+            commandQueue.dumpState();
+          }
+        });
+      }
+
+      // When the graph building is finished, notify event listeners.
+      _graph.sealed.listen((_) {
+        eventAllTestsKnown();
+      });
+
+      // Queue commands as they become "runnable"
+      CommandEnqueuer(_graph);
+
+      // CommandExecutor will execute commands
+      var executor = CommandExecutorImpl(
+          _globalConfiguration, maxProcesses, maxBrowserProcesses,
+          adbDevicePool: adbDevicePool);
+
+      // Run "runnable commands" using [executor] subject to
+      // maxProcesses/maxBrowserProcesses constraint
+      commandQueue = CommandQueue(_graph, testCaseEnqueuer, executor,
+          maxProcesses, maxBrowserProcesses, verbose);
+
+      // Finish test cases when all commands were run (or some failed)
+      var testCaseCompleter =
+          TestCaseCompleter(_graph, testCaseEnqueuer, commandQueue);
+      testCaseCompleter.finishedTestCases.listen((TestCase finishedTestCase) {
+        resetDebugTimer();
+
+        eventFinishedTestCase(finishedTestCase);
+      }, onDone: () {
+        // Wait until the commandQueue/exectutor is done (it may need to stop
+        // batch runners, browser controllers, ....)
+        commandQueue.done.then((_) {
+          cancelDebugTimer();
+          eventAllTestsDone();
+        });
+      });
+
+      resetDebugTimer();
+    }
+
+    // Build up the dependency graph
+    testCaseEnqueuer = TestCaseEnqueuer(_graph, (TestCase newTestCase) {
+      eventTestAdded(newTestCase);
+    });
+
+    // Either list or run the tests
+    if (_globalConfiguration.listTests) {
+      setupForListing(testCaseEnqueuer);
+    } else {
+      setupForRunning(testCaseEnqueuer);
+    }
+
+    // Start enqueing all TestCases
+    testCaseEnqueuer.enqueueTestSuites(testSuites);
+  }
+
+  void eventFinishedTestCase(TestCase testCase) {
+    for (var listener in _eventListener) {
+      listener.done(testCase);
+    }
+  }
+
+  void eventTestAdded(TestCase testCase) {
+    for (var listener in _eventListener) {
+      listener.testAdded();
+    }
+  }
+
+  void eventAllTestsKnown() {
+    for (var listener in _eventListener) {
+      listener.allTestsKnown();
+    }
+  }
+
+  void eventAllTestsDone() {
+    for (var listener in _eventListener) {
+      listener.allDone();
+    }
+    _allDone();
+  }
+}
+
+/// [TestCaseEnqueuer] takes a list of TestSuites, generates TestCases and
+/// builds a dependency graph of all commands in every TestSuite.
+///
+/// It maintains three helper data structures:
+///
+/// - command2node: A mapping from a [Command] to a node in the dependency
+///   graph.
+///
+/// - command2testCases: A mapping from [Command] to all TestCases that it is
+///   part of.
+///
+/// - remainingTestCases: A set of TestCases that were enqueued but are not
+///   finished.
+///
+/// [Command] and it's subclasses all have hashCode/operator== methods defined
+/// on them, so we can safely use them as keys in Map/Set objects.
+class TestCaseEnqueuer {
+  final Graph<Command> graph;
+  final Function _onTestCaseAdded;
+
+  final command2node = <Command, Node<Command>>{};
+  final command2testCases = <Command, List<TestCase>>{};
+  final remainingTestCases = <TestCase>{};
+
+  TestCaseEnqueuer(this.graph, this._onTestCaseAdded);
+
+  void enqueueTestSuites(List<TestSuite> testSuites) {
+    // Cache information about test cases per test suite. For multiple
+    // configurations there is no need to repeatedly search the file
+    // system, generate tests, and search test files for options.
+    var testCache = <String, List<TestInformation>>{};
+
+    var iterator = testSuites.iterator;
+    void enqueueNextSuite() {
+      if (!iterator.moveNext()) {
+        // We're finished with building the dependency graph.
+        graph.seal();
+      } else {
+        iterator.current.forEachTest(_newTest, testCache, enqueueNextSuite);
+      }
+    }
+
+    enqueueNextSuite();
+  }
+
+  /// Adds a test case to the list of active test cases, and adds its commands
+  /// to the dependency graph of commands.
+  ///
+  /// If the repeat flag is > 1, replicates the test case and its commands,
+  /// adding an index field with a distinct value to each of the copies.
+  ///
+  /// Each copy of the test case depends on the previous copy of the test
+  /// case completing, with its first command having a dependency on the last
+  /// command of the previous copy of the test case. This dependency is
+  /// marked as a "timingDependency", so that it doesn't depend on the previous
+  /// test completing successfully, just on it completing.
+  void _newTest(TestCase testCase) {
+    Node<Command> lastNode;
+    for (var i = 0; i < testCase.configuration.repeat; ++i) {
+      if (i > 0) {
+        testCase = testCase.indexedCopy(i);
+      }
+      remainingTestCases.add(testCase);
+      bool isFirstCommand = true;
+      for (var command in testCase.commands) {
+        // Make exactly *one* node in the dependency graph for every command.
+        // This ensures that we never have two commands c1 and c2 in the graph
+        // with "c1 == c2".
+        var node = command2node[command];
+        if (node == null) {
+          var requiredNodes =
+              (lastNode != null) ? [lastNode] : <Node<Command>>[];
+          node = graph.add(command, requiredNodes,
+              timingDependency: isFirstCommand);
+          command2node[command] = node;
+          command2testCases[command] = <TestCase>[];
+        }
+        // Keep mapping from command to all testCases that refer to it
+        command2testCases[command].add(testCase);
+
+        lastNode = node;
+        isFirstCommand = false;
+      }
+      _onTestCaseAdded(testCase);
+    }
+  }
+}
+
+/// [CommandEnqueuer] will:
+///
+/// - Change node.state to NodeState.enqueuing as soon as all dependencies have
+///   a state of NodeState.Successful.
+/// - Change node.state to NodeState.unableToRun if one or more dependencies
+///   have a state of NodeState.failed/NodeState.unableToRun.
+class CommandEnqueuer {
+  static const _initStates = [NodeState.initialized, NodeState.waiting];
+
+  static const _finishedStates = [
+    NodeState.successful,
+    NodeState.failed,
+    NodeState.unableToRun
+  ];
+
+  final Graph<Command> _graph;
+
+  CommandEnqueuer(this._graph) {
+    _graph.added.listen(_changeNodeStateIfNecessary);
+
+    _graph.changed.listen((event) {
+      if (event.from == NodeState.waiting ||
+          event.from == NodeState.processing) {
+        if (_finishedStates.contains(event.to)) {
+          for (var dependentNode in event.node.neededFor) {
+            _changeNodeStateIfNecessary(dependentNode);
+          }
+        }
+      }
+    });
+  }
+
+  /// Called when either a new node was added or if one of it's dependencies
+  /// changed it's state.
+  void _changeNodeStateIfNecessary(Node<Command> node) {
+    if (_initStates.contains(node.state)) {
+      bool allDependenciesFinished =
+          node.dependencies.every((dep) => _finishedStates.contains(dep.state));
+      bool anyDependenciesUnsuccessful = node.dependencies.any((dep) =>
+          [NodeState.failed, NodeState.unableToRun].contains(dep.state));
+      bool allDependenciesSuccessful =
+          node.dependencies.every((dep) => dep.state == NodeState.successful);
+
+      var newState = NodeState.waiting;
+      if (allDependenciesSuccessful ||
+          (allDependenciesFinished && node.timingDependency)) {
+        newState = NodeState.enqueuing;
+      } else if (anyDependenciesUnsuccessful) {
+        newState = NodeState.unableToRun;
+      }
+      if (node.state != newState) {
+        _graph.changeState(node, newState);
+      }
+    }
+  }
+}
+
+/// [CommandQueue] will listen for nodes entering the NodeState.enqueuing state,
+/// queue them up and run them. While nodes are processed they will be in the
+/// NodeState.processing state. After running a command, the node will change
+/// to a state of NodeState.Successful or NodeState.failed.
+///
+/// It provides a synchronous stream [completedCommands] which provides the
+/// [CommandOutputs] for the finished commands.
+///
+/// It provides a [done] future, which will complete once there are no more
+/// nodes left in the states Initialized/Waiting/Enqueing/Processing
+/// and the [executor] has cleaned up it's resources.
+class CommandQueue {
+  final Graph<Command> graph;
+  final CommandExecutor executor;
+  final TestCaseEnqueuer enqueuer;
+
+  final _runQueue = Queue<Command>();
+  final _commandOutputStream = StreamController<CommandOutput>(sync: true);
+  final _completer = Completer<Null>();
+
+  int _numProcesses = 0;
+  int _maxProcesses;
+  int _numBrowserProcesses = 0;
+  int _maxBrowserProcesses;
+  bool _finishing = false;
+  bool _verbose = false;
+
+  CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses,
+      this._maxBrowserProcesses, this._verbose) {
+    graph.changed.listen((event) {
+      if (event.to == NodeState.enqueuing) {
+        assert(event.from == NodeState.initialized ||
+            event.from == NodeState.waiting);
+        graph.changeState(event.node, NodeState.processing);
+        var command = event.node.data;
+        if (event.node.dependencies.isNotEmpty) {
+          _runQueue.addFirst(command);
+        } else {
+          _runQueue.add(command);
+        }
+        Timer.run(() => _tryRunNextCommand());
+      } else if (event.to == NodeState.unableToRun) {
+        _checkDone();
+      }
+    });
+
+    // We're finished if the graph is sealed and all nodes are in a finished
+    // state (Successful, Failed or UnableToRun).
+    // So we're calling '_checkDone()' to check whether that condition is met
+    // and we can cleanup.
+    graph.sealed.listen((event) {
+      _checkDone();
+    });
+  }
+
+  Stream<CommandOutput> get completedCommands => _commandOutputStream.stream;
+
+  Future get done => _completer.future;
+
+  void _tryRunNextCommand() {
+    _checkDone();
+
+    if (_numProcesses < _maxProcesses && !_runQueue.isEmpty) {
+      Command command = _runQueue.removeFirst();
+      var isBrowserCommand = command is BrowserTestCommand;
+
+      if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) {
+        // If there is no free browser runner, put it back into the queue.
+        _runQueue.add(command);
+        // Don't lose a process.
+        Timer(Duration(milliseconds: 100), _tryRunNextCommand);
+        return;
+      }
+
+      _numProcesses++;
+      if (isBrowserCommand) _numBrowserProcesses++;
+
+      var node = enqueuer.command2node[command];
+      Iterable<TestCase> testCases = enqueuer.command2testCases[command];
+      // If a command is part of many TestCases we set the timeout to be
+      // the maximum over all [TestCase.timeout]s. At some point, we might
+      // eliminate [TestCase.timeout] completely and move it to [Command].
+      int timeout = testCases
+          .map((TestCase test) => test.timeout)
+          .fold(0, (int a, b) => math.max(a, b));
+
+      if (_verbose) {
+        print('Running "${command.displayName}" command: $command');
+      }
+
+      executor.runCommand(node, command, timeout).then((CommandOutput output) {
+        assert(command == output.command);
+
+        _commandOutputStream.add(output);
+        if (output.canRunDependendCommands) {
+          graph.changeState(node, NodeState.successful);
+        } else {
+          graph.changeState(node, NodeState.failed);
+        }
+
+        _numProcesses--;
+        if (isBrowserCommand) _numBrowserProcesses--;
+
+        // Don't lose a process
+        Timer.run(() => _tryRunNextCommand());
+      });
+    }
+  }
+
+  void _checkDone() {
+    if (!_finishing &&
+        _runQueue.isEmpty &&
+        _numProcesses == 0 &&
+        graph.isSealed &&
+        graph.stateCount(NodeState.initialized) == 0 &&
+        graph.stateCount(NodeState.waiting) == 0 &&
+        graph.stateCount(NodeState.enqueuing) == 0 &&
+        graph.stateCount(NodeState.processing) == 0) {
+      _finishing = true;
+      executor.cleanup().then((_) {
+        _completer.complete();
+        _commandOutputStream.close();
+      });
+    }
+  }
+
+  void dumpState() {
+    print("");
+    print("CommandQueue state:");
+    print("  Processes: used: $_numProcesses max: $_maxProcesses");
+    print("  BrowserProcesses: used: $_numBrowserProcesses "
+        "max: $_maxBrowserProcesses");
+    print("  Finishing: $_finishing");
+    print("  Queue (length = ${_runQueue.length}):");
+    for (var command in _runQueue) {
+      print("      $command");
+    }
+  }
+}
+
+/// [CommandExecutor] is responsible for executing commands. It will make sure
+/// that the following two constraints are satisfied
+///  - `numberOfProcessesUsed <= maxProcesses`
+///  - `numberOfBrowserProcessesUsed <= maxBrowserProcesses`
+///
+/// It provides a [runCommand] method which will complete with a
+/// [CommandOutput] object.
+///
+/// It provides a [cleanup] method to free all the allocated resources.
+abstract class CommandExecutor {
+  Future cleanup();
+  // TODO(kustermann): The [timeout] parameter should be a property of Command.
+  Future<CommandOutput> runCommand(
+      Node<Command> node, covariant Command command, int timeout);
+}
+
+class CommandExecutorImpl implements CommandExecutor {
+  final TestConfiguration globalConfiguration;
+  final int maxProcesses;
+  final int maxBrowserProcesses;
+  AdbDevicePool adbDevicePool;
+
+  /// For dart2js and analyzer batch processing,
+  /// we keep a list of batch processes.
+  final _batchProcesses = <String, List<BatchRunnerProcess>>{};
+
+  /// We keep a BrowserTestRunner for every configuration.
+  final _browserTestRunners = <TestConfiguration, BrowserTestRunner>{};
+
+  bool _finishing = false;
+
+  CommandExecutorImpl(
+      this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses,
+      {this.adbDevicePool});
+
+  Future cleanup() {
+    assert(!_finishing);
+    _finishing = true;
+
+    Future _terminateBatchRunners() {
+      var futures = <Future>[];
+      for (var runners in _batchProcesses.values) {
+        futures.addAll(runners.map((runner) => runner.terminate()));
+      }
+      return Future.wait(futures);
+    }
+
+    Future _terminateBrowserRunners() {
+      var futures =
+          _browserTestRunners.values.map((runner) => runner.terminate());
+      return Future.wait(futures);
+    }
+
+    return Future.wait([
+      _terminateBatchRunners(),
+      _terminateBrowserRunners(),
+    ]);
+  }
+
+  Future<CommandOutput> runCommand(node, Command command, int timeout) {
+    assert(!_finishing);
+
+    Future<CommandOutput> runCommand(int retriesLeft) {
+      return _runCommand(command, timeout).then((CommandOutput output) {
+        if (retriesLeft > 0 && shouldRetryCommand(output)) {
+          DebugLogger.warning("Rerunning Command: ($retriesLeft "
+              "attempt(s) remains) [cmd: $command]");
+          return runCommand(retriesLeft - 1);
+        } else {
+          return Future.value(output);
+        }
+      });
+    }
+
+    return runCommand(command.maxNumRetries);
+  }
+
+  Future<CommandOutput> _runCommand(Command command, int timeout) {
+    if (command is BrowserTestCommand) {
+      return _startBrowserControllerTest(command, timeout);
+    } else if (command is VMKernelCompilationCommand) {
+      // For now, we always run vm_compile_to_kernel in batch mode.
+      var name = command.displayName;
+      assert(name == 'vm_compile_to_kernel');
+      return _getBatchRunner(name)
+          .runCommand(name, command, timeout, command.arguments);
+    } else if (command is CompilationCommand &&
+        globalConfiguration.batchDart2JS &&
+        command.displayName == 'dart2js') {
+      return _getBatchRunner("dart2js")
+          .runCommand("dart2js", command, timeout, command.arguments);
+    } else if (command is AnalysisCommand && globalConfiguration.batch) {
+      return _getBatchRunner(command.displayName)
+          .runCommand(command.displayName, command, timeout, command.arguments);
+    } else if (command is CompilationCommand &&
+        (command.displayName == 'dartdevc' ||
+            command.displayName == 'dartdevk' ||
+            command.displayName == 'fasta') &&
+        globalConfiguration.batch) {
+      return _getBatchRunner(command.displayName)
+          .runCommand(command.displayName, command, timeout, command.arguments);
+    } else if (command is ScriptCommand) {
+      return command.run();
+    } else if (command is AdbPrecompilationCommand ||
+        command is AdbDartkCommand) {
+      assert(adbDevicePool != null);
+      return adbDevicePool.acquireDevice().then((AdbDevice device) async {
+        try {
+          if (command is AdbPrecompilationCommand) {
+            return await _runAdbPrecompilationCommand(device, command, timeout);
+          } else {
+            return await _runAdbDartkCommand(
+                device, command as AdbDartkCommand, timeout);
+          }
+        } finally {
+          await adbDevicePool.releaseDevice(device);
+        }
+      });
+    } else if (command is VmBatchCommand) {
+      var name = command.displayName;
+      return _getBatchRunner(command.displayName + command.dartFile)
+          .runCommand(name, command, timeout, command.arguments);
+    } else if (command is CompilationCommand &&
+        command.displayName == 'babel') {
+      return RunningProcess(command, timeout,
+              configuration: globalConfiguration,
+              outputFile: io.File(command.outputFile))
+          .run();
+    } else if (command is ProcessCommand) {
+      return RunningProcess(command, timeout,
+              configuration: globalConfiguration)
+          .run();
+    } else {
+      throw ArgumentError("Unknown command type ${command.runtimeType}.");
+    }
+  }
+
+  Future<CommandOutput> _runAdbPrecompilationCommand(
+      AdbDevice device, AdbPrecompilationCommand command, int timeout) async {
+    var runner = command.precompiledRunnerFilename;
+    var processTest = command.processTestFilename;
+    var testdir = command.precompiledTestDirectory;
+    var arguments = command.arguments;
+    var devicedir = DartPrecompiledAdbRuntimeConfiguration.DeviceDir;
+    var deviceTestDir = DartPrecompiledAdbRuntimeConfiguration.DeviceTestDir;
+
+    // We copy all the files which the vm precompiler puts into the test
+    // directory.
+    List<String> files = io.Directory(testdir)
+        .listSync()
+        .map((file) => file.path)
+        .map((path) => path.substring(path.lastIndexOf('/') + 1))
+        .toList();
+
+    var timeoutDuration = Duration(seconds: timeout);
+
+    var steps = <_StepFunction>[];
+
+    steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir]));
+    steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir]));
+    steps.add(() =>
+        device.pushCachedData(runner, '$devicedir/dart_precompiled_runtime'));
+    steps.add(
+        () => device.pushCachedData(processTest, '$devicedir/process_test'));
+    steps.add(() => device.runAdbShellCommand([
+          'chmod',
+          '777',
+          '$devicedir/dart_precompiled_runtime $devicedir/process_test'
+        ]));
+
+    for (var file in files) {
+      steps.add(() => device
+          .runAdbCommand(['push', '$testdir/$file', '$deviceTestDir/$file']));
+    }
+
+    steps.add(() => device.runAdbShellCommand(
+        [
+          '$devicedir/dart_precompiled_runtime',
+        ]..addAll(arguments),
+        timeout: timeoutDuration));
+
+    var stopwatch = Stopwatch()..start();
+    var writer = StringBuffer();
+
+    await device.waitForBootCompleted();
+    await device.waitForDevice();
+
+    AdbCommandResult result;
+    for (var i = 0; i < steps.length; i++) {
+      var fun = steps[i];
+      var commandStopwatch = Stopwatch()..start();
+      result = await fun();
+
+      writer.writeln("Executing ${result.command}");
+      if (result.stdout.isNotEmpty) {
+        writer.writeln("Stdout:\n${result.stdout.trim()}");
+      }
+      if (result.stderr.isNotEmpty) {
+        writer.writeln("Stderr:\n${result.stderr.trim()}");
+      }
+      writer.writeln("ExitCode: ${result.exitCode}");
+      writer.writeln("Time: ${commandStopwatch.elapsed}");
+      writer.writeln("");
+
+      // If one command fails, we stop processing the others and return
+      // immediately.
+      if (result.exitCode != 0) break;
+    }
+    return createCommandOutput(command, result.exitCode, result.timedOut,
+        utf8.encode('$writer'), [], stopwatch.elapsed, false);
+  }
+
+  Future<CommandOutput> _runAdbDartkCommand(
+      AdbDevice device, AdbDartkCommand command, int timeout) async {
+    final String buildPath = command.buildPath;
+    final String hostKernelFile = command.kernelFile;
+    final List<String> arguments = command.arguments;
+    final String devicedir = DartkAdbRuntimeConfiguration.DeviceDir;
+    final String deviceTestDir = DartkAdbRuntimeConfiguration.DeviceTestDir;
+
+    final timeoutDuration = Duration(seconds: timeout);
+
+    final steps = <_StepFunction>[];
+
+    steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir]));
+    steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir]));
+    steps.add(
+        () => device.pushCachedData("${buildPath}/dart", '$devicedir/dart'));
+    steps.add(() => device
+        .runAdbCommand(['push', hostKernelFile, '$deviceTestDir/out.dill']));
+
+    for (var lib in command.extraLibraries) {
+      var libName = "lib${lib}.so";
+      steps.add(() => device.runAdbCommand(
+          ['push', '${buildPath}/$libName', '$deviceTestDir/$libName']));
+    }
+
+    steps.add(() => device.runAdbShellCommand(
+        [
+          'export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$deviceTestDir;'
+              '$devicedir/dart',
+        ]..addAll(arguments),
+        timeout: timeoutDuration));
+
+    var stopwatch = Stopwatch()..start();
+    var writer = StringBuffer();
+
+    await device.waitForBootCompleted();
+    await device.waitForDevice();
+
+    AdbCommandResult result;
+    for (var i = 0; i < steps.length; i++) {
+      var step = steps[i];
+      var commandStopwatch = Stopwatch()..start();
+      result = await step();
+
+      writer.writeln("Executing ${result.command}");
+      if (result.stdout.isNotEmpty) {
+        writer.writeln("Stdout:\n${result.stdout.trim()}");
+      }
+      if (result.stderr.isNotEmpty) {
+        writer.writeln("Stderr:\n${result.stderr.trim()}");
+      }
+      writer.writeln("ExitCode: ${result.exitCode}");
+      writer.writeln("Time: ${commandStopwatch.elapsed}");
+      writer.writeln("");
+
+      // If one command fails, we stop processing the others and return
+      // immediately.
+      if (result.exitCode != 0) break;
+    }
+    return createCommandOutput(command, result.exitCode, result.timedOut,
+        utf8.encode('$writer'), [], stopwatch.elapsed, false);
+  }
+
+  BatchRunnerProcess _getBatchRunner(String identifier) {
+    // Start batch processes if needed.
+    var runners = _batchProcesses[identifier];
+    if (runners == null) {
+      runners = List<BatchRunnerProcess>(maxProcesses);
+      for (int i = 0; i < maxProcesses; i++) {
+        runners[i] = BatchRunnerProcess(useJson: identifier == "fasta");
+      }
+      _batchProcesses[identifier] = runners;
+    }
+
+    for (var runner in runners) {
+      if (!runner._currentlyRunning) return runner;
+    }
+    throw Exception('Unable to find inactive batch runner.');
+  }
+
+  Future<CommandOutput> _startBrowserControllerTest(
+      BrowserTestCommand browserCommand, int timeout) {
+    var completer = Completer<CommandOutput>();
+
+    var callback = (BrowserTestOutput output) {
+      completer.complete(BrowserCommandOutput(browserCommand, output));
+    };
+
+    var browserTest = BrowserTest(browserCommand.url, callback, timeout);
+    _getBrowserTestRunner(browserCommand.configuration).then((testRunner) {
+      testRunner.enqueueTest(browserTest);
+    });
+
+    return completer.future;
+  }
+
+  Future<BrowserTestRunner> _getBrowserTestRunner(
+      TestConfiguration configuration) async {
+    if (_browserTestRunners[configuration] == null) {
+      var testRunner = BrowserTestRunner(
+          configuration, globalConfiguration.localIP, maxBrowserProcesses);
+      if (globalConfiguration.isVerbose) {
+        testRunner.logger = DebugLogger.info;
+      }
+      _browserTestRunners[configuration] = testRunner;
+      await testRunner.start();
+    }
+    return _browserTestRunners[configuration];
+  }
+}
+
+bool shouldRetryCommand(CommandOutput output) {
+  if (!output.successful) {
+    List<String> stdout, stderr;
+
+    decodeOutput() {
+      if (stdout == null && stderr == null) {
+        stdout = decodeUtf8(output.stderr).split("\n");
+        stderr = decodeUtf8(output.stderr).split("\n");
+      }
+    }
+
+    final command = output.command;
+
+    // The dartk batch compiler sometimes runs out of memory. In such a case we
+    // will retry running it.
+    if (command is VMKernelCompilationCommand) {
+      if (output.hasCrashed) {
+        bool containsOutOfMemoryMessage(String line) {
+          return line.contains('Exhausted heap space, trying to allocat');
+        }
+
+        decodeOutput();
+        if (stdout.any(containsOutOfMemoryMessage) ||
+            stderr.any(containsOutOfMemoryMessage)) {
+          return true;
+        }
+      }
+    }
+
+    if (io.Platform.operatingSystem == 'linux') {
+      decodeOutput();
+      // No matter which command we ran: If we get failures due to the
+      // "xvfb-run" issue 7564, try re-running the test.
+      bool containsFailureMsg(String line) {
+        return line.contains(_cannotOpenDisplayMessage) ||
+            line.contains(_failedToRunCommandMessage);
+      }
+
+      if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+/// [TestCaseCompleter] will listen for
+/// NodeState.processing -> NodeState.{successful,failed} state changes and
+/// will complete a TestCase if it is finished.
+///
+/// It provides a stream [finishedTestCases], which will stream all TestCases
+/// once they're finished. After all TestCases are done, the stream will be
+/// closed.
+class TestCaseCompleter {
+  static const _completedStates = [NodeState.failed, NodeState.successful];
+
+  final Graph<Command> _graph;
+  final TestCaseEnqueuer _enqueuer;
+  final CommandQueue _commandQueue;
+
+  final Map<Command, CommandOutput> _outputs = {};
+  final StreamController<TestCase> _controller = StreamController();
+  bool _closed = false;
+
+  TestCaseCompleter(this._graph, this._enqueuer, this._commandQueue) {
+    var finishedRemainingTestCases = false;
+
+    // Store all the command outputs -- they will be delivered synchronously
+    // (i.e. before state changes in the graph)
+    _commandQueue.completedCommands.listen((CommandOutput output) {
+      _outputs[output.command] = output;
+    }, onDone: () {
+      _completeTestCasesIfPossible(List.from(_enqueuer.remainingTestCases));
+      finishedRemainingTestCases = true;
+      assert(_enqueuer.remainingTestCases.isEmpty);
+      _checkDone();
+    });
+
+    // Listen for NodeState.Processing -> NodeState.{Successful,Failed}
+    // changes.
+    _graph.changed.listen((event) {
+      if (event.from == NodeState.processing && !finishedRemainingTestCases) {
+        var command = event.node.data;
+
+        assert(_completedStates.contains(event.to));
+        assert(_outputs[command] != null);
+
+        _completeTestCasesIfPossible(_enqueuer.command2testCases[command]);
+        _checkDone();
+      }
+    });
+
+    // Listen also for GraphSealedEvents. If there is not a single node in the
+    // graph, we still want to finish after the graph was sealed.
+    _graph.sealed.listen((_) {
+      if (!_closed && _enqueuer.remainingTestCases.isEmpty) {
+        _controller.close();
+        _closed = true;
+      }
+    });
+  }
+
+  Stream<TestCase> get finishedTestCases => _controller.stream;
+
+  void _checkDone() {
+    if (!_closed && _graph.isSealed && _enqueuer.remainingTestCases.isEmpty) {
+      _controller.close();
+      _closed = true;
+    }
+  }
+
+  void _completeTestCasesIfPossible(Iterable<TestCase> testCases) {
+    // Update TestCases with command outputs.
+    for (TestCase test in testCases) {
+      for (var icommand in test.commands) {
+        var output = _outputs[icommand];
+        if (output != null) {
+          test.commandOutputs[icommand] = output;
+        }
+      }
+    }
+
+    void completeTestCase(TestCase testCase) {
+      if (_enqueuer.remainingTestCases.contains(testCase)) {
+        _controller.add(testCase);
+        _enqueuer.remainingTestCases.remove(testCase);
+      } else {
+        DebugLogger.error("${testCase.displayName} would be finished twice");
+      }
+    }
+
+    for (var testCase in testCases) {
+      // Ask the [testCase] if it's done. Note that we assume, that
+      // [TestCase.isFinished] will return true if all commands were executed
+      // or if a previous one failed.
+      if (testCase.isFinished) {
+        completeTestCase(testCase);
+      }
+    }
+  }
+}
+
+class BatchRunnerProcess {
+  /// When true, the command line is passed to the test runner as a
+  /// JSON-encoded list of strings.
+  final bool _useJson;
+
+  Completer<CommandOutput> _completer;
+  ProcessCommand _command;
+  List<String> _arguments;
+  String _runnerType;
+
+  io.Process _process;
+  Map<String, String> _processEnvironmentOverrides;
+  Completer<Null> _stdoutCompleter;
+  Completer<Null> _stderrCompleter;
+  StreamSubscription<String> _stdoutSubscription;
+  StreamSubscription<String> _stderrSubscription;
+  Function _processExitHandler;
+
+  bool _currentlyRunning = false;
+  OutputLog _testStdout;
+  OutputLog _testStderr;
+  String _status;
+  DateTime _startTime;
+  Timer _timer;
+  int _testCount = 0;
+
+  BatchRunnerProcess({bool useJson = true}) : _useJson = useJson;
+
+  Future<CommandOutput> runCommand(String runnerType, ProcessCommand command,
+      int timeout, List<String> arguments) {
+    assert(_completer == null);
+    assert(!_currentlyRunning);
+
+    _completer = Completer();
+    bool sameRunnerType = _runnerType == runnerType &&
+        _dictEquals(_processEnvironmentOverrides, command.environmentOverrides);
+    _runnerType = runnerType;
+    _currentlyRunning = true;
+    _command = command;
+    _arguments = arguments;
+    _processEnvironmentOverrides = command.environmentOverrides;
+
+    // TOOD(jmesserly): this restarts `dartdevc --batch` to work around a
+    // memory leak, see https://github.com/dart-lang/sdk/issues/30314.
+    var clearMemoryLeak = command is CompilationCommand &&
+        command.displayName == 'dartdevc' &&
+        ++_testCount % 100 == 0;
+    if (_process == null) {
+      // Start process if not yet started.
+      _startProcess(() {
+        doStartTest(command, timeout);
+      });
+    } else if (!sameRunnerType || clearMemoryLeak) {
+      // Restart this runner with the right executable for this test if needed.
+      _processExitHandler = (_) {
+        _startProcess(() {
+          doStartTest(command, timeout);
+        });
+      };
+      _process.kill();
+      _stdoutSubscription.cancel();
+      _stderrSubscription.cancel();
+    } else {
+      doStartTest(command, timeout);
+    }
+    return _completer.future;
+  }
+
+  Future<bool> terminate() {
+    if (_process == null) return Future.value(true);
+    var terminateCompleter = Completer<bool>();
+    _processExitHandler = (_) {
+      terminateCompleter.complete(true);
+    };
+    _process.kill();
+    _stdoutSubscription.cancel();
+    _stderrSubscription.cancel();
+
+    return terminateCompleter.future;
+  }
+
+  void doStartTest(Command command, int timeout) {
+    _startTime = DateTime.now();
+    _testStdout = OutputLog();
+    _testStderr = OutputLog();
+    _status = null;
+    _stdoutCompleter = Completer();
+    _stderrCompleter = Completer();
+    _timer = Timer(Duration(seconds: timeout), _timeoutHandler);
+
+    var line = _createArgumentsLine(_arguments, timeout);
+    _process.stdin.write(line);
+    _stdoutSubscription.resume();
+    _stderrSubscription.resume();
+    Future.wait([_stdoutCompleter.future, _stderrCompleter.future])
+        .then((_) => _reportResult());
+  }
+
+  String _createArgumentsLine(List<String> arguments, int timeout) {
+    if (_useJson) {
+      return "${jsonEncode(arguments)}\n";
+    } else {
+      return arguments.join(' ') + '\n';
+    }
+  }
+
+  void _reportResult() {
+    if (!_currentlyRunning) return;
+
+    var outcome = _status.split(" ")[2];
+    var exitCode = 0;
+    if (outcome == "CRASH") exitCode = unhandledCompilerExceptionExitCode;
+    if (outcome == "PARSE_FAIL") exitCode = parseFailExitCode;
+    if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
+    var output = createCommandOutput(
+        _command,
+        exitCode,
+        (outcome == "TIMEOUT"),
+        _testStdout.toList(),
+        _testStderr.toList(),
+        DateTime.now().difference(_startTime),
+        false);
+    assert(_completer != null);
+    _completer.complete(output);
+    _completer = null;
+    _currentlyRunning = false;
+  }
+
+  void Function(int) makeExitHandler(String status) {
+    return (int exitCode) {
+      if (_currentlyRunning) {
+        if (_timer != null) _timer.cancel();
+        _status = status;
+        _stdoutSubscription.cancel();
+        _stderrSubscription.cancel();
+        _startProcess(_reportResult);
+      } else {
+        // No active test case running.
+        _process = null;
+      }
+    };
+  }
+
+  void _timeoutHandler() {
+    _processExitHandler = makeExitHandler(">>> TEST TIMEOUT");
+    _process.kill();
+  }
+
+  void _startProcess(void Function() callback) {
+    assert(_command is ProcessCommand);
+    var executable = _command.executable;
+    var arguments = _command.batchArguments.toList();
+    arguments.add('--batch');
+    var environment = Map<String, String>.from(io.Platform.environment);
+    if (_processEnvironmentOverrides != null) {
+      for (var key in _processEnvironmentOverrides.keys) {
+        environment[key] = _processEnvironmentOverrides[key];
+      }
+    }
+    var processFuture =
+        io.Process.start(executable, arguments, environment: environment);
+    processFuture.then((io.Process p) {
+      _process = p;
+
+      Stream<String> _stdoutStream =
+          _process.stdout.transform(utf8.decoder).transform(LineSplitter());
+      _stdoutSubscription = _stdoutStream.listen((String line) {
+        if (line.startsWith('>>> TEST')) {
+          _status = line;
+        } else if (line.startsWith('>>> BATCH')) {
+          // ignore
+        } else if (line.startsWith('>>> ')) {
+          throw Exception("Unexpected command from batch runner: '$line'.");
+        } else {
+          _testStdout.add(encodeUtf8(line));
+          _testStdout.add("\n".codeUnits);
+        }
+        if (_status != null) {
+          _stdoutSubscription.pause();
+          _timer.cancel();
+          _stdoutCompleter.complete(null);
+        }
+      });
+      _stdoutSubscription.pause();
+
+      Stream<String> _stderrStream =
+          _process.stderr.transform(utf8.decoder).transform(LineSplitter());
+      _stderrSubscription = _stderrStream.listen((String line) {
+        if (line.startsWith('>>> EOF STDERR')) {
+          _stderrSubscription.pause();
+          _stderrCompleter.complete(null);
+        } else {
+          _testStderr.add(encodeUtf8(line));
+          _testStderr.add("\n".codeUnits);
+        }
+      });
+      _stderrSubscription.pause();
+
+      _processExitHandler = makeExitHandler(">>> TEST CRASH");
+      _process.exitCode.then((exitCode) {
+        _processExitHandler(exitCode);
+      });
+
+      _process.stdin.done.catchError((err) {
+        print('Error on batch runner input stream stdin');
+        print('  Previous test\'s status: $_status');
+        print('  Error: $err');
+        throw err;
+      });
+      callback();
+    }).catchError((e) {
+      // TODO(floitsch): should we try to report the stacktrace?
+      print("Process error:");
+      print("  Command: $executable ${arguments.join(' ')} ($_arguments)");
+      print("  Error: $e");
+      // If there is an error starting a batch process, chances are that
+      // it will always fail. So rather than re-trying a 1000+ times, we
+      // exit.
+      io.exit(1);
+      return true;
+    });
+  }
+
+  bool _dictEquals(Map a, Map b) {
+    if (a == null) return b == null;
+    if (b == null) return false;
+    if (a.length != b.length) return false;
+    for (var key in a.keys) {
+      if (a[key] != b[key]) return false;
+    }
+    return true;
+  }
+}
diff --git a/pkg/test_runner/lib/src/repository.dart b/pkg/test_runner/lib/src/repository.dart
index 18ea378..79687fb 100644
--- a/pkg/test_runner/lib/src/repository.dart
+++ b/pkg/test_runner/lib/src/repository.dart
@@ -8,7 +8,7 @@
 /// Provides information about the surrounding Dart repository.
 class Repository {
   /// File path pointing to the root directory of the Dart checkout.
-  static Path get dir => new Path(uri.toFilePath());
+  static Path get dir => Path(uri.toFilePath());
 
   /// The URI pointing to the root of the Dart checkout.
   ///
diff --git a/pkg/test_runner/lib/src/reset_safari.dart b/pkg/test_runner/lib/src/reset_safari.dart
index 07cefdf..3084518 100644
--- a/pkg/test_runner/lib/src/reset_safari.dart
+++ b/pkg/test_runner/lib/src/reset_safari.dart
@@ -34,7 +34,7 @@
   "Library/Preferences/$safari.plist",
 ];
 
-const Duration defaultPollDelay = const Duration(milliseconds: 1);
+const Duration defaultPollDelay = Duration(milliseconds: 1);
 
 final String cpgi = "$safari.ContentPageGroupIdentifier";
 
@@ -97,12 +97,12 @@
 }
 ''';
 
-Future<Null> get pollDelay => new Future.delayed(defaultPollDelay);
+Future<Null> get pollDelay => Future.delayed(defaultPollDelay);
 
 String signalArgument(String defaultSignal,
-    {bool force: false, bool testOnly: false}) {
+    {bool force = false, bool testOnly = false}) {
   if (force && testOnly) {
-    throw new ArgumentError("[force] and [testOnly] can't both be true.");
+    throw ArgumentError("[force] and [testOnly] can't both be true.");
   }
   if (force) return "-KILL";
   if (testOnly) return "-0";
@@ -110,7 +110,7 @@
 }
 
 Future<int> kill(List<String> pids,
-    {bool force: false, bool testOnly: false}) async {
+    {bool force = false, bool testOnly = false}) async {
   var arguments = [signalArgument("-TERM", force: force, testOnly: testOnly)]
     ..addAll(pids);
   var result = await Process.run(killLocation, arguments);
@@ -118,7 +118,7 @@
 }
 
 Future<int> pkill(String pattern,
-    {bool force: false, bool testOnly: false}) async {
+    {bool force = false, bool testOnly = false}) async {
   var arguments = [
     signalArgument("-HUP", force: force, testOnly: testOnly),
     pattern
@@ -130,7 +130,7 @@
 Uri validatedBundleName(Uri bundle) {
   if (bundle == null) return Uri.base.resolve(defaultSafariBundleLocation);
   if (!bundle.path.endsWith("/")) {
-    throw new ArgumentError("Bundle ('$bundle') must end with a slash ('/').");
+    throw ArgumentError("Bundle ('$bundle') must end with a slash ('/').");
   }
   return bundle;
 }
@@ -144,7 +144,7 @@
     var stdout = result.stdout as String;
     var pids =
         stdout.split("\n").where((String line) => !line.isEmpty).toList();
-    var timer = new Timer(const Duration(seconds: 10), () {
+    var timer = Timer(const Duration(seconds: 10), () {
       print("Kill -9 Safari $pids");
       kill(pids, force: true);
     });
@@ -156,7 +156,7 @@
     }
     timer.cancel();
   }
-  var timer = new Timer(const Duration(seconds: 10), () {
+  var timer = Timer(const Duration(seconds: 10), () {
     print("Kill -9 $safari");
     pkill(safari, force: true);
   });
@@ -170,12 +170,12 @@
 }
 
 Future<Null> deleteIfExists(Uri uri) async {
-  var directory = new Directory.fromUri(uri);
+  var directory = Directory.fromUri(uri);
   if (await directory.exists()) {
     print("Deleting directory '$uri'.");
     await directory.delete(recursive: true);
   } else {
-    var file = new File.fromUri(uri);
+    var file = File.fromUri(uri);
     if (await file.exists()) {
       print("Deleting file '$uri'.");
       await file.delete();
diff --git a/pkg/test_runner/lib/src/runtime_configuration.dart b/pkg/test_runner/lib/src/runtime_configuration.dart
index 38c10b1..16690f8 100644
--- a/pkg/test_runner/lib/src/runtime_configuration.dart
+++ b/pkg/test_runner/lib/src/runtime_configuration.dart
@@ -28,31 +28,31 @@
       case Runtime.ie9:
       case Runtime.safari:
         // TODO(ahe): Replace this with one or more browser runtimes.
-        return new DummyRuntimeConfiguration();
+        return DummyRuntimeConfiguration();
 
       case Runtime.jsshell:
-        return new JsshellRuntimeConfiguration();
+        return JsshellRuntimeConfiguration();
 
       case Runtime.d8:
-        return new D8RuntimeConfiguration();
+        return D8RuntimeConfiguration();
 
       case Runtime.none:
-        return new NoneRuntimeConfiguration();
+        return NoneRuntimeConfiguration();
 
       case Runtime.vm:
         if (configuration.system == System.android) {
-          return new DartkAdbRuntimeConfiguration();
+          return DartkAdbRuntimeConfiguration();
         }
-        return new StandaloneDartRuntimeConfiguration();
+        return StandaloneDartRuntimeConfiguration();
 
       case Runtime.dartPrecompiled:
         if (configuration.system == System.android) {
-          return new DartPrecompiledAdbRuntimeConfiguration(
+          return DartPrecompiledAdbRuntimeConfiguration(
             useBlobs: configuration.useBlobs,
             useElf: configuration.useElf,
           );
         } else {
-          return new DartPrecompiledRuntimeConfiguration(
+          return DartPrecompiledRuntimeConfiguration(
             useBlobs: configuration.useBlobs,
             useElf: configuration.useElf,
           );
@@ -60,7 +60,7 @@
         break;
 
       case Runtime.selfCheck:
-        return new SelfCheckRuntimeConfiguration();
+        return SelfCheckRuntimeConfiguration();
     }
     throw "unreachable";
   }
@@ -73,8 +73,8 @@
 
   int timeoutMultiplier(
       {Mode mode,
-      bool isChecked: false,
-      bool isReload: false,
+      bool isChecked = false,
+      bool isReload = false,
       Architecture arch}) {
     return 1;
   }
@@ -89,9 +89,7 @@
     throw "Unimplemented runtime '$runtimeType'";
   }
 
-  /**
-   * The output directory for this suite's configuration.
-   */
+  /// The output directory for this suite's configuration.
   String get buildDir => _configuration.buildDirectory;
 
   List<String> dart2jsPreambles(Uri preambleDir) => [];
@@ -237,8 +235,8 @@
 
   int timeoutMultiplier(
       {Mode mode,
-      bool isChecked: false,
-      bool isReload: false,
+      bool isChecked = false,
+      bool isReload = false,
       Architecture arch}) {
     var multiplier = 1;
 
@@ -389,7 +387,7 @@
 
   void searchForSelfCheckers() {
     Uri pkg = Repository.uri.resolve('pkg');
-    for (var entry in new Directory.fromUri(pkg).listSync(recursive: true)) {
+    for (var entry in Directory.fromUri(pkg).listSync(recursive: true)) {
       if (entry is File && entry.path.endsWith('_self_check.dart')) {
         selfCheckers.add(entry.path);
       }
diff --git a/pkg/test_runner/lib/src/status_reporter.dart b/pkg/test_runner/lib/src/status_reporter.dart
index 1a0d7ae..b8b4d78 100644
--- a/pkg/test_runner/lib/src/status_reporter.dart
+++ b/pkg/test_runner/lib/src/status_reporter.dart
@@ -84,13 +84,13 @@
   if (result.exitCode != 0) {
     print('ERROR');
     print(result.stderr);
-    throw new Exception('Error while building.');
+    throw Exception('Error while building.');
   }
   print('Done building.');
 }
 
 void sanityCheck(String output) {
-  var splitter = new LineSplitter();
+  var splitter = LineSplitter();
   var lines = splitter.convert(output);
   // Looks like this:
   // Total: 15556 tests
@@ -104,16 +104,15 @@
   }
   if (count != total) {
     print('Count: $count, total: $total');
-    throw new Exception(
-        'Count and total do not align. Please validate manually.');
+    throw Exception('Count and total do not align. Please validate manually.');
   }
 }
 
 void main(List<String> args) {
   var combinations = _combinations[Platform.operatingSystem];
 
-  var arches = new Set<String>();
-  var modes = new Set<String>();
+  var arches = <String>{};
+  var modes = <String>{};
 
   if (args.contains('--simple')) {
     arches = ['ia32'].toSet();
@@ -155,7 +154,7 @@
           if (result.exitCode != 0) {
             print(result.stdout);
             print(result.stderr);
-            throw new Exception("Error running: ${args.join(" ")}");
+            throw Exception("Error running: ${args.join(" ")}");
           }
 
           // Find "JSON:"
diff --git a/pkg/test_runner/lib/src/summary_report.dart b/pkg/test_runner/lib/src/summary_report.dart
index fc0f787..6db17f7 100644
--- a/pkg/test_runner/lib/src/summary_report.dart
+++ b/pkg/test_runner/lib/src/summary_report.dart
@@ -8,7 +8,7 @@
 
 import "test_case.dart";
 
-final summaryReport = new SummaryReport();
+final summaryReport = SummaryReport();
 
 class SummaryReport {
   int _total = 0;
diff --git a/pkg/test_runner/lib/src/test_case.dart b/pkg/test_runner/lib/src/test_case.dart
index bbe9a68..6d1aa4e 100644
--- a/pkg/test_runner/lib/src/test_case.dart
+++ b/pkg/test_runner/lib/src/test_case.dart
@@ -1,54 +1,30 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2019, 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.
 
-/**
- * Classes and methods for executing tests.
- *
- * This module includes:
- * - Managing parallel execution of tests, including timeout checks.
- * - Evaluating the output of each test as pass/fail/crash/timeout.
- */
 import 'dart:async';
-import 'dart:collection';
-import 'dart:convert';
 // We need to use the 'io' prefix here, otherwise io.exitCode will shadow
 // CommandOutput.exitCode in subclasses of CommandOutput.
 import 'dart:io' as io;
-import 'dart:math' as math;
 
 import "package:status_file/expectation.dart";
 
-import 'android.dart';
-import 'browser_controller.dart';
 import 'command.dart';
 import 'command_output.dart';
 import 'configuration.dart';
-import 'dependency_graph.dart';
+import 'output_log.dart';
+import 'process_queue.dart';
 import 'repository.dart';
-import 'runtime_configuration.dart';
-import 'test_progress.dart';
 import 'test_suite.dart';
 import 'utils.dart';
 
-const int unhandledCompilerExceptionExitCode = 253;
-const int parseFailExitCode = 245;
-const int slowTimeoutMultiplier = 4;
-const int extraSlowTimeoutMultiplier = 8;
-const int nonUtfFakeExitCode = 0xFFFD;
-
-const cannotOpenDisplayMessage = 'Gtk-WARNING **: cannot open display';
-const failedToRunCommandMessage = 'Failed to run command. return code=1';
-
-typedef void TestCaseEvent(TestCase testCase);
-typedef void ExitCodeEvent(int exitCode);
-typedef void EnqueueMoreWork(ProcessQueue queue);
-typedef void Action();
-typedef Future<AdbCommandResult> StepFunction();
+const _slowTimeoutMultiplier = 4;
+const _extraSlowTimeoutMultiplier = 8;
+const nonUtfFakeExitCode = 0xFFFD;
 
 /// Some IO tests use these variables and get confused if the host environment
 /// variables are inherited so they are excluded.
-const _excludedEnvironmentVariables = const [
+const _excludedEnvironmentVariables = [
   'http_proxy',
   'https_proxy',
   'no_proxy',
@@ -57,39 +33,35 @@
   'NO_PROXY'
 ];
 
-/**
- * TestCase contains all the information needed to run a test and evaluate
- * its output.  Running a test involves starting a separate process, with
- * the executable and arguments given by the TestCase, and recording its
- * stdout and stderr output streams, and its exit code.  TestCase only
- * contains static information about the test; actually running the test is
- * performed by [ProcessQueue] using a [RunningProcess] object.
- *
- * The output information is stored in a [CommandOutput] instance contained
- * in TestCase.commandOutputs. The last CommandOutput instance is responsible
- * for evaluating if the test has passed, failed, crashed, or timed out, and the
- * TestCase has information about what the expected result of the test should
- * be.
- *
- * The TestCase has a callback function, [completedHandler], that is run when
- * the test is completed.
- */
+/// TestCase contains all the information needed to run a test and evaluate
+/// its output.  Running a test involves starting a separate process, with
+/// the executable and arguments given by the TestCase, and recording its
+/// stdout and stderr output streams, and its exit code.  TestCase only
+/// contains static information about the test; actually running the test is
+/// performed by [ProcessQueue] using a [RunningProcess] object.
+///
+/// The output information is stored in a [CommandOutput] instance contained
+/// in TestCase.commandOutputs. The last CommandOutput instance is responsible
+/// for evaluating if the test has passed, failed, crashed, or timed out, and
+/// the TestCase has information about what the expected result of the test
+/// should be.
+///
+/// The TestCase has a callback function, [completedHandler], that is run when
+/// the test is completed.
 class TestCase extends UniqueObject {
-  // Flags set in _expectations from the optional argument info.
-  static final int HAS_RUNTIME_ERROR = 1 << 0;
-  static final int HAS_SYNTAX_ERROR = 1 << 1;
-  static final int HAS_COMPILE_ERROR = 1 << 2;
-  static final int HAS_STATIC_WARNING = 1 << 3;
-  static final int HAS_CRASH = 1 << 4;
-  /**
-   * A list of commands to execute. Most test cases have a single command.
-   * Dart2js tests have two commands, one to compile the source and another
-   * to execute it. Some isolate tests might even have three, if they require
-   * compiling multiple sources that are run in isolation.
-   */
+  /// Flags set in _expectations from the optional argument info.
+  static const _hasRuntimeError = 1 << 0;
+  static const _hasSyntaxError = 1 << 1;
+  static const _hasCompileError = 1 << 2;
+  static const _hasStaticWarning = 1 << 3;
+  static const _hasCrash = 1 << 4;
+
+  /// A list of commands to execute. Most test cases have a single command.
+  /// Dart2js tests have two commands, one to compile the source and another
+  /// to execute it. Some isolate tests might even have three, if they require
+  /// compiling multiple sources that are run in isolation.
   List<Command> commands;
-  Map<Command, CommandOutput> commandOutputs =
-      new Map<Command, CommandOutput>();
+  Map<Command, CommandOutput> commandOutputs = {};
 
   TestConfiguration configuration;
   String displayName;
@@ -113,28 +85,27 @@
   void _setExpectations(TestInformation info) {
     // We don't want to keep the entire (large) TestInformation structure,
     // so we copy the needed bools into flags set in a single integer.
-    if (info.hasRuntimeError) _expectations |= HAS_RUNTIME_ERROR;
-    if (info.hasSyntaxError) _expectations |= HAS_SYNTAX_ERROR;
-    if (info.hasCrash) _expectations |= HAS_CRASH;
+    if (info.hasRuntimeError) _expectations |= _hasRuntimeError;
+    if (info.hasSyntaxError) _expectations |= _hasSyntaxError;
+    if (info.hasCrash) _expectations |= _hasCrash;
     if (info.hasCompileError || info.hasSyntaxError) {
-      _expectations |= HAS_COMPILE_ERROR;
+      _expectations |= _hasCompileError;
     }
-    if (info.hasStaticWarning) _expectations |= HAS_STATIC_WARNING;
+    if (info.hasStaticWarning) _expectations |= _hasStaticWarning;
   }
 
   TestCase indexedCopy(int index) {
     var newCommands = commands.map((c) => c.indexedCopy(index)).toList();
-    return new TestCase(
-        displayName, newCommands, configuration, expectedOutcomes)
+    return TestCase(displayName, newCommands, configuration, expectedOutcomes)
       .._expectations = _expectations
       ..hash = hash;
   }
 
-  bool get hasRuntimeError => _expectations & HAS_RUNTIME_ERROR != 0;
-  bool get hasStaticWarning => _expectations & HAS_STATIC_WARNING != 0;
-  bool get hasSyntaxError => _expectations & HAS_SYNTAX_ERROR != 0;
-  bool get hasCompileError => _expectations & HAS_COMPILE_ERROR != 0;
-  bool get hasCrash => _expectations & HAS_CRASH != 0;
+  bool get hasRuntimeError => _expectations & _hasRuntimeError != 0;
+  bool get hasStaticWarning => _expectations & _hasStaticWarning != 0;
+  bool get hasSyntaxError => _expectations & _hasSyntaxError != 0;
+  bool get hasCompileError => _expectations & _hasCompileError != 0;
+  bool get hasCrash => _expectations & _hasCrash != 0;
   bool get isNegative =>
       hasCompileError ||
       hasRuntimeError && configuration.runtime != Runtime.none ||
@@ -180,7 +151,7 @@
 
   CommandOutput get lastCommandOutput {
     if (commandOutputs.length == 0) {
-      throw new Exception("CommandOutputs is empty, maybe no command was run? ("
+      throw Exception("CommandOutputs is empty, maybe no command was run? ("
           "displayName: '$displayName', "
           "configurationString: '$configurationString')");
     }
@@ -189,7 +160,7 @@
 
   Command get lastCommandExecuted {
     if (commandOutputs.length == 0) {
-      throw new Exception("CommandOutputs is empty, maybe no command was run? ("
+      throw Exception("CommandOutputs is empty, maybe no command was run? ("
           "displayName: '$displayName', "
           "configurationString: '$configurationString')");
     }
@@ -199,9 +170,9 @@
   int get timeout {
     var result = configuration.timeout;
     if (expectedOutcomes.contains(Expectation.slow)) {
-      result *= slowTimeoutMultiplier;
+      result *= _slowTimeoutMultiplier;
     } else if (expectedOutcomes.contains(Expectation.extraSlow)) {
-      result *= extraSlowTimeoutMultiplier;
+      result *= _extraSlowTimeoutMultiplier;
     }
     return result;
   }
@@ -233,152 +204,15 @@
   }
 
   bool get isFinished {
-    return commandOutputs.length > 0 &&
+    return commandOutputs.isNotEmpty &&
         (!lastCommandOutput.successful ||
             commands.length == commandOutputs.length);
   }
 }
 
-/**
- * An OutputLog records the output from a test, but truncates it if
- * it is longer than MAX_HEAD characters, and just keeps the head and
- * the last TAIL_LENGTH characters of the output.
- */
-class OutputLog implements StreamConsumer<List<int>> {
-  static const int MAX_HEAD = 500 * 1024;
-  static const int TAIL_LENGTH = 10 * 1024;
-  List<int> head = <int>[];
-  List<int> tail;
-  List<int> complete;
-  bool dataDropped = false;
-  bool hasNonUtf8 = false;
-  StreamSubscription _subscription;
-
-  OutputLog();
-
-  void add(List<int> data) {
-    if (complete != null) {
-      throw new StateError("Cannot add to OutputLog after calling toList");
-    }
-    if (tail == null) {
-      head.addAll(data);
-      if (head.length > MAX_HEAD) {
-        tail = head.sublist(MAX_HEAD);
-        head.length = MAX_HEAD;
-      }
-    } else {
-      tail.addAll(data);
-    }
-    if (tail != null && tail.length > 2 * TAIL_LENGTH) {
-      tail = _truncatedTail();
-      dataDropped = true;
-    }
-  }
-
-  List<int> _truncatedTail() => tail.length > TAIL_LENGTH
-      ? tail.sublist(tail.length - TAIL_LENGTH)
-      : tail;
-
-  void _checkUtf8(List<int> data) {
-    try {
-      utf8.decode(data, allowMalformed: false);
-    } on FormatException {
-      hasNonUtf8 = true;
-      String malformed = utf8.decode(data, allowMalformed: true);
-      data
-        ..clear()
-        ..addAll(utf8.encode(malformed))
-        ..addAll("""
-
-  *****************************************************************************
-
-  test.dart: The output of this test contained non-UTF8 formatted data.
-
-  *****************************************************************************
-
-  """
-            .codeUnits);
-    }
-  }
-
-  List<int> toList() {
-    if (complete == null) {
-      complete = head;
-      if (dataDropped) {
-        complete.addAll("""
-
-*****************************************************************************
-
-test.dart: Data was removed due to excessive length. If you need the limit to
-be increased, please contact dart-engprod or file an issue.
-
-*****************************************************************************
-
-"""
-            .codeUnits);
-        complete.addAll(_truncatedTail());
-      } else if (tail != null) {
-        complete.addAll(tail);
-      }
-      head = null;
-      tail = null;
-      _checkUtf8(complete);
-    }
-    return complete;
-  }
-
-  @override
-  Future addStream(Stream<List<int>> stream) {
-    _subscription = stream.listen(this.add);
-    return _subscription.asFuture();
-  }
-
-  @override
-  Future close() {
-    toList();
-    return _subscription?.cancel();
-  }
-
-  Future cancel() {
-    return _subscription?.cancel();
-  }
-}
-
-// An [OutputLog] that tees the output to a file as well.
-class FileOutputLog extends OutputLog {
-  io.File _outputFile;
-  io.IOSink _sink;
-
-  FileOutputLog(this._outputFile);
-
-  @override
-  void add(List<int> data) {
-    super.add(data);
-    _sink ??= _outputFile.openWrite();
-    _sink.add(data);
-  }
-
-  @override
-  Future close() {
-    return Future.wait([
-      super.close(),
-      if (_sink != null) _sink.flush().whenComplete(_sink.close)
-    ]);
-  }
-
-  @override
-  Future cancel() {
-    return Future.wait([
-      super.cancel(),
-      if (_sink != null) _sink.flush().whenComplete(_sink.close)
-    ]);
-  }
-}
-
-// Helper to get a list of all child pids for a parent process.
-// The first element of the list is the parent pid.
-Future<List<int>> _getPidList(int pid, List<String> diagnostics) async {
-  var pids = [pid];
+/// Helper to get a list of all child pids for a parent process.
+Future<List<int>> _getPidList(int parentId, List<String> diagnostics) async {
+  var pids = [parentId];
   List<String> lines;
   var startLine = 0;
   if (io.Platform.isLinux || io.Platform.isMacOS) {
@@ -414,16 +248,14 @@
   return pids;
 }
 
-/**
- * A RunningProcess actually runs a test, getting the command lines from
- * its [TestCase], starting the test process (and first, a compilation
- * process if the TestCase is a [BrowserTestCase]), creating a timeout
- * timer, and recording the results in a new [CommandOutput] object, which it
- * attaches to the TestCase.  The lifetime of the RunningProcess is limited
- * to the time it takes to start the process, run the process, and record
- * the result; there are no pointers to it, so it should be available to
- * be garbage collected as soon as it is done.
- */
+/// A RunningProcess actually runs a test, getting the command lines from
+/// its [TestCase], starting the test process (and first, a compilation
+/// process if the TestCase is a [BrowserTestCase]), creating a timeout
+/// timer, and recording the results in a new [CommandOutput] object, which it
+/// attaches to the TestCase.  The lifetime of the RunningProcess is limited
+/// to the time it takes to start the process, run the process, and record
+/// the result; there are no pointers to it, so it should be available to
+/// be garbage collected as soon as it is done.
 class RunningProcess {
   ProcessCommand command;
   int timeout;
@@ -443,8 +275,8 @@
   }
 
   Future<CommandOutput> run() {
-    completer = new Completer<CommandOutput>();
-    startTime = new DateTime.now();
+    completer = Completer<CommandOutput>();
+    startTime = DateTime.now();
     _runCommand();
     return completer.future;
   }
@@ -523,17 +355,17 @@
           }
         }
 
-        // Wait for the process to finish or timeout
+        // Wait for the process to finish or timeout.
         process.exitCode
             .timeout(Duration(seconds: timeout), onTimeout: timeoutHandler)
             .then((exitCode) {
           // This timeout is used to close stdio to the subprocess once we got
           // the exitCode. Sometimes descendants of the subprocess keep stdio
           // handles alive even though the direct subprocess is dead.
-          Future.wait([stdoutFuture, stderrFuture]).timeout(MAX_STDIO_DELAY,
+          Future.wait([stdoutFuture, stderrFuture]).timeout(maxStdioDelay,
               onTimeout: () async {
             DebugLogger.warning(
-                "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
+                "$maxStdioDelayPassedMessage (command: $command)");
             await stdout.cancel();
             await stderr.cancel();
             _commandComplete(exitCode);
@@ -580,7 +412,7 @@
         timedOut,
         stdoutData,
         stderrData,
-        new DateTime.now().difference(startTime),
+        DateTime.now().difference(startTime),
         compilationSkipped,
         pid);
     commandOutput.diagnostics.addAll(diagnostics);
@@ -588,7 +420,7 @@
   }
 
   Map<String, String> _createProcessEnvironment() {
-    var environment = new Map<String, String>.from(io.Platform.environment);
+    var environment = Map<String, String>.from(io.Platform.environment);
 
     if (command.environmentOverrides != null) {
       for (var key in command.environmentOverrides.keys) {
@@ -606,1173 +438,3 @@
     return environment;
   }
 }
-
-class BatchRunnerProcess {
-  /// When true, the command line is passed to the test runner as a
-  /// JSON-encoded list of strings.
-  final bool _useJson;
-
-  Completer<CommandOutput> _completer;
-  ProcessCommand _command;
-  List<String> _arguments;
-  String _runnerType;
-
-  io.Process _process;
-  Map<String, String> _processEnvironmentOverrides;
-  Completer<Null> _stdoutCompleter;
-  Completer<Null> _stderrCompleter;
-  StreamSubscription<String> _stdoutSubscription;
-  StreamSubscription<String> _stderrSubscription;
-  Function _processExitHandler;
-
-  bool _currentlyRunning = false;
-  OutputLog _testStdout;
-  OutputLog _testStderr;
-  String _status;
-  DateTime _startTime;
-  Timer _timer;
-  int _testCount = 0;
-
-  BatchRunnerProcess({bool useJson: true}) : _useJson = useJson;
-
-  Future<CommandOutput> runCommand(String runnerType, ProcessCommand command,
-      int timeout, List<String> arguments) {
-    assert(_completer == null);
-    assert(!_currentlyRunning);
-
-    _completer = new Completer();
-    bool sameRunnerType = _runnerType == runnerType &&
-        _dictEquals(_processEnvironmentOverrides, command.environmentOverrides);
-    _runnerType = runnerType;
-    _currentlyRunning = true;
-    _command = command;
-    _arguments = arguments;
-    _processEnvironmentOverrides = command.environmentOverrides;
-
-    // TOOD(jmesserly): this restarts `dartdevc --batch` to work around a
-    // memory leak, see https://github.com/dart-lang/sdk/issues/30314.
-    var clearMemoryLeak = command is CompilationCommand &&
-        command.displayName == 'dartdevc' &&
-        ++_testCount % 100 == 0;
-    if (_process == null) {
-      // Start process if not yet started.
-      _startProcess(() {
-        doStartTest(command, timeout);
-      });
-    } else if (!sameRunnerType || clearMemoryLeak) {
-      // Restart this runner with the right executable for this test if needed.
-      _processExitHandler = (_) {
-        _startProcess(() {
-          doStartTest(command, timeout);
-        });
-      };
-      _process.kill();
-      _stdoutSubscription.cancel();
-      _stderrSubscription.cancel();
-    } else {
-      doStartTest(command, timeout);
-    }
-    return _completer.future;
-  }
-
-  Future<bool> terminate() {
-    if (_process == null) return new Future.value(true);
-    var terminateCompleter = new Completer<bool>();
-    _processExitHandler = (_) {
-      terminateCompleter.complete(true);
-    };
-    _process.kill();
-    _stdoutSubscription.cancel();
-    _stderrSubscription.cancel();
-
-    return terminateCompleter.future;
-  }
-
-  void doStartTest(Command command, int timeout) {
-    _startTime = new DateTime.now();
-    _testStdout = new OutputLog();
-    _testStderr = new OutputLog();
-    _status = null;
-    _stdoutCompleter = new Completer();
-    _stderrCompleter = new Completer();
-    _timer = new Timer(new Duration(seconds: timeout), _timeoutHandler);
-
-    var line = _createArgumentsLine(_arguments, timeout);
-    _process.stdin.write(line);
-    _stdoutSubscription.resume();
-    _stderrSubscription.resume();
-    Future.wait([_stdoutCompleter.future, _stderrCompleter.future])
-        .then((_) => _reportResult());
-  }
-
-  String _createArgumentsLine(List<String> arguments, int timeout) {
-    if (_useJson) {
-      return "${jsonEncode(arguments)}\n";
-    } else {
-      return arguments.join(' ') + '\n';
-    }
-  }
-
-  void _reportResult() {
-    if (!_currentlyRunning) return;
-    // _status == '>>> TEST {PASS, FAIL, OK, CRASH, TIMEOUT, PARSE_FAIL}'
-
-    var outcome = _status.split(" ")[2];
-    var exitCode = 0;
-    if (outcome == "CRASH") exitCode = unhandledCompilerExceptionExitCode;
-    if (outcome == "PARSE_FAIL") exitCode = parseFailExitCode;
-    if (outcome == "FAIL" || outcome == "TIMEOUT") exitCode = 1;
-    var output = createCommandOutput(
-        _command,
-        exitCode,
-        (outcome == "TIMEOUT"),
-        _testStdout.toList(),
-        _testStderr.toList(),
-        new DateTime.now().difference(_startTime),
-        false);
-    assert(_completer != null);
-    _completer.complete(output);
-    _completer = null;
-    _currentlyRunning = false;
-  }
-
-  ExitCodeEvent makeExitHandler(String status) {
-    void handler(int exitCode) {
-      if (_currentlyRunning) {
-        if (_timer != null) _timer.cancel();
-        _status = status;
-        _stdoutSubscription.cancel();
-        _stderrSubscription.cancel();
-        _startProcess(_reportResult);
-      } else {
-        // No active test case running.
-        _process = null;
-      }
-    }
-
-    return handler;
-  }
-
-  void _timeoutHandler() {
-    _processExitHandler = makeExitHandler(">>> TEST TIMEOUT");
-    _process.kill();
-  }
-
-  void _startProcess(Action callback) {
-    assert(_command is ProcessCommand);
-    var executable = _command.executable;
-    var arguments = _command.batchArguments.toList();
-    arguments.add('--batch');
-    var environment = new Map<String, String>.from(io.Platform.environment);
-    if (_processEnvironmentOverrides != null) {
-      for (var key in _processEnvironmentOverrides.keys) {
-        environment[key] = _processEnvironmentOverrides[key];
-      }
-    }
-    var processFuture =
-        io.Process.start(executable, arguments, environment: environment);
-    processFuture.then((io.Process p) {
-      _process = p;
-
-      Stream<String> _stdoutStream =
-          _process.stdout.transform(utf8.decoder).transform(new LineSplitter());
-      _stdoutSubscription = _stdoutStream.listen((String line) {
-        if (line.startsWith('>>> TEST')) {
-          _status = line;
-        } else if (line.startsWith('>>> BATCH')) {
-          // ignore
-        } else if (line.startsWith('>>> ')) {
-          throw new Exception("Unexpected command from batch runner: '$line'.");
-        } else {
-          _testStdout.add(encodeUtf8(line));
-          _testStdout.add("\n".codeUnits);
-        }
-        if (_status != null) {
-          _stdoutSubscription.pause();
-          _timer.cancel();
-          _stdoutCompleter.complete(null);
-        }
-      });
-      _stdoutSubscription.pause();
-
-      Stream<String> _stderrStream =
-          _process.stderr.transform(utf8.decoder).transform(new LineSplitter());
-      _stderrSubscription = _stderrStream.listen((String line) {
-        if (line.startsWith('>>> EOF STDERR')) {
-          _stderrSubscription.pause();
-          _stderrCompleter.complete(null);
-        } else {
-          _testStderr.add(encodeUtf8(line));
-          _testStderr.add("\n".codeUnits);
-        }
-      });
-      _stderrSubscription.pause();
-
-      _processExitHandler = makeExitHandler(">>> TEST CRASH");
-      _process.exitCode.then((exitCode) {
-        _processExitHandler(exitCode);
-      });
-
-      _process.stdin.done.catchError((err) {
-        print('Error on batch runner input stream stdin');
-        print('  Previous test\'s status: $_status');
-        print('  Error: $err');
-        throw err;
-      });
-      callback();
-    }).catchError((e) {
-      // TODO(floitsch): should we try to report the stacktrace?
-      print("Process error:");
-      print("  Command: $executable ${arguments.join(' ')} ($_arguments)");
-      print("  Error: $e");
-      // If there is an error starting a batch process, chances are that
-      // it will always fail. So rather than re-trying a 1000+ times, we
-      // exit.
-      io.exit(1);
-      return true;
-    });
-  }
-
-  bool _dictEquals(Map a, Map b) {
-    if (a == null) return b == null;
-    if (b == null) return false;
-    if (a.length != b.length) return false;
-    for (var key in a.keys) {
-      if (a[key] != b[key]) return false;
-    }
-    return true;
-  }
-}
-
-/**
- * [TestCaseEnqueuer] takes a list of TestSuites, generates TestCases and
- * builds a dependency graph of all commands in every TestSuite.
- *
- * It will maintain three helper data structures
- *  - command2node: A mapping from a [Command] to a node in the dependency graph
- *  - command2testCases: A mapping from [Command] to all TestCases that it is
- *    part of.
- *  - remainingTestCases: A set of TestCases that were enqueued but are not
- *    finished
- *
- * [Command] and it's subclasses all have hashCode/operator== methods defined
- * on them, so we can safely use them as keys in Map/Set objects.
- */
-class TestCaseEnqueuer {
-  final Graph<Command> graph;
-  final Function _onTestCaseAdded;
-
-  final command2node = <Command, Node<Command>>{};
-  final command2testCases = <Command, List<TestCase>>{};
-  final remainingTestCases = new Set<TestCase>();
-
-  TestCaseEnqueuer(this.graph, this._onTestCaseAdded);
-
-  void enqueueTestSuites(List<TestSuite> testSuites) {
-    // Cache information about test cases per test suite. For multiple
-    // configurations there is no need to repeatedly search the file
-    // system, generate tests, and search test files for options.
-    var testCache = <String, List<TestInformation>>{};
-
-    var iterator = testSuites.iterator;
-    void enqueueNextSuite() {
-      if (!iterator.moveNext()) {
-        // We're finished with building the dependency graph.
-        graph.seal();
-      } else {
-        iterator.current.forEachTest(_newTest, testCache, enqueueNextSuite);
-      }
-    }
-
-    enqueueNextSuite();
-  }
-
-  /// Adds a test case to the list of active test cases, and adds its commands
-  /// to the dependency graph of commands.
-  ///
-  /// If the repeat flag is > 1, replicates the test case and its commands,
-  /// adding an index field with a distinct value to each of the copies.
-  ///
-  /// Each copy of the test case depends on the previous copy of the test
-  /// case completing, with its first command having a dependency on the last
-  /// command of the previous copy of the test case. This dependency is
-  /// marked as a "timingDependency", so that it doesn't depend on the previous
-  /// test completing successfully, just on it completing.
-  void _newTest(TestCase testCase) {
-    Node<Command> lastNode;
-    for (int i = 0; i < testCase.configuration.repeat; ++i) {
-      if (i > 0) {
-        testCase = testCase.indexedCopy(i);
-      }
-      remainingTestCases.add(testCase);
-      bool isFirstCommand = true;
-      for (var command in testCase.commands) {
-        // Make exactly *one* node in the dependency graph for every command.
-        // This ensures that we never have two commands c1 and c2 in the graph
-        // with "c1 == c2".
-        var node = command2node[command];
-        if (node == null) {
-          var requiredNodes =
-              (lastNode != null) ? [lastNode] : <Node<Command>>[];
-          node = graph.add(command, requiredNodes,
-              timingDependency: isFirstCommand);
-          command2node[command] = node;
-          command2testCases[command] = <TestCase>[];
-        }
-        // Keep mapping from command to all testCases that refer to it
-        command2testCases[command].add(testCase);
-
-        lastNode = node;
-        isFirstCommand = false;
-      }
-      _onTestCaseAdded(testCase);
-    }
-  }
-}
-
-/*
- * [CommandEnqueuer] will
- *  - change node.state to NodeState.Enqueuing as soon as all dependencies have
- *    a state of NodeState.Successful
- *  - change node.state to NodeState.UnableToRun if one or more dependencies
- *    have a state of NodeState.Failed/NodeState.UnableToRun.
- */
-class CommandEnqueuer {
-  static const _initStates = const [NodeState.initialized, NodeState.waiting];
-
-  static const _finishedStates = const [
-    NodeState.successful,
-    NodeState.failed,
-    NodeState.unableToRun
-  ];
-
-  final Graph<Command> _graph;
-
-  CommandEnqueuer(this._graph) {
-    _graph.added.listen(_changeNodeStateIfNecessary);
-
-    _graph.changed.listen((event) {
-      if (event.from == NodeState.waiting ||
-          event.from == NodeState.processing) {
-        if (_finishedStates.contains(event.to)) {
-          for (var dependentNode in event.node.neededFor) {
-            _changeNodeStateIfNecessary(dependentNode);
-          }
-        }
-      }
-    });
-  }
-
-  // Called when either a new node was added or if one of it's dependencies
-  // changed it's state.
-  void _changeNodeStateIfNecessary(Node<Command> node) {
-    if (_initStates.contains(node.state)) {
-      bool allDependenciesFinished =
-          node.dependencies.every((dep) => _finishedStates.contains(dep.state));
-      bool anyDependenciesUnsuccessful = node.dependencies.any((dep) =>
-          [NodeState.failed, NodeState.unableToRun].contains(dep.state));
-      bool allDependenciesSuccessful =
-          node.dependencies.every((dep) => dep.state == NodeState.successful);
-
-      var newState = NodeState.waiting;
-      if (allDependenciesSuccessful ||
-          (allDependenciesFinished && node.timingDependency)) {
-        newState = NodeState.enqueuing;
-      } else if (anyDependenciesUnsuccessful) {
-        newState = NodeState.unableToRun;
-      }
-      if (node.state != newState) {
-        _graph.changeState(node, newState);
-      }
-    }
-  }
-}
-
-/*
- * [CommandQueue] will listen for nodes entering the NodeState.ENQUEUING state,
- * queue them up and run them. While nodes are processed they will be in the
- * NodeState.PROCESSING state. After running a command, the node will change
- * to a state of NodeState.Successful or NodeState.Failed.
- *
- * It provides a synchronous stream [completedCommands] which provides the
- * [CommandOutputs] for the finished commands.
- *
- * It provides a [done] future, which will complete once there are no more
- * nodes left in the states Initialized/Waiting/Enqueing/Processing
- * and the [executor] has cleaned up it's resources.
- */
-class CommandQueue {
-  final Graph<Command> graph;
-  final CommandExecutor executor;
-  final TestCaseEnqueuer enqueuer;
-
-  final Queue<Command> _runQueue = new Queue<Command>();
-  final _commandOutputStream = new StreamController<CommandOutput>(sync: true);
-  final _completer = new Completer<Null>();
-
-  int _numProcesses = 0;
-  int _maxProcesses;
-  int _numBrowserProcesses = 0;
-  int _maxBrowserProcesses;
-  bool _finishing = false;
-  bool _verbose = false;
-
-  CommandQueue(this.graph, this.enqueuer, this.executor, this._maxProcesses,
-      this._maxBrowserProcesses, this._verbose) {
-    graph.changed.listen((event) {
-      if (event.to == NodeState.enqueuing) {
-        assert(event.from == NodeState.initialized ||
-            event.from == NodeState.waiting);
-        graph.changeState(event.node, NodeState.processing);
-        var command = event.node.data;
-        if (event.node.dependencies.isNotEmpty) {
-          _runQueue.addFirst(command);
-        } else {
-          _runQueue.add(command);
-        }
-        Timer.run(() => _tryRunNextCommand());
-      } else if (event.to == NodeState.unableToRun) {
-        _checkDone();
-      }
-    });
-
-    // We're finished if the graph is sealed and all nodes are in a finished
-    // state (Successful, Failed or UnableToRun).
-    // So we're calling '_checkDone()' to check whether that condition is met
-    // and we can cleanup.
-    graph.sealed.listen((event) {
-      _checkDone();
-    });
-  }
-
-  Stream<CommandOutput> get completedCommands => _commandOutputStream.stream;
-
-  Future get done => _completer.future;
-
-  void _tryRunNextCommand() {
-    _checkDone();
-
-    if (_numProcesses < _maxProcesses && !_runQueue.isEmpty) {
-      Command command = _runQueue.removeFirst();
-      var isBrowserCommand = command is BrowserTestCommand;
-
-      if (isBrowserCommand && _numBrowserProcesses == _maxBrowserProcesses) {
-        // If there is no free browser runner, put it back into the queue.
-        _runQueue.add(command);
-        // Don't lose a process.
-        new Timer(new Duration(milliseconds: 100), _tryRunNextCommand);
-        return;
-      }
-
-      _numProcesses++;
-      if (isBrowserCommand) _numBrowserProcesses++;
-
-      var node = enqueuer.command2node[command];
-      Iterable<TestCase> testCases = enqueuer.command2testCases[command];
-      // If a command is part of many TestCases we set the timeout to be
-      // the maximum over all [TestCase.timeout]s. At some point, we might
-      // eliminate [TestCase.timeout] completely and move it to [Command].
-      int timeout = testCases
-          .map((TestCase test) => test.timeout)
-          .fold(0, (int a, b) => math.max(a, b));
-
-      if (_verbose) {
-        print('Running "${command.displayName}" command: $command');
-      }
-
-      executor.runCommand(node, command, timeout).then((CommandOutput output) {
-        assert(command == output.command);
-
-        _commandOutputStream.add(output);
-        if (output.canRunDependendCommands) {
-          graph.changeState(node, NodeState.successful);
-        } else {
-          graph.changeState(node, NodeState.failed);
-        }
-
-        _numProcesses--;
-        if (isBrowserCommand) _numBrowserProcesses--;
-
-        // Don't lose a process
-        Timer.run(() => _tryRunNextCommand());
-      });
-    }
-  }
-
-  void _checkDone() {
-    if (!_finishing &&
-        _runQueue.isEmpty &&
-        _numProcesses == 0 &&
-        graph.isSealed &&
-        graph.stateCount(NodeState.initialized) == 0 &&
-        graph.stateCount(NodeState.waiting) == 0 &&
-        graph.stateCount(NodeState.enqueuing) == 0 &&
-        graph.stateCount(NodeState.processing) == 0) {
-      _finishing = true;
-      executor.cleanup().then((_) {
-        _completer.complete();
-        _commandOutputStream.close();
-      });
-    }
-  }
-
-  void dumpState() {
-    print("");
-    print("CommandQueue state:");
-    print("  Processes: used: $_numProcesses max: $_maxProcesses");
-    print("  BrowserProcesses: used: $_numBrowserProcesses "
-        "max: $_maxBrowserProcesses");
-    print("  Finishing: $_finishing");
-    print("  Queue (length = ${_runQueue.length}):");
-    for (var command in _runQueue) {
-      print("      $command");
-    }
-  }
-}
-
-/*
- * [CommandExecutor] is responsible for executing commands. It will make sure
- * that the following two constraints are satisfied
- *  - [:numberOfProcessesUsed <= maxProcesses:]
- *  - [:numberOfBrowserProcessesUsed <= maxBrowserProcesses:]
- *
- * It provides a [runCommand] method which will complete with a
- * [CommandOutput] object.
- *
- * It provides a [cleanup] method to free all the allocated resources.
- */
-abstract class CommandExecutor {
-  Future cleanup();
-  // TODO(kustermann): The [timeout] parameter should be a property of Command
-  Future<CommandOutput> runCommand(
-      Node<Command> node, covariant Command command, int timeout);
-}
-
-class CommandExecutorImpl implements CommandExecutor {
-  final TestConfiguration globalConfiguration;
-  final int maxProcesses;
-  final int maxBrowserProcesses;
-  AdbDevicePool adbDevicePool;
-
-  // For dart2js and analyzer batch processing,
-  // we keep a list of batch processes.
-  final _batchProcesses = new Map<String, List<BatchRunnerProcess>>();
-  // We keep a BrowserTestRunner for every configuration.
-  final _browserTestRunners = new Map<TestConfiguration, BrowserTestRunner>();
-
-  bool _finishing = false;
-
-  CommandExecutorImpl(
-      this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses,
-      {this.adbDevicePool});
-
-  Future cleanup() {
-    assert(!_finishing);
-    _finishing = true;
-
-    Future _terminateBatchRunners() {
-      var futures = <Future>[];
-      for (var runners in _batchProcesses.values) {
-        futures.addAll(runners.map((runner) => runner.terminate()));
-      }
-      return Future.wait(futures);
-    }
-
-    Future _terminateBrowserRunners() {
-      var futures =
-          _browserTestRunners.values.map((runner) => runner.terminate());
-      return Future.wait(futures);
-    }
-
-    return Future.wait([
-      _terminateBatchRunners(),
-      _terminateBrowserRunners(),
-    ]);
-  }
-
-  Future<CommandOutput> runCommand(node, Command command, int timeout) {
-    assert(!_finishing);
-
-    Future<CommandOutput> runCommand(int retriesLeft) {
-      return _runCommand(command, timeout).then((CommandOutput output) {
-        if (retriesLeft > 0 && shouldRetryCommand(output)) {
-          DebugLogger.warning("Rerunning Command: ($retriesLeft "
-              "attempt(s) remains) [cmd: $command]");
-          return runCommand(retriesLeft - 1);
-        } else {
-          return new Future.value(output);
-        }
-      });
-    }
-
-    return runCommand(command.maxNumRetries);
-  }
-
-  Future<CommandOutput> _runCommand(Command command, int timeout) {
-    if (command is BrowserTestCommand) {
-      return _startBrowserControllerTest(command, timeout);
-    } else if (command is VMKernelCompilationCommand) {
-      // For now, we always run vm_compile_to_kernel in batch mode.
-      var name = command.displayName;
-      assert(name == 'vm_compile_to_kernel');
-      return _getBatchRunner(name)
-          .runCommand(name, command, timeout, command.arguments);
-    } else if (command is CompilationCommand &&
-        globalConfiguration.batchDart2JS &&
-        command.displayName == 'dart2js') {
-      return _getBatchRunner("dart2js")
-          .runCommand("dart2js", command, timeout, command.arguments);
-    } else if (command is AnalysisCommand && globalConfiguration.batch) {
-      return _getBatchRunner(command.displayName)
-          .runCommand(command.displayName, command, timeout, command.arguments);
-    } else if (command is CompilationCommand &&
-        (command.displayName == 'dartdevc' ||
-            command.displayName == 'dartdevk' ||
-            command.displayName == 'fasta') &&
-        globalConfiguration.batch) {
-      return _getBatchRunner(command.displayName)
-          .runCommand(command.displayName, command, timeout, command.arguments);
-    } else if (command is ScriptCommand) {
-      return command.run();
-    } else if (command is AdbPrecompilationCommand ||
-        command is AdbDartkCommand) {
-      assert(adbDevicePool != null);
-      return adbDevicePool.acquireDevice().then((AdbDevice device) async {
-        try {
-          if (command is AdbPrecompilationCommand) {
-            return await _runAdbPrecompilationCommand(device, command, timeout);
-          } else {
-            return await _runAdbDartkCommand(
-                device, command as AdbDartkCommand, timeout);
-          }
-        } finally {
-          await adbDevicePool.releaseDevice(device);
-        }
-      });
-    } else if (command is VmBatchCommand) {
-      var name = command.displayName;
-      return _getBatchRunner(command.displayName + command.dartFile)
-          .runCommand(name, command, timeout, command.arguments);
-    } else if (command is CompilationCommand &&
-        command.displayName == 'babel') {
-      return new RunningProcess(command, timeout,
-              configuration: globalConfiguration,
-              outputFile: io.File(command.outputFile))
-          .run();
-    } else if (command is ProcessCommand) {
-      return new RunningProcess(command, timeout,
-              configuration: globalConfiguration)
-          .run();
-    } else {
-      throw new ArgumentError("Unknown command type ${command.runtimeType}.");
-    }
-  }
-
-  Future<CommandOutput> _runAdbPrecompilationCommand(
-      AdbDevice device, AdbPrecompilationCommand command, int timeout) async {
-    var runner = command.precompiledRunnerFilename;
-    var processTest = command.processTestFilename;
-    var testdir = command.precompiledTestDirectory;
-    var arguments = command.arguments;
-    var devicedir = DartPrecompiledAdbRuntimeConfiguration.DeviceDir;
-    var deviceTestDir = DartPrecompiledAdbRuntimeConfiguration.DeviceTestDir;
-
-    // We copy all the files which the vm precompiler puts into the test
-    // directory.
-    List<String> files = new io.Directory(testdir)
-        .listSync()
-        .map((file) => file.path)
-        .map((path) => path.substring(path.lastIndexOf('/') + 1))
-        .toList();
-
-    var timeoutDuration = new Duration(seconds: timeout);
-
-    var steps = <StepFunction>[];
-
-    steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir]));
-    steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir]));
-    steps.add(() =>
-        device.pushCachedData(runner, '$devicedir/dart_precompiled_runtime'));
-    steps.add(
-        () => device.pushCachedData(processTest, '$devicedir/process_test'));
-    steps.add(() => device.runAdbShellCommand([
-          'chmod',
-          '777',
-          '$devicedir/dart_precompiled_runtime $devicedir/process_test'
-        ]));
-
-    for (var file in files) {
-      steps.add(() => device
-          .runAdbCommand(['push', '$testdir/$file', '$deviceTestDir/$file']));
-    }
-
-    steps.add(() => device.runAdbShellCommand(
-        [
-          '$devicedir/dart_precompiled_runtime',
-        ]..addAll(arguments),
-        timeout: timeoutDuration));
-
-    var stopwatch = new Stopwatch()..start();
-    var writer = new StringBuffer();
-
-    await device.waitForBootCompleted();
-    await device.waitForDevice();
-
-    AdbCommandResult result;
-    for (var i = 0; i < steps.length; i++) {
-      var fun = steps[i];
-      var commandStopwatch = new Stopwatch()..start();
-      result = await fun();
-
-      writer.writeln("Executing ${result.command}");
-      if (result.stdout.length > 0) {
-        writer.writeln("Stdout:\n${result.stdout.trim()}");
-      }
-      if (result.stderr.length > 0) {
-        writer.writeln("Stderr:\n${result.stderr.trim()}");
-      }
-      writer.writeln("ExitCode: ${result.exitCode}");
-      writer.writeln("Time: ${commandStopwatch.elapsed}");
-      writer.writeln("");
-
-      // If one command fails, we stop processing the others and return
-      // immediately.
-      if (result.exitCode != 0) break;
-    }
-    return createCommandOutput(command, result.exitCode, result.timedOut,
-        utf8.encode('$writer'), [], stopwatch.elapsed, false);
-  }
-
-  Future<CommandOutput> _runAdbDartkCommand(
-      AdbDevice device, AdbDartkCommand command, int timeout) async {
-    final String buildPath = command.buildPath;
-    final String processTest = command.processTestFilename;
-    final String hostKernelFile = command.kernelFile;
-    final List<String> arguments = command.arguments;
-    final String devicedir = DartkAdbRuntimeConfiguration.DeviceDir;
-    final String deviceTestDir = DartkAdbRuntimeConfiguration.DeviceTestDir;
-
-    final timeoutDuration = new Duration(seconds: timeout);
-
-    final steps = <StepFunction>[];
-
-    steps.add(() => device.runAdbShellCommand(['rm', '-Rf', deviceTestDir]));
-    steps.add(() => device.runAdbShellCommand(['mkdir', '-p', deviceTestDir]));
-    steps.add(
-        () => device.pushCachedData("${buildPath}/dart", '$devicedir/dart'));
-    steps.add(() => device
-        .runAdbCommand(['push', hostKernelFile, '$deviceTestDir/out.dill']));
-
-    for (final String lib in command.extraLibraries) {
-      final String libname = "lib${lib}.so";
-      steps.add(() => device.runAdbCommand(
-          ['push', '${buildPath}/$libname', '$deviceTestDir/$libname']));
-    }
-
-    steps.add(() => device.runAdbShellCommand(
-        [
-          'export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$deviceTestDir;'
-              '$devicedir/dart',
-        ]..addAll(arguments),
-        timeout: timeoutDuration));
-
-    final stopwatch = new Stopwatch()..start();
-    final writer = new StringBuffer();
-
-    await device.waitForBootCompleted();
-    await device.waitForDevice();
-
-    AdbCommandResult result;
-    for (var i = 0; i < steps.length; i++) {
-      var step = steps[i];
-      var commandStopwatch = new Stopwatch()..start();
-      result = await step();
-
-      writer.writeln("Executing ${result.command}");
-      if (result.stdout.length > 0) {
-        writer.writeln("Stdout:\n${result.stdout.trim()}");
-      }
-      if (result.stderr.length > 0) {
-        writer.writeln("Stderr:\n${result.stderr.trim()}");
-      }
-      writer.writeln("ExitCode: ${result.exitCode}");
-      writer.writeln("Time: ${commandStopwatch.elapsed}");
-      writer.writeln("");
-
-      // If one command fails, we stop processing the others and return
-      // immediately.
-      if (result.exitCode != 0) break;
-    }
-    return createCommandOutput(command, result.exitCode, result.timedOut,
-        utf8.encode('$writer'), [], stopwatch.elapsed, false);
-  }
-
-  BatchRunnerProcess _getBatchRunner(String identifier) {
-    // Start batch processes if needed
-    var runners = _batchProcesses[identifier];
-    if (runners == null) {
-      runners = new List<BatchRunnerProcess>(maxProcesses);
-      for (int i = 0; i < maxProcesses; i++) {
-        runners[i] = new BatchRunnerProcess(useJson: identifier == "fasta");
-      }
-      _batchProcesses[identifier] = runners;
-    }
-
-    for (var runner in runners) {
-      if (!runner._currentlyRunning) return runner;
-    }
-    throw new Exception('Unable to find inactive batch runner.');
-  }
-
-  Future<CommandOutput> _startBrowserControllerTest(
-      BrowserTestCommand browserCommand, int timeout) {
-    var completer = new Completer<CommandOutput>();
-
-    var callback = (BrowserTestOutput output) {
-      completer.complete(new BrowserCommandOutput(browserCommand, output));
-    };
-
-    var browserTest = new BrowserTest(browserCommand.url, callback, timeout);
-    _getBrowserTestRunner(browserCommand.configuration).then((testRunner) {
-      testRunner.enqueueTest(browserTest);
-    });
-
-    return completer.future;
-  }
-
-  Future<BrowserTestRunner> _getBrowserTestRunner(
-      TestConfiguration configuration) async {
-    if (_browserTestRunners[configuration] == null) {
-      var testRunner = new BrowserTestRunner(
-          configuration, globalConfiguration.localIP, maxBrowserProcesses);
-      if (globalConfiguration.isVerbose) {
-        testRunner.logger = DebugLogger.info;
-      }
-      _browserTestRunners[configuration] = testRunner;
-      await testRunner.start();
-    }
-    return _browserTestRunners[configuration];
-  }
-}
-
-bool shouldRetryCommand(CommandOutput output) {
-  if (!output.successful) {
-    List<String> stdout, stderr;
-
-    decodeOutput() {
-      if (stdout == null && stderr == null) {
-        stdout = decodeUtf8(output.stderr).split("\n");
-        stderr = decodeUtf8(output.stderr).split("\n");
-      }
-    }
-
-    final command = output.command;
-
-    // The dartk batch compiler sometimes runs out of memory. In such a case we
-    // will retry running it.
-    if (command is VMKernelCompilationCommand) {
-      if (output.hasCrashed) {
-        bool containsOutOfMemoryMessage(String line) {
-          return line.contains('Exhausted heap space, trying to allocat');
-        }
-
-        decodeOutput();
-        if (stdout.any(containsOutOfMemoryMessage) ||
-            stderr.any(containsOutOfMemoryMessage)) {
-          return true;
-        }
-      }
-    }
-
-    if (io.Platform.operatingSystem == 'linux') {
-      decodeOutput();
-      // No matter which command we ran: If we get failures due to the
-      // "xvfb-run" issue 7564, try re-running the test.
-      bool containsFailureMsg(String line) {
-        return line.contains(cannotOpenDisplayMessage) ||
-            line.contains(failedToRunCommandMessage);
-      }
-
-      if (stdout.any(containsFailureMsg) || stderr.any(containsFailureMsg)) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-/*
- * [TestCaseCompleter] will listen for
- * NodeState.Processing -> NodeState.{Successful,Failed} state changes and
- * will complete a TestCase if it is finished.
- *
- * It provides a stream [finishedTestCases], which will stream all TestCases
- * once they're finished. After all TestCases are done, the stream will be
- * closed.
- */
-class TestCaseCompleter {
-  static const _completedStates = const [
-    NodeState.failed,
-    NodeState.successful
-  ];
-
-  final Graph<Command> _graph;
-  final TestCaseEnqueuer _enqueuer;
-  final CommandQueue _commandQueue;
-
-  final Map<Command, CommandOutput> _outputs = {};
-  final StreamController<TestCase> _controller = new StreamController();
-  bool _closed = false;
-
-  TestCaseCompleter(this._graph, this._enqueuer, this._commandQueue) {
-    var finishedRemainingTestCases = false;
-
-    // Store all the command outputs -- they will be delivered synchronously
-    // (i.e. before state changes in the graph)
-    _commandQueue.completedCommands.listen((CommandOutput output) {
-      _outputs[output.command] = output;
-    }, onDone: () {
-      _completeTestCasesIfPossible(new List.from(_enqueuer.remainingTestCases));
-      finishedRemainingTestCases = true;
-      assert(_enqueuer.remainingTestCases.isEmpty);
-      _checkDone();
-    });
-
-    // Listen for NodeState.Processing -> NodeState.{Successful,Failed}
-    // changes.
-    _graph.changed.listen((event) {
-      if (event.from == NodeState.processing && !finishedRemainingTestCases) {
-        var command = event.node.data;
-
-        assert(_completedStates.contains(event.to));
-        assert(_outputs[command] != null);
-
-        _completeTestCasesIfPossible(_enqueuer.command2testCases[command]);
-        _checkDone();
-      }
-    });
-
-    // Listen also for GraphSealedEvents. If there is not a single node in the
-    // graph, we still want to finish after the graph was sealed.
-    _graph.sealed.listen((_) {
-      if (!_closed && _enqueuer.remainingTestCases.isEmpty) {
-        _controller.close();
-        _closed = true;
-      }
-    });
-  }
-
-  Stream<TestCase> get finishedTestCases => _controller.stream;
-
-  void _checkDone() {
-    if (!_closed && _graph.isSealed && _enqueuer.remainingTestCases.isEmpty) {
-      _controller.close();
-      _closed = true;
-    }
-  }
-
-  void _completeTestCasesIfPossible(Iterable<TestCase> testCases) {
-    // Update TestCases with command outputs
-    for (TestCase test in testCases) {
-      for (var icommand in test.commands) {
-        var output = _outputs[icommand];
-        if (output != null) {
-          test.commandOutputs[icommand] = output;
-        }
-      }
-    }
-
-    void completeTestCase(TestCase testCase) {
-      if (_enqueuer.remainingTestCases.contains(testCase)) {
-        _controller.add(testCase);
-        _enqueuer.remainingTestCases.remove(testCase);
-      } else {
-        DebugLogger.error("${testCase.displayName} would be finished twice");
-      }
-    }
-
-    for (var testCase in testCases) {
-      // Ask the [testCase] if it's done. Note that we assume, that
-      // [TestCase.isFinished] will return true if all commands were executed
-      // or if a previous one failed.
-      if (testCase.isFinished) {
-        completeTestCase(testCase);
-      }
-    }
-  }
-}
-
-class ProcessQueue {
-  TestConfiguration _globalConfiguration;
-
-  Function _allDone;
-  final Graph<Command> _graph = new Graph();
-  List<EventListener> _eventListener;
-
-  ProcessQueue(
-      this._globalConfiguration,
-      int maxProcesses,
-      int maxBrowserProcesses,
-      DateTime startTime,
-      List<TestSuite> testSuites,
-      this._eventListener,
-      this._allDone,
-      [bool verbose = false,
-      AdbDevicePool adbDevicePool]) {
-    void setupForListing(TestCaseEnqueuer testCaseEnqueuer) {
-      _graph.sealed.listen((_) {
-        var testCases = testCaseEnqueuer.remainingTestCases.toList();
-        testCases.sort((a, b) => a.displayName.compareTo(b.displayName));
-
-        print("\nGenerating all matching test cases ....\n");
-
-        for (TestCase testCase in testCases) {
-          eventFinishedTestCase(testCase);
-          var outcomes = testCase.expectedOutcomes.map((o) => '$o').toList()
-            ..sort();
-          print("${testCase.displayName}   "
-              "Expectations: ${outcomes.join(', ')}   "
-              "Configuration: '${testCase.configurationString}'");
-        }
-        eventAllTestsKnown();
-      });
-    }
-
-    TestCaseEnqueuer testCaseEnqueuer;
-    CommandQueue commandQueue;
-
-    void setupForRunning(TestCaseEnqueuer testCaseEnqueuer) {
-      Timer _debugTimer;
-      // If we haven't seen a single test finishing during a 10 minute period
-      // something is definitely wrong, so we dump the debugging information.
-      final debugTimerDuration = const Duration(minutes: 10);
-
-      void cancelDebugTimer() {
-        if (_debugTimer != null) {
-          _debugTimer.cancel();
-        }
-      }
-
-      void resetDebugTimer() {
-        cancelDebugTimer();
-        _debugTimer = new Timer(debugTimerDuration, () {
-          print("The debug timer of test.dart expired. Please report this issue"
-              " to whesse@ and provide the following information:");
-          print("");
-          print("Graph is sealed: ${_graph.isSealed}");
-          print("");
-          _graph.dumpCounts();
-          print("");
-          var unfinishedNodeStates = [
-            NodeState.initialized,
-            NodeState.waiting,
-            NodeState.enqueuing,
-            NodeState.processing
-          ];
-
-          for (var nodeState in unfinishedNodeStates) {
-            if (_graph.stateCount(nodeState) > 0) {
-              print("Commands in state '$nodeState':");
-              print("=================================");
-              print("");
-              for (var node in _graph.nodes) {
-                if (node.state == nodeState) {
-                  var command = node.data;
-                  var testCases = testCaseEnqueuer.command2testCases[command];
-                  print("  Command: $command");
-                  for (var testCase in testCases) {
-                    print("    Enqueued by: ${testCase.configurationString} "
-                        "-- ${testCase.displayName}");
-                  }
-                  print("");
-                }
-              }
-              print("");
-              print("");
-            }
-          }
-
-          if (commandQueue != null) {
-            commandQueue.dumpState();
-          }
-        });
-      }
-
-      // When the graph building is finished, notify event listeners.
-      _graph.sealed.listen((_) {
-        eventAllTestsKnown();
-      });
-
-      // Queue commands as they become "runnable"
-      new CommandEnqueuer(_graph);
-
-      // CommandExecutor will execute commands
-      var executor = new CommandExecutorImpl(
-          _globalConfiguration, maxProcesses, maxBrowserProcesses,
-          adbDevicePool: adbDevicePool);
-
-      // Run "runnable commands" using [executor] subject to
-      // maxProcesses/maxBrowserProcesses constraint
-      commandQueue = new CommandQueue(_graph, testCaseEnqueuer, executor,
-          maxProcesses, maxBrowserProcesses, verbose);
-
-      // Finish test cases when all commands were run (or some failed)
-      var testCaseCompleter =
-          new TestCaseCompleter(_graph, testCaseEnqueuer, commandQueue);
-      testCaseCompleter.finishedTestCases.listen((TestCase finishedTestCase) {
-        resetDebugTimer();
-
-        eventFinishedTestCase(finishedTestCase);
-      }, onDone: () {
-        // Wait until the commandQueue/exectutor is done (it may need to stop
-        // batch runners, browser controllers, ....)
-        commandQueue.done.then((_) {
-          cancelDebugTimer();
-          eventAllTestsDone();
-        });
-      });
-
-      resetDebugTimer();
-    }
-
-    // Build up the dependency graph
-    testCaseEnqueuer = new TestCaseEnqueuer(_graph, (TestCase newTestCase) {
-      eventTestAdded(newTestCase);
-    });
-
-    // Either list or run the tests
-    if (_globalConfiguration.listTests) {
-      setupForListing(testCaseEnqueuer);
-    } else {
-      setupForRunning(testCaseEnqueuer);
-    }
-
-    // Start enqueing all TestCases
-    testCaseEnqueuer.enqueueTestSuites(testSuites);
-  }
-
-  void eventFinishedTestCase(TestCase testCase) {
-    for (var listener in _eventListener) {
-      listener.done(testCase);
-    }
-  }
-
-  void eventTestAdded(TestCase testCase) {
-    for (var listener in _eventListener) {
-      listener.testAdded();
-    }
-  }
-
-  void eventAllTestsKnown() {
-    for (var listener in _eventListener) {
-      listener.allTestsKnown();
-    }
-  }
-
-  void eventAllTestsDone() {
-    for (var listener in _eventListener) {
-      listener.allDone();
-    }
-    _allDone();
-  }
-}
diff --git a/pkg/test_runner/lib/src/test_configurations.dart b/pkg/test_runner/lib/src/test_configurations.dart
index a6a2fdd..a452642 100644
--- a/pkg/test_runner/lib/src/test_configurations.dart
+++ b/pkg/test_runner/lib/src/test_configurations.dart
@@ -12,43 +12,38 @@
 import 'configuration.dart';
 import 'path.dart';
 import 'test_progress.dart';
-import 'test_case.dart';
+import 'process_queue.dart';
 import 'test_suite.dart';
 import 'utils.dart';
 
-/**
- * The directories that contain test suites which follow the conventions
- * required by [StandardTestSuite]'s forDirectory constructor.
- * New test suites should follow this convention because it makes it much
- * simpler to add them to test.dart.  Existing test suites should be
- * moved to here, if possible.
-*/
+/// The directories that contain test suites which follow the conventions
+/// required by [StandardTestSuite]'s forDirectory constructor.
+/// New test suites should follow this convention because it makes it much
+/// simpler to add them to test.dart.  Existing test suites should be
+/// moved to here, if possible.
 final TEST_SUITE_DIRECTORIES = [
-  new Path('third_party/pkg/dartdoc'),
-  new Path('pkg'),
-  new Path('third_party/pkg_tested'),
-  new Path('runtime/tests/vm'),
-  new Path('runtime/observatory/tests/service'),
-  new Path('runtime/observatory/tests/observatory_ui'),
-  new Path('samples'),
-  new Path('samples-dev'),
-  new Path('tests/compiler/dart2js'),
-  new Path('tests/compiler/dart2js_extra'),
-  new Path('tests/compiler/dart2js_native'),
-  new Path('tests/compiler/dartdevc_native'),
-  new Path('tests/corelib_2'),
-  new Path('tests/kernel'),
-  new Path('tests/language_2'),
-  new Path('tests/lib_2'),
-  new Path('tests/standalone'),
-  new Path('tests/standalone_2'),
-  new Path('tests/ffi'),
-  new Path('utils/tests/peg'),
+  Path('third_party/pkg/dartdoc'),
+  Path('pkg'),
+  Path('third_party/pkg_tested'),
+  Path('runtime/tests/vm'),
+  Path('runtime/observatory/tests/service'),
+  Path('runtime/observatory/tests/observatory_ui'),
+  Path('samples'),
+  Path('samples-dev'),
+  Path('tests/compiler/dart2js'),
+  Path('tests/compiler/dart2js_extra'),
+  Path('tests/compiler/dart2js_native'),
+  Path('tests/compiler/dartdevc_native'),
+  Path('tests/corelib_2'),
+  Path('tests/kernel'),
+  Path('tests/language_2'),
+  Path('tests/lib_2'),
+  Path('tests/standalone'),
+  Path('tests/standalone_2'),
+  Path('tests/ffi'),
+  Path('utils/tests/peg'),
 ];
 
-// This file is created by gclient runhooks.
-final VS_TOOLCHAIN_FILE = new Path("build/win_toolchain.json");
-
 Future testConfigurations(List<TestConfiguration> configurations) async {
   var startTime = DateTime.now();
   var startStopwatch = Stopwatch()..start();
@@ -120,20 +115,20 @@
 
     // If we specifically pass in a suite only run that.
     if (configuration.suiteDirectory != null) {
-      var suitePath = new Path(configuration.suiteDirectory);
-      testSuites.add(new PKGTestSuite(configuration, suitePath));
+      var suitePath = Path(configuration.suiteDirectory);
+      testSuites.add(PKGTestSuite(configuration, suitePath));
     } else {
       for (var testSuiteDir in TEST_SUITE_DIRECTORIES) {
         var name = testSuiteDir.filename;
         if (configuration.selectors.containsKey(name)) {
-          testSuites.add(
-              new StandardTestSuite.forDirectory(configuration, testSuiteDir));
+          testSuites
+              .add(StandardTestSuite.forDirectory(configuration, testSuiteDir));
         }
       }
 
       for (var key in configuration.selectors.keys) {
         if (key == 'co19_2') {
-          testSuites.add(new Co19TestSuite(configuration, key));
+          testSuites.add(Co19TestSuite(configuration, key));
         } else if ((configuration.compiler == Compiler.none ||
                 configuration.compiler == Compiler.dartk ||
                 configuration.compiler == Compiler.dartkb) &&
@@ -141,10 +136,10 @@
             key == 'vm') {
           // vm tests contain both cc tests (added here) and dart tests (added
           // in [TEST_SUITE_DIRECTORIES]).
-          testSuites.add(new VMTestSuite(configuration));
+          testSuites.add(VMTestSuite(configuration));
         } else if (configuration.compiler == Compiler.dart2analyzer) {
           if (key == 'analyze_library') {
-            testSuites.add(new AnalyzeLibraryTestSuite(configuration));
+            testSuites.add(AnalyzeLibraryTestSuite(configuration));
           }
         }
       }
@@ -188,49 +183,49 @@
       progressIndicator = Progress.compact;
       formatter = Formatter.color;
       printFailures = false;
-      eventListener.add(new StatusFileUpdatePrinter());
+      eventListener.add(StatusFileUpdatePrinter());
     }
     if (firstConf.silentFailures) {
       printFailures = false;
     }
-    eventListener.add(new SummaryPrinter());
+    eventListener.add(SummaryPrinter());
     if (printFailures) {
       // The buildbot has it's own failure summary since it needs to wrap it
       // into '@@@'-annotated sections.
       var printFailureSummary = progressIndicator != Progress.buildbot;
-      eventListener.add(new TestFailurePrinter(printFailureSummary, formatter));
+      eventListener.add(TestFailurePrinter(printFailureSummary, formatter));
     }
     if (firstConf.printPassingStdout) {
-      eventListener.add(new PassingStdoutPrinter(formatter));
+      eventListener.add(PassingStdoutPrinter(formatter));
     }
     eventListener.add(ProgressIndicator.fromProgress(
         progressIndicator, startTime, formatter));
     if (printTiming) {
-      eventListener.add(new TimingPrinter(startTime));
+      eventListener.add(TimingPrinter(startTime));
     }
-    eventListener.add(new SkippedCompilationsPrinter());
+    eventListener.add(SkippedCompilationsPrinter());
     if (progressIndicator == Progress.status) {
-      eventListener.add(new TimedProgressPrinter());
+      eventListener.add(TimedProgressPrinter());
     }
   }
 
   if (firstConf.writeResults) {
-    eventListener.add(new ResultWriter(firstConf, startTime, startStopwatch));
+    eventListener.add(ResultWriter(firstConf, startTime, startStopwatch));
   }
 
   if (firstConf.copyCoreDumps) {
-    eventListener.add(new UnexpectedCrashLogger());
+    eventListener.add(UnexpectedCrashLogger());
   }
 
   // The only progress indicator when listing tests should be the
   // the summary printer.
   if (listTests) {
-    eventListener.add(new SummaryPrinter(jsonOnly: reportInJson));
+    eventListener.add(SummaryPrinter(jsonOnly: reportInJson));
   } else {
     if (!firstConf.cleanExit) {
-      eventListener.add(new ExitCodeSetter());
+      eventListener.add(ExitCodeSetter());
     }
-    eventListener.add(new IgnoredTestMonitor());
+    eventListener.add(IgnoredTestMonitor());
   }
 
   // If any of the configurations need to access android devices we'll first
@@ -250,6 +245,6 @@
 
   // [firstConf] is needed here, since the ProcessQueue needs to know the
   // settings of 'noBatch' and 'local_ip'
-  new ProcessQueue(firstConf, maxProcesses, maxBrowserProcesses, startTime,
+  ProcessQueue(firstConf, maxProcesses, maxBrowserProcesses, startTime,
       testSuites, eventListener, allTestsFinished, verbose, adbDevicePool);
 }
diff --git a/pkg/test_runner/lib/src/test_progress.dart b/pkg/test_runner/lib/src/test_progress.dart
index 1a80df8..19cbea8 100644
--- a/pkg/test_runner/lib/src/test_progress.dart
+++ b/pkg/test_runner/lib/src/test_progress.dart
@@ -19,11 +19,11 @@
 /// Controls how message strings are processed before being displayed.
 class Formatter {
   /// Messages are left as-is.
-  static const normal = const Formatter._();
+  static const normal = Formatter._();
 
   /// Messages are wrapped in ANSI escape codes to color them for display on a
   /// terminal.
-  static const color = const _ColorFormatter();
+  static const color = _ColorFormatter();
 
   const Formatter._();
 
@@ -143,16 +143,16 @@
       // folder next to core dumps and name them
       // `binary.${mode}_${arch}_${binary_name}`.
       final binName = lastCommand.executable;
-      final binFile = new File(binName);
-      final binBaseName = new Path(binName).filename;
+      final binFile = File(binName);
+      final binBaseName = Path(binName).filename;
       if (!archivedBinaries.containsKey(binName) && binFile.existsSync()) {
         final archived = "binary.${mode}_${arch}_${binBaseName}";
-        TestUtils.copyFile(new Path(binName), new Path(archived));
+        TestUtils.copyFile(Path(binName), Path(archived));
         // On Windows also copy PDB file for the binary.
         if (Platform.isWindows) {
-          final pdbPath = new Path("$binName.pdb");
-          if (new File(pdbPath.toNativePath()).existsSync()) {
-            TestUtils.copyFile(pdbPath, new Path("$archived.pdb"));
+          final pdbPath = Path("$binName.pdb");
+          if (File(pdbPath.toNativePath()).existsSync()) {
+            TestUtils.copyFile(pdbPath, Path("$archived.pdb"));
           }
         }
         archivedBinaries[binName] = archived;
@@ -160,11 +160,11 @@
 
       final kernelServiceBaseName = 'kernel-service.dart.snapshot';
       final kernelService =
-          new File('${binFile.parent.path}/$kernelServiceBaseName');
+          File('${binFile.parent.path}/$kernelServiceBaseName');
       if (!archivedBinaries.containsKey(kernelService) &&
           kernelService.existsSync()) {
         final archived = "binary.${mode}_${arch}_${kernelServiceBaseName}";
-        TestUtils.copyFile(new Path(kernelService.path), new Path(archived));
+        TestUtils.copyFile(Path(kernelService.path), Path(archived));
         archivedBinaries[kernelServiceBaseName] = archived;
       }
 
@@ -180,7 +180,7 @@
         RandomAccessFile unexpectedCrashesFile;
         try {
           unexpectedCrashesFile =
-              new File('unexpected-crashes').openSync(mode: FileMode.append);
+              File('unexpected-crashes').openSync(mode: FileMode.append);
           unexpectedCrashesFile.writeStringSync(
               "${test.displayName},${pid},${binaries.join(',')}\n");
         } catch (e) {
@@ -216,8 +216,8 @@
 }
 
 class TimingPrinter extends EventListener {
-  final _command2testCases = new Map<Command, List<TestCase>>();
-  final _commandOutputs = new Set<CommandOutput>();
+  final _commandToTestCases = <Command, List<TestCase>>{};
+  final _commandOutputs = <CommandOutput>{};
   DateTime _startTime;
 
   TimingPrinter(this._startTime);
@@ -226,22 +226,22 @@
     for (var commandOutput in testCase.commandOutputs.values) {
       var command = commandOutput.command;
       _commandOutputs.add(commandOutput);
-      _command2testCases.putIfAbsent(command, () => <TestCase>[]);
-      _command2testCases[command].add(testCase);
+      _commandToTestCases.putIfAbsent(command, () => <TestCase>[]);
+      _commandToTestCases[command].add(testCase);
     }
   }
 
   void allDone() {
-    Duration d = (new DateTime.now()).difference(_startTime);
+    var d = DateTime.now().difference(_startTime);
     print('\n--- Total time: ${_timeString(d)} ---');
     var outputs = _commandOutputs.toList();
     outputs.sort((a, b) {
       return b.time.inMilliseconds - a.time.inMilliseconds;
     });
-    for (int i = 0; i < 20 && i < outputs.length; i++) {
+    for (var i = 0; i < 20 && i < outputs.length; i++) {
       var commandOutput = outputs[i];
       var command = commandOutput.command;
-      var testCases = _command2testCases[command];
+      var testCases = _commandToTestCases[command];
 
       var testCasesDescription = testCases.map((testCase) {
         return "${testCase.configurationString}/${testCase.displayName}";
@@ -255,7 +255,7 @@
 }
 
 class StatusFileUpdatePrinter extends EventListener {
-  var statusToConfigs = new Map<String, List<String>>();
+  var statusToConfigs = <String, List<String>>{};
   var _failureSummary = <String>[];
 
   void done(TestCase test) {
@@ -399,7 +399,7 @@
   void done(TestCase test) {
     if (!test.unexpectedOutput) {
       var lines = <String>[];
-      var output = new OutputWriter(_formatter, lines);
+      var output = OutputWriter(_formatter, lines);
       for (final command in test.commands) {
         var commandOutput = test.commandOutputs[command];
         if (commandOutput == null) continue;
@@ -422,15 +422,15 @@
       Progress progress, DateTime startTime, Formatter formatter) {
     switch (progress) {
       case Progress.compact:
-        return new CompactProgressIndicator(startTime, formatter);
+        return CompactProgressIndicator(startTime, formatter);
       case Progress.line:
-        return new LineProgressIndicator();
+        return LineProgressIndicator();
       case Progress.verbose:
-        return new VerboseProgressIndicator(startTime);
+        return VerboseProgressIndicator(startTime);
       case Progress.status:
-        return new ProgressIndicator(startTime);
+        return ProgressIndicator(startTime);
       case Progress.buildbot:
-        return new BuildbotProgressIndicator(startTime);
+        return BuildbotProgressIndicator(startTime);
     }
 
     throw "unreachable";
@@ -491,7 +491,7 @@
     var progressPadded = (_allTestsKnown ? percent : '--').padLeft(3);
     var passedPadded = _passedTests.toString().padLeft(5);
     var failedPadded = _failedTests.toString().padLeft(5);
-    var elapsed = (new DateTime.now()).difference(_startTime);
+    var elapsed = (DateTime.now()).difference(_startTime);
     var progressLine = '\r[${_timeString(elapsed)} | $progressPadded% | '
         '+${_formatter.passed(passedPadded)} | '
         '-${_formatter.failed(failedPadded)}]';
@@ -604,7 +604,7 @@
 List<String> _buildFailureOutput(TestCase test,
     [Formatter formatter = Formatter.normal]) {
   var lines = <String>[];
-  var output = new OutputWriter(formatter, lines);
+  var output = OutputWriter(formatter, lines);
   _writeFailureStatus(test, formatter, output);
   _writeFailureOutput(test, formatter, output);
   _writeFailureReproductionCommands(test, formatter, output);
@@ -614,7 +614,7 @@
 List<String> _buildFailureLog(TestCase test) {
   final formatter = Formatter.normal;
   final lines = <String>[];
-  final output = new OutputWriter(formatter, lines);
+  final output = OutputWriter(formatter, lines);
   _writeFailureOutput(test, formatter, output);
   _writeFailureReproductionCommands(test, formatter, output);
   return lines;
@@ -717,7 +717,7 @@
 
   void done(TestCase test) {
     if (_configuration != test.configuration) {
-      throw new Exception("Two configurations in the same run. "
+      throw Exception("Two configurations in the same run. "
           "Cannot output results for multiple configurations.");
     }
     final name = test.displayName;
diff --git a/pkg/test_runner/lib/src/test_suite.dart b/pkg/test_runner/lib/src/test_suite.dart
index c7efac8..1204a81 100644
--- a/pkg/test_runner/lib/src/test_suite.dart
+++ b/pkg/test_runner/lib/src/test_suite.dart
@@ -2,16 +2,14 @@
 // 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.
 
-/**
- * Classes and methods for enumerating and preparing tests.
- *
- * This library includes:
- *
- * - Creating tests by listing all the Dart files in certain directories,
- *   and creating [TestCase]s for those files that meet the relevant criteria.
- * - Preparing tests, including copying files and frameworks to temporary
- *   directories, and computing the command line and arguments to be run.
- */
+/// Classes and methods for enumerating and preparing tests.
+///
+/// This library includes:
+///
+/// - Creating tests by listing all the Dart files in certain directories,
+///   and creating [TestCase]s for those files that meet the relevant criteria.
+/// - Preparing tests, including copying files and frameworks to temporary
+///   directories, and computing the command line and arguments to be run.
 import 'dart:async';
 import 'dart:io';
 import 'dart:math';
@@ -20,7 +18,6 @@
 
 import 'browser.dart';
 import 'command.dart';
-import 'compiler_configuration.dart';
 import 'configuration.dart';
 import 'expectation_set.dart';
 import 'multitest.dart';
@@ -32,59 +29,54 @@
 import 'testing_servers.dart';
 import 'utils.dart';
 
-RegExp multiHtmlTestGroupRegExp = new RegExp(r"\s*[^/]\s*group\('[^,']*");
-RegExp multiHtmlTestRegExp = new RegExp(r"useHtmlIndividualConfiguration\(\)");
-// Require at least one non-space character before '//[/#]'
-RegExp multiTestRegExp = new RegExp(r"\S *"
-    r"//[#/] \w+:(.*)");
-RegExp dartExtension = new RegExp(r'\.dart$');
+RegExp _multiHtmlTestGroupRegExp = RegExp(r"\s*[^/]\s*group\('[^,']*");
+RegExp _multiHtmlTestRegExp = RegExp(r"useHtmlIndividualConfiguration\(\)");
 
-/**
- * A simple function that tests [arg] and returns `true` or `false`.
- */
-typedef bool Predicate<T>(T arg);
+/// Require at least one non-space character before '//[/#]'.
+RegExp _multiTestRegExp = RegExp(r"\S *//[#/] \w+:(.*)");
 
-typedef void CreateTest(Path filePath, Path originTestPath,
+typedef TestCaseEvent = void Function(TestCase testCase);
+
+/// A simple function that tests [arg] and returns `true` or `false`.
+typedef Predicate<T> = bool Function(T arg);
+
+typedef CreateTest = void Function(Path filePath, Path originTestPath,
     {bool hasSyntaxError,
     bool hasCompileError,
     bool hasRuntimeError,
     bool hasStaticWarning,
     String multitestKey});
 
-typedef void VoidFunction();
+typedef VoidFunction = void Function();
 
-/**
- * Calls [function] asynchronously. Returns a future that completes with the
- * result of the function. If the function is `null`, returns a future that
- * completes immediately with `null`.
- */
+/// Calls [function] asynchronously. Returns a future that completes with the
+/// result of the function. If the function is `null`, returns a future that
+/// completes immediately with `null`.
 Future asynchronously<T>(T function()) {
-  if (function == null) return new Future<T>.value(null);
+  if (function == null) return Future<T>.value(null);
 
-  var completer = new Completer<T>();
+  var completer = Completer<T>();
   Timer.run(() => completer.complete(function()));
 
   return completer.future;
 }
 
-/** A completer that waits until all added [Future]s complete. */
+/// A completer that waits until all added [Future]s complete.
 // TODO(rnystrom): Copied from web_components. Remove from here when it gets
 // added to dart:core. (See #6626.)
 class FutureGroup {
-  static const _FINISHED = -1;
+  static const _finished = -1;
   int _pending = 0;
-  Completer<List> _completer = new Completer<List>();
-  final List<Future> futures = <Future>[];
+  Completer<List> _completer = Completer();
+  final List<Future> futures = [];
   bool wasCompleted = false;
 
-  /**
-   * Wait for [task] to complete (assuming this barrier has not already been
-   * marked as completed, otherwise you'll get an exception indicating that a
-   * future has already been completed).
-   */
+  /// Wait for [task] to complete (assuming this barrier has not already been
+  /// marked as completed, otherwise you'll get an exception indicating that a
+  /// future has already been completed).
   void add(Future task) {
-    if (_pending == _FINISHED) {
-      throw new Exception("FutureFutureAlreadyCompleteException");
+    if (_pending == _finished) {
+      throw Exception("FutureFutureAlreadyCompleteException");
     }
     _pending++;
     var handledTaskFuture = task.catchError((e, StackTrace s) {
@@ -95,7 +87,7 @@
     }).then((_) {
       _pending--;
       if (_pending == 0) {
-        _pending = _FINISHED;
+        _pending = _finished;
         if (!wasCompleted) {
           _completer.complete(futures);
           wasCompleted = true;
@@ -108,18 +100,17 @@
   Future<List> get future => _completer.future;
 }
 
-/**
- * A TestSuite represents a collection of tests.  It creates a [TestCase]
- * object for each test to be run, and passes the test cases to a callback.
- *
- * Most TestSuites represent a directory or directory tree containing tests,
- * and a status file containing the expected results when these tests are run.
- */
+/// A TestSuite represents a collection of tests.  It creates a [TestCase]
+/// object for each test to be run, and passes the test cases to a callback.
+///
+/// Most TestSuites represent a directory or directory tree containing tests,
+/// and a status file containing the expected results when these tests are run.
 abstract class TestSuite {
   final TestConfiguration configuration;
   final String suiteName;
   final List<String> statusFilePaths;
-  // This function is set by subclasses before enqueueing starts.
+
+  /// This function is set by subclasses before enqueueing starts.
   Function doTest;
   Map<String, String> _environmentOverrides;
 
@@ -131,24 +122,18 @@
       _environmentOverrides['DART_SUPPRESS_WER'] = '1';
       if (configuration.copyCoreDumps) {
         _environmentOverrides['DART_CRASHPAD_HANDLER'] =
-            new Path(buildDir + '/crashpad_handler.exe')
-                .absolute
-                .toNativePath();
+            Path(buildDir + '/crashpad_handler.exe').absolute.toNativePath();
       }
     }
   }
 
   Map<String, String> get environmentOverrides => _environmentOverrides;
 
-  /**
-   * The output directory for this suite's configuration.
-   */
+  /// The output directory for this suite's configuration.
   String get buildDir => configuration.buildDirectory;
 
-  /**
-   * The path to the compiler for this suite's configuration. Returns `null` if
-   * no compiler should be used.
-   */
+  /// The path to the compiler for this suite's configuration. Returns `null` if
+  /// no compiler should be used.
   String get compilerPath {
     var compilerConfiguration = configuration.compilerConfiguration;
     if (!compilerConfiguration.hasCompiler) return null;
@@ -159,25 +144,23 @@
     return name;
   }
 
-  /**
-   * Call the callback function onTest with a [TestCase] argument for each
-   * test in the suite.  When all tests have been processed, call [onDone].
-   *
-   * The [testCache] argument provides a persistent store that can be used to
-   * cache information about the test suite, so that directories do not need
-   * to be listed each time.
-   */
+  /// Call the callback function onTest with a [TestCase] argument for each
+  /// test in the suite.  When all tests have been processed, call [onDone].
+  ///
+  /// The [testCache] argument provides a persistent store that can be used to
+  /// cache information about the test suite, so that directories do not need
+  /// to be listed each time.
   Future forEachTest(
       TestCaseEvent onTest, Map<String, List<TestInformation>> testCache,
       [VoidFunction onDone]);
 
-  // This function will be called for every TestCase of this test suite.
-  // It will
-  //  - handle sharding
-  //  - update SummaryReport
-  //  - handle SKIP/SKIP_BY_DESIGN markers
-  //  - test if the selector matches
-  // and will enqueue the test (if necessary).
+  /// This function will be called for every TestCase of this test suite.
+  /// It will:
+  ///  - handle sharding
+  ///  - update SummaryReport
+  ///  - handle SKIP/SKIP_BY_DESIGN markers
+  ///  - test if the selector matches
+  /// and will enqueue the test (if necessary).
   void enqueueNewTestCase(
       String testName, List<Command> commands, Set<Expectation> expectations,
       [TestInformation info]) {
@@ -196,8 +179,7 @@
     }
 
     var negative = info != null ? isNegative(info) : false;
-    var testCase = new TestCase(
-        displayName, commands, configuration, expectations,
+    var testCase = TestCase(displayName, commands, configuration, expectations,
         info: info);
     if (negative &&
         configuration.runtimeConfiguration.shouldSkipNegativeTests) {
@@ -264,20 +246,20 @@
     relative = relative.directoryPath.append(relative.filenameWithoutExtension);
     String testUniqueName = TestUtils.getShortName(relative.toString());
 
-    Path generatedTestPath = new Path(buildDir)
+    Path generatedTestPath = Path(buildDir)
         .append('generated_$name')
         .append(dirname)
         .append(testUniqueName);
 
-    TestUtils.mkdirRecursive(new Path('.'), generatedTestPath);
-    return new File(generatedTestPath.toNativePath())
+    TestUtils.mkdirRecursive(Path('.'), generatedTestPath);
+    return File(generatedTestPath.toNativePath())
         .absolute
         .path
         .replaceAll('\\', '/');
   }
 
   String buildTestCaseDisplayName(Path suiteDir, Path originTestPath,
-      {String multitestName: ""}) {
+      {String multitestName = ""}) {
     Path testNamePath = originTestPath.relativeTo(suiteDir);
     var directory = testNamePath.directoryPath;
     var filenameWithoutExt = testNamePath.filenameWithoutExtension;
@@ -294,11 +276,8 @@
     return testName;
   }
 
-  /**
-   * Create a directories for generated assets (tests, html files,
-   * pubspec checkouts ...).
-   */
-
+  /// Create a directories for generated assets (tests, html files,
+  /// pubspec checkouts ...).
   String createOutputDirectory(Path testPath) {
     var checked = configuration.isChecked ? '-checked' : '';
     var legacy = configuration.noPreviewDart2 ? '-legacy' : '';
@@ -355,7 +334,7 @@
     // For listing the tests we use the '$runnerName.host' binary if it exists
     // and use '$runnerName' if it doesn't.
     var hostBinary = '$targetRunnerPath.host$binarySuffix';
-    if (new File(hostBinary).existsSync()) {
+    if (File(hostBinary).existsSync()) {
       hostRunnerPath = hostBinary;
     } else {
       hostRunnerPath = targetRunnerPath;
@@ -368,10 +347,10 @@
 
     var statusFiles =
         statusFilePaths.map((statusFile) => "$dartDir/$statusFile").toList();
-    var expectations = new ExpectationSet.read(statusFiles, configuration);
+    var expectations = ExpectationSet.read(statusFiles, configuration);
 
     try {
-      for (VmUnitTest test in await _listTests(hostRunnerPath)) {
+      for (VMUnitTest test in await _listTests(hostRunnerPath)) {
         _addTest(expectations, test);
       }
 
@@ -384,7 +363,7 @@
     }
   }
 
-  void _addTest(ExpectationSet testExpectations, VmUnitTest test) {
+  void _addTest(ExpectationSet testExpectations, VMUnitTest test) {
     final fullName = 'cc/${test.name}';
     var expectations = testExpectations.expectations(fullName);
 
@@ -416,7 +395,7 @@
       final filename = configuration.architecture == Architecture.x64
           ? '$buildDir/gen/kernel-service.dart.snapshot'
           : '$buildDir/gen/kernel_service.dill';
-      final dfePath = new Path(filename).absolute.toNativePath();
+      final dfePath = Path(filename).absolute.toNativePath();
       // '--dfe' has to be the first argument for run_vm_test to pick it up.
       args.insert(0, '--dfe=$dfePath');
     }
@@ -431,7 +410,7 @@
     enqueueNewTestCase(fullName, [command], expectations, testInfo);
   }
 
-  Future<Iterable<VmUnitTest>> _listTests(String runnerPath) async {
+  Future<Iterable<VMUnitTest>> _listTests(String runnerPath) async {
     var result = await Process.run(runnerPath, ["--list"]);
     if (result.exitCode != 0) {
       throw "Failed to list tests: '$runnerPath --list'. "
@@ -444,16 +423,16 @@
         .where((name) => name.isNotEmpty)
         .map((String line) {
       final parts = line.split(' ');
-      return VmUnitTest(parts[0].trim(), parts.skip(1).single);
+      return VMUnitTest(parts[0].trim(), parts.skip(1).single);
     });
   }
 }
 
-class VmUnitTest {
+class VMUnitTest {
   final String name;
   final String expectation;
 
-  VmUnitTest(this.name, this.expectation);
+  VMUnitTest(this.name, this.expectation);
 }
 
 class TestInformation {
@@ -475,16 +454,14 @@
       this.hasCompileError,
       this.hasRuntimeError,
       this.hasStaticWarning,
-      {this.multitestKey: '',
-      this.hasCrash: false}) {
+      {this.multitestKey = '',
+      this.hasCrash = false}) {
     assert(filePath.isAbsolute);
   }
 }
 
-/**
- * A standard [TestSuite] implementation that searches for tests in a
- * directory, and creates [TestCase]s that compile and/or run them.
- */
+/// A standard [TestSuite] implementation that searches for tests in a
+/// directory, and creates [TestCase]s that compile and/or run them.
 class StandardTestSuite extends TestSuite {
   final Path suiteDir;
   ExpectationSet testExpectations;
@@ -498,26 +475,26 @@
 
   StandardTestSuite(TestConfiguration configuration, String suiteName,
       Path suiteDirectory, List<String> statusFilePaths,
-      {bool recursive: false})
+      {bool recursive = false})
       : dartDir = Repository.dir,
         listRecursively = recursive,
         suiteDir = Repository.dir.join(suiteDirectory),
         extraVmOptions = configuration.vmOptions,
         super(configuration, suiteName, statusFilePaths) {
-    // Initialize _dart2JsBootstrapDependencies
+    // Initialize _dart2JsBootstrapDependencies.
     if (!configuration.useSdk) {
       _dart2JsBootstrapDependencies = [];
     } else {
       _dart2JsBootstrapDependencies = [
         Uri.base
-            .resolveUri(new Uri.directory(buildDir))
+            .resolveUri(Uri.directory(buildDir))
             .resolve('dart-sdk/bin/snapshots/dart2js.dart.snapshot')
       ];
     }
 
-    // Initialize _testListPossibleFilenames
+    // Initialize _testListPossibleFilenames.
     if (configuration.testList != null) {
-      _testListPossibleFilenames = Set<String>();
+      _testListPossibleFilenames = <String>{};
       for (String s in configuration.testList) {
         if (s.startsWith("$suiteName/")) {
           s = s.substring(s.indexOf('/') + 1);
@@ -537,46 +514,44 @@
       }
     }
 
-    // Initialize _selectorFilenameRegExp
-    String pattern = configuration.selectors[suiteName].pattern;
+    // Initialize _selectorFilenameRegExp.
+    var pattern = configuration.selectors[suiteName].pattern;
     if (pattern.contains("/")) {
-      String lastPart = pattern.substring(pattern.lastIndexOf("/") + 1);
+      var lastPart = pattern.substring(pattern.lastIndexOf("/") + 1);
       // If the selector is a multitest name ending in a number or 'none'
       // we also accept test file names that don't contain that last part.
       if (int.tryParse(lastPart) != null || lastPart == "none") {
         pattern = pattern.substring(0, pattern.lastIndexOf("/"));
       }
     }
-    _selectorFilenameRegExp = new RegExp(pattern);
+    _selectorFilenameRegExp = RegExp(pattern);
   }
 
-  /**
-   * Creates a test suite whose file organization matches an expected structure.
-   * To use this, your suite should look like:
-   *
-   *     dart/
-   *       path/
-   *         to/
-   *           mytestsuite/
-   *             mytestsuite.status
-   *             example1_test.dart
-   *             example2_test.dart
-   *             example3_test.dart
-   *
-   * The important parts:
-   *
-   * * The leaf directory name is the name of your test suite.
-   * * The status file uses the same name.
-   * * Test files are directly in that directory and end in "_test.dart".
-   *
-   * If you follow that convention, then you can construct one of these like:
-   *
-   * new StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite');
-   *
-   * instead of having to create a custom [StandardTestSuite] subclass. In
-   * particular, if you add 'path/to/mytestsuite' to [TEST_SUITE_DIRECTORIES]
-   * in test.dart, this will all be set up for you.
-   */
+  /// Creates a test suite whose file organization matches an expected structure.
+  /// To use this, your suite should look like:
+  ///
+  ///     dart/
+  ///       path/
+  ///         to/
+  ///           mytestsuite/
+  ///             mytestsuite.status
+  ///             example1_test.dart
+  ///             example2_test.dart
+  ///             example3_test.dart
+  ///
+  /// The important parts:
+  ///
+  /// * The leaf directory name is the name of your test suite.
+  /// * The status file uses the same name.
+  /// * Test files are directly in that directory and end in "_test.dart".
+  ///
+  /// If you follow that convention, then you can construct one of these like:
+  ///
+  /// new StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite');
+  ///
+  /// instead of having to create a custom [StandardTestSuite] subclass. In
+  /// particular, if you add 'path/to/mytestsuite' to [TEST_SUITE_DIRECTORIES]
+  /// in test.dart, this will all be set up for you.
   factory StandardTestSuite.forDirectory(
       TestConfiguration configuration, Path directory) {
     var name = directory.filename;
@@ -594,7 +569,7 @@
       '$directory/${name}_vm.status',
     ];
 
-    return new StandardTestSuite(configuration, name, directory, status_paths,
+    return StandardTestSuite(configuration, name, directory, status_paths,
         recursive: true);
   }
 
@@ -627,28 +602,26 @@
     if (onDone != null) onDone();
   }
 
-  /**
-   * Reads the status files and completes with the parsed expectations.
-   */
+  /// Reads the status files and completes with the parsed expectations.
   ExpectationSet readExpectations() {
     var statusFiles = statusFilePaths.where((String statusFilePath) {
-      var file = new File(dartDir.append(statusFilePath).toNativePath());
+      var file = File(dartDir.append(statusFilePath).toNativePath());
       return file.existsSync();
     }).map((statusFilePath) {
       return dartDir.append(statusFilePath).toNativePath();
     }).toList();
 
-    return new ExpectationSet.read(statusFiles, configuration);
+    return ExpectationSet.read(statusFiles, configuration);
   }
 
   Future enqueueTests() {
-    Directory dir = new Directory(suiteDir.toNativePath());
+    Directory dir = Directory(suiteDir.toNativePath());
     return dir.exists().then((exists) {
       if (!exists) {
         print('Directory containing tests missing: ${suiteDir.toNativePath()}');
-        return new Future.value(null);
+        return Future.value(null);
       } else {
-        var group = new FutureGroup();
+        var group = FutureGroup();
         enqueueDirectory(dir, group);
         return group.future;
       }
@@ -679,7 +652,7 @@
 
     if (!isTestFile(filename)) return;
 
-    var optionsFromFile = readOptionsFromFile(new Uri.file(filename));
+    var optionsFromFile = readOptionsFromFile(Uri.file(filename));
     CreateTest createTestCase = makeTestCaseCreator(optionsFromFile);
 
     if (optionsFromFile['isMultitest'] as bool) {
@@ -709,11 +682,11 @@
     if (optionsFromFile['packageRoot'] == null &&
         optionsFromFile['packages'] == null) {
       if (configuration.packageRoot != null) {
-        packageRoot = new Path(configuration.packageRoot);
+        packageRoot = Path(configuration.packageRoot);
         optionsFromFile['packageRoot'] = packageRoot.toNativePath();
       }
       if (configuration.packages != null) {
-        Path packages = new Path(configuration.packages);
+        Path packages = Path(configuration.packages);
         optionsFromFile['packages'] = packages.toNativePath();
       }
     }
@@ -801,23 +774,22 @@
       var path = info.filePath;
       if (vmOptionsVariant != 0) {
         // Ensure a unique directory for each test case.
-        path = path.join(new Path(vmOptionsVariant.toString()));
+        path = path.join(Path(vmOptionsVariant.toString()));
       }
       tempDir = createCompilationOutputDirectory(path);
 
       var otherResources =
           info.optionsFromFile['otherResources'] as List<String>;
       for (var name in otherResources) {
-        var namePath = new Path(name);
+        var namePath = Path(name);
         var fromPath = info.filePath.directoryPath.join(namePath);
-        new File('$tempDir/$name').parent.createSync(recursive: true);
-        new File(fromPath.toNativePath()).copySync('$tempDir/$name');
+        File('$tempDir/$name').parent.createSync(recursive: true);
+        File(fromPath.toNativePath()).copySync('$tempDir/$name');
       }
     }
 
-    CommandArtifact compilationArtifact =
-        compilerConfiguration.computeCompilationArtifact(
-            tempDir, compileTimeArguments, environmentOverrides);
+    var compilationArtifact = compilerConfiguration.computeCompilationArtifact(
+        tempDir, compileTimeArguments, environmentOverrides);
     if (!configuration.skipCompilation) {
       commands.addAll(compilationArtifact.commands);
     }
@@ -835,20 +807,19 @@
             s.replaceAll("__RANDOM__", "${Random().nextInt(0x7fffffff)}"))
         .toList();
 
-    List<String> runtimeArguments =
-        compilerConfiguration.computeRuntimeArguments(
-            configuration.runtimeConfiguration,
-            info,
-            vmOptions,
-            sharedOptions,
-            dartOptions,
-            args,
-            compilationArtifact);
+    var runtimeArguments = compilerConfiguration.computeRuntimeArguments(
+        configuration.runtimeConfiguration,
+        info,
+        vmOptions,
+        sharedOptions,
+        dartOptions,
+        args,
+        compilationArtifact);
 
-    Map<String, String> environment = environmentOverrides;
+    var environment = environmentOverrides;
     var extraEnv = info.optionsFromFile['environment'] as Map<String, String>;
     if (extraEnv != null) {
-      environment = new Map.from(environment)..addAll(extraEnv);
+      environment = {...environment, ...extraEnv};
     }
 
     return commands
@@ -865,10 +836,10 @@
         {bool hasSyntaxError,
         bool hasCompileError,
         bool hasRuntimeError,
-        bool hasStaticWarning: false,
+        bool hasStaticWarning = false,
         String multitestKey}) {
       // Cache the test information for each test case.
-      var info = new TestInformation(filePath, originTestPath, optionsFromFile,
+      var info = TestInformation(filePath, originTestPath, optionsFromFile,
           hasSyntaxError, hasCompileError, hasRuntimeError, hasStaticWarning,
           multitestKey: multitestKey);
       cachedTests.add(info);
@@ -876,30 +847,30 @@
     };
   }
 
-  /**
-   * _createUrlPathFromFile takes a [file], which is either located in the dart
-   * or in the build directory, and will return a String representing
-   * the relative path to either the dart or the build directory.
-   * Thus, the returned [String] will be the path component of the URL
-   * corresponding to [file] (the http server serves files relative to the
-   * dart/build directories).
-   */
+  /// Takes a [file], which is either located in the dart or in the build
+  /// directory, and returns a String representing the relative path to either
+  /// the dart or the build directory.
+  ///
+  /// Thus, the returned [String] will be the path component of the URL
+  /// corresponding to [file] (the HTTP server serves files relative to the
+  /// dart/build directories).
   String _createUrlPathFromFile(Path file) {
     file = file.absolute;
 
-    var relativeBuildDir = new Path(configuration.buildDirectory);
+    var relativeBuildDir = Path(configuration.buildDirectory);
     var buildDir = relativeBuildDir.absolute;
     var dartDir = Repository.dir.absolute;
 
     var fileString = file.toString();
     if (fileString.startsWith(buildDir.toString())) {
       var fileRelativeToBuildDir = file.relativeTo(buildDir);
-      return "/$PREFIX_BUILDDIR/$fileRelativeToBuildDir";
+      return "/$prefixBuildDir/$fileRelativeToBuildDir";
     } else if (fileString.startsWith(dartDir.toString())) {
       var fileRelativeToDartDir = file.relativeTo(dartDir);
-      return "/$PREFIX_DARTDIR/$fileRelativeToDartDir";
+      return "/$prefixDartDir/$fileRelativeToDartDir";
     }
-    // Unreachable
+
+    // Unreachable.
     print("Cannot create URL for path $file. Not in build or dart directory.");
     exit(1);
     return null;
@@ -918,7 +889,7 @@
     if (subtestName != null) {
       parameters['group'] = subtestName;
     }
-    return new Uri(
+    return Uri(
             scheme: 'http',
             host: configuration.localIP,
             port: serverPort,
@@ -954,7 +925,7 @@
 
     // Use existing HTML document if available.
     String content;
-    var customHtml = new File(
+    var customHtml = File(
         info.filePath.directoryPath.append('$nameNoExt.html').toNativePath());
     if (customHtml.existsSync()) {
       outputDir = tempDir;
@@ -963,18 +934,18 @@
     } else {
       // Synthesize an HTML file for the test.
       if (configuration.compiler == Compiler.dart2js) {
-        var scriptPath = _createUrlPathFromFile(
-            new Path('$compilationTempDir/$nameNoExt.js'));
+        var scriptPath =
+            _createUrlPathFromFile(Path('$compilationTempDir/$nameNoExt.js'));
         content = dart2jsHtml(fileName, scriptPath);
       } else {
         var jsDir =
-            new Path(compilationTempDir).relativeTo(Repository.dir).toString();
+            Path(compilationTempDir).relativeTo(Repository.dir).toString();
         content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
       }
     }
 
     var htmlPath = '$tempDir/test.html';
-    new File(htmlPath).writeAsStringSync(content);
+    File(htmlPath).writeAsStringSync(content);
 
     // Construct the command(s) that compile all the inputs needed by the
     // browser test.
@@ -1019,7 +990,7 @@
     // Construct the command that executes the browser test.
     commands = commands.toList();
 
-    var htmlPathSubtest = _createUrlPathFromFile(new Path(htmlPath));
+    var htmlPathSubtest = _createUrlPathFromFile(Path(htmlPath));
     var fullHtmlPath = _uriForBrowserTest(htmlPathSubtest, subtestName);
 
     commands.add(Command.browserTest(fullHtmlPath, configuration,
@@ -1034,7 +1005,7 @@
       Path filePath, Map<String, dynamic> optionsFromFile) {
     var args = configuration.standardOptions.toList();
 
-    String packages = packagesArgument(optionsFromFile['packageRoot'] as String,
+    var packages = packagesArgument(optionsFromFile['packageRoot'] as String,
         optionsFromFile['packages'] as String);
     if (packages != null) {
       args.add(packages);
@@ -1067,74 +1038,72 @@
     }
   }
 
-  /**
-   * Special options for individual tests are currently specified in various
-   * ways: with comments directly in test files, by using certain imports, or by
-   * creating additional files in the test directories.
-   *
-   * Here is a list of options that are used by 'test.dart' today:
-   *   - Flags can be passed to the vm process that runs the test by adding a
-   *   comment to the test file:
-   *
-   *     // VMOptions=--flag1 --flag2
-   *
-   *   - Flags can be passed to dart2js, vm or dartdevc by adding a comment to
-   *   the test file:
-   *
-   *     // SharedOptions=--flag1 --flag2
-   *
-   *   - Flags can be passed to dart2js by adding a comment to the test file:
-   *
-   *     // dart2jsOptions=--flag1 --flag2
-   *
-   *   - Flags can be passed to the dart script that contains the test also
-   *   using comments, as follows:
-   *
-   *     // DartOptions=--flag1 --flag2
-   *
-   *   - Extra environment variables can be passed to the process that runs
-   *   the test by adding comment(s) to the test file:
-   *
-   *     // Environment=ENV_VAR1=foo bar
-   *     // Environment=ENV_VAR2=bazz
-   *
-   *   - Most tests are not web tests, but can (and will be) wrapped within
-   *   an HTML file and another script file to test them also on browser
-   *   environments (e.g. language and corelib tests are run this way).
-   *   We deduce that if a file with the same name as the test, but ending in
-   *   .html instead of .dart exists, the test was intended to be a web test
-   *   and no wrapping is necessary.
-   *
-   *     // SharedObjects=foobar
-   *
-   *   - This test requires libfoobar.so, libfoobar.dylib or foobar.dll to be
-   *   in the system linker path of the VM.
-   *
-   *   - 'test.dart' assumes tests fail if
-   *   the process returns a non-zero exit code (in the case of web tests, we
-   *   check for PASS/FAIL indications in the test output).
-   *
-   * This method is static as the map is cached and shared amongst
-   * configurations, so it may not use [configuration].
-   */
+  /// Special options for individual tests are currently specified in various
+  /// ways: with comments directly in test files, by using certain imports, or
+  /// by creating additional files in the test directories.
+  ///
+  /// Here is a list of options that are used by 'test.dart' today:
+  ///   - Flags can be passed to the vm process that runs the test by adding a
+  ///   comment to the test file:
+  ///
+  ///     // VMOptions=--flag1 --flag2
+  ///
+  ///   - Flags can be passed to dart2js, vm or dartdevc by adding a comment to
+  ///   the test file:
+  ///
+  ///     // SharedOptions=--flag1 --flag2
+  ///
+  ///   - Flags can be passed to dart2js by adding a comment to the test file:
+  ///
+  ///     // dart2jsOptions=--flag1 --flag2
+  ///
+  ///   - Flags can be passed to the dart script that contains the test also
+  ///   using comments, as follows:
+  ///
+  ///     // DartOptions=--flag1 --flag2
+  ///
+  ///   - Extra environment variables can be passed to the process that runs
+  ///   the test by adding comment(s) to the test file:
+  ///
+  ///     // Environment=ENV_VAR1=foo bar
+  ///     // Environment=ENV_VAR2=bazz
+  ///
+  ///   - Most tests are not web tests, but can (and will be) wrapped within
+  ///   an HTML file and another script file to test them also on browser
+  ///   environments (e.g. language and corelib tests are run this way).
+  ///   We deduce that if a file with the same name as the test, but ending in
+  ///   .html instead of .dart exists, the test was intended to be a web test
+  ///   and no wrapping is necessary.
+  ///
+  ///     // SharedObjects=foobar
+  ///
+  ///   - This test requires libfoobar.so, libfoobar.dylib or foobar.dll to be
+  ///   in the system linker path of the VM.
+  ///
+  ///   - 'test.dart' assumes tests fail if
+  ///   the process returns a non-zero exit code (in the case of web tests, we
+  ///   check for PASS/FAIL indications in the test output).
+  ///
+  /// This method is static as the map is cached and shared amongst
+  /// configurations, so it may not use [configuration].
   Map<String, dynamic> readOptionsFromFile(Uri uri) {
     if (uri.path.endsWith('.dill')) {
       return optionsFromKernelFile();
     }
-    RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)");
-    RegExp environmentRegExp = new RegExp(r"// Environment=(.*)");
-    RegExp otherResourcesRegExp = new RegExp(r"// OtherResources=(.*)");
-    RegExp sharedObjectsRegExp = new RegExp(r"// SharedObjects=(.*)");
-    RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
-    RegExp packagesRegExp = new RegExp(r"// Packages=(.*)");
-    RegExp isolateStubsRegExp = new RegExp(r"// IsolateStubs=(.*)");
+    var testOptionsRegExp = RegExp(r"// VMOptions=(.*)");
+    var environmentRegExp = RegExp(r"// Environment=(.*)");
+    var otherResourcesRegExp = RegExp(r"// OtherResources=(.*)");
+    var sharedObjectsRegExp = RegExp(r"// SharedObjects=(.*)");
+    var packageRootRegExp = RegExp(r"// PackageRoot=(.*)");
+    var packagesRegExp = RegExp(r"// Packages=(.*)");
+    var isolateStubsRegExp = RegExp(r"// IsolateStubs=(.*)");
     // TODO(gram) Clean these up once the old directives are not supported.
-    RegExp domImportRegExp = new RegExp(
+    var domImportRegExp = RegExp(
         r"^[#]?import.*dart:(html|web_audio|indexed_db|svg|web_sql)",
         multiLine: true);
 
-    var bytes = new File.fromUri(uri).readAsBytesSync();
-    String contents = decodeUtf8(bytes);
+    var bytes = File.fromUri(uri).readAsBytesSync();
+    var contents = decodeUtf8(bytes);
     bytes = null;
 
     // Find the options in the file.
@@ -1151,11 +1120,11 @@
         s.split(' ').where((e) => e != '').toList();
 
     List<String> singleListOfOptions(String name) {
-      var matches = new RegExp('// $name=(.*)').allMatches(contents);
+      var matches = RegExp('// $name=(.*)').allMatches(contents);
       List<String> options;
       for (var match in matches) {
         if (options != null) {
-          throw new Exception(
+          throw Exception(
               'More than one "// $name=" line in test ${uri.toFilePath()}');
         }
         options = wordSplit(match[1]);
@@ -1176,10 +1145,10 @@
 
     matches = environmentRegExp.allMatches(contents);
     for (var match in matches) {
-      final String envDef = match[1];
-      final int pos = envDef.indexOf('=');
-      final String name = (pos < 0) ? envDef : envDef.substring(0, pos);
-      final String value = (pos < 0) ? '' : envDef.substring(pos + 1);
+      var envDef = match[1];
+      var pos = envDef.indexOf('=');
+      var name = (pos < 0) ? envDef : envDef.substring(0, pos);
+      var value = (pos < 0) ? '' : envDef.substring(pos + 1);
       environment ??= <String, String>{};
       environment[name] = value;
     }
@@ -1187,7 +1156,7 @@
     matches = packageRootRegExp.allMatches(contents);
     for (var match in matches) {
       if (packageRoot != null || packages != null) {
-        throw new Exception(
+        throw Exception(
             'More than one "// Package... line in test ${uri.toFilePath()}');
       }
       packageRoot = match[1];
@@ -1195,15 +1164,14 @@
         // PackageRoot=none means that no packages or package-root option
         // should be given. Any other value overrides package-root and
         // removes any packages option.  Don't use with // Packages=.
-        packageRoot =
-            uri.resolveUri(new Uri.directory(packageRoot)).toFilePath();
+        packageRoot = uri.resolveUri(Uri.directory(packageRoot)).toFilePath();
       }
     }
 
     matches = packagesRegExp.allMatches(contents);
     for (var match in matches) {
       if (packages != null || packageRoot != null) {
-        throw new Exception(
+        throw Exception(
             'More than one "// Package..." line in test ${uri.toFilePath()}');
       }
       packages = match[1];
@@ -1211,7 +1179,7 @@
         // Packages=none means that no packages or package-root option
         // should be given. Any other value overrides packages and removes
         // any package-root option. Don't use with // PackageRoot=.
-        packages = uri.resolveUri(new Uri.file(packages)).toFilePath();
+        packages = uri.resolveUri(Uri.file(packages)).toFilePath();
       }
     }
 
@@ -1227,14 +1195,14 @@
       sharedObjects.addAll(wordSplit(match[1]));
     }
 
-    var isMultitest = multiTestRegExp.hasMatch(contents);
-    var isMultiHtmlTest = multiHtmlTestRegExp.hasMatch(contents);
+    var isMultitest = _multiTestRegExp.hasMatch(contents);
+    var isMultiHtmlTest = _multiHtmlTestRegExp.hasMatch(contents);
     var isolateMatch = isolateStubsRegExp.firstMatch(contents);
     var isolateStubs = isolateMatch != null ? isolateMatch[1] : '';
     var containsDomImport = domImportRegExp.hasMatch(contents);
 
     var subtestNames = <String>[];
-    var matchesIter = multiHtmlTestGroupRegExp.allMatches(contents).iterator;
+    var matchesIter = _multiHtmlTestGroupRegExp.allMatches(contents).iterator;
     while (matchesIter.moveNext() && isMultiHtmlTest) {
       var fullMatch = matchesIter.current.group(0);
       subtestNames.add(fullMatch.substring(fullMatch.indexOf("'") + 1));
@@ -1294,10 +1262,10 @@
 
   Map<String, dynamic> optionsFromKernelFile() {
     return const {
-      "vmOptions": const [const <String>[]],
-      "sharedOptions": const <String>[],
-      "dart2jsOptions": const <String>[],
-      "dartOptions": const <String>[],
+      "vmOptions": [<String>[]],
+      "sharedOptions": <String>[],
+      "dart2jsOptions": <String>[],
+      "dartOptions": <String>[],
       "packageRoot": null,
       "packages": null,
       "hasSyntaxError": false,
@@ -1306,14 +1274,14 @@
       "hasStaticWarning": false,
       "isMultitest": false,
       "isMultiHtmlTest": false,
-      "subtestNames": const [],
+      "subtestNames": [],
       "isolateStubs": '',
       "containsDomImport": false,
     };
   }
 
   List<List<String>> getVmOptions(Map<String, dynamic> optionsFromFile) {
-    const compilers = const [
+    const compilers = [
       Compiler.none,
       Compiler.dartk,
       Compiler.dartkb,
@@ -1323,7 +1291,7 @@
       Compiler.appJitk,
     ];
 
-    const runtimes = const [Runtime.none, Runtime.dartPrecompiled, Runtime.vm];
+    const runtimes = [Runtime.none, Runtime.dartPrecompiled, Runtime.vm];
 
     var needsVmOptions = compilers.contains(configuration.compiler) &&
         runtimes.contains(configuration.runtime);
@@ -1346,7 +1314,7 @@
     var dir = filePath.directoryPath;
     var nameNoExt = filePath.filenameWithoutExtension;
     var customHtmlPath = dir.append('$nameNoExt.html');
-    var customHtml = new File(customHtmlPath.toNativePath());
+    var customHtml = File(customHtmlPath.toNativePath());
     if (!customHtml.existsSync()) {
       super._enqueueBrowserTest(
           packageRoot, packages, info, testName, expectations);
@@ -1361,7 +1329,7 @@
 
 class AnalyzeLibraryTestSuite extends StandardTestSuite {
   static Path _libraryPath(TestConfiguration configuration) =>
-      new Path(configuration.useSdk
+      Path(configuration.useSdk
           ? '${configuration.buildDirectory}/dart-sdk'
           : 'sdk');
 
@@ -1375,9 +1343,9 @@
       const ['--fatal-warnings', '--fatal-type-errors', '--sdk-warnings'];
 
   Future enqueueTests() {
-    var group = new FutureGroup();
+    var group = FutureGroup();
 
-    var dir = new Directory(suiteDir.append('lib').toNativePath());
+    var dir = Directory(suiteDir.append('lib').toNativePath());
     if (dir.existsSync()) {
       enqueueDirectory(dir, group);
     }
diff --git a/pkg/test_runner/lib/src/testing_servers.dart b/pkg/test_runner/lib/src/testing_servers.dart
index 1d1d6bd..92d3949 100644
--- a/pkg/test_runner/lib/src/testing_servers.dart
+++ b/pkg/test_runner/lib/src/testing_servers.dart
@@ -14,7 +14,7 @@
 
 class DispatchingServer {
   HttpServer server;
-  Map<String, Function> _handlers = new Map<String, Function>();
+  Map<String, Function> _handlers = {};
   Function _notFound;
 
   DispatchingServer(
@@ -57,16 +57,14 @@
 /// In case a path does not refer to a file but rather to a directory, a
 /// directory listing will be displayed.
 
-const PREFIX_BUILDDIR = 'root_build';
-const PREFIX_DARTDIR = 'root_dart';
+const prefixBuildDir = 'root_build';
+const prefixDartDir = 'root_dart';
 
-/**
- * Runs a set of servers that are initialized specifically for the needs of our
- * test framework, such as dealing with package-root.
- */
+/// Runs a set of servers that are initialized specifically for the needs of our
+/// test framework, such as dealing with package-root.
 class TestingServers {
-  static final _CACHE_EXPIRATION_IN_SECONDS = 30;
-  static final _HARMLESS_REQUEST_PATH_ENDINGS = [
+  static final _cacheExpirationSeconds = 30;
+  static final _harmlessRequestPathSuffixes = [
     "/apple-touch-icon.png",
     "/apple-touch-icon-precomposed.png",
     "/favicon.ico",
@@ -91,20 +89,20 @@
       String dartDirectory,
       String packageRoot,
       String packages]) {
-    _buildDirectory = Uri.base.resolveUri(new Uri.directory(buildDirectory));
+    _buildDirectory = Uri.base.resolveUri(Uri.directory(buildDirectory));
     if (dartDirectory == null) {
       _dartDirectory = Repository.uri;
     } else {
-      _dartDirectory = Uri.base.resolveUri(new Uri.directory(dartDirectory));
+      _dartDirectory = Uri.base.resolveUri(Uri.directory(dartDirectory));
     }
     if (packageRoot == null) {
       if (packages == null) {
         _packages = _dartDirectory.resolve('.packages');
       } else {
-        _packages = new Uri.file(packages);
+        _packages = Uri.file(packages);
       }
     } else {
-      _packageRoot = new Uri.directory(packageRoot);
+      _packageRoot = Uri.directory(packageRoot);
     }
   }
 
@@ -116,20 +114,19 @@
 
   DispatchingServer get server => _server;
 
-  /**
-   * [startServers] will start two Http servers.
-   * The first server listens on [port] and sets
-   *   "Access-Control-Allow-Origin: *"
-   * The second server listens on [crossOriginPort] and sets
-   *   "Access-Control-Allow-Origin: client:port1
-   *   "Access-Control-Allow-Credentials: true"
-   */
+  /// [startServers] will start two Http servers.
+  ///
+  /// The first server listens on [port] and sets
+  ///   "Access-Control-Allow-Origin: *"
+  /// The second server listens on [crossOriginPort] and sets
+  ///   "Access-Control-Allow-Origin: client:port1
+  ///   "Access-Control-Allow-Credentials: true"
   Future startServers(String host,
-      {int port: 0, int crossOriginPort: 0}) async {
+      {int port = 0, int crossOriginPort = 0}) async {
     if (_packages != null) {
       _resolver = await SyncPackageResolver.loadConfig(_packages);
     } else {
-      _resolver = new SyncPackageResolver.root(_packageRoot);
+      _resolver = SyncPackageResolver.root(_packageRoot);
     }
     _server = await _startHttpServer(host, port: port);
     await _startHttpServer(host,
@@ -142,7 +139,7 @@
     var script = _dartDirectory.resolve('pkg/test_runner/bin/http_server.dart');
     var buildDirectory = _buildDirectory.toFilePath();
 
-    var command = [
+    return [
       dart,
       script.toFilePath(),
       '-p',
@@ -152,20 +149,13 @@
       '--network',
       network,
       '--build-directory=$buildDirectory',
-      '--runtime=${runtime.name}'
-    ];
-
-    if (useContentSecurityPolicy) {
-      command.add('--csp');
-    }
-
-    if (_packages != null) {
-      command.add('--packages=${_packages.toFilePath()}');
-    } else if (_packageRoot != null) {
-      command.add('--package-root=${_packageRoot.toFilePath()}');
-    }
-
-    return command.join(' ');
+      '--runtime=${runtime.name}',
+      if (useContentSecurityPolicy) '--csp',
+      if (_packages != null)
+        '--packages=${_packages.toFilePath()}'
+      else if (_packageRoot != null)
+        '--package-root=${_packageRoot.toFilePath()}'
+    ].join(' ');
   }
 
   void stopServers() {
@@ -179,17 +169,17 @@
   }
 
   Future<DispatchingServer> _startHttpServer(String host,
-      {int port: 0, int allowedPort: -1}) {
+      {int port = 0, int allowedPort = -1}) {
     return HttpServer.bind(host, port).then((HttpServer httpServer) {
-      var server = new DispatchingServer(httpServer, _onError, _sendNotFound);
+      var server = DispatchingServer(httpServer, _onError, _sendNotFound);
       server.addHandler('/echo', _handleEchoRequest);
       server.addHandler('/ws', _handleWebSocketRequest);
       fileHandler(HttpRequest request) {
         _handleFileOrDirectoryRequest(request, allowedPort);
       }
 
-      server.addHandler('/$PREFIX_BUILDDIR', fileHandler);
-      server.addHandler('/$PREFIX_DARTDIR', fileHandler);
+      server.addHandler('/$prefixBuildDir', fileHandler);
+      server.addHandler('/$prefixDartDir', fileHandler);
       server.addHandler('/packages', fileHandler);
       _serverList.add(httpServer);
       return server;
@@ -200,13 +190,12 @@
       HttpRequest request, int allowedPort) async {
     // Enable browsers to cache file/directory responses.
     var response = request.response;
-    response.headers
-        .set("Cache-Control", "max-age=$_CACHE_EXPIRATION_IN_SECONDS");
+    response.headers.set("Cache-Control", "max-age=$_cacheExpirationSeconds");
     try {
       var path = _getFileUriFromRequestUri(request.uri);
       if (path != null) {
-        var file = new File.fromUri(path);
-        var directory = new Directory.fromUri(path);
+        var file = File.fromUri(path);
+        var directory = Directory.fromUri(path);
         if (await file.exists()) {
           _sendFileContent(request, response, allowedPort, file);
         } else if (await directory.exists()) {
@@ -218,9 +207,9 @@
       } else {
         if (request.uri.path == '/') {
           var entries = [
-            new _Entry('root_dart', 'root_dart/'),
-            new _Entry('root_build', 'root_build/'),
-            new _Entry('echo', 'echo')
+            _Entry('root_dart', 'root_dart/'),
+            _Entry('root_build', 'root_build/'),
+            _Entry('echo', 'echo')
           ];
           _sendDirectoryListing(entries, request, response);
         } else {
@@ -269,32 +258,32 @@
     if (pathSegments.length == 0) return null;
     int packagesIndex = pathSegments.indexOf('packages');
     if (packagesIndex != -1) {
-      var packageUri = new Uri(
+      var packageUri = Uri(
           scheme: 'package',
           pathSegments: pathSegments.skip(packagesIndex + 1));
       return _resolver.resolveUri(packageUri);
     }
-    if (pathSegments[0] == PREFIX_BUILDDIR) {
+    if (pathSegments[0] == prefixBuildDir) {
       return _buildDirectory.resolve(pathSegments.skip(1).join('/'));
     }
-    if (pathSegments[0] == PREFIX_DARTDIR) {
+    if (pathSegments[0] == prefixDartDir) {
       return _dartDirectory.resolve(pathSegments.skip(1).join('/'));
     }
     return null;
   }
 
   Future<List<_Entry>> _listDirectory(Directory directory) {
-    var completer = new Completer<List<_Entry>>();
+    var completer = Completer<List<_Entry>>();
     var entries = <_Entry>[];
 
     directory.list().listen((FileSystemEntity fse) {
       var segments = fse.uri.pathSegments;
       if (fse is File) {
         var filename = segments.last;
-        entries.add(new _Entry(filename, filename));
+        entries.add(_Entry(filename, filename));
       } else if (fse is Directory) {
         var dirname = segments[segments.length - 2];
-        entries.add(new _Entry(dirname, '$dirname/'));
+        entries.add(_Entry(dirname, '$dirname/'));
       }
     }, onDone: () {
       completer.complete(entries);
@@ -392,7 +381,7 @@
 
   void _sendNotFound(HttpRequest request) {
     bool isHarmlessPath(String path) {
-      return _HARMLESS_REQUEST_PATH_ENDINGS.any((pattern) {
+      return _harmlessRequestPathSuffixes.any((pattern) {
         return path.contains(pattern);
       });
     }
@@ -431,7 +420,7 @@
   }
 }
 
-// Helper class for displaying directory listings.
+/// Helper class for displaying directory listings.
 class _Entry implements Comparable<_Entry> {
   final String name;
   final String displayName;
diff --git a/pkg/test_runner/lib/src/utils.dart b/pkg/test_runner/lib/src/utils.dart
index ec97ce1..1d1d0a5 100644
--- a/pkg/test_runner/lib/src/utils.dart
+++ b/pkg/test_runner/lib/src/utils.dart
@@ -9,17 +9,17 @@
 import 'configuration.dart';
 import 'path.dart';
 
-// This is the maximum time we expect stdout/stderr of subprocesses to deliver
-// data after we've got the exitCode.
-const Duration MAX_STDIO_DELAY = const Duration(seconds: 30);
+/// This is the maximum time we expect stdout/stderr of subprocesses to deliver
+/// data after we've got the exitCode.
+const Duration maxStdioDelay = Duration(seconds: 30);
 
-String MAX_STDIO_DELAY_PASSED_MESSAGE =
+final maxStdioDelayPassedMessage =
     """Not waiting for stdout/stderr from subprocess anymore
- ($MAX_STDIO_DELAY passed). Please note that this could be an indicator
+ ($maxStdioDelay passed). Please note that this could be an indicator
  that there is a hanging process which we were unable to kill.""";
 
 /// The names of the packages that are available for use in tests.
-const testPackages = const [
+const testPackages = [
   "async_helper",
   "collection",
   "expect",
@@ -34,12 +34,10 @@
 class DebugLogger {
   static IOSink _sink;
 
-  /**
-   * If [path] was null, the DebugLogger will write messages to stdout.
-   */
+  /// If [path] was null, the DebugLogger will write messages to stdout.
   static void init(Path path) {
     if (path != null) {
-      _sink = new File(path.toNativePath()).openWrite(mode: FileMode.append);
+      _sink = File(path.toNativePath()).openWrite(mode: FileMode.append);
     }
   }
 
@@ -82,18 +80,19 @@
     }
   }
 
-  static String get _datetime => "${new DateTime.now()}";
+  static String get _datetime => "${DateTime.now()}";
 }
 
-String prettifyJson(Object json, {int startIndentation: 0, int shiftWidth: 6}) {
+String prettifyJson(Object json,
+    {int startIndentation = 0, int shiftWidth = 6}) {
   int currentIndentation = startIndentation;
-  var buffer = new StringBuffer();
+  var buffer = StringBuffer();
 
   String indentationString() {
-    return new List.filled(currentIndentation, ' ').join('');
+    return List.filled(currentIndentation, ' ').join('');
   }
 
-  addString(String s, {bool indentation: true, bool newLine: true}) {
+  addString(String s, {bool indentation = true, bool newLine = true}) {
     if (indentation) {
       buffer.write(indentationString());
     }
@@ -102,7 +101,7 @@
   }
 
   prettifyJsonInternal(Object obj,
-      {bool indentation: true, bool newLine: true}) {
+      {bool indentation = true, bool newLine = true}) {
     if (obj is List) {
       addString("[", indentation: indentation);
       currentIndentation += shiftWidth;
@@ -132,15 +131,13 @@
   return buffer.toString();
 }
 
-/**
- * [areByteArraysEqual] compares a range of bytes from [buffer1] with a
- * range of bytes from [buffer2].
- *
- * Returns [true] if the [count] bytes in [buffer1] (starting at
- * [offset1]) match the [count] bytes in [buffer2] (starting at
- * [offset2]).
- * Otherwise [false] is returned.
- */
+/// [areByteArraysEqual] compares a range of bytes from [buffer1] with a
+/// range of bytes from [buffer2].
+///
+/// Returns [true] if the [count] bytes in [buffer1] (starting at
+/// [offset1]) match the [count] bytes in [buffer2] (starting at
+/// [offset2]).
+/// Otherwise [false] is returned.
 bool areByteArraysEqual(
     List<int> buffer1, int offset1, List<int> buffer2, int offset2, int count) {
   if ((offset1 + count) > buffer1.length ||
@@ -156,12 +153,10 @@
   return true;
 }
 
-/**
- * [findBytes] searches for [pattern] in [data] beginning at [startPos].
- *
- * Returns [true] if [pattern] was found in [data].
- * Otherwise [false] is returned.
- */
+/// [findBytes] searches for [pattern] in [data] beginning at [startPos].
+///
+/// Returns [true] if [pattern] was found in [data].
+/// Otherwise [false] is returned.
 int findBytes(List<int> data, List<int> pattern, [int startPos = 0]) {
   // TODO(kustermann): Use one of the fast string-matching algorithms!
   for (int i = startPos; i < (data.length - pattern.length); i++) {
@@ -201,7 +196,7 @@
 }
 
 String indent(String string, int numSpaces) {
-  var spaces = new List.filled(numSpaces, ' ').join('');
+  var spaces = List.filled(numSpaces, ' ').join('');
   return string
       .replaceAll('\r\n', '\n')
       .split('\n')
@@ -232,8 +227,8 @@
   }
 }
 
-// This function is pretty stupid and only puts quotes around an argument if
-// it the argument contains a space.
+/// This function is pretty stupid and only puts quotes around an argument if
+/// it the argument contains a space.
 String escapeCommandLineArgument(String argument) {
   if (argument.contains(' ')) {
     return '"$argument"';
@@ -263,7 +258,7 @@
         addJson(object[key]);
       }
     } else {
-      throw new Exception("Can't build hashcode for non json-like object "
+      throw Exception("Can't build hashcode for non json-like object "
           "(${object.runtimeType})");
     }
   }
@@ -296,7 +291,7 @@
     }
     return false;
   } else {
-    throw new Exception("Can't compare two non json-like objects "
+    throw Exception("Can't compare two non json-like objects "
         "(a: ${a.runtimeType}, b: ${b.runtimeType})");
   }
 }
@@ -315,57 +310,51 @@
 class LastModifiedCache {
   Map<String, DateTime> _cache = <String, DateTime>{};
 
-  /**
-   * Returns the last modified date of the given [uri].
-   *
-   * The return value will be cached for future queries. If [uri] is a local
-   * file, it's last modified [Date] will be returned. If the file does not
-   * exist, null will be returned instead.
-   * In case [uri] is not a local file, this method will always return
-   * the current date.
-   */
+  /// Returns the last modified date of the given [uri].
+  ///
+  /// The return value will be cached for future queries. If [uri] is a local
+  /// file, it's last modified [Date] will be returned. If the file does not
+  /// exist, null will be returned instead.
+  /// In case [uri] is not a local file, this method will always return
+  /// the current date.
   DateTime getLastModified(Uri uri) {
     if (uri.scheme == "file") {
       if (_cache.containsKey(uri.path)) {
         return _cache[uri.path];
       }
-      var file = new File(new Path(uri.path).toNativePath());
+      var file = File(Path(uri.path).toNativePath());
       _cache[uri.path] = file.existsSync() ? file.lastModifiedSync() : null;
       return _cache[uri.path];
     }
-    return new DateTime.now();
+    return DateTime.now();
   }
 }
 
 class ExistsCache {
   Map<String, bool> _cache = <String, bool>{};
 
-  /**
-   * Returns true if the file in [path] exists, false otherwise.
-   *
-   * The information will be cached.
-   */
+  /// Returns true if the file in [path] exists, false otherwise.
+  ///
+  /// The information will be cached.
   bool doesFileExist(String path) {
     if (!_cache.containsKey(path)) {
-      _cache[path] = new File(path).existsSync();
+      _cache[path] = File(path).existsSync();
     }
     return _cache[path];
   }
 }
 
 class TestUtils {
-  static LastModifiedCache lastModifiedCache = new LastModifiedCache();
-  static ExistsCache existsCache = new ExistsCache();
+  static LastModifiedCache lastModifiedCache = LastModifiedCache();
+  static ExistsCache existsCache = ExistsCache();
 
-  /**
-   * Creates a directory using a [relativePath] to an existing
-   * [base] directory if that [relativePath] does not already exist.
-   */
+  /// Creates a directory using a [relativePath] to an existing
+  /// [base] directory if that [relativePath] does not already exist.
   static Directory mkdirRecursive(Path base, Path relativePath) {
     if (relativePath.isAbsolute) {
-      base = new Path('/');
+      base = Path('/');
     }
-    Directory dir = new Directory(base.toNativePath());
+    Directory dir = Directory(base.toNativePath());
     assert(dir.existsSync());
     var segments = relativePath.segments();
     for (String segment in segments) {
@@ -376,7 +365,7 @@
         // Skip the directory creation for a path like "/E:".
         continue;
       }
-      dir = new Directory(base.toNativePath());
+      dir = Directory(base.toNativePath());
       if (!dir.existsSync()) {
         dir.createSync();
       }
@@ -385,23 +374,19 @@
     return dir;
   }
 
-  /**
-   * Keep a map of files copied to avoid race conditions.
-   */
+  /// Keep a map of files copied to avoid race conditions.
   static Map<String, Future> _copyFilesMap = {};
 
-  /**
-   * Copy a [source] file to a new place.
-   * Assumes that the directory for [dest] already exists.
-   */
+  /// Copy a [source] file to a new place.
+  /// Assumes that the directory for [dest] already exists.
   static Future copyFile(Path source, Path dest) {
     return _copyFilesMap.putIfAbsent(dest.toNativePath(),
-        () => new File(source.toNativePath()).copy(dest.toNativePath()));
+        () => File(source.toNativePath()).copy(dest.toNativePath()));
   }
 
   static Future copyDirectory(String source, String dest) {
-    source = new Path(source).toNativePath();
-    dest = new Path(dest).toNativePath();
+    source = Path(source).toNativePath();
+    dest = Path(dest).toNativePath();
 
     var executable = 'cp';
     var args = ['-Rp', source, dest];
@@ -411,7 +396,7 @@
     }
     return Process.run(executable, args).then((ProcessResult result) {
       if (result.exitCode != 0) {
-        throw new Exception("Failed to execute '$executable "
+        throw Exception("Failed to execute '$executable "
             "${args.join(' ')}'.");
       }
     });
@@ -422,18 +407,18 @@
     // deleting them. Use the system tools to delete our long paths.
     // See issue 16264.
     if (Platform.operatingSystem == 'windows') {
-      var native_path = new Path(path).toNativePath();
+      var native_path = Path(path).toNativePath();
       // Running this in a shell sucks, but rmdir is not part of the standard
       // path.
       return Process.run('rmdir', ['/s', '/q', native_path], runInShell: true)
           .then((ProcessResult result) {
         if (result.exitCode != 0) {
-          throw new Exception('Can\'t delete path $native_path. '
+          throw Exception('Can\'t delete path $native_path. '
               'This path might be too long');
         }
       });
     } else {
-      var dir = new Directory(path);
+      var dir = Directory(path);
       return dir.delete(recursive: true);
     }
   }
@@ -459,7 +444,7 @@
     }
   }
 
-  static final debugLogFilePath = new Path(".debug.log");
+  static final debugLogFilePath = Path(".debug.log");
 
   /// If test.py was invoked with '--write-results' it will write
   /// test outcomes to this file in the '--output-directory'.
@@ -479,10 +464,11 @@
     }
   }
 
-  static int shortNameCounter = 0; // Make unique short file names on Windows.
+  /// Make unique short file names on Windows.
+  static int shortNameCounter = 0;
 
   static String getShortName(String path) {
-    const pathReplacements = const {
+    const pathReplacements = {
       "tests_co19_src_Language_12_Expressions_14_Function_Invocation_":
           "co19_fn_invoke_",
       "tests_co19_src_LayoutTests_fast_css_getComputedStyle_getComputedStyle-":
diff --git a/pkg/test_runner/test/dependency_graph_test.dart b/pkg/test_runner/test/dependency_graph_test.dart
index 84b4d6a..86c8966 100644
--- a/pkg/test_runner/test/dependency_graph_test.dart
+++ b/pkg/test_runner/test/dependency_graph_test.dart
@@ -7,7 +7,7 @@
 import 'package:test_runner/src/dependency_graph.dart';
 
 main() {
-  var graph = new Graph<int>();
+  var graph = Graph<int>();
   var numberOfEvents = 0;
   var addEventAssertions = [];
   var changeEventAssertions = [];
diff --git a/pkg/test_runner/test/skipping_dart2js_compilations_helper.dart b/pkg/test_runner/test/skipping_dart2js_compilations_helper.dart
index cda26da..74fc991 100644
--- a/pkg/test_runner/test/skipping_dart2js_compilations_helper.dart
+++ b/pkg/test_runner/test/skipping_dart2js_compilations_helper.dart
@@ -6,6 +6,6 @@
 
 main(List<String> arguments) {
   var outputFile = arguments[0];
-  var file = new File(outputFile);
+  var file = File(outputFile);
   file.createSync();
 }
diff --git a/pkg/test_runner/test/skipping_dart2js_compilations_test.dart b/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
index 7f61583..16fb24b 100644
--- a/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
+++ b/pkg/test_runner/test/skipping_dart2js_compilations_test.dart
@@ -27,10 +27,8 @@
 import 'package:test_runner/src/repository.dart';
 import 'package:test_runner/src/test_case.dart';
 
-/**
- * This class is reponsible for setting up the files necessary for this test
- * as well as touching a file.
- */
+/// This class is reponsible for setting up the files necessary for this test
+/// as well as touching a file.
 class FileUtils {
   Directory tempDir;
   File testJs;
@@ -59,7 +57,7 @@
     }
     if (createJsDeps) {
       testJsDeps = _createFile(testJsDepsFilePath);
-      var path = new Path(tempDir.path).append("test.dart").absolute;
+      var path = Path(tempDir.path).append("test.dart").absolute;
       _writeToFile(testJsDeps, "file://$path");
     }
   }
@@ -71,7 +69,7 @@
     if (testSnapshot != null) testSnapshot.deleteSync();
 
     // if the script did run, it created this file, so we need to delete it
-    File file = new File(scriptOutputPath.toNativePath());
+    File file = File(scriptOutputPath.toNativePath());
     if (file.existsSync()) {
       file.deleteSync();
     }
@@ -80,25 +78,23 @@
   }
 
   Path get scriptOutputPath {
-    return new Path(tempDir.path)
-        .append('created_if_command_did_run.txt')
-        .absolute;
+    return Path(tempDir.path).append('created_if_command_did_run.txt').absolute;
   }
 
   Path get testDartFilePath {
-    return new Path(tempDir.path).append('test.dart').absolute;
+    return Path(tempDir.path).append('test.dart').absolute;
   }
 
   Path get testJsFilePath {
-    return new Path(tempDir.path).append('test.js').absolute;
+    return Path(tempDir.path).append('test.js').absolute;
   }
 
   Path get testJsDepsFilePath {
-    return new Path(tempDir.path).append('test.js.deps').absolute;
+    return Path(tempDir.path).append('test.js.deps').absolute;
   }
 
   Path get testSnapshotFilePath {
-    return new Path(tempDir.path).append('test_dart2js.snapshot').absolute;
+    return Path(tempDir.path).append('test_dart2js.snapshot').absolute;
   }
 
   void touchFile(File file) {
@@ -107,8 +103,8 @@
 
   void _writeToFile(File file, String content) {
     if (content != null) {
-      var fd = new File(file.resolveSymbolicLinksSync())
-          .openSync(mode: FileMode.write);
+      var fd =
+          File(file.resolveSymbolicLinksSync()).openSync(mode: FileMode.write);
       fd.writeStringSync(content);
       fd.closeSync();
     }
@@ -119,7 +115,7 @@
   }
 
   File _createFile(Path path) {
-    var file = new File(path.toNativePath());
+    var file = File(path.toNativePath());
     file.createSync();
     return file;
   }
@@ -137,10 +133,10 @@
     if (_shouldHaveRun) {
       Expect.equals(0, output.stdout.length);
       Expect.isTrue(
-          new File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
+          File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
     } else {
       Expect.isFalse(
-          new File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
+          File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
     }
   }
 }
@@ -164,37 +160,37 @@
   // This script is in [sdk]/pkg/test_runner/test.
   Repository.uri = Platform.script.resolve('../../..');
 
-  var fs_noTestJs = new FileUtils(
+  var fs_noTestJs = FileUtils(
       createJs: false,
       createJsDeps: true,
       createDart: true,
       createSnapshot: true);
-  var fs_noTestJsDeps = new FileUtils(
+  var fs_noTestJsDeps = FileUtils(
       createJs: true,
       createJsDeps: false,
       createDart: true,
       createSnapshot: true);
-  var fs_noTestDart = new FileUtils(
+  var fs_noTestDart = FileUtils(
       createJs: true,
       createJsDeps: true,
       createDart: false,
       createSnapshot: true);
-  var fs_noTestSnapshot = new FileUtils(
+  var fs_noTestSnapshot = FileUtils(
       createJs: true,
       createJsDeps: true,
       createDart: true,
       createSnapshot: false);
-  var fs_notUpToDate_snapshot = new FileUtils(
+  var fs_notUpToDate_snapshot = FileUtils(
       createJs: true,
       createJsDeps: true,
       createDart: true,
       createSnapshot: true);
-  var fs_notUpToDate_dart = new FileUtils(
+  var fs_notUpToDate_dart = FileUtils(
       createJs: true,
       createJsDeps: true,
       createDart: true,
       createSnapshot: true);
-  var fs_upToDate = new FileUtils(
+  var fs_upToDate = FileUtils(
       createJs: true,
       createJsDeps: true,
       createDart: true,
@@ -215,9 +211,9 @@
     fs_upToDate.touchFile(fs_upToDate.testJs);
 
     Future runTest(String name, FileUtils fileUtils, bool shouldRun) {
-      var completedHandler = new CommandCompletedHandler(fileUtils, shouldRun);
+      var completedHandler = CommandCompletedHandler(fileUtils, shouldRun);
       var command = makeCompilationCommand(name, fileUtils) as ProcessCommand;
-      var process = new RunningProcess(command, 60);
+      var process = RunningProcess(command, 60);
       return process.run().then((CommandOutput output) {
         completedHandler.processCompletedTest(output);
       });
@@ -250,5 +246,5 @@
 
   // We need to wait some time to make sure that the files we 'touch' get a
   // bigger timestamp than the old ones
-  new Timer(new Duration(seconds: 1), touchFilesAndRunTests);
+  Timer(Duration(seconds: 1), touchFilesAndRunTests);
 }
diff --git a/pkg/test_runner/test/test_runner_test.dart b/pkg/test_runner/test/test_runner_test.dart
index 7cc1f97..e4cdc46 100644
--- a/pkg/test_runner/test/test_runner_test.dart
+++ b/pkg/test_runner/test/test_runner_test.dart
@@ -14,6 +14,7 @@
 import "package:test_runner/src/command.dart";
 import "package:test_runner/src/configuration.dart";
 import "package:test_runner/src/options.dart";
+import "package:test_runner/src/process_queue.dart";
 import "package:test_runner/src/repository.dart";
 import "package:test_runner/src/test_case.dart";
 import "package:test_runner/src/test_suite.dart";
@@ -41,10 +42,8 @@
     numCompletedTests++;
     if (testCase.displayName == "fail-unexpected") {
       if (!testCase.unexpectedOutput) {
-        var stdout =
-            new String.fromCharCodes(testCase.lastCommandOutput.stdout);
-        var stderr =
-            new String.fromCharCodes(testCase.lastCommandOutput.stderr);
+        var stdout = String.fromCharCodes(testCase.lastCommandOutput.stdout);
+        var stderr = String.fromCharCodes(testCase.lastCommandOutput.stderr);
         print("stdout = [$stdout]");
         print("stderr = [$stderr]");
         throw "Test case ${testCase.displayName} passed unexpectedly, "
@@ -52,10 +51,8 @@
       }
     } else {
       if (testCase.unexpectedOutput) {
-        var stdout =
-            new String.fromCharCodes(testCase.lastCommandOutput.stdout);
-        var stderr =
-            new String.fromCharCodes(testCase.lastCommandOutput.stderr);
+        var stdout = String.fromCharCodes(testCase.lastCommandOutput.stdout);
+        var stderr = String.fromCharCodes(testCase.lastCommandOutput.stderr);
         print("stdout = [$stdout]");
         print("stderr = [$stderr]");
         throw "Test case ${testCase.displayName} failed, "
@@ -121,24 +118,18 @@
 
   TestCase _makeTestCase(String name, timeout, Command command,
       Iterable<Expectation> expectations) {
-    var configuration = new OptionsParser().parse(['--timeout', '$timeout'])[0];
-    return new TestCase(name, [command], configuration,
-        new Set<Expectation>.from(expectations));
+    var configuration = OptionsParser().parse(['--timeout', '$timeout'])[0];
+    return TestCase(
+        name, [command], configuration, Set<Expectation>.from(expectations));
   }
 }
 
 void testProcessQueue() {
   var maxProcesses = 2;
   var maxBrowserProcesses = maxProcesses;
-  var config = new OptionsParser().parse(['--noBatch'])[0];
-  new ProcessQueue(
-      config,
-      maxProcesses,
-      maxBrowserProcesses,
-      new DateTime.now(),
-      [new CustomTestSuite(config)],
-      [new EventListener()],
-      TestController.finished);
+  var config = OptionsParser().parse(['--noBatch'])[0];
+  ProcessQueue(config, maxProcesses, maxBrowserProcesses, DateTime.now(),
+      [CustomTestSuite(config)], [EventListener()], TestController.finished);
 }
 
 class EventListener extends progress.EventListener {
@@ -165,7 +156,7 @@
         break;
       case 'timeout':
         // This process should be killed by the test after DEFAULT_TIMEOUT
-        new Timer(new Duration(hours: 42), () {});
+        Timer(Duration(hours: 42), () {});
         break;
       default:
         throw "Unknown option ${arguments[0]} passed to test_runner_test";
@@ -183,7 +174,7 @@
   var extension = getPlatformExecutableExtension();
   var executable = Platform.executable;
   var dirIndex = executable.lastIndexOf('dart');
-  var buffer = new StringBuffer(executable.substring(0, dirIndex));
+  var buffer = StringBuffer(executable.substring(0, dirIndex));
   buffer.write('process_test$extension');
   return buffer.toString();
 }
diff --git a/pkg/test_runner/tool/co19.dart b/pkg/test_runner/tool/co19.dart
index a89485f..72b7a6d 100644
--- a/pkg/test_runner/tool/co19.dart
+++ b/pkg/test_runner/tool/co19.dart
@@ -15,32 +15,20 @@
 import 'package:test_runner/src/options.dart';
 import 'package:test_runner/src/test_configurations.dart';
 
-const List<String> COMMON_ARGUMENTS = const <String>[
+const List<String> _commonArguments = <String>[
   '--report',
   '--progress=diff',
   'co19'
 ];
 
-const List<List<String>> COMMAND_LINES = const <List<String>>[
-  const <String>['-mrelease,debug', '-rvm', '-cnone'],
-  const <String>['-mrelease,debug', '-rvm', '-cnone', '--checked'],
-  const <String>['-mrelease', '-rnone', '-cdart2analyzer'],
-  const <String>['-mrelease', '-rd8', '-cdart2js', '--use-sdk'],
-  const <String>[
-    '-mrelease',
-    '-rd8,jsshell',
-    '-cdart2js',
-    '--use-sdk',
-    '--minified'
-  ],
-  const <String>[
-    '-mrelease',
-    '-rd8,jsshell',
-    '-cdart2js',
-    '--use-sdk',
-    '--checked'
-  ],
-  const <String>[
+const List<List<String>> _commandLines = <List<String>>[
+  <String>['-mrelease,debug', '-rvm', '-cnone'],
+  <String>['-mrelease,debug', '-rvm', '-cnone', '--checked'],
+  <String>['-mrelease', '-rnone', '-cdart2analyzer'],
+  <String>['-mrelease', '-rd8', '-cdart2js', '--use-sdk'],
+  <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk', '--minified'],
+  <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk', '--checked'],
+  <String>[
     '-mrelease',
     '-rd8,jsshell',
     '-cdart2js',
@@ -51,17 +39,17 @@
 ];
 
 void main(List<String> args) {
-  var optionsParser = new OptionsParser();
+  var optionsParser = OptionsParser();
   var configurations = <TestConfiguration>[];
-  for (var commandLine in COMMAND_LINES) {
+  for (var commandLine in _commandLines) {
     var arguments = <String>[];
-    arguments.addAll(COMMON_ARGUMENTS);
+    arguments.addAll(_commonArguments);
     arguments.addAll(args);
     arguments.addAll(commandLine);
     configurations.addAll(optionsParser.parse(arguments));
   }
 
-  if (configurations != null || configurations.length > 0) {
+  if (configurations != null || configurations.isNotEmpty) {
     testConfigurations(configurations);
   }
 }