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);
}
}