OLD | NEW |
(Empty) | |
| 1 part of unittest; |
| 2 |
| 3 /** Simulates spread arguments using named arguments. */ |
| 4 // TODO(sigmund): remove this class and simply use a closure with named |
| 5 // arguments (if still applicable). |
| 6 class _SpreadArgsHelper { |
| 7 final Function callback; |
| 8 final int minExpectedCalls; |
| 9 final int maxExpectedCalls; |
| 10 final Function isDone; |
| 11 final String id; |
| 12 int actualCalls = 0; |
| 13 final TestCase testCase; |
| 14 bool complete; |
| 15 static const sentinel = const _Sentinel(); |
| 16 |
| 17 _SpreadArgsHelper(Function callback, int minExpected, int maxExpected, |
| 18 Function isDone, String id) |
| 19 : this.callback = callback, |
| 20 minExpectedCalls = minExpected, |
| 21 maxExpectedCalls = (maxExpected == 0 && minExpected > 0) |
| 22 ? minExpected |
| 23 : maxExpected, |
| 24 this.isDone = isDone, |
| 25 this.testCase = currentTestCase, |
| 26 this.id = _makeCallbackId(id, callback) { |
| 27 ensureInitialized(); |
| 28 if (testCase == null) { |
| 29 throw new StateError("No valid test. Did you forget to run your test " |
| 30 "inside a call to test()?"); |
| 31 } |
| 32 |
| 33 if (isDone != null || minExpected > 0) { |
| 34 testCase._callbackFunctionsOutstanding++; |
| 35 complete = false; |
| 36 } else { |
| 37 complete = true; |
| 38 } |
| 39 } |
| 40 |
| 41 static String _makeCallbackId(String id, Function callback) { |
| 42 // Try to create a reasonable id. |
| 43 if (id != null) { |
| 44 return "$id "; |
| 45 } else { |
| 46 // If the callback is not an anonymous closure, try to get the |
| 47 // name. |
| 48 var fname = callback.toString(); |
| 49 var prefix = "Function '"; |
| 50 var pos = fname.indexOf(prefix); |
| 51 if (pos > 0) { |
| 52 pos += prefix.length; |
| 53 var epos = fname.indexOf("'", pos); |
| 54 if (epos > 0) { |
| 55 return "${fname.substring(pos, epos)} "; |
| 56 } |
| 57 } |
| 58 } |
| 59 return ''; |
| 60 } |
| 61 |
| 62 bool shouldCallBack() { |
| 63 ++actualCalls; |
| 64 if (testCase.isComplete) { |
| 65 // Don't run if the test is done. We don't throw here as this is not |
| 66 // the current test, but we do mark the old test as having an error |
| 67 // if it previously passed. |
| 68 if (testCase.result == PASS) { |
| 69 testCase._error( |
| 70 'Callback ${id}called ($actualCalls) after test case ' |
| 71 '${testCase.description} has already been marked as ' |
| 72 '${testCase.result}.'); |
| 73 } |
| 74 return false; |
| 75 } else if (maxExpectedCalls >= 0 && actualCalls > maxExpectedCalls) { |
| 76 throw new TestFailure('Callback ${id}called more times than expected ' |
| 77 '($maxExpectedCalls).'); |
| 78 } |
| 79 return true; |
| 80 } |
| 81 |
| 82 void after() { |
| 83 if (!complete) { |
| 84 if (minExpectedCalls > 0 && actualCalls < minExpectedCalls) return; |
| 85 if (isDone != null && !isDone()) return; |
| 86 |
| 87 // Mark this callback as complete and remove it from the testcase |
| 88 // oustanding callback count; if that hits zero the testcase is done. |
| 89 complete = true; |
| 90 testCase._markCallbackComplete(); |
| 91 } |
| 92 } |
| 93 |
| 94 invoke0() { |
| 95 return _guardAsync( |
| 96 () { |
| 97 if (shouldCallBack()) { |
| 98 return callback(); |
| 99 } |
| 100 }, |
| 101 after, testCase); |
| 102 } |
| 103 |
| 104 invoke1(arg1) { |
| 105 return _guardAsync( |
| 106 () { |
| 107 if (shouldCallBack()) { |
| 108 return callback(arg1); |
| 109 } |
| 110 }, |
| 111 after, testCase); |
| 112 } |
| 113 |
| 114 invoke2(arg1, arg2) { |
| 115 return _guardAsync( |
| 116 () { |
| 117 if (shouldCallBack()) { |
| 118 return callback(arg1, arg2); |
| 119 } |
| 120 }, |
| 121 after, testCase); |
| 122 } |
| 123 } |
OLD | NEW |