Chromium Code Reviews| Index: tools/testing/dart/test_runner.dart |
| diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart |
| index 0d641366b737a25db8168df207f5e5105243306f..09e2b06823e9ac8462e116b9186f1a6688a64089 100644 |
| --- a/tools/testing/dart/test_runner.dart |
| +++ b/tools/testing/dart/test_runner.dart |
| @@ -18,6 +18,7 @@ import "dart:convert" show LineSplitter, UTF8, JSON; |
| // CommandOutput.exitCode in subclasses of CommandOutput. |
| import "dart:io" as io; |
| import "dart:math" as math; |
| +import 'android.dart'; |
| import 'dependency_graph.dart' as dgraph; |
| import "browser_controller.dart"; |
| import "path.dart"; |
| @@ -344,6 +345,33 @@ class VmCommand extends ProcessCommand { |
| : super._("vm", executable, arguments, environmentOverrides); |
| } |
| +class AdbPrecompilationCommand extends Command { |
| + final String precompiledRunnerFilename; |
| + final String precompiledTestDirectory; |
| + final bool useBlobs; |
| + |
| + AdbPrecompilationCommand._(this.precompiledRunnerFilename, |
| + this.precompiledTestDirectory, |
| + this.useBlobs) |
| + : super._("adb_precompilation"); |
| + |
| + void _buildHashCode(HashCodeBuilder builder) { |
| + super._buildHashCode(builder); |
| + builder.add(precompiledRunnerFilename); |
| + builder.add(precompiledTestDirectory); |
| + builder.add(useBlobs); |
| + } |
| + |
| + bool _equal(AdbPrecompilationCommand other) => |
| + super._equal(other) && |
| + precompiledRunnerFilename == other.precompiledRunnerFilename && |
| + useBlobs == other.useBlobs && |
| + precompiledTestDirectory == other.precompiledTestDirectory; |
| + |
| + String toString() => 'Steps to push precompiled runner and precompiled code ' |
| + 'to an attached device. Uses (and requires) adb.'; |
| +} |
| + |
| class JSCommandlineCommand extends ProcessCommand { |
| JSCommandlineCommand._( |
| String displayName, String executable, List<String> arguments, |
| @@ -610,6 +638,14 @@ class CommandBuilder { |
| return _getUniqueCommand(command); |
| } |
| + AdbPrecompilationCommand getAdbPrecompiledCommand(String precompiledRunner, |
| + String testDirectory, |
| + bool useBlobs) { |
| + var command = new AdbPrecompilationCommand._( |
| + precompiledRunner, testDirectory, useBlobs); |
| + return _getUniqueCommand(command); |
| + } |
| + |
| Command getJSCommandlineCommand(String displayName, executable, arguments, |
| [environment = null]) { |
| var command = new JSCommandlineCommand._( |
| @@ -1625,6 +1661,9 @@ CommandOutput createCommandOutput(Command command, int exitCode, bool timedOut, |
| } else if (command is VmCommand) { |
| return new VmCommandOutputImpl( |
| command, exitCode, timedOut, stdout, stderr, time, pid); |
| + } else if (command is AdbPrecompilationCommand) { |
| + return new VmCommandOutputImpl( |
| + command, exitCode, timedOut, stdout, stderr, time, pid); |
| } else if (command is CompilationCommand) { |
| if (command.displayName == 'precompiler' || |
| command.displayName == 'dart2snapshot') { |
| @@ -2396,6 +2435,7 @@ class CommandExecutorImpl implements CommandExecutor { |
| final Map globalConfiguration; |
| final int maxProcesses; |
| final int maxBrowserProcesses; |
| + AdbDevicePool adbDevicePool; |
| // For dart2js and analyzer batch processing, |
| // we keep a list of batch processes. |
| @@ -2406,7 +2446,8 @@ class CommandExecutorImpl implements CommandExecutor { |
| bool _finishing = false; |
| CommandExecutorImpl( |
| - this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses); |
| + this.globalConfiguration, this.maxProcesses, this.maxBrowserProcesses, |
| + {this.adbDevicePool}); |
| Future cleanup() { |
| assert(!_finishing); |
| @@ -2460,11 +2501,92 @@ class CommandExecutorImpl implements CommandExecutor { |
| .runCommand(command.flavor, command, timeout, command.arguments); |
| } else if (command is ScriptCommand) { |
| return command.run(); |
| + } else if (command is AdbPrecompilationCommand) { |
| + assert(adbDevicePool != null); |
| + return adbDevicePool.aquireDevice().then((AdbDevice device) { |
|
Florian Schneider
2016/04/27 13:53:05
s/aquire/acquire/
kustermann
2016/05/02 10:40:23
Done.
|
| + return _runAdbPrecompilationCommand(device, command).whenComplete(() { |
| + adbDevicePool.releaseDevice(device); |
| + }); |
| + }); |
| } else { |
| return new RunningProcess(command, timeout).run(); |
| } |
| } |
| + Future<CommandOutput> _runAdbPrecompilationCommand( |
| + AdbDevice device, AdbPrecompilationCommand command) async { |
| + var runner = command.precompiledRunnerFilename; |
| + var testdir = command.precompiledTestDirectory; |
| + var devicedir = '/data/local/tmp/precompilation-testing'; |
| + |
| + // We copy all the files which the vm precompiler puts into the test |
| + // directory. |
| + List<String> files = new io.Directory(testdir) |
| + .listSync() |
| + .where((fse) => fse is io.File) |
| + .map((file) => file.path) |
| + .map((path) => path.substring(path.lastIndexOf('/') + 1)) |
| + .toList(); |
| + |
| + // All closures are of type "Future<AdbCommandResult> run()" |
| + List<Function> steps = []; |
| + |
| + steps.add(() => device.runAdbShellCommand( |
| + ['rm', '-Rf', devicedir])); |
| + steps.add(() => device.runAdbShellCommand( |
| + ['mkdir', devicedir])); |
| + steps.add(() => device.runAdbCommand( |
| + ['push', runner, '$devicedir/runner'])); |
|
Florian Schneider
2016/04/28 13:18:30
Maybe add a TODO that we should push the runner (d
kustermann
2016/05/02 10:40:23
Done.
|
| + steps.add(() => device.runAdbShellCommand( |
| + ['chmod', '777', '$devicedir/runner'])); |
| + |
| + for (var file in files) { |
| + steps.add(() => device.runAdbCommand( |
| + ['push', '$testdir/$file', '$devicedir/$file'])); |
| + } |
| + |
| + if (command.useBlobs) { |
| + steps.add(() => device.runAdbShellCommand( |
| + ['$devicedir/runner', '--run-precompiled-snapshot=$devicedir', |
| + '--use_blobs', 'ignored.dart'])); |
| + } else { |
| + steps.add(() => device.runAdbShellCommand( |
| + ['$devicedir/runner', '--run-precompiled-snapshot=$devicedir', |
| + 'ignored.dart'])); |
| + } |
| + |
| + 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, false, UTF8.encode('$writer'), |
| + [], stopwatch.elapsed, false); |
| + } |
| + |
| BatchRunnerProcess _getBatchRunner(String identifier) { |
| // Start batch processes if needed |
| var runners = _batchProcesses[identifier]; |
| @@ -2716,7 +2838,8 @@ class ProcessQueue { |
| DateTime startTime, testSuites, this._eventListener, this._allDone, |
| [bool verbose = false, |
| String recordingOutputFile, |
| - String recordedInputFile]) { |
| + String recordedInputFile, |
| + AdbDevicePool adbDevicePool]) { |
| void setupForListing(TestCaseEnqueuer testCaseEnqueuer) { |
| _graph.events |
| .where((event) => event is dgraph.GraphSealedEvent) |
| @@ -2817,7 +2940,8 @@ class ProcessQueue { |
| executor = new ReplayingCommandExecutor(new Path(recordedInputFile)); |
| } else { |
| executor = new CommandExecutorImpl( |
| - _globalConfiguration, maxProcesses, maxBrowserProcesses); |
| + _globalConfiguration, maxProcesses, |
| + maxBrowserProcesses, adbDevicePool: adbDevicePool); |
| } |
| // Run "runnable commands" using [executor] subject to |