OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library test.runner.vm.isolate_test; | 5 library test.runner.vm.isolate_test; |
6 | 6 |
| 7 import 'dart:async'; |
7 import 'dart:isolate'; | 8 import 'dart:isolate'; |
8 | 9 |
9 import '../../backend/live_test.dart'; | 10 import '../../backend/live_test.dart'; |
10 import '../../backend/live_test_controller.dart'; | 11 import '../../backend/live_test_controller.dart'; |
11 import '../../backend/metadata.dart'; | 12 import '../../backend/metadata.dart'; |
12 import '../../backend/state.dart'; | 13 import '../../backend/state.dart'; |
13 import '../../backend/suite.dart'; | 14 import '../../backend/suite.dart'; |
14 import '../../backend/test.dart'; | 15 import '../../backend/test.dart'; |
15 import '../../util/remote_exception.dart'; | 16 import '../../util/remote_exception.dart'; |
16 | 17 |
17 /// A test in another isolate. | 18 /// A test in another isolate. |
18 class IsolateTest implements Test { | 19 class IsolateTest implements Test { |
19 final String name; | 20 final String name; |
20 final Metadata metadata; | 21 final Metadata metadata; |
21 | 22 |
22 /// The port on which to communicate with the remote test. | 23 /// The port on which to communicate with the remote test. |
23 final SendPort _sendPort; | 24 final SendPort _sendPort; |
24 | 25 |
25 IsolateTest(this.name, this.metadata, this._sendPort); | 26 IsolateTest(this.name, this.metadata, this._sendPort); |
26 | 27 |
27 /// Loads a single runnable instance of this test. | 28 /// Loads a single runnable instance of this test. |
28 LiveTest load(Suite suite) { | 29 LiveTest load(Suite suite) { |
| 30 var controller; |
| 31 |
| 32 // We get a new send port for communicating with the live test, since |
| 33 // [_sendPort] is only for communicating with the non-live test. This will |
| 34 // be non-null once the test starts running. |
| 35 var sendPortCompleter; |
| 36 |
29 var receivePort; | 37 var receivePort; |
30 var controller; | |
31 controller = new LiveTestController(suite, this, () { | 38 controller = new LiveTestController(suite, this, () { |
32 controller.setState(const State(Status.running, Result.success)); | 39 controller.setState(const State(Status.running, Result.success)); |
33 | 40 |
| 41 sendPortCompleter = new Completer(); |
34 receivePort = new ReceivePort(); | 42 receivePort = new ReceivePort(); |
35 _sendPort.send({ | 43 _sendPort.send({ |
36 'command': 'run', | 44 'command': 'run', |
37 'reply': receivePort.sendPort | 45 'reply': receivePort.sendPort |
38 }); | 46 }); |
39 | 47 |
40 receivePort.listen((message) { | 48 receivePort.listen((message) { |
41 if (message['type'] == 'error') { | 49 if (message['type'] == 'started') { |
| 50 sendPortCompleter.complete(message['reply']); |
| 51 } else if (message['type'] == 'error') { |
42 var asyncError = RemoteException.deserialize(message['error']); | 52 var asyncError = RemoteException.deserialize(message['error']); |
43 controller.addError(asyncError.error, asyncError.stackTrace); | 53 controller.addError(asyncError.error, asyncError.stackTrace); |
44 } else if (message['type'] == 'state-change') { | 54 } else if (message['type'] == 'state-change') { |
45 controller.setState( | 55 controller.setState( |
46 new State( | 56 new State( |
47 new Status.parse(message['status']), | 57 new Status.parse(message['status']), |
48 new Result.parse(message['result']))); | 58 new Result.parse(message['result']))); |
49 } else if (message['type'] == 'print') { | 59 } else if (message['type'] == 'print') { |
50 controller.print(message['line']); | 60 controller.print(message['line']); |
51 } else { | 61 } else { |
52 assert(message['type'] == 'complete'); | 62 assert(message['type'] == 'complete'); |
53 controller.completer.complete(); | 63 controller.completer.complete(); |
54 } | 64 } |
55 }); | 65 }); |
56 }, onClose: () { | 66 }, () { |
57 if (receivePort != null) receivePort.close(); | 67 // If the test has finished running, just disconnect the receive port. The |
| 68 // Dart process won't terminate if there are any live receive ports open. |
| 69 if (controller.completer.isCompleted) { |
| 70 receivePort.close(); |
| 71 return; |
| 72 } |
| 73 |
| 74 // If the test is still running, send it a message telling it to shut down |
| 75 // ASAP. This causes the [Invoker] to eagerly throw exceptions whenever |
| 76 // the test touches it. |
| 77 sendPortCompleter.future.then((sendPort) { |
| 78 sendPort.send({'command': 'close'}); |
| 79 return controller.completer.future; |
| 80 }).then((_) => receivePort.close()); |
58 }); | 81 }); |
59 return controller.liveTest; | 82 return controller.liveTest; |
60 } | 83 } |
61 } | 84 } |
OLD | NEW |