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

Unified Diff: utils/testrunner/pipeline_utils.dart

Issue 14247033: Updated testrunner: (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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: utils/testrunner/pipeline_utils.dart
===================================================================
--- utils/testrunner/pipeline_utils.dart (revision 21707)
+++ utils/testrunner/pipeline_utils.dart (working copy)
@@ -4,7 +4,7 @@
part of pipeline;
-List stdout, stderr, log;
+List log;
var replyPort;
int _procId = 1;
Map _procs = {};
@@ -14,7 +14,7 @@
* [tmpDir] directory, with name [basis], but with any extension
* stripped and replaced by [suffix].
*/
-String createTempName(String tmpDir, String basis, String suffix) {
+String createTempName(String tmpDir, String basis, [String suffix='']) {
var p = new Path(basis);
return '$tmpDir${Platform.pathSeparator}'
'${p.filenameWithoutExtension}${suffix}';
@@ -41,9 +41,7 @@
/** Create a file [fileName] and populate it with [contents]. */
void writeFile(String fileName, String contents) {
var file = new File(fileName);
- var ostream = file.openOutputStream(FileMode.WRITE);
- ostream.writeString(contents);
- ostream.close();
+ file.writeAsStringSync(contents);
}
/*
@@ -59,62 +57,84 @@
* Returns a [Future] for when the process terminates.
*/
Future _processHelper(String command, List<String> args,
Siggi Cherem (dart-lang) 2013/04/19 21:39:39 is this duplicate code with the other _processHelp
gram 2013/04/22 23:54:27 No, it is not a dup; it has some subtle difference
Siggi Cherem (dart-lang) 2013/04/23 01:10:04 I think you can use Future.wait instead, using str
gram 2013/04/23 22:53:40 Done.
- [int timeout = 300, int procId = 0, Function outputMonitor]) {
- var completer = procId == 0 ? new Completer() : null;
+ List stdout, List stderr,
+ [int timeout = 30, int procId = 0, Function outputMonitor]) {
+ var completer = procId == 0 ? (new Completer()) : null;
+ var timer = null;
+ if (Platform.operatingSystem == 'windows' && command.endsWith('.bat')) {
+ var oldArgs = args;
+ args = new List();
+ args.add('/k');
+ // TODO(gram): We may need some escaping here if any of the
+ // components contain spaces.
+ args.add("$command ${oldArgs.join(' ')}");
+ command='cmd.exe';
+ }
log.add('Running $command ${args.join(" ")}');
- var timer = null;
- var stdoutHandler, stderrHandler;
+ // We are not done until the process has exited and both the stdout
+ // and stderr streams have drained; at that point we want to return
+ // the process exit code. We manage this with local state consisting
+ // of three flags and an int in a List.
+ // There is probably a better way to do this.
+ var doneState = [ false, false, false, 0 ];
var processFuture = Process.start(command, args);
processFuture.then((process) {
- _procs[procId] = process;
+ _procs[procId.toString()] = process;
timer = new Timer(new Duration(seconds: timeout), () {
timer = null;
process.kill();
});
- process.onExit = (exitCode) {
+ process.exitCode.then((exitCode) {
if (timer != null) {
timer.cancel();
}
- process.close();
if (completer != null) {
- completer.complete(exitCode);
+ doneState[3] = exitCode;
+ _checkComplete(doneState, 2, completer);
}
- };
-
- _pipeStream(process.stdout, stdout, outputMonitor);
- _pipeStream(process.stderr, stderr, outputMonitor);
- });
- processFuture.handleException((e) {
+ });
+ _pipeStream(process.stdout, stdout, outputMonitor,
+ doneState, 0, completer);
+ _pipeStream(process.stderr, stderr, outputMonitor,
+ doneState, 1, completer);
+ })
+ .catchError((e) {
stderr.add("Error starting process:");
stderr.add(" Command: $command");
- stderr.add(" Error: $e");
- completePipeline(-1);
- return true;
+ stderr.add(" Error: ${e.error}");
+ completePipeline(stdout, stderr, -1);
});
- return completer.future;
+ return completer == null ? null : completer.future;
}
-void _pipeStream(InputStream stream, List<String> destination,
- Function outputMonitor) {
- var source = new StringInputStream(stream);
- source.onLine = () {
- if (source.available() == 0) return;
- var line = source.readLine();
- while (null != line) {
+void _checkComplete(List doneState, int index, Completer completer) {
+ doneState[index] = true;
+ if (completer != null && doneState[0] && doneState[1] && doneState[2]) {
+ completer.complete(doneState[3]);
+ }
+}
+
+void _pipeStream(Stream stream, List<String> destination,
+ Function outputMonitor,
+ List doneState, int stateIndex, Completer completer) {
+ stream
+ .transform(new StringDecoder())
+ .transform(new LineTransformer())
+ .listen((String line) {
if (config["immediate"] && line.startsWith('###')) {
- // TODO - when we dump the list later skip '###' messages if immediate.
print(line.substring(3));
}
if (outputMonitor != null) {
outputMonitor(line);
}
destination.add(line);
- line = source.readLine();
- }
- };
+ },
+ onDone: () {
+ _checkComplete(doneState, stateIndex, completer);
+ });
}
/**
@@ -124,26 +144,32 @@
* Returns a [Future] for when the process terminates.
*/
Future runCommand(String command, List<String> args,
- [int timeout = 300, Function outputMonitor]) {
- return _processHelper(command, args, timeout, outputMonitor:outputMonitor);
+ List stdout, List stderr,
+ [int timeout = 30, Function outputMonitor]) {
+ return _processHelper(command, args, stdout, stderr,
+ timeout, 0, outputMonitor);
}
/**
* Start an external process [cmd] with command line arguments [args].
* Returns an ID by which it can later be stopped.
*/
-int startProcess(String command, List<String> args, [Function outputMonitor]) {
+int startProcess(String command, List<String> args, List stdout, List stderr,
+ [Function outputMonitor]) {
int id = _procId++;
- _processHelper(command, args, 3000, id,
- outputMonitor:outputMonitor).then((e) {
- _procs.remove(id);
- });
+ var f = _processHelper(command, args, stdout, stderr, 3000, id,
+ outputMonitor);
+ if (f != null) {
+ f.then((e) {
+ _procs.remove(id.toString());
+ });
+ }
return id;
}
/** Checks if a process is still running. */
bool isProcessRunning(int id) {
- return _procs.containsKey(id);
+ return _procs.containsKey(id.toString());
}
/**
@@ -151,15 +177,16 @@
* given the id string.
*/
void stopProcess(int id) {
- if (_procs.containsKey(id)) {
- Process p = _procs.remove(id);
+ var sid = id.toString();
+ if (_procs.containsKey(sid)) {
+ Process p = _procs.remove(sid);
p.kill();
}
}
/** Delete a file named [fname] if it exists. */
bool cleanup(String fname) {
- if (fname != null && !config['keep-files']) {
+ if (fname != null && config['clean-files']) {
var f = new File(fname);
try {
if (f.existsSync()) {
@@ -173,6 +200,22 @@
return true;
}
+/** Delete a directory named [dname] if it exists. */
+bool cleanupDir(String dname) {
+ if (dname != null && config['clean-files']) {
+ var d = new Directory(dname);
+ try {
+ if (d.existsSync()) {
+ logMessage('Removing $dname');
+ d.deleteSync(recursive: true);
+ }
+ } catch (e) {
+ return false;
+ }
+ }
+ return true;
+}
+
initPipeline(port) {
replyPort = port;
stdout = new List();
@@ -180,9 +223,12 @@
log = new List();
}
-void completePipeline([exitCode = 0]) {
+void completePipeline(List stdout, List stderr, [exitCode = 0]) {
replyPort.send([stdout, stderr, log, exitCode]);
}
/** Utility function to log diagnostic messages. */
void logMessage(msg) => log.add(msg);
+
+/** Turn file paths into standard form with forward slashes. */
+String normalizePath(String p) => (new Path(p)).toString();

Powered by Google App Engine
This is Rietveld 408576698