Add Process wrapper (#34)
Initially contains `Future<int> get done`
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5b5bfa..dc8760c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,8 @@
+#### 3.0.6
+
+* Added class `Process`, a simple wrapper around dart:io's `Process` class.
+
#### 3.0.5
* Fixes for missing_return analysis errors with 2.10.0-dev.1.0.
diff --git a/lib/process.dart b/lib/process.dart
index 2fddabb..f9de50f 100644
--- a/lib/process.dart
+++ b/lib/process.dart
@@ -3,4 +3,5 @@
// BSD-style license that can be found in the LICENSE file.
export 'src/interface/local_process_manager.dart';
+export 'src/interface/process.dart';
export 'src/interface/process_manager.dart';
diff --git a/lib/src/interface/process.dart b/lib/src/interface/process.dart
new file mode 100644
index 0000000..cd6d4e5
--- /dev/null
+++ b/lib/src/interface/process.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2017, 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:io' as io;
+
+/// A wrapper around an [io.Process] class that adds some convenience methods.
+class Process implements io.Process {
+ /// Constructs a [Process] object that delegates to the specified underlying
+ /// object.
+ const Process(this.delegate);
+
+ final io.Process delegate;
+
+ @override
+ Future<int> get exitCode => delegate.exitCode;
+
+ /// A [Future] that completes when the process has exited and its standard
+ /// output and error streams have closed.
+ ///
+ /// This exists as an alternative to [exitCode], which does not guarantee
+ /// that the stdio streams have closed (it is possible for the exit code to
+ /// be available before stdout and stderr have closed).
+ ///
+ /// The future returned here will complete with the exit code of the process.
+ Future<int> get done async {
+ int result;
+ await Future.wait<void>(<Future<void>>[
+ delegate.stdout.length,
+ delegate.stderr.length,
+ delegate.exitCode.then((int value) {
+ result = value;
+ }),
+ ]);
+ assert(result != null);
+ return result;
+ }
+
+ @override
+ bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
+ return delegate.kill(signal);
+ }
+
+ @override
+ int get pid => delegate.pid;
+
+ @override
+ Stream<List<int>> get stderr => delegate.stderr;
+
+ @override
+ io.IOSink get stdin => delegate.stdin;
+
+ @override
+ Stream<List<int>> get stdout => delegate.stdout;
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 9a312dd..7c34541 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: process
-version: 3.0.5
+version: 3.0.6
authors:
- Todd Volkert <tvolkert@google.com>
- Michael Goderbauer <goderbauer@google.com>
diff --git a/test/src/interface/process_test.dart b/test/src/interface/process_test.dart
new file mode 100644
index 0000000..d205b97
--- /dev/null
+++ b/test/src/interface/process_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2017, 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:io' as io;
+
+import 'package:process/process.dart';
+import 'package:test/test.dart';
+
+void main() {
+ group('done', () {
+ test('completes only when all done', () async {
+ TestProcess delegate = new TestProcess();
+ Process process = new Process(delegate);
+ bool done = false;
+ // ignore: unawaited_futures
+ process.done.then((int result) {
+ done = true;
+ });
+ expect(done, isFalse);
+ delegate.exitCodeCompleter.complete(0);
+ await Future<void>.value();
+ expect(done, isFalse);
+ await delegate.stdoutController.close();
+ await Future<void>.value();
+ expect(done, isFalse);
+ await delegate.stderrController.close();
+ await Future<void>.value();
+ expect(done, isTrue);
+ expect(await process.exitCode, 0);
+ });
+ });
+}
+
+class TestProcess implements io.Process {
+ TestProcess([this.pid = 123])
+ : exitCodeCompleter = new Completer<int>(),
+ stdoutController = new StreamController<List<int>>(),
+ stderrController = new StreamController<List<int>>();
+
+ @override
+ final int pid;
+ final Completer<int> exitCodeCompleter;
+ final StreamController<List<int>> stdoutController;
+ final StreamController<List<int>> stderrController;
+
+ @override
+ Future<int> get exitCode => exitCodeCompleter.future;
+
+ @override
+ bool kill([io.ProcessSignal signal = io.ProcessSignal.sigterm]) {
+ exitCodeCompleter.complete(-1);
+ return true;
+ }
+
+ @override
+ Stream<List<int>> get stderr => stderrController.stream;
+
+ @override
+ io.IOSink get stdin => throw UnsupportedError('Not supported');
+
+ @override
+ Stream<List<int>> get stdout => stdoutController.stream;
+}