blob: 16bbfdfdfb08bcaf43b5c8ee36bbea919a95390d [file] [log] [blame]
// Copyright (c) 2016, 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 file.
library testing.stdio_process;
import 'dart:async' show EventSink, Future, Stream, StreamTransformer, Timer;
import 'dart:convert' show utf8;
import 'dart:io' show Process, ProcessSignal, Stdout;
import 'dart:io' as io show stderr, stdout;
import 'chain.dart' show Result;
import 'expectation.dart' show ExpectationSet;
class StdioProcess {
final int exitCode;
final String output;
StdioProcess(this.exitCode, this.output);
Result<int> toResult({int expected: 0}) {
if (exitCode == expected) {
return new Result<int>.pass(exitCode);
} else {
return new Result<int>(
exitCode, ExpectationSet.Default["RuntimeError"], output);
static StreamTransformer<String, String> transformToStdio(Stdout stdio) {
return new StreamTransformer<String, String>.fromHandlers(
handleData: (String data, EventSink<String> sink) {
static Future<StdioProcess> run(String executable, List<String> arguments,
{String input,
Duration timeout: const Duration(seconds: 60),
bool suppressOutput: true,
bool runInShell: false}) async {
Process process =
await Process.start(executable, arguments, runInShell: runInShell);
Timer timer;
StringBuffer sb = new StringBuffer();
if (timeout != null) {
timer = new Timer(timeout, () {
sb.write("Process timed out: ");
sb.write(" ");
sb.writeAll(arguments, " ");
sb.writeln("Sending SIGTERM to process");
timer = new Timer(const Duration(seconds: 10), () {
sb.writeln("Sending SIGKILL to process");
if (input != null) {
await process.stdin.flush();
Future closeFuture = process.stdin.close();
Stream stdoutStream = process.stdout.transform(utf8.decoder);
Stream stderrStream = process.stderr.transform(utf8.decoder);
if (!suppressOutput) {
stdoutStream = stdoutStream.transform(transformToStdio(io.stdout));
stderrStream = stderrStream.transform(transformToStdio(io.stderr));
Future<List<String>> stdoutFuture = stdoutStream.toList();
Future<List<String>> stderrFuture = stderrStream.toList();
int exitCode = await process.exitCode;
sb.writeAll(await stdoutFuture);
sb.writeAll(await stderrFuture);
await closeFuture;
return new StdioProcess(exitCode, "$sb");