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

Side by Side Diff: lib/src/expect_async.dart

Issue 934413002: Replace the existing unittest APIs with the new runner infrastructure. (Closed) Base URL: git@github.com:dart-lang/unittest@master
Patch Set: Code review changes Created 5 years, 10 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/configuration.dart ('k') | lib/src/expected_function.dart » ('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 unittest.expected_function; 5 library unittest.expect_async;
6 6
7 import '../unittest.dart'; 7 import 'expect.dart';
8 8 import 'invoker.dart';
9 import 'internal_test_case.dart'; 9 import 'state.dart';
10 10
11 /// An object used to detect unpassed arguments. 11 /// An object used to detect unpassed arguments.
12 const _PLACEHOLDER = const Object(); 12 const _PLACEHOLDER = const Object();
13 13
14 // Functions used to check how many arguments a callback takes. 14 // Functions used to check how many arguments a callback takes.
15 typedef _Func0(); 15 typedef _Func0();
16 typedef _Func1(a); 16 typedef _Func1(a);
17 typedef _Func2(a, b); 17 typedef _Func2(a, b);
18 typedef _Func3(a, b, c); 18 typedef _Func3(a, b, c);
19 typedef _Func4(a, b, c, d); 19 typedef _Func4(a, b, c, d);
20 typedef _Func5(a, b, c, d, e); 20 typedef _Func5(a, b, c, d, e);
21 typedef _Func6(a, b, c, d, e, f); 21 typedef _Func6(a, b, c, d, e, f);
22 22
23 typedef bool _IsDoneCallback(); 23 typedef bool _IsDoneCallback();
24 24
25 /// A wrapper for a function that ensures that it's called the appropriate 25 /// A wrapper for a function that ensures that it's called the appropriate
26 /// number of times. 26 /// number of times.
27 /// 27 ///
28 /// The containing test won't be considered to have completed successfully until 28 /// The containing test won't be considered to have completed successfully until
29 /// this function has been called the appropriate number of times. 29 /// this function has been called the appropriate number of times.
30 /// 30 ///
31 /// The wrapper function is accessible via [func]. It supports up to six 31 /// The wrapper function is accessible via [func]. It supports up to six
32 /// optional and/or required positional arguments, but no named arguments. 32 /// optional and/or required positional arguments, but no named arguments.
33 class ExpectedFunction { 33 class _ExpectedFunction {
34 /// The wrapped callback. 34 /// The wrapped callback.
35 final Function _callback; 35 final Function _callback;
36 36
37 /// The minimum number of calls that are expected to be made to the function. 37 /// The minimum number of calls that are expected to be made to the function.
38 /// 38 ///
39 /// If fewer calls than this are made, the test will fail. 39 /// If fewer calls than this are made, the test will fail.
40 final int _minExpectedCalls; 40 final int _minExpectedCalls;
41 41
42 /// The maximum number of calls that are expected to be made to the function. 42 /// The maximum number of calls that are expected to be made to the function.
43 /// 43 ///
(...skipping 14 matching lines...) Expand all
58 final String _id; 58 final String _id;
59 59
60 /// An optional description of why the function is expected to be called. 60 /// An optional description of why the function is expected to be called.
61 /// 61 ///
62 /// If not passed, this will be an empty string. 62 /// If not passed, this will be an empty string.
63 final String _reason; 63 final String _reason;
64 64
65 /// The number of times the function has been called. 65 /// The number of times the function has been called.
66 int _actualCalls = 0; 66 int _actualCalls = 0;
67 67
68 /// The test case in which this function was wrapped. 68 /// The test invoker in which this function was wrapped.
69 final InternalTestCase _testCase; 69 final Invoker _invoker;
70 70
71 /// Whether this function has been called the requisite number of times. 71 /// Whether this function has been called the requisite number of times.
72 bool _complete; 72 bool _complete;
73 73
74 /// Wraps [callback] in a function that asserts that it's called at least 74 /// Wraps [callback] in a function that asserts that it's called at least
75 /// [minExpected] times and no more than [maxExpected] times. 75 /// [minExpected] times and no more than [maxExpected] times.
76 /// 76 ///
77 /// If passed, [id] is used as a descriptive name fo the function and [reason] 77 /// If passed, [id] is used as a descriptive name fo the function and [reason]
78 /// as a reason it's expected to be called. If [isDone] is passed, the test 78 /// as a reason it's expected to be called. If [isDone] is passed, the test
79 /// won't be allowed to complete until it returns `true`. 79 /// won't be allowed to complete until it returns `true`.
80 ExpectedFunction(Function callback, int minExpected, int maxExpected, 80 _ExpectedFunction(Function callback, int minExpected, int maxExpected,
81 {String id, String reason, bool isDone()}) 81 {String id, String reason, bool isDone()})
82 : this._callback = callback, 82 : this._callback = callback,
83 _minExpectedCalls = minExpected, 83 _minExpectedCalls = minExpected,
84 _maxExpectedCalls = (maxExpected == 0 && minExpected > 0) 84 _maxExpectedCalls = (maxExpected == 0 && minExpected > 0)
85 ? minExpected 85 ? minExpected
86 : maxExpected, 86 : maxExpected,
87 this._isDone = isDone, 87 this._isDone = isDone,
88 this._reason = reason == null ? '' : '\n$reason', 88 this._reason = reason == null ? '' : '\n$reason',
89 this._testCase = currentTestCase as InternalTestCase, 89 this._invoker = Invoker.current,
90 this._id = _makeCallbackId(id, callback) { 90 this._id = _makeCallbackId(id, callback) {
91 ensureInitialized(); 91 if (_invoker == null) {
92 if (_testCase == null) { 92 throw new StateError("[expectAsync] was called outside of a test.");
93 throw new StateError("No valid test. Did you forget to run your test " 93 } else if (maxExpected > 0 && minExpected > maxExpected) {
94 "inside a call to test()?"); 94 throw new ArgumentError("max ($maxExpected) may not be less than count "
95 "($minExpected).");
95 } 96 }
96 97
97 if (isDone != null || minExpected > 0) { 98 if (isDone != null || minExpected > 0) {
98 _testCase.callbackFunctionsOutstanding++; 99 _invoker.addOutstandingCallback();
99 _complete = false; 100 _complete = false;
100 } else { 101 } else {
101 _complete = true; 102 _complete = true;
102 } 103 }
103 } 104 }
104 105
105 /// Tries to find a reasonable name for [callback]. 106 /// Tries to find a reasonable name for [callback].
106 /// 107 ///
107 /// If [id] is passed, uses that. Otherwise, tries to determine a name from 108 /// If [id] is passed, uses that. Otherwise, tries to determine a name from
108 /// calling `toString`. If no name can be found, returns the empty string. 109 /// calling `toString`. If no name can be found, returns the empty string.
(...skipping 17 matching lines...) Expand all
126 /// wrapped function (up to a total of 6). 127 /// wrapped function (up to a total of 6).
127 Function get func { 128 Function get func {
128 if (_callback is _Func6) return _max6; 129 if (_callback is _Func6) return _max6;
129 if (_callback is _Func5) return _max5; 130 if (_callback is _Func5) return _max5;
130 if (_callback is _Func4) return _max4; 131 if (_callback is _Func4) return _max4;
131 if (_callback is _Func3) return _max3; 132 if (_callback is _Func3) return _max3;
132 if (_callback is _Func2) return _max2; 133 if (_callback is _Func2) return _max2;
133 if (_callback is _Func1) return _max1; 134 if (_callback is _Func1) return _max1;
134 if (_callback is _Func0) return _max0; 135 if (_callback is _Func0) return _max0;
135 136
137 _invoker.removeOutstandingCallback();
136 throw new ArgumentError( 138 throw new ArgumentError(
137 'The wrapped function has more than 6 required arguments'); 139 'The wrapped function has more than 6 required arguments');
138 } 140 }
139 141
140 // This indirection is critical. It ensures the returned function has an 142 // This indirection is critical. It ensures the returned function has an
141 // argument count of zero. 143 // argument count of zero.
142 _max0() => _max6(); 144 _max0() => _max6();
143 145
144 _max1([a0 = _PLACEHOLDER]) => _max6(a0); 146 _max1([a0 = _PLACEHOLDER]) => _max6(a0);
145 147
146 _max2([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER]) => _max6(a0, a1); 148 _max2([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER]) => _max6(a0, a1);
147 149
148 _max3([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER]) => 150 _max3([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER]) =>
149 _max6(a0, a1, a2); 151 _max6(a0, a1, a2);
150 152
151 _max4([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, 153 _max4([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
152 a3 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3); 154 a3 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3);
153 155
154 _max5([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, 156 _max5([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
155 a3 = _PLACEHOLDER, a4 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3, a4); 157 a3 = _PLACEHOLDER, a4 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3, a4);
156 158
157 _max6([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, 159 _max6([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER,
158 a3 = _PLACEHOLDER, a4 = _PLACEHOLDER, a5 = _PLACEHOLDER]) => 160 a3 = _PLACEHOLDER, a4 = _PLACEHOLDER, a5 = _PLACEHOLDER]) =>
159 _run([a0, a1, a2, a3, a4, a5].where((a) => a != _PLACEHOLDER)); 161 _run([a0, a1, a2, a3, a4, a5].where((a) => a != _PLACEHOLDER));
160 162
161 /// Runs the wrapped function with [args] and returns its return value. 163 /// Runs the wrapped function with [args] and returns its return value.
162 ///
163 /// This will pass any errors on to [_testCase] and return `null`.
164 _run(Iterable args) { 164 _run(Iterable args) {
165 // Note that in the old unittest, this returned `null` if it encountered an
166 // error, where now it just re-throws that error because Zone machinery will
167 // pass it to the invoker anyway.
165 try { 168 try {
166 _actualCalls++; 169 _actualCalls++;
167 if (_testCase.isComplete) { 170 if (_invoker.liveTest.isComplete &&
168 // Don't run the callback if the test is done. We don't throw here as 171 _invoker.liveTest.state.result == Result.success) {
169 // this is not the current test, but we do mark the old test as having 172 throw 'Callback ${_id}called ($_actualCalls) after test case '
170 // an error if it previously passed. 173 '${_invoker.liveTest.test.name} had already completed.$_reason';
171 if (_testCase.result == PASS) {
172 _testCase.error(
173 'Callback ${_id}called ($_actualCalls) after test case '
174 '${_testCase.description} had already been marked as '
175 '${_testCase.result}.$_reason');
176 }
177 return null;
178 } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) { 174 } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) {
179 throw new TestFailure('Callback ${_id}called more times than expected ' 175 throw new TestFailure('Callback ${_id}called more times than expected '
180 '($_maxExpectedCalls).$_reason'); 176 '($_maxExpectedCalls).$_reason');
181 } 177 }
182 178
183 return Function.apply(_callback, args.toList()); 179 return Function.apply(_callback, args.toList());
184 } catch (error, stackTrace) { 180 } catch (error, stackTrace) {
185 _testCase.registerException(error, stackTrace); 181 _invoker.handleError(error, stackTrace);
186 return null; 182 return null;
187 } finally { 183 } finally {
188 _afterRun(); 184 _afterRun();
189 } 185 }
190 } 186 }
191 187
192 /// After each time the function is run, check to see if it's complete. 188 /// After each time the function is run, check to see if it's complete.
193 void _afterRun() { 189 void _afterRun() {
194 if (_complete) return; 190 if (_complete) return;
195 if (_minExpectedCalls > 0 && _actualCalls < _minExpectedCalls) return; 191 if (_minExpectedCalls > 0 && _actualCalls < _minExpectedCalls) return;
196 if (_isDone != null && !_isDone()) return; 192 if (_isDone != null && !_isDone()) return;
197 193
198 // Mark this callback as complete and remove it from the test case's 194 // Mark this callback as complete and remove it from the test case's
199 // oustanding callback count; if that hits zero the test is done. 195 // oustanding callback count; if that hits zero the test is done.
200 _complete = true; 196 _complete = true;
201 _testCase.markCallbackComplete(); 197 _invoker.removeOutstandingCallback();
202 } 198 }
203 } 199 }
200
201 /// Indicate that [callback] is expected to be called [count] number of times
202 /// (by default 1).
203 ///
204 /// The unittest framework will wait for the callback to run the [count] times
205 /// before it considers the current test to be complete. [callback] may take up
206 /// to six optional or required positional arguments; named arguments are not
207 /// supported.
208 ///
209 /// [max] can be used to specify an upper bound on the number of calls; if this
210 /// is exceeded the test will fail. If [max] is `0` (the default), the callback
211 /// is expected to be called exactly [count] times. If [max] is `-1`, the
212 /// callback is allowed to be called any number of times greater than [count].
213 ///
214 /// Both [id] and [reason] are optional and provide extra information about the
215 /// callback when debugging. [id] should be the name of the callback, while
216 /// [reason] should be the reason the callback is expected to be called.
217 Function expectAsync(Function callback,
218 {int count: 1, int max: 0, String id, String reason}) =>
219 new _ExpectedFunction(callback, count, max, id: id, reason: reason).func;
220
221 /// Indicate that [callback] is expected to be called until [isDone] returns
222 /// true.
223 ///
224 /// [isDone] is called after each time the function is run. Only when it returns
225 /// true will the callback be considered complete. [callback] may take up to six
226 /// optional or required positional arguments; named arguments are not
227 /// supported.
228 ///
229 /// Both [id] and [reason] are optional and provide extra information about the
230 /// callback when debugging. [id] should be the name of the callback, while
231 /// [reason] should be the reason the callback is expected to be called.
232 Function expectAsyncUntil(Function callback, bool isDone(),
233 {String id, String reason}) => new _ExpectedFunction(callback, 0, -1,
234 id: id, reason: reason, isDone: isDone).func;
OLDNEW
« no previous file with comments | « lib/src/configuration.dart ('k') | lib/src/expected_function.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698