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 'operating_system.dart'; |
17 import 'outstanding_callback_counter.dart'; | 18 import 'outstanding_callback_counter.dart'; |
18 import 'state.dart'; | 19 import 'state.dart'; |
19 import 'suite.dart'; | 20 import 'suite.dart'; |
20 import 'test.dart'; | 21 import 'test.dart'; |
| 22 import 'test_platform.dart'; |
21 | 23 |
22 /// A test in this isolate. | 24 /// A test in this isolate. |
23 class LocalTest implements Test { | 25 class LocalTest extends Test { |
24 final String name; | 26 final String name; |
25 final Metadata metadata; | 27 final Metadata metadata; |
26 | 28 |
27 /// The test body. | 29 /// The test body. |
28 final AsyncFunction _body; | 30 final AsyncFunction _body; |
29 | 31 |
30 LocalTest(this.name, this.metadata, body()) | 32 LocalTest(this.name, this.metadata, body()) |
31 : _body = body; | 33 : _body = body; |
32 | 34 |
33 /// Loads a single runnable instance of this test. | 35 /// Loads a single runnable instance of this test. |
34 LiveTest load(Suite suite) { | 36 LiveTest load(Suite suite) { |
35 var invoker = new Invoker._(suite, this); | 37 var invoker = new Invoker._(suite, this); |
36 return invoker.liveTest; | 38 return invoker.liveTest; |
37 } | 39 } |
38 | 40 |
39 Test change({String name, Metadata metadata}) { | 41 Test forPlatform(TestPlatform platform, {OperatingSystem os}) { |
40 if (name == name && metadata == this.metadata) return this; | 42 if (!metadata.testOn.evaluate(platform, os: os)) return null; |
41 if (name == null) name = this.name; | 43 return new LocalTest(name, metadata.forPlatform(platform, os: os), _body); |
42 if (metadata == null) metadata = this.metadata; | |
43 return new LocalTest(name, metadata, _body); | |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 /// 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. |
48 /// | 48 /// |
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. |
(...skipping 22 matching lines...) Expand all Loading... |
76 Future get onClose => _closable | 76 Future get onClose => _closable |
77 ? _onCloseCompleter.future | 77 ? _onCloseCompleter.future |
78 // If we're in an unclosable block, return a future that will never | 78 // If we're in an unclosable block, return a future that will never |
79 // complete. | 79 // complete. |
80 : new Completer().future; | 80 : new Completer().future; |
81 final _onCloseCompleter = new Completer(); | 81 final _onCloseCompleter = new Completer(); |
82 | 82 |
83 /// The test being run. | 83 /// The test being run. |
84 LocalTest get _test => liveTest.test as LocalTest; | 84 LocalTest get _test => liveTest.test as LocalTest; |
85 | 85 |
86 /// The test metadata merged with the suite metadata. | |
87 final Metadata metadata; | |
88 | |
89 /// The outstanding callback counter for the current zone. | 86 /// The outstanding callback counter for the current zone. |
90 OutstandingCallbackCounter get _outstandingCallbacks { | 87 OutstandingCallbackCounter get _outstandingCallbacks { |
91 var counter = Zone.current[_counterKey]; | 88 var counter = Zone.current[_counterKey]; |
92 if (counter != null) return counter; | 89 if (counter != null) return counter; |
93 throw new StateError("Can't add or remove outstanding callbacks outside " | 90 throw new StateError("Can't add or remove outstanding callbacks outside " |
94 "of a test body."); | 91 "of a test body."); |
95 } | 92 } |
96 | 93 |
97 /// An opaque object used as a key in the zone value map to identify | 94 /// An opaque object used as a key in the zone value map to identify |
98 /// [_outstandingCallbacks]. | 95 /// [_outstandingCallbacks]. |
(...skipping 14 matching lines...) Expand all Loading... |
113 /// | 110 /// |
114 /// Tracking this ensures that [_timeoutTimer] isn't created in a | 111 /// Tracking this ensures that [_timeoutTimer] isn't created in a |
115 /// timer-mocking zone created by the test. | 112 /// timer-mocking zone created by the test. |
116 Zone _invokerZone; | 113 Zone _invokerZone; |
117 | 114 |
118 /// The timer for tracking timeouts. | 115 /// The timer for tracking timeouts. |
119 /// | 116 /// |
120 /// This will be `null` until the test starts running. | 117 /// This will be `null` until the test starts running. |
121 Timer _timeoutTimer; | 118 Timer _timeoutTimer; |
122 | 119 |
123 Invoker._(Suite suite, LocalTest test) | 120 Invoker._(Suite suite, LocalTest test) { |
124 : metadata = suite.metadata.merge(test.metadata) { | |
125 _controller = new LiveTestController( | 121 _controller = new LiveTestController( |
126 suite, test, _onRun, _onCloseCompleter.complete); | 122 suite, test, _onRun, _onCloseCompleter.complete); |
127 } | 123 } |
128 | 124 |
129 /// Tells the invoker that there's a callback running that it should wait for | 125 /// Tells the invoker that there's a callback running that it should wait for |
130 /// before considering the test successful. | 126 /// before considering the test successful. |
131 /// | 127 /// |
132 /// Each call to [addOutstandingCallback] should be followed by a call to | 128 /// Each call to [addOutstandingCallback] should be followed by a call to |
133 /// [removeOutstandingCallback] once the callbak is no longer running. Note | 129 /// [removeOutstandingCallback] once the callbak is no longer running. Note |
134 /// that only successful tests wait for outstanding callbacks; as soon as a | 130 /// that only successful tests wait for outstanding callbacks; as soon as a |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 } | 194 } |
199 | 195 |
200 /// Notifies the invoker that progress is being made. | 196 /// Notifies the invoker that progress is being made. |
201 /// | 197 /// |
202 /// Each heartbeat resets the timeout timer. This helps ensure that | 198 /// Each heartbeat resets the timeout timer. This helps ensure that |
203 /// long-running tests that still make progress don't time out. | 199 /// long-running tests that still make progress don't time out. |
204 void heartbeat() { | 200 void heartbeat() { |
205 if (liveTest.isComplete) return; | 201 if (liveTest.isComplete) return; |
206 if (_timeoutTimer != null) _timeoutTimer.cancel(); | 202 if (_timeoutTimer != null) _timeoutTimer.cancel(); |
207 | 203 |
208 var timeout = metadata.timeout.apply(new Duration(seconds: 30)); | 204 var timeout = liveTest.test.metadata.timeout |
| 205 .apply(new Duration(seconds: 30)); |
209 if (timeout == null) return; | 206 if (timeout == null) return; |
210 _timeoutTimer = _invokerZone.createTimer(timeout, | 207 _timeoutTimer = _invokerZone.createTimer(timeout, |
211 Zone.current.bindCallback(() { | 208 Zone.current.bindCallback(() { |
212 if (liveTest.isComplete) return; | 209 if (liveTest.isComplete) return; |
213 _handleError( | 210 _handleError( |
214 new TimeoutException( | 211 new TimeoutException( |
215 "Test timed out after ${niceDuration(timeout)}.", timeout)); | 212 "Test timed out after ${niceDuration(timeout)}.", timeout)); |
216 })); | 213 })); |
217 } | 214 } |
218 | 215 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 // outstanding callback counters at once. | 277 // outstanding callback counters at once. |
281 _counterKey: outstandingCallbacksForBody, | 278 _counterKey: outstandingCallbacksForBody, |
282 _closableKey: true | 279 _closableKey: true |
283 }, | 280 }, |
284 zoneSpecification: new ZoneSpecification( | 281 zoneSpecification: new ZoneSpecification( |
285 print: (self, parent, zone, line) => _controller.print(line)), | 282 print: (self, parent, zone, line) => _controller.print(line)), |
286 onError: _handleError); | 283 onError: _handleError); |
287 }); | 284 }); |
288 } | 285 } |
289 } | 286 } |
OLD | NEW |