Chromium Code Reviews| Index: lib/src/frontend/expect_async.dart |
| diff --git a/lib/src/frontend/expect_async.dart b/lib/src/frontend/expect_async.dart |
| index aa4b8b6114efa3d6b8fe71dc61b3eebcdcf6b1a3..b330308c4ede54a32497c021616abea3d6279bfa 100644 |
| --- a/lib/src/frontend/expect_async.dart |
| +++ b/lib/src/frontend/expect_async.dart |
| @@ -11,13 +11,13 @@ import 'expect.dart'; |
| const _PLACEHOLDER = const Object(); |
| // Functions used to check how many arguments a callback takes. |
| -typedef _Func0(); |
| -typedef _Func1(a); |
| -typedef _Func2(a, b); |
| -typedef _Func3(a, b, c); |
| -typedef _Func4(a, b, c, d); |
| -typedef _Func5(a, b, c, d, e); |
| -typedef _Func6(a, b, c, d, e, f); |
| +typedef T Func0<T>(); |
| +typedef T Func1<T, A>(A a); |
| +typedef T Func2<T, A, B>(A a, B b); |
| +typedef T Func3<T, A, B, C>(A a, B b, C c); |
| +typedef T Func4<T, A, B, C, D>(A a, B b, C c, D d); |
| +typedef T Func5<T, A, B, C, D, E>(A a, B b, C c, D d, E e); |
| +typedef T Func6<T, A, B, C, D, E, F>(A a, B b, C c, D d, E e, F f); |
| typedef bool _IsDoneCallback(); |
| @@ -29,7 +29,7 @@ typedef bool _IsDoneCallback(); |
| /// |
| /// The wrapper function is accessible via [func]. It supports up to six |
| /// optional and/or required positional arguments, but no named arguments. |
| -class _ExpectedFunction { |
| +class _ExpectedFunction<T> { |
| /// The wrapped callback. |
| final Function _callback; |
| @@ -83,9 +83,8 @@ class _ExpectedFunction { |
| {String id, String reason, bool isDone()}) |
| : this._callback = callback, |
| _minExpectedCalls = minExpected, |
| - _maxExpectedCalls = (maxExpected == 0 && minExpected > 0) |
| - ? minExpected |
| - : maxExpected, |
| + _maxExpectedCalls = |
| + (maxExpected == 0 && minExpected > 0) ? minExpected : maxExpected, |
|
nweiz
2016/11/21 22:08:02
Nit: Please don't include unrelated whitespace dif
floitsch
2016/11/22 14:14:27
I tried, but writing multiline function signatures
|
| this._isDone = isDone, |
| this._reason = reason == null ? '' : '\n$reason', |
| this._zone = Zone.current, |
| @@ -128,13 +127,13 @@ class _ExpectedFunction { |
| /// Returns a function that has the same number of positional arguments as the |
| /// wrapped function (up to a total of 6). |
| Function get func { |
| - if (_callback is _Func6) return _max6; |
| - if (_callback is _Func5) return _max5; |
| - if (_callback is _Func4) return _max4; |
| - if (_callback is _Func3) return _max3; |
| - if (_callback is _Func2) return _max2; |
| - if (_callback is _Func1) return _max1; |
| - if (_callback is _Func0) return _max0; |
| + if (_callback is Func6) return _max6; |
| + if (_callback is Func5) return _max5; |
| + if (_callback is Func4) return _max4; |
| + if (_callback is Func3) return _max3; |
| + if (_callback is Func2) return _max2; |
| + if (_callback is Func1) return _max1; |
| + if (_callback is Func0) return _max0; |
| _invoker.removeOutstandingCallback(); |
| throw new ArgumentError( |
| @@ -143,27 +142,41 @@ class _ExpectedFunction { |
| // This indirection is critical. It ensures the returned function has an |
| // argument count of zero. |
| - _max0() => _max6(); |
| + T _max0() => _max6(); |
|
nweiz
2016/11/21 22:08:02
Since these are being accessed outside the class n
floitsch
2016/11/22 14:14:27
Done.
|
| - _max1([a0 = _PLACEHOLDER]) => _max6(a0); |
| + T _max1([a0 = _PLACEHOLDER]) => _max6(a0); |
| - _max2([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER]) => _max6(a0, a1); |
| + T _max2([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER]) => _max6(a0, a1); |
| - _max3([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER]) => |
| + T _max3([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER]) => |
| _max6(a0, a1, a2); |
| - _max4([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, |
| - a3 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3); |
| - |
| - _max5([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, |
| - a3 = _PLACEHOLDER, a4 = _PLACEHOLDER]) => _max6(a0, a1, a2, a3, a4); |
| - |
| - _max6([a0 = _PLACEHOLDER, a1 = _PLACEHOLDER, a2 = _PLACEHOLDER, |
| - a3 = _PLACEHOLDER, a4 = _PLACEHOLDER, a5 = _PLACEHOLDER]) => |
| + T _max4( |
| + [a0 = _PLACEHOLDER, |
| + a1 = _PLACEHOLDER, |
| + a2 = _PLACEHOLDER, |
| + a3 = _PLACEHOLDER]) => |
| + _max6(a0, a1, a2, a3); |
| + |
| + T _max5( |
| + [a0 = _PLACEHOLDER, |
| + a1 = _PLACEHOLDER, |
| + a2 = _PLACEHOLDER, |
| + a3 = _PLACEHOLDER, |
| + a4 = _PLACEHOLDER]) => |
| + _max6(a0, a1, a2, a3, a4); |
| + |
| + T _max6( |
| + [a0 = _PLACEHOLDER, |
| + a1 = _PLACEHOLDER, |
| + a2 = _PLACEHOLDER, |
| + a3 = _PLACEHOLDER, |
| + a4 = _PLACEHOLDER, |
| + a5 = _PLACEHOLDER]) => |
| _run([a0, a1, a2, a3, a4, a5].where((a) => a != _PLACEHOLDER)); |
| /// Runs the wrapped function with [args] and returns its return value. |
| - _run(Iterable args) { |
| + T _run(Iterable args) { |
| // Note that in the old test, this returned `null` if it encountered an |
| // error, where now it just re-throws that error because Zone machinery will |
| // pass it to the invoker anyway. |
| @@ -171,13 +184,13 @@ class _ExpectedFunction { |
| _actualCalls++; |
| if (_invoker.liveTest.state.shouldBeDone) { |
| throw 'Callback ${_id}called ($_actualCalls) after test case ' |
| - '${_invoker.liveTest.test.name} had already completed.$_reason'; |
| + '${_invoker.liveTest.test.name} had already completed.$_reason'; |
| } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) { |
| throw new TestFailure('Callback ${_id}called more times than expected ' |
| - '($_maxExpectedCalls).$_reason'); |
| + '($_maxExpectedCalls).$_reason'); |
| } |
| - return Function.apply(_callback, args.toList()); |
| + return Function.apply(_callback, args.toList()) as T; |
| } catch (error, stackTrace) { |
| _zone.handleUncaughtError(error, stackTrace); |
| return null; |
| @@ -202,6 +215,10 @@ class _ExpectedFunction { |
| /// Indicate that [callback] is expected to be called [count] number of times |
| /// (by default 1). |
|
nweiz
2016/11/21 22:08:02
Remove the old documentation.
floitsch
2016/11/22 14:14:27
Done.
|
| /// |
| +/// This function is deprecated. Use [expectAsync0], [expectAsync1], |
|
nweiz
2016/11/21 22:08:02
"is deprecated because it doesn't work well with s
floitsch
2016/11/22 14:14:27
Done.
|
| +/// [expectAsync2], [expectAsync3], [expectAsync4], [expectAsync5], or |
| +/// [expectAsync6] instead. |
| +/// |
| /// The test framework will wait for the callback to run the [count] times |
| /// before it considers the current test to be complete. [callback] may take up |
| /// to six optional or required positional arguments; named arguments are not |
| @@ -215,8 +232,9 @@ class _ExpectedFunction { |
| /// Both [id] and [reason] are optional and provide extra information about the |
| /// callback when debugging. [id] should be the name of the callback, while |
| /// [reason] should be the reason the callback is expected to be called. |
| +@deprecated |
|
nweiz
2016/11/21 22:08:02
Use @Deprecated and mention that it will be remove
floitsch
2016/11/22 14:14:27
Done.
|
| Function expectAsync(Function callback, |
| - {int count: 1, int max: 0, String id, String reason}) { |
| + {int count: 1, int max: 0, String id, String reason}) { |
| if (Invoker.current == null) { |
| throw new StateError("expectAsync() may only be called within a test."); |
| } |
| @@ -225,9 +243,145 @@ Function expectAsync(Function callback, |
| .func; |
| } |
| +/// Indicate that [callback] is expected to be called [count] number of times |
| +/// (by default 1). |
| +/// |
| +/// The test framework will wait for the callback to run the [count] times |
| +/// before it considers the current test to be complete. |
| +/// |
| +/// [max] can be used to specify an upper bound on the number of calls; if this |
| +/// is exceeded the test will fail. If [max] is `0` (the default), the callback |
| +/// is expected to be called exactly [count] times. If [max] is `-1`, the |
| +/// callback is allowed to be called any number of times greater than [count]. |
| +/// |
| +/// Both [id] and [reason] are optional and provide extra information about the |
| +/// callback when debugging. [id] should be the name of the callback, while |
| +/// [reason] should be the reason the callback is expected to be called. |
|
nweiz
2016/11/21 22:08:03
Add a paragraph describing the difference between
floitsch
2016/11/22 14:14:27
Done.
|
| +Func0<dynamic/*=T*/ > expectAsync0/*<T>*/(dynamic/*=T*/ callback(), |
|
nweiz
2016/11/21 22:08:02
Nit: "<dynamic/*=T*/>"
floitsch
2016/11/22 14:14:27
I don't understand.
If it's the spacing: I used th
|
| + {int count: 1, int max: 0, String id, String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
|
nweiz
2016/11/21 22:08:02
"expectAsync0()"
floitsch
2016/11/22 14:14:27
Done.
|
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max0; |
| +} |
| + |
| +/// See [expectAsync0]. |
|
nweiz
2016/11/21 22:08:02
I'd prefer to copy the docs from [expectAsync0] ra
floitsch
2016/11/22 14:14:27
Done.
|
| +Func1<dynamic/*=T*/, dynamic/*=A*/ > expectAsync1/*<T, A>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max1; |
| +} |
| + |
| +/// See [expectAsync0]. |
| +Func2<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/ > expectAsync2/*<T, A, B>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max2; |
| +} |
| + |
| +/// See [expectAsync0]. |
| +Func3<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/ > |
| + expectAsync3/*<T, A, B, C>*/( |
| + dynamic/*=T*/ callback( |
| + dynamic/*=A*/ a, dynamic/*=B*/ b, dynamic/*=C*/ c), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max3; |
| +} |
| + |
| +/// See [expectAsync0]. |
| +Func4<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/ > |
| + expectAsync4/*<T, A, B, C, D>*/( |
| + dynamic/*=T*/ callback( |
| + dynamic/*=A*/ a, dynamic/*=B*/ b, dynamic/*=C*/ c, dynamic/*=D*/ d), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max4; |
| +} |
| + |
| +/// See [expectAsync0]. |
| +Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/, dynamic/*=E*/ > |
| + expectAsync5/*<T, A, B, C, D, E>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b, |
| + dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max5; |
| +} |
| + |
| +/// See [expectAsync0]. |
| +Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/, dynamic/*=E*/, dynamic/*=F*/ > |
| + expectAsync6/*<T, A, B, C, D, E, F>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b, |
| + dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e, dynamic/*=F*/ f), |
| + {int count: 1, |
| + int max: 0, |
| + String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError("expectAsync() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, count, max, |
| + id: id, reason: reason) |
| + ._max6; |
| +} |
| + |
| /// Indicate that [callback] is expected to be called until [isDone] returns |
| /// true. |
| /// |
| +/// Deprecated. Use [expectAsyncUntil0], [expectAsyncUntil1], |
| +/// [expectAsyncUntil2], [expectAsyncUntil3], [expectAsyncUntil4], |
| +/// [expectAsyncUntil5], or [expectAsyncUntil6] instead. |
| +/// |
| /// [isDone] is called after each time the function is run. Only when it returns |
| /// true will the callback be considered complete. [callback] may take up to six |
| /// optional or required positional arguments; named arguments are not |
| @@ -236,6 +390,7 @@ Function expectAsync(Function callback, |
| /// Both [id] and [reason] are optional and provide extra information about the |
| /// callback when debugging. [id] should be the name of the callback, while |
| /// [reason] should be the reason the callback is expected to be called. |
| +@deprecated |
| Function expectAsyncUntil(Function callback, bool isDone(), |
| {String id, String reason}) { |
| if (Invoker.current == null) { |
| @@ -244,5 +399,132 @@ Function expectAsyncUntil(Function callback, bool isDone(), |
| } |
| return new _ExpectedFunction(callback, 0, -1, |
| - id: id, reason: reason, isDone: isDone).func; |
| + id: id, reason: reason, isDone: isDone) |
| + .func; |
| +} |
| + |
| +/// Indicate that [callback] is expected to be called until [isDone] returns |
| +/// true. |
| +/// |
| +/// [isDone] is called after each time the function is run. Only when it returns |
| +/// true will the callback be considered complete. |
| +/// |
| +/// Both [id] and [reason] are optional and provide extra information about the |
| +/// callback when debugging. [id] should be the name of the callback, while |
| +/// [reason] should be the reason the callback is expected to be called. |
| +Func0<dynamic/*=T*/ > expectAsyncUntil0/*<T>*/( |
| + dynamic/*=T*/ callback(), bool isDone(), |
| + {String id, String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max0; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func1<dynamic/*=T*/, dynamic/*=A*/ > expectAsyncUntil1/*<T, A>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a), bool isDone(), |
| + {String id, String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max1; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func2<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/ > |
| + expectAsyncUntil2/*<T, A, B>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b), bool isDone(), |
| + {String id, String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max2; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func3<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/ > |
| + expectAsyncUntil3/*<T, A, B, C>*/( |
| + dynamic/*=T*/ callback( |
| + dynamic/*=A*/ a, dynamic/*=B*/ b, dynamic/*=C*/ c), |
| + bool isDone(), |
| + {String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max3; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func4<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/ > |
| + expectAsyncUntil4/*<T, A, B, C, D>*/( |
| + dynamic/*=T*/ callback( |
| + dynamic/*=A*/ a, dynamic/*=B*/ b, dynamic/*=C*/ c, dynamic/*=D*/ d), |
| + bool isDone(), |
| + {String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max4; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func5<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/, dynamic/*=E*/ > |
| + expectAsyncUntil5/*<T, A, B, C, D, E>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b, |
| + dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e), |
| + bool isDone(), |
| + {String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max5; |
| +} |
| + |
| +/// See [expectAsyncUntil0]. |
| +Func6<dynamic/*=T*/, dynamic/*=A*/, dynamic/*=B*/, dynamic/*=C*/, |
| + dynamic/*=D*/, dynamic/*=E*/, dynamic/*=F*/ > |
| + expectAsyncUntil6/*<T, A, B, C, D, E, F>*/( |
| + dynamic/*=T*/ callback(dynamic/*=A*/ a, dynamic/*=B*/ b, |
| + dynamic/*=C*/ c, dynamic/*=D*/ d, dynamic/*=E*/ e, dynamic/*=F*/ f), |
| + bool isDone(), |
| + {String id, |
| + String reason}) { |
| + if (Invoker.current == null) { |
| + throw new StateError( |
| + "expectAsyncUntil() may only be called within a test."); |
| + } |
| + |
| + return new _ExpectedFunction/*<T>*/(callback, 0, -1, |
| + id: id, reason: reason, isDone: isDone) |
| + ._max6; |
| } |