Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Unified Diff: tools/testing/dart/android.dart

Issue 1922163002: Initial support to test.dart for running precompiler tests on android devices (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Cleanup of CL and of existing code. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/testing/dart/android.dart
diff --git a/tools/testing/dart/android.dart b/tools/testing/dart/android.dart
index 1d390715733707bd716b615c676b5b17a7e6d3ee..9bf2926cdc8a82929cecf6ddd8e85c63e2b93c6a 100644
--- a/tools/testing/dart/android.dart
+++ b/tools/testing/dart/android.dart
@@ -7,30 +7,40 @@ library android;
import "dart:async";
import "dart:convert" show LineSplitter, UTF8;
import "dart:core";
+import "dart:collection";
import "dart:io";
import "path.dart";
import "utils.dart";
-Future _executeCommand(String executable, List<String> args,
- [String stdin = ""]) {
- return _executeCommandRaw(executable, args, stdin).then((results) => null);
-}
-
-Future _executeCommandGetOutput(String executable, List<String> args,
- [String stdin = ""]) {
- return _executeCommandRaw(executable, args, stdin).then((output) => output);
+class AdbCommandResult {
+ final String command;
+ final String stdout;
+ final String stderr;
+ final int exitCode;
+
+ AdbCommandResult(this.command, this.stdout, this.stderr, this.exitCode);
+
+ void throwIfFailed() {
+ if (exitCode != 0) {
+ var error = "Running: $command failed:"
+ "stdout: \n $stdout"
+ "stderr: \n $stderr"
+ "exitCode: \n $exitCode";
+ throw new Exception(error);
+ }
+ }
}
/**
- * [_executeCommandRaw] will write [stdin] to the standard input of the created
+ * [_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 _executeCommandRaw(String executable, List<String> args,
- [String stdin = ""]) {
+Future<AdbCommandResult> _executeCommand(
+ String executable, List<String> args, [String stdin = ""]) {
Future<String> getOutput(Stream<List<int>> stream) {
return stream
.transform(UTF8.decoder)
@@ -38,31 +48,19 @@ Future _executeCommandRaw(String executable, List<String> args,
.then((data) => data.join(""));
}
- DebugLogger.info("Running: '\$ $executable ${args.join(' ')}'");
- return Process.start(executable, args).then((Process process) {
+ return Process.start(executable, args).then((Process process) async {
if (stdin != null && stdin != '') {
process.stdin.write(stdin);
}
process.stdin.close();
- var futures = [
- getOutput(process.stdout),
- getOutput(process.stderr),
- process.exitCode
- ];
- return Future.wait(futures).then((results) {
- bool success = results[2] == 0;
- if (!success) {
- var error = "Running: '\$ $executable ${args.join(' ')}' failed:"
- "stdout: \n ${results[0]}"
- "stderr: \n ${results[1]}"
- "exitCode: \n ${results[2]}";
- throw new Exception(error);
- } else {
- DebugLogger.info("Success: $executable finished");
- }
- return results[0];
- });
+ var results = await Future.wait([
+ getOutput(process.stdout),
+ getOutput(process.stderr),
+ process.exitCode
+ ]);
+ String command = '$executable ${args.join(' ')}';
Bill Hesse 2016/04/27 13:54:40 It may be legal to have ' inside ' because it is i
kustermann 2016/05/02 10:40:23 Done.
+ return new AdbCommandResult(command, results[0], results[1], results[2]);
});
}
@@ -152,7 +150,7 @@ class AndroidEmulator {
* Helper class to create avd device configurations.
*/
class AndroidHelper {
- static Future createAvd(String name, String target) {
+ static Future createAvd(String name, String target) async {
var args = [
'--silent',
'create',
@@ -166,7 +164,8 @@ class AndroidHelper {
'armeabi-v7a'
];
// We're adding newlines to stdin to simulate <enter>.
- return _executeCommand("android", args, "\n\n\n\n");
+ var result = await _executeCommand("android", args, "\n\n\n\n");
+ result.throwIfFailed();
}
}
@@ -192,25 +191,15 @@ class AdbDevice {
* Polls the 'sys.boot_completed' property. Returns as soon as the property is
* 1.
*/
- Future waitForBootCompleted() {
- var timeout = const Duration(seconds: 2);
- var completer = new Completer();
-
- checkUntilBooted() {
- _adbCommandGetOutput(['shell', 'getprop', 'sys.boot_completed'])
- .then((String stdout) {
- stdout = stdout.trim();
- if (stdout == '1') {
- completer.complete();
- } else {
- new Timer(timeout, checkUntilBooted);
- }
- }).catchError((error) {
- new Timer(timeout, checkUntilBooted);
- });
+ Future waitForBootCompleted() async {
+ while (true) {
+ try {
+ AdbCommandResult result =
+ await _adbCommand(['shell', 'getprop', 'sys.boot_completed']);
+ if (result.stdout.trim() == '1') return;
+ } catch (_) { }
+ await new Future.delayed(const Duration(seconds: 2));
}
- checkUntilBooted();
- return completer.future;
}
/**
@@ -299,22 +288,48 @@ class AdbDevice {
return _adbCommand(arguments);
}
- Future _adbCommand(List<String> adbArgs) {
- if (_deviceId != null) {
- var extendedAdbArgs = ['-s', _deviceId];
- extendedAdbArgs.addAll(adbArgs);
- adbArgs = extendedAdbArgs;
+ Future<AdbCommandResult> runAdbCommand(List<String> adbArgs) {
+ return _executeCommand("adb", _deviceSpecificArgs(adbArgs));
+ }
+
+ Future<AdbCommandResult> runAdbShellCommand(List<String> shellArgs) async {
+ 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));
+ int exitCode = result.exitCode;
+ var lines = result
+ .stdout.split('\n')
+ .where((line) => line.trim().length > 0)
+ .toList();
+ if (lines.length > 0) {
+ int index = lines.last.indexOf(MARKER);
+ assert(index >= 0);
+ exitCode = int.parse(lines.last.substring(index + MARKER.length).trim());
}
- return _executeCommand("adb", adbArgs);
+ return new AdbCommandResult(
+ result.command, result.stdout, result.stderr, exitCode);
+ }
+
+ Future<AdbCommandResult> _adbCommand(List<String> adbArgs) async {
+ var result = await _executeCommand("adb", _deviceSpecificArgs(adbArgs));
+ result.throwIfFailed();
+ return result;
}
- Future<String> _adbCommandGetOutput(List<String> adbArgs) {
+ List<String> _deviceSpecificArgs(List<String> adbArgs) {
if (_deviceId != null) {
var extendedAdbArgs = ['-s', _deviceId];
extendedAdbArgs.addAll(adbArgs);
adbArgs = extendedAdbArgs;
}
- return _executeCommandGetOutput("adb", adbArgs);
+ return adbArgs;
}
}
@@ -350,3 +365,45 @@ class Intent {
Intent(this.action, this.package, this.activity, [this.dataUri]);
}
+
+/**
+ * Discovers all available devices and supports acquire/release.
+ */
+class AdbDevicePool {
+ final Queue<AdbDevice> _idleDevices = new Queue<AdbDevice>();
+ final Queue<Completer> _waiter = new Queue<Completer>();
+
+ AdbDevicePool(List<AdbDevice> idleDevices) {
+ _idleDevices.addAll(idleDevices);
+ }
+
+ static Future<AdbDevicePool> create() async {
+ var names = await AdbHelper.listDevices();
+ var devices = names.map((id) => new AdbDevice(id)).toList();
+ if (devices.length == 0) {
+ throw new Exception(
+ 'No android devices found. '
+ 'Please make sure "adb devices" shows your device!');
+ }
+ return new AdbDevicePool(devices);
+ }
+
+ Future<AdbDevice> acquireDevice() async {
+ if (_idleDevices.length > 0) {
+ return _idleDevices.removeFirst();
+ } else {
+ var completer = new Completer();
+ _waiter.add(completer);
+ return completer.future;
+ }
+ }
+
+ void releaseDevice(AdbDevice device) {
+ if (_waiter.length > 0) {
+ Completer completer = _waiter.removeFirst();
+ completer.complete(device);
+ } else {
+ _idleDevices.add(device);
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698