| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 /// Helper functions for running code in a Zone. | 5 /// Helper functions for running code in a Zone. |
| 6 library testing.zone_helper; | 6 library testing.zone_helper; |
| 7 | 7 |
| 8 import 'dart:async' show | 8 import 'dart:async' show Completer, Future, ZoneSpecification, runZoned; |
| 9 Completer, | |
| 10 Future, | |
| 11 ZoneSpecification, | |
| 12 runZoned; | |
| 13 | 9 |
| 14 import 'dart:io' show | 10 import 'dart:io' show exit, stderr; |
| 15 exit, | |
| 16 stderr; | |
| 17 | 11 |
| 18 import 'dart:isolate' show | 12 import 'dart:isolate' show Capability, Isolate, ReceivePort; |
| 19 Capability, | |
| 20 Isolate, | |
| 21 ReceivePort; | |
| 22 | 13 |
| 23 import 'log.dart' show | 14 import 'log.dart' show logUncaughtError; |
| 24 logUncaughtError; | |
| 25 | 15 |
| 26 Future runGuarded( | 16 Future runGuarded(Future f(), |
| 27 Future f(), | |
| 28 {void printLineOnStdout(line), | 17 {void printLineOnStdout(line), |
| 29 void handleLateError(error, StackTrace stackTrace)}) { | 18 void handleLateError(error, StackTrace stackTrace)}) { |
| 30 | |
| 31 var printWrapper; | 19 var printWrapper; |
| 32 if (printLineOnStdout != null) { | 20 if (printLineOnStdout != null) { |
| 33 printWrapper = (_1, _2, _3, String line) { | 21 printWrapper = (_1, _2, _3, String line) { |
| 34 printLineOnStdout(line); | 22 printLineOnStdout(line); |
| 35 }; | 23 }; |
| 36 } | 24 } |
| 37 | 25 |
| 38 Completer completer = new Completer(); | 26 Completer completer = new Completer(); |
| 39 | 27 |
| 40 handleUncaughtError(error, StackTrace stackTrace) { | 28 handleUncaughtError(error, StackTrace stackTrace) { |
| 41 logUncaughtError(error, stackTrace); | 29 logUncaughtError(error, stackTrace); |
| 42 if (!completer.isCompleted) { | 30 if (!completer.isCompleted) { |
| 43 completer.completeError(error, stackTrace); | 31 completer.completeError(error, stackTrace); |
| 44 } else if (handleLateError != null) { | 32 } else if (handleLateError != null) { |
| 45 handleLateError(error, stackTrace); | 33 handleLateError(error, stackTrace); |
| 46 } else { | 34 } else { |
| 47 String errorString = "error.toString() failed."; | 35 String errorString = "error.toString() failed."; |
| 48 try { | 36 try { |
| 49 errorString = "$error"; | 37 errorString = "$error"; |
| 50 } catch (_) { | 38 } catch (_) { |
| 51 // Ignored. | 39 // Ignored. |
| 52 } | 40 } |
| 53 stderr.write("$errorString\n" + | 41 stderr |
| 54 (stackTrace == null ? "" : "$stackTrace")); | 42 .write("$errorString\n" + (stackTrace == null ? "" : "$stackTrace")); |
| 55 stderr.flush(); | 43 stderr.flush(); |
| 56 exit(255); | 44 exit(255); |
| 57 } | 45 } |
| 58 } | 46 } |
| 59 | 47 |
| 60 ZoneSpecification specification = new ZoneSpecification(print: printWrapper); | 48 ZoneSpecification specification = new ZoneSpecification(print: printWrapper); |
| 61 | 49 |
| 62 ReceivePort errorPort = new ReceivePort(); | 50 ReceivePort errorPort = new ReceivePort(); |
| 63 Future errorFuture = errorPort.listen((List errors) { | 51 Future errorFuture = errorPort.listen((List errors) { |
| 64 Isolate.current.removeErrorListener(errorPort.sendPort); | 52 Isolate.current.removeErrorListener(errorPort.sendPort); |
| 65 errorPort.close(); | 53 errorPort.close(); |
| 66 var error = errors[0]; | 54 var error = errors[0]; |
| 67 var stackTrace = errors[1]; | 55 var stackTrace = errors[1]; |
| 68 if (stackTrace != null) { | 56 if (stackTrace != null) { |
| 69 stackTrace = new StackTrace.fromString(stackTrace); | 57 stackTrace = new StackTrace.fromString(stackTrace); |
| 70 } | 58 } |
| 71 handleUncaughtError(error, stackTrace); | 59 handleUncaughtError(error, stackTrace); |
| 72 }).asFuture(); | 60 }).asFuture(); |
| 73 | 61 |
| 74 Isolate.current.setErrorsFatal(false); | 62 Isolate.current.setErrorsFatal(false); |
| 75 Isolate.current.addErrorListener(errorPort.sendPort); | 63 Isolate.current.addErrorListener(errorPort.sendPort); |
| 76 return acknowledgeControlMessages(Isolate.current).then((_) { | 64 return acknowledgeControlMessages(Isolate.current).then((_) { |
| 77 runZoned( | 65 runZoned(() => new Future(f).then(completer.complete), |
| 78 () => new Future(f).then(completer.complete), | 66 zoneSpecification: specification, onError: handleUncaughtError); |
| 79 zoneSpecification: specification, | |
| 80 onError: handleUncaughtError); | |
| 81 | 67 |
| 82 return completer.future.whenComplete(() { | 68 return completer.future.whenComplete(() { |
| 83 errorPort.close(); | 69 errorPort.close(); |
| 84 Isolate.current.removeErrorListener(errorPort.sendPort); | 70 Isolate.current.removeErrorListener(errorPort.sendPort); |
| 85 return acknowledgeControlMessages(Isolate.current) | 71 return acknowledgeControlMessages(Isolate.current) |
| 86 .then((_) => errorFuture); | 72 .then((_) => errorFuture); |
| 87 }); | 73 }); |
| 88 }); | 74 }); |
| 89 } | 75 } |
| 90 | 76 |
| 91 /// Ping [isolate] to ensure control messages have been delivered. Control | 77 /// Ping [isolate] to ensure control messages have been delivered. Control |
| 92 /// messages are things like [Isolate.addErrorListener] and | 78 /// messages are things like [Isolate.addErrorListener] and |
| 93 /// [Isolate.addOnExitListener]. | 79 /// [Isolate.addOnExitListener]. |
| 94 Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) { | 80 Future acknowledgeControlMessages(Isolate isolate, {Capability resume}) { |
| 95 ReceivePort ping = new ReceivePort(); | 81 ReceivePort ping = new ReceivePort(); |
| 96 Isolate.current.ping(ping.sendPort); | 82 Isolate.current.ping(ping.sendPort); |
| 97 if (resume == null) { | 83 if (resume == null) { |
| 98 return ping.first; | 84 return ping.first; |
| 99 } else { | 85 } else { |
| 100 return ping.first.then((_) => isolate.resume(resume)); | 86 return ping.first.then((_) => isolate.resume(resume)); |
| 101 } | 87 } |
| 102 } | 88 } |
| OLD | NEW |