Index: lib/src/backend/invoker.dart |
diff --git a/lib/src/backend/invoker.dart b/lib/src/backend/invoker.dart |
index 221c52a06a3667638c1ec85ea2efda388906d061..46c61eb9123e9db4a9a5c8ef86f03a4156cac60e 100644 |
--- a/lib/src/backend/invoker.dart |
+++ b/lib/src/backend/invoker.dart |
@@ -93,6 +93,11 @@ class Invoker { |
return Zone.current[#test.invoker]; |
} |
+ /// The timer for tracking timeouts. |
+ /// |
+ /// This will be `null` until the test starts running. |
+ Timer _timeoutTimer; |
+ |
Invoker._(Suite suite, LocalTest test) |
: metadata = suite.metadata.merge(test.metadata) { |
_controller = new LiveTestController(suite, test, _onRun, () { |
@@ -117,8 +122,10 @@ class Invoker { |
/// Tells the invoker that a callback declared with [addOutstandingCallback] |
/// is no longer running. |
- void removeOutstandingCallback() => |
- _outstandingCallbacks.removeOutstandingCallback(); |
+ void removeOutstandingCallback() { |
+ heartbeat(); |
+ _outstandingCallbacks.removeOutstandingCallback(); |
+ } |
/// Runs [fn] and returns once all (registered) outstanding callbacks it |
/// transitively invokes have completed. |
@@ -129,6 +136,8 @@ class Invoker { |
/// Note that outstanding callbacks registered within [fn] will *not* be |
/// registered as outstanding callback outside of [fn]. |
Future waitForOutstandingCallbacks(fn()) { |
+ heartbeat(); |
+ |
var counter = new OutstandingCallbackCounter(); |
runZoned(() { |
// TODO(nweiz): Use async/await here once issue 23497 has been fixed in |
@@ -143,6 +152,23 @@ class Invoker { |
return counter.noOutstandingCallbacks; |
} |
+ /// Notifies the invoker that progress is being made. |
+ /// |
+ /// Each heartbeat resets the timeout timer. This helps ensure that |
+ /// long-running tests that still make progress don't time out. |
+ void heartbeat() { |
+ if (_liveTest.isComplete) return; |
+ if (_timeoutTimer != null) _timeoutTimer.cancel(); |
+ |
+ var timeout = metadata.timeout.apply(new Duration(seconds: 30)); |
kevmoo
2015/05/29 01:26:46
This implies that 30s is the max time allowed betw
nweiz
2015/05/29 20:25:39
This is already pluggable via the @Timeout annotat
|
+ _timeoutTimer = new Timer(timeout, () { |
+ if (liveTest.isComplete) return; |
+ handleError( |
+ new TimeoutException( |
+ "Test timed out after ${niceDuration(timeout)}.", timeout)); |
+ }); |
+ } |
+ |
/// Notifies the invoker of an asynchronous error. |
/// |
/// Note that calling this explicitly is rarely necessary, since any |
@@ -182,16 +208,6 @@ class Invoker { |
// stable versions. |
Chain.capture(() { |
runZonedWithValues(() { |
- // TODO(nweiz): Reset this timer whenever the user's code interacts |
- // with the library. |
- var timeout = metadata.timeout.apply(new Duration(seconds: 30)); |
- var timer = new Timer(timeout, () { |
- if (liveTest.isComplete) return; |
- handleError( |
- new TimeoutException( |
- "Test timed out after ${niceDuration(timeout)}.", timeout)); |
- }); |
- |
// Run the test asynchronously so that the "running" state change has |
// a chance to hit its event handler(s) before the test produces an |
// error. If an error is emitted before the first state change is |
@@ -209,7 +225,7 @@ class Invoker { |
return waitForOutstandingCallbacks(() => |
runZoned(_test._tearDown, onError: handleError)); |
}).then((_) { |
- timer.cancel(); |
+ _timeoutTimer.cancel(); |
_controller.setState( |
new State(Status.complete, liveTest.state.result)); |