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

Unified Diff: pkg/unittest/lib/unittest.dart

Issue 12366004: When we have excess callbacks, throw instead of calling error() so that we (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/unittest/test/unittest_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/unittest/lib/unittest.dart
===================================================================
--- pkg/unittest/lib/unittest.dart (revision 19168)
+++ pkg/unittest/lib/unittest.dart (working copy)
@@ -288,17 +288,18 @@
// arguments (if still applicable).
class _SpreadArgsHelper {
Function _callback;
- int _expectedCalls;
+ int _minExpectedCalls;
Siggi Cherem (dart-lang) 2013/02/28 19:29:23 Now that we don't have _init, can we make some of
gram 2013/02/28 22:49:50 Done.
+ int _maxExpectedCalls;
int _actualCalls = 0;
int _testNum;
TestCase _testCase;
- Function _shouldCallBack;
Function _isDone;
String _id;
+ bool _complete;
Siggi Cherem (dart-lang) 2013/02/28 19:29:23 since this class is private and we don't return it
gram 2013/02/28 22:49:50 Done.
static const _sentinel = const _Sentinel();
- _init(Function callback, Function shouldCallBack, Function isDone,
- [expectedCalls = 0]) {
+ _SpreadArgsHelper(Function callback, int minExpected, int maxExpected,
Siggi Cherem (dart-lang) 2013/02/28 19:29:23 more precisely: _SpreadArgsHelper(Function callbac
gram 2013/02/28 22:49:50 Done.
+ Function isDone, String id) {
ensureInitialized();
if (!(_currentTest >= 0 &&
_currentTest < _tests.length &&
@@ -310,73 +311,83 @@
_currentTest < _tests.length &&
_tests[_currentTest] != null);
_callback = callback;
- _shouldCallBack = shouldCallBack;
+ _minExpectedCalls = minExpected;
+ if (maxExpected == 0 && minExpected > 0) {
+ _maxExpectedCalls = minExpected;
+ } else {
+ _maxExpectedCalls = maxExpected;
+ }
_isDone = isDone;
- _expectedCalls = expectedCalls;
_testNum = _currentTest;
_testCase = _tests[_currentTest];
- if (expectedCalls > 0) {
+ if (isDone != null || minExpected > 0) {
_testCase.callbackFunctionsOutstanding++;
+ _complete = false;
+ } else {
+ _complete = true;
}
+
+ // Try to create a reasonable id.
_id = '';
- // If the callback is not an anonymous closure, try to get the
- // name.
- var fname = callback.toString();
- var prefix = "Function '";
- var pos = fname.indexOf(prefix);
- if (pos > 0) {
- pos += prefix.length;
- var epos = fname.indexOf("'", pos);
- if (epos > 0) {
- _id = "${fname.substring(pos, epos)} ";
+ if (id != null) {
+ _id = "$id ";
+ } else {
+ // If the callback is not an anonymous closure, try to get the
+ // name.
+ var fname = callback.toString();
+ var prefix = "Function '";
+ var pos = fname.indexOf(prefix);
+ if (pos > 0) {
+ pos += prefix.length;
+ var epos = fname.indexOf("'", pos);
+ if (epos > 0) {
+ _id = "${fname.substring(pos, epos)} ";
+ }
}
}
}
- _SpreadArgsHelper(callback, shouldCallBack, isDone) {
- _init(callback, shouldCallBack, isDone);
- }
-
- _SpreadArgsHelper.fixedCallCount(callback, expectedCalls, id) {
- _init(callback, _checkCallCount, _allCallsDone, expectedCalls);
- if (id != null) {
- _id = "$id ";
+ _shouldCallBack() {
+ ++_actualCalls;
+ if (_testCase.isComplete) {
+ // Don't run if the test is done. We don't throw here as this is not
+ // the current test, but we do mark the old test as having an error
+ // if it previously passed.
+ if (_testCase.result == PASS) {
+ _testCase.error(
+ 'Callback ${_id}called after test case ${_testCase.description} '
+ 'has already been marked as done.',
+ '');
+ }
+ return false;
+ } else if (_maxExpectedCalls >= 0 && _actualCalls > _maxExpectedCalls) {
+ throw new TestFailure('Callback ${_id}called more times than expected '
+ '($_maxExpectedCalls).');
}
+ return true;
}
- _SpreadArgsHelper.variableCallCount(callback, isDone) {
- _init(callback, _always, isDone, 1);
- }
-
- _SpreadArgsHelper.optionalCalls(callback) {
- _init(callback, _always, () => false, 0);
- }
-
_after() {
- if (_isDone()) {
- _handleCallbackFunctionComplete(_testNum, _id);
+ if (!_complete) {
+ if (_minExpectedCalls > 0 && _actualCalls < _minExpectedCalls) {
+ return;
+ }
+ if (_isDone != null && !_isDone()) {
+ return;
+ }
+ // Mark this callback as complete and remove it from the testcase
+ // oustanding callback count; if that hits zero the testcase is done.
+ _complete = true;
+ if (--_testCase.callbackFunctionsOutstanding == 0 &&
+ !_testCase.isComplete) {
+ _testCase.pass();
+ }
}
}
- _allCallsDone() => _actualCalls == _expectedCalls;
-
- _always() {
- // Always run except if the test is done.
- if (_testCase.isComplete) {
- _testCase.error(
- 'Callback ${_id}called after already being marked '
- 'as done ($_actualCalls).',
- '');
- return false;
- } else {
- return true;
- }
- }
-
invoke([arg0 = _sentinel, arg1 = _sentinel, arg2 = _sentinel,
arg3 = _sentinel, arg4 = _sentinel]) {
return guardAsync(() {
- ++_actualCalls;
if (!_shouldCallBack()) {
return;
} else if (arg0 == _sentinel) {
@@ -402,7 +413,6 @@
invoke0() {
return guardAsync(
() {
- ++_actualCalls;
if (_shouldCallBack()) {
return _callback();
}
@@ -413,7 +423,6 @@
invoke1(arg1) {
return guardAsync(
() {
- ++_actualCalls;
if (_shouldCallBack()) {
return _callback(arg1);
}
@@ -424,23 +433,12 @@
invoke2(arg1, arg2) {
return guardAsync(
() {
- ++_actualCalls;
if (_shouldCallBack()) {
return _callback(arg1, arg2);
}
},
_after, _testNum);
}
-
- /** Returns false if we exceded the number of expected calls. */
- bool _checkCallCount() {
- if (_actualCalls > _expectedCalls) {
- _testCase.error('Callback ${_id}called more times than expected '
- '($_actualCalls > $_expectedCalls).', '');
- return false;
- }
- return true;
- }
}
/**
@@ -453,9 +451,9 @@
* to provide more descriptive error messages if the callback is called more
* often than expected.
*/
-Function _expectAsync(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke;
+Function _expectAsync(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke;
}
/**
@@ -466,26 +464,31 @@
* tracked and reported. [callback] should take 0 positional arguments (named
* arguments are not supported). [id] can be used to provide more
* descriptive error messages if the callback is called more often than
- * expected.
+ * expected. [max] can be used to specify an upper bound on the number of
+ * calls; if this is exceeded the test will fail (or be marked as in error if
+ * it was already complete). A value of 0 for [max] (the default) will set
+ * the upper bound to the same value as [count]; i.e. the callback should be
+ * called exactly [count] times. A value of -1 for [max] will mean no upper
+ * bound.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync0(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke0;
+Function expectAsync0(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke0;
}
/** Like [expectAsync0] but [callback] should take 1 positional argument. */
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync1(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke1;
+Function expectAsync1(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke1;
}
/** Like [expectAsync0] but [callback] should take 2 positional arguments. */
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsync2(Function callback, {int count: 1, String id}) {
- return new _SpreadArgsHelper.
- fixedCallCount(callback, count, id).invoke2;
+Function expectAsync2(Function callback,
+ {int count: 1, int max: 0, String id}) {
+ return new _SpreadArgsHelper(callback, count, max, null, id).invoke2;
}
/**
@@ -494,10 +497,12 @@
* when it returns true will it continue with the following test. Using
* [expectAsyncUntil] will also ensure that errors that occur within
* [callback] are tracked and reported. [callback] should take between 0 and
- * 4 positional arguments (named arguments are not supported).
+ * 4 positional arguments (named arguments are not supported). [id] can be
+ * used to identify the callback in error messages (for example if it is called
+ * after the test case is complete).
*/
-Function _expectAsyncUntil(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke;
+Function _expectAsyncUntil(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke;
Siggi Cherem (dart-lang) 2013/02/28 19:29:23 strange - I was expecting that max was always >= 0
gram 2013/02/28 22:49:50 -1 means unlimited
}
/**
@@ -506,27 +511,29 @@
* when it returns true will it continue with the following test. Using
* [expectAsyncUntil0] will also ensure that errors that occur within
* [callback] are tracked and reported. [callback] should take 0 positional
- * arguments (named arguments are not supported).
+ * arguments (named arguments are not supported). [id] can be used to
+ * identify the callback in error messages (for example if it is called
+ * after the test case is complete).
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil0(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke0;
+Function expectAsyncUntil0(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke0;
}
/**
* Like [expectAsyncUntil0] but [callback] should take 1 positional argument.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil1(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke1;
+Function expectAsyncUntil1(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke1;
}
/**
* Like [expectAsyncUntil0] but [callback] should take 2 positional arguments.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function expectAsyncUntil2(Function callback, Function isDone) {
- return new _SpreadArgsHelper.variableCallCount(callback, isDone).invoke2;
+Function expectAsyncUntil2(Function callback, Function isDone, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, isDone, id).invoke2;
}
/**
@@ -535,10 +542,11 @@
* test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
* might optionally be called but may never be called during the test.
* [callback] should take between 0 and 4 positional arguments (named arguments
- * are not supported).
+ * are not supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
*/
-Function _protectAsync(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke;
+Function _protectAsync(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke;
}
/**
@@ -547,27 +555,28 @@
* test. This is thus similar to expectAsync0. Use it to wrap any callbacks that
* might optionally be called but may never be called during the test.
* [callback] should take 0 positional arguments (named arguments are not
- * supported).
+ * supported). [id] can be used to identify the callback in error
+ * messages (for example if it is called after the test case is complete).
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync0(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke0;
+Function protectAsync0(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke0;
}
/**
* Like [protectAsync0] but [callback] should take 1 positional argument.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync1(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke1;
+Function protectAsync1(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke1;
}
/**
* Like [protectAsync0] but [callback] should take 2 positional arguments.
*/
// TODO(sigmund): deprecate this API when issue 2706 is fixed.
-Function protectAsync2(Function callback) {
- return new _SpreadArgsHelper.optionalCalls(callback).invoke2;
+Function protectAsync2(Function callback, {String id}) {
+ return new _SpreadArgsHelper(callback, 0, -1, null, id).invoke2;
}
/**
@@ -630,38 +639,6 @@
_testTeardown = teardownTest;
}
-/**
- * Called when one of the callback functions is done with all expected
- * calls.
- */
-void _handleCallbackFunctionComplete(testNum, [id = '']) {
- // TODO (gram): we defer this to give the nextBatch recursive
- // stack a chance to unwind. This is a temporary hack but
- // really a bunch of code here needs to be fixed. We have a
- // single array that is being iterated through by nextBatch(),
- // which is recursively invoked in the case of async tests that
- // run synchronously. Bad things can then happen.
- _defer(() {
- if (_currentTest != testNum) {
- if (_tests[testNum].result == PASS) {
- _tests[testNum].error("${id}Unexpected extra callbacks", '');
- }
- } else if (_currentTest < _tests.length) {
- final testCase = _tests[_currentTest];
- --testCase.callbackFunctionsOutstanding;
- if (testCase.callbackFunctionsOutstanding < 0) {
- // TODO(gram): Check: Can this even happen?
- testCase.error(
- 'More calls to _handleCallbackFunctionComplete() than expected.',
- '');
- } else if (testCase.callbackFunctionsOutstanding == 0 &&
- !testCase.isComplete) {
- testCase.pass();
- }
- }
- });
-}
-
/** Advance to the next test case. */
void _nextTestCase() {
_defer(() {
@@ -671,14 +648,6 @@
}
/**
- * Temporary hack: expose old API.
- * TODO(gram) remove this when WebKit tests are working with new framework
- */
-void callbackDone() {
- _handleCallbackFunctionComplete(_currentTest);
-}
-
-/**
* Utility function that can be used to notify the test framework that an
* error was caught outside of this library.
*/
@@ -772,11 +741,11 @@
*/
_registerException(testNum, e, [trace]) {
trace = trace == null ? '' : trace.toString();
+ String message = (e is TestFailure) ? e.message : 'Caught $e';
if (_tests[testNum].result == null) {
- String message = (e is TestFailure) ? e.message : 'Caught $e';
_tests[testNum].fail(message, trace);
} else {
- _tests[testNum].error('Caught $e', trace);
+ _tests[testNum].error(message, trace);
}
}
« no previous file with comments | « no previous file | pkg/unittest/test/unittest_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698