blob: 25a3f3b773fb61ef78cd146c4c075443182f1267 [file] [log] [blame]
// 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:convert';
import 'dart:io' as io;
import 'package:process/process.dart';
import 'package:test/test.dart';
void main() {
group('ProcessWrapper', () {
late TestProcess delegate;
late ProcessWrapper process;
setUp(() {
delegate = TestProcess();
process = ProcessWrapper(delegate);
});
group('done', () {
late bool done;
setUp(() {
done = false;
// ignore: unawaited_futures
process.done.then((int result) {
done = true;
});
});
test('completes only when all done', () async {
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);
});
test('works in conjunction with subscribers to stdio streams', () async {
process.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter())
.listen(print);
delegate.exitCodeCompleter.complete(0);
await delegate.stdoutController.close();
await delegate.stderrController.close();
await Future<void>.value();
expect(done, isTrue);
});
});
group('stdio', () {
test('streams properly close', () async {
Future<void> testStream(
Stream<List<int>> stream,
StreamController<List<int>> controller,
String name,
) async {
bool closed = false;
stream.listen(
(_) {},
onDone: () {
closed = true;
},
);
await controller.close();
await Future<void>.value();
expect(closed, isTrue, reason: 'for $name');
}
await testStream(process.stdout, delegate.stdoutController, 'stdout');
await testStream(process.stderr, delegate.stderrController, 'stderr');
});
});
});
}
class TestProcess implements io.Process {
TestProcess([this.pid = 123])
: exitCodeCompleter = Completer<int>(),
stdoutController = StreamController<List<int>>(),
stderrController = 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;
}