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

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

Issue 1372353003: Don't early-exit teardowns after a signal. (Closed) Base URL: git@github.com:dart-lang/test@master
Patch Set: Don't re-zone unnecessarily. 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
« no previous file with comments | « lib/src/backend/group.dart ('k') | pubspec.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 /// 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
50 /// using [Invoker.current]. It's used to track asynchronous callbacks and 50 /// using [Invoker.current]. It's used to track asynchronous callbacks and
51 /// report asynchronous errors. 51 /// report asynchronous errors.
52 class Invoker { 52 class Invoker {
53 /// The live test being driven by the invoker. 53 /// The live test being driven by the invoker.
54 /// 54 ///
55 /// This provides a view into the state of the test being executed. 55 /// This provides a view into the state of the test being executed.
56 LiveTest get liveTest => _controller.liveTest; 56 LiveTest get liveTest => _controller.liveTest;
57 LiveTestController _controller; 57 LiveTestController _controller;
58 58
59 bool get _closable => Zone.current[_closableKey];
60
61 /// An opaque object used as a key in the zone value map to identify
62 /// [_closable].
63 ///
64 /// This is an instance variable to ensure that multiple invokers don't step
65 /// on one anothers' toes.
66 final _closableKey = new Object();
67
59 /// Whether the test has been closed. 68 /// Whether the test has been closed.
60 /// 69 ///
61 /// Once the test is closed, [expect] and [expectAsync] will throw 70 /// Once the test is closed, [expect] and [expectAsync] will throw
62 /// [ClosedException]s whenever accessed to help the test stop executing as 71 /// [ClosedException]s whenever accessed to help the test stop executing as
63 /// soon as possible. 72 /// soon as possible.
64 bool get closed => _onCloseCompleter.isCompleted; 73 bool get closed => _closable && _onCloseCompleter.isCompleted;
65 74
66 /// A future that completes once the test has been closed. 75 /// A future that completes once the test has been closed.
67 Future get onClose => _onCloseCompleter.future; 76 Future get onClose => _closable
77 ? _onCloseCompleter.future
78 : new Completer().future;
kevmoo 2015/10/01 02:21:23 Wha? Please explain...
nweiz 2015/10/01 21:16:27 This is just a future that will never fire.
68 final _onCloseCompleter = new Completer(); 79 final _onCloseCompleter = new Completer();
69 80
70 /// The test being run. 81 /// The test being run.
71 LocalTest get _test => liveTest.test as LocalTest; 82 LocalTest get _test => liveTest.test as LocalTest;
72 83
73 /// The test metadata merged with the suite metadata. 84 /// The test metadata merged with the suite metadata.
74 final Metadata metadata; 85 final Metadata metadata;
75 86
76 /// The outstanding callback counter for the current zone. 87 /// The outstanding callback counter for the current zone.
77 OutstandingCallbackCounter get _outstandingCallbacks { 88 OutstandingCallbackCounter get _outstandingCallbacks {
78 var counter = Zone.current[this]; 89 var counter = Zone.current[_counterKey];
79 if (counter != null) return counter; 90 if (counter != null) return counter;
80 throw new StateError("Can't add or remove outstanding callbacks outside " 91 throw new StateError("Can't add or remove outstanding callbacks outside "
81 "of a test body."); 92 "of a test body.");
82 } 93 }
83 94
95 /// An opaque object used as a key in the zone value map to identify
96 /// [_outstandingCallbacks].
97 ///
98 /// This is an instance variable to ensure that multiple invokers don't step
99 /// on one anothers' toes.
100 final _counterKey = new Object();
101
84 /// The current invoker, or `null` if none is defined. 102 /// The current invoker, or `null` if none is defined.
85 /// 103 ///
86 /// An invoker is only set within the zone scope of a running test. 104 /// An invoker is only set within the zone scope of a running test.
87 static Invoker get current { 105 static Invoker get current {
88 // TODO(nweiz): Use a private symbol when dart2js supports it (issue 17526). 106 // TODO(nweiz): Use a private symbol when dart2js supports it (issue 17526).
89 return Zone.current[#test.invoker]; 107 return Zone.current[#test.invoker];
90 } 108 }
91 109
92 /// The zone that the top level of [_test.body] is running in. 110 /// The zone that the top level of [_test.body] is running in.
93 /// 111 ///
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 heartbeat(); 169 heartbeat();
152 170
153 var counter = new OutstandingCallbackCounter(); 171 var counter = new OutstandingCallbackCounter();
154 runZoned(() { 172 runZoned(() {
155 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in 173 // TODO(nweiz): Use async/await here once issue 23497 has been fixed in
156 // two stable versions. 174 // two stable versions.
157 runZoned(() { 175 runZoned(() {
158 new Future.sync(fn).then((_) => counter.removeOutstandingCallback()); 176 new Future.sync(fn).then((_) => counter.removeOutstandingCallback());
159 }, onError: _handleError); 177 }, onError: _handleError);
160 }, zoneValues: { 178 }, zoneValues: {
161 // Use the invoker as a key so that multiple invokers can have different 179 _counterKey: counter
162 // outstanding callback counters at once.
163 this: counter
164 }); 180 });
165 181
166 return counter.noOutstandingCallbacks; 182 return counter.noOutstandingCallbacks;
167 } 183 }
168 184
185 /// Runs [fn] in a zone where [closed] is always `false`.
186 ///
187 /// This is useful for running code that should be able to register callbacks
188 /// and interact with the test framework normally even when the invoker is
189 /// closed, for example cleanup code.
190 unclosable(fn()) {
191 heartbeat();
192
193 return runZoned(fn, zoneValues: {
194 _closableKey: false
195 });
196 }
197
169 /// Notifies the invoker that progress is being made. 198 /// Notifies the invoker that progress is being made.
170 /// 199 ///
171 /// Each heartbeat resets the timeout timer. This helps ensure that 200 /// Each heartbeat resets the timeout timer. This helps ensure that
172 /// long-running tests that still make progress don't time out. 201 /// long-running tests that still make progress don't time out.
173 void heartbeat() { 202 void heartbeat() {
174 if (liveTest.isComplete) return; 203 if (liveTest.isComplete) return;
175 if (_timeoutTimer != null) _timeoutTimer.cancel(); 204 if (_timeoutTimer != null) _timeoutTimer.cancel();
176 205
177 var timeout = metadata.timeout.apply(new Duration(seconds: 30)); 206 var timeout = metadata.timeout.apply(new Duration(seconds: 30));
178 if (timeout == null) return; 207 if (timeout == null) return;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 new State(Status.complete, liveTest.state.result)); 269 new State(Status.complete, liveTest.state.result));
241 270
242 // Use [Timer.run] here to avoid starving the DOM or other 271 // Use [Timer.run] here to avoid starving the DOM or other
243 // non-microtask events. 272 // non-microtask events.
244 Timer.run(_controller.completer.complete); 273 Timer.run(_controller.completer.complete);
245 }); 274 });
246 }, zoneValues: { 275 }, zoneValues: {
247 #test.invoker: this, 276 #test.invoker: this,
248 // Use the invoker as a key so that multiple invokers can have different 277 // Use the invoker as a key so that multiple invokers can have different
249 // outstanding callback counters at once. 278 // outstanding callback counters at once.
250 this: outstandingCallbacksForBody 279 _counterKey: outstandingCallbacksForBody,
280 _closableKey: true
251 }, 281 },
252 zoneSpecification: new ZoneSpecification( 282 zoneSpecification: new ZoneSpecification(
253 print: (self, parent, zone, line) => _controller.print(line)), 283 print: (self, parent, zone, line) => _controller.print(line)),
254 onError: _handleError); 284 onError: _handleError);
255 }); 285 });
256 } 286 }
257 } 287 }
OLDNEW
« no previous file with comments | « lib/src/backend/group.dart ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698