Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: lib/src/backend/invoker.dart

Issue 1361303002: Get rid of LocalTest.tearDown. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698