Commit f379a019 authored by Adam Barth's avatar Adam Barth

Handle subprocess crashes during testing

parent 76a51409
...@@ -82,32 +82,48 @@ void main() { ...@@ -82,32 +82,48 @@ void main() {
} }
'''); ''');
Completer completer = new Completer();
Process process = await _startProcess(listenerFile.path, Process process = await _startProcess(listenerFile.path,
packageRoot: p.absolute(config.packageRoot)); packageRoot: p.absolute(config.packageRoot));
JSONSocket socket = new JSONSocket(await info.socket); Future cleanupTempDirectory() async {
if (tempDir == null)
await tempDir.delete(recursive: true); return;
Directory dirToDelete = tempDir;
tempDir = null;
await dirToDelete.delete(recursive: true);
}
void shutdown() { process.exitCode.then((int exitCode) async {
process.kill();
info.server.close(force: true); info.server.close(force: true);
await cleanupTempDirectory();
if (!completer.isCompleted) {
String error = await process.stderr.transform(UTF8.decoder).first;
completer.completeError(
new LoadException(path, error), new Trace.current());
} }
});
Future<JSONSocket> socket = (() async {
return new JSONSocket(await info.socket);
})();
var completer = new Completer(); socket.then((JSONSocket socket) async {
await cleanupTempDirectory();
StreamSubscription subscription; StreamSubscription subscription;
subscription = socket.stream.listen((response) { subscription = socket.stream.listen((response) {
if (response["type"] == "print") { if (response["type"] == "print") {
print(response["line"]); print(response["line"]);
} else if (response["type"] == "loadException") { } else if (response["type"] == "loadException") {
shutdown(); process.kill();
completer.completeError( completer.completeError(
new LoadException(path, response["message"]), new LoadException(path, response["message"]),
new Trace.current()); new Trace.current());
} else if (response["type"] == "error") { } else if (response["type"] == "error") {
shutdown(); process.kill();
var asyncError = RemoteException.deserialize(response["error"]); AsyncError asyncError = RemoteException.deserialize(response["error"]);
completer.completeError( completer.completeError(
new LoadException(path, asyncError.error), new LoadException(path, asyncError.error),
asyncError.stackTrace); asyncError.stackTrace);
...@@ -117,6 +133,7 @@ void main() { ...@@ -117,6 +133,7 @@ void main() {
completer.complete(response["tests"]); completer.complete(response["tests"]);
} }
}); });
});
return new RunnerSuite(const VMEnvironment(), return new RunnerSuite(const VMEnvironment(),
(await completer.future).map((test) { (await completer.future).map((test) {
...@@ -127,5 +144,5 @@ void main() { ...@@ -127,5 +144,5 @@ void main() {
path: path, path: path,
platform: TestPlatform.vm, platform: TestPlatform.vm,
os: currentOS, os: currentOS,
onClose: shutdown); onClose: process.kill);
} }
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'package:test/src/backend/live_test.dart'; import 'package:test/src/backend/live_test.dart';
import 'package:test/src/backend/live_test_controller.dart'; import 'package:test/src/backend/live_test_controller.dart';
import 'package:test/src/backend/metadata.dart'; import 'package:test/src/backend/metadata.dart';
...@@ -16,23 +18,24 @@ class RemoteTest implements Test { ...@@ -16,23 +18,24 @@ class RemoteTest implements Test {
final String name; final String name;
final Metadata metadata; final Metadata metadata;
final JSONSocket _socket; final Future<JSONSocket> _socket;
final int _index; final int _index;
RemoteTest(this.name, this.metadata, this._socket, this._index); RemoteTest(this.name, this.metadata, this._socket, this._index);
LiveTest load(Suite suite) { LiveTest load(Suite suite) {
var controller; LiveTestController controller;
var subscription; StreamSubscription subscription;
controller = new LiveTestController(suite, this, () { controller = new LiveTestController(suite, this, () async {
controller.setState(const State(Status.running, Result.success)); controller.setState(const State(Status.running, Result.success));
_socket.send({'command': 'run', 'index': _index}); JSONSocket socket = await _socket;
socket.send({'command': 'run', 'index': _index});
subscription = _socket.stream.listen((message) { subscription = socket.stream.listen((message) {
if (message['type'] == 'error') { if (message['type'] == 'error') {
var asyncError = RemoteException.deserialize(message['error']); AsyncError asyncError = RemoteException.deserialize(message['error']);
controller.addError(asyncError.error, asyncError.stackTrace); controller.addError(asyncError.error, asyncError.stackTrace);
} else if (message['type'] == 'state-change') { } else if (message['type'] == 'state-change') {
controller.setState( controller.setState(
...@@ -48,8 +51,9 @@ class RemoteTest implements Test { ...@@ -48,8 +51,9 @@ class RemoteTest implements Test {
controller.completer.complete(); controller.completer.complete();
} }
}); });
}, () { }, () async {
_socket.send({'command': 'close'}); JSONSocket socket = await _socket;
socket.send({'command': 'close'});
if (subscription != null) { if (subscription != null) {
subscription.cancel(); subscription.cancel();
subscription = null; subscription = null;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment