Chromium Code Reviews| 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.backend.invoker; | 5 library test.backend.invoker; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:stack_trace/stack_trace.dart'; | 9 import 'package:stack_trace/stack_trace.dart'; |
| 10 | 10 |
| 11 import '../frontend/expect.dart'; | 11 import '../frontend/expect.dart'; |
| 12 import '../utils.dart'; | 12 import '../utils.dart'; |
| 13 import 'closed_exception.dart'; | 13 import 'closed_exception.dart'; |
| 14 import 'live_test.dart'; | 14 import 'live_test.dart'; |
| 15 import 'live_test_controller.dart'; | 15 import 'live_test_controller.dart'; |
| 16 import 'metadata.dart'; | 16 import 'metadata.dart'; |
| 17 import 'outstanding_callback_counter.dart'; | 17 import 'outstanding_callback_counter.dart'; |
| 18 import 'state.dart'; | 18 import 'state.dart'; |
| 19 import 'suite.dart'; | 19 import 'suite.dart'; |
| 20 import 'test.dart'; | 20 import 'test.dart'; |
| 21 | 21 |
| 22 /// A test in this isolate. | 22 /// A test in this isolate. |
| 23 class LocalTest implements Test { | 23 class LocalTest implements Test { |
| 24 final String name; | 24 final String name; |
| 25 final Metadata metadata; | 25 final Metadata metadata; |
| 26 | 26 |
| 27 /// The test body. | 27 /// The test body. |
| 28 final AsyncFunction _body; | 28 final AsyncFunction _body; |
| 29 | 29 |
| 30 /// The callback used to clean up after the test. | 30 LocalTest(this.name, this.metadata, body()) |
| 31 /// | 31 : _body = body; |
| 32 /// This is separated out from [_body] because it needs to run once the test's | |
| 33 /// asynchronous computation has finished, even if that's different from the | |
| 34 /// completion of the main body of the test. | |
| 35 final AsyncFunction _tearDown; | |
| 36 | |
| 37 LocalTest(this.name, this.metadata, body(), {tearDown()}) | |
| 38 : _body = body, | |
| 39 _tearDown = tearDown; | |
| 40 | 32 |
| 41 /// Loads a single runnable instance of this test. | 33 /// Loads a single runnable instance of this test. |
| 42 LiveTest load(Suite suite) { | 34 LiveTest load(Suite suite) { |
| 43 var invoker = new Invoker._(suite, this); | 35 var invoker = new Invoker._(suite, this); |
| 44 return invoker.liveTest; | 36 return invoker.liveTest; |
| 45 } | 37 } |
| 46 | 38 |
| 47 Test change({String name, Metadata metadata}) { | 39 Test change({String name, Metadata metadata}) { |
| 48 if (name == name && metadata == this.metadata) return this; | 40 if (name == name && metadata == this.metadata) return this; |
| 49 if (name == null) name = this.name; | 41 if (name == null) name = this.name; |
| 50 if (metadata == null) metadata = this.metadata; | 42 if (metadata == null) metadata = this.metadata; |
| 51 return new LocalTest(name, metadata, _body, tearDown: _tearDown); | 43 return new LocalTest(name, metadata, _body); |
| 52 } | 44 } |
| 53 } | 45 } |
| 54 | 46 |
| 55 /// The class responsible for managing the lifecycle of a single local test. | 47 /// The class responsible for managing the lifecycle of a single local test. |
| 56 /// | 48 /// |
| 57 /// The current invoker is accessible within the zone scope of the running test | 49 /// The current invoker is accessible within the zone scope of the running test |
| 58 /// using [Invoker.current]. It's used to track asynchronous callbacks and | 50 /// using [Invoker.current]. It's used to track asynchronous callbacks and |
| 59 /// report asynchronous errors. | 51 /// report asynchronous errors. |
| 60 class Invoker { | 52 class Invoker { |
| 61 /// The live test being driven by the invoker. | 53 /// The live test being driven by the invoker. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 140 /// | 132 /// |
| 141 /// Future calls to [addOutstandingCallback] and [removeOutstandingCallback] | 133 /// Future calls to [addOutstandingCallback] and [removeOutstandingCallback] |
| 142 /// will be ignored. | 134 /// will be ignored. |
| 143 void removeAllOutstandingCallbacks() => | 135 void removeAllOutstandingCallbacks() => |
| 144 _outstandingCallbacks.removeAllOutstandingCallbacks(); | 136 _outstandingCallbacks.removeAllOutstandingCallbacks(); |
| 145 | 137 |
| 146 /// Runs [fn] and returns once all (registered) outstanding callbacks it | 138 /// Runs [fn] and returns once all (registered) outstanding callbacks it |
| 147 /// transitively invokes have completed. | 139 /// transitively invokes have completed. |
| 148 /// | 140 /// |
| 149 /// If [fn] itself returns a future, this will automatically wait until that | 141 /// If [fn] itself returns a future, this will automatically wait until that |
| 150 /// future completes as well. | 142 /// future completes as well. Note that outstanding callbacks registered |
| 143 /// within [fn] will *not* be registered as outstanding callback outside of | |
| 144 /// [fn]. | |
| 151 /// | 145 /// |
| 152 /// Note that outstanding callbacks registered within [fn] will *not* be | 146 /// If [fn] produces an unhandled error, this marks the current test as |
| 153 /// registered as outstanding callback outside of [fn]. | 147 /// failed, removes all outstanding callbacks registered within [fn], and the |
| 148 /// completes returned future. It does not remove any outstanding callbacks | |
|
Bob Nystrom
2015/09/24 16:05:02
"and the completes returned future" no has grammar
nweiz
2015/09/24 19:56:20
Done.
| |
| 149 /// registered outside of [fn]. | |
| 154 Future waitForOutstandingCallbacks(fn()) { | 150 Future waitForOutstandingCallbacks(fn()) { |
| 155 heartbeat(); | 151 heartbeat(); |
| 156 | 152 |
| 157 var counter = new OutstandingCallbackCounter(); | 153 var counter = new OutstandingCallbackCounter(); |
| 158 runZoned(() { | 154 runZoned(() { |
| 159 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in | 155 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in |
| 160 // two stable versions. | 156 // two stable versions. |
| 161 new Future.sync(fn).then((_) => counter.removeOutstandingCallback()); | 157 runZoned(() { |
| 158 new Future.sync(fn).then((_) => counter.removeOutstandingCallback()); | |
| 159 }, onError: _handleError); | |
| 162 }, zoneValues: { | 160 }, zoneValues: { |
| 163 // Use the invoker as a key so that multiple invokers can have different | 161 // Use the invoker as a key so that multiple invokers can have different |
| 164 // outstanding callback counters at once. | 162 // outstanding callback counters at once. |
| 165 this: counter | 163 this: counter |
| 166 }); | 164 }); |
| 167 | 165 |
| 168 return counter.noOutstandingCallbacks; | 166 return counter.noOutstandingCallbacks; |
| 169 } | 167 } |
| 170 | 168 |
| 171 /// Notifies the invoker that progress is being made. | 169 /// Notifies the invoker that progress is being made. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 // Run the test asynchronously so that the "running" state change has | 228 // Run the test asynchronously so that the "running" state change has |
| 231 // a chance to hit its event handler(s) before the test produces an | 229 // a chance to hit its event handler(s) before the test produces an |
| 232 // error. If an error is emitted before the first state change is | 230 // error. If an error is emitted before the first state change is |
| 233 // handled, we can end up with [onError] callbacks firing before the | 231 // handled, we can end up with [onError] callbacks firing before the |
| 234 // corresponding [onStateChange], which violates the timing | 232 // corresponding [onStateChange], which violates the timing |
| 235 // guarantees. | 233 // guarantees. |
| 236 new Future(_test._body) | 234 new Future(_test._body) |
| 237 .then((_) => removeOutstandingCallback()); | 235 .then((_) => removeOutstandingCallback()); |
| 238 | 236 |
| 239 _outstandingCallbacks.noOutstandingCallbacks.then((_) { | 237 _outstandingCallbacks.noOutstandingCallbacks.then((_) { |
| 240 if (_test._tearDown == null) return null; | |
| 241 | |
| 242 // Reset the outstanding callback counter to wait for callbacks from | |
| 243 // the test's `tearDown` to complete. | |
| 244 return waitForOutstandingCallbacks(() => | |
| 245 runZoned(_test._tearDown, onError: _handleError)); | |
| 246 }).then((_) { | |
| 247 if (_timeoutTimer != null) _timeoutTimer.cancel(); | 238 if (_timeoutTimer != null) _timeoutTimer.cancel(); |
| 248 _controller.setState( | 239 _controller.setState( |
| 249 new State(Status.complete, liveTest.state.result)); | 240 new State(Status.complete, liveTest.state.result)); |
| 250 | 241 |
| 251 // Use [Timer.run] here to avoid starving the DOM or other | 242 // Use [Timer.run] here to avoid starving the DOM or other |
| 252 // non-microtask events. | 243 // non-microtask events. |
| 253 Timer.run(_controller.completer.complete); | 244 Timer.run(_controller.completer.complete); |
| 254 }); | 245 }); |
| 255 }, zoneValues: { | 246 }, zoneValues: { |
| 256 #test.invoker: this, | 247 #test.invoker: this, |
| 257 // Use the invoker as a key so that multiple invokers can have different | 248 // Use the invoker as a key so that multiple invokers can have different |
| 258 // outstanding callback counters at once. | 249 // outstanding callback counters at once. |
| 259 this: outstandingCallbacksForBody | 250 this: outstandingCallbacksForBody |
| 260 }, | 251 }, |
| 261 zoneSpecification: new ZoneSpecification( | 252 zoneSpecification: new ZoneSpecification( |
| 262 print: (self, parent, zone, line) => _controller.print(line)), | 253 print: (self, parent, zone, line) => _controller.print(line)), |
| 263 onError: _handleError); | 254 onError: _handleError); |
| 264 }); | 255 }); |
| 265 } | 256 } |
| 266 } | 257 } |
| OLD | NEW |