Commit f379a019 authored by Adam Barth's avatar Adam Barth

Handle subprocess crashes during testing

parent 76a51409
...@@ -82,42 +82,59 @@ void main() { ...@@ -82,42 +82,59 @@ 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;
void shutdown() { tempDir = null;
process.kill(); await dirToDelete.delete(recursive: true);
info.server.close(force: true);
} }
var completer = new Completer(); process.exitCode.then((int exitCode) async {
info.server.close(force: true);
StreamSubscription subscription; await cleanupTempDirectory();
subscription = socket.stream.listen((response) { if (!completer.isCompleted) {
if (response["type"] == "print") { String error = await process.stderr.transform(UTF8.decoder).first;
print(response["line"]);
} else if (response["type"] == "loadException") {
shutdown();
completer.completeError(
new LoadException(path, response["message"]),
new Trace.current());
} else if (response["type"] == "error") {
shutdown();
var asyncError = RemoteException.deserialize(response["error"]);
completer.completeError( completer.completeError(
new LoadException(path, asyncError.error), new LoadException(path, error), new Trace.current());
asyncError.stackTrace);
} else {
assert(response["type"] == "success");
subscription.cancel();
completer.complete(response["tests"]);
} }
}); });
Future<JSONSocket> socket = (() async {
return new JSONSocket(await info.socket);
})();
socket.then((JSONSocket socket) async {
await cleanupTempDirectory();
StreamSubscription subscription;
subscription = socket.stream.listen((response) {
if (response["type"] == "print") {
print(response["line"]);
} else if (response["type"] == "loadException") {
process.kill();
completer.completeError(
new LoadException(path, response["message"]),
new Trace.current());
} else if (response["type"] == "error") {
process.kill();
AsyncError asyncError = RemoteException.deserialize(response["error"]);
completer.completeError(
new LoadException(path, asyncError.error),
asyncError.stackTrace);
} else {
assert(response["type"] == "success");
subscription.cancel();
completer.complete(response["tests"]);
}
});
});
return new RunnerSuite(const VMEnvironment(), return new RunnerSuite(const VMEnvironment(),
(await completer.future).map((test) { (await completer.future).map((test) {
var testMetadata = new Metadata.deserialize(test['metadata']); var testMetadata = new Metadata.deserialize(test['metadata']);
...@@ -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