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

Unified Diff: pkg/scheduled_test/lib/src/mock_clock.dart

Issue 12251012: Add built-in timeouts to scheduled_test. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review changes 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 | « pkg/scheduled_test/lib/scheduled_test.dart ('k') | pkg/scheduled_test/lib/src/schedule.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/scheduled_test/lib/src/mock_clock.dart
diff --git a/pkg/scheduled_test/lib/src/mock_clock.dart b/pkg/scheduled_test/lib/src/mock_clock.dart
new file mode 100644
index 0000000000000000000000000000000000000000..efcc7eb2481a2dbca6d260857f6743b07ccefe6b
--- /dev/null
+++ b/pkg/scheduled_test/lib/src/mock_clock.dart
@@ -0,0 +1,105 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// A library that wraps [Timer] in a way that can be mocked out in test code.
+/// Application code only needs to use [newTimer] to get an instance of [Timer].
+/// Then test code can call [mock] to mock out all new [Timer] instances so that
+/// they're controllable by a returned [Clock] object.
+library mock_clock;
+
+import 'dart:async';
+
+import 'utils.dart';
+
+/// The mock clock object. New [Timer]s will be mocked if and only if this is
+/// non-`null`.
+Clock _clock;
+
+/// Whether or not mocking is active.
+bool get _mocked => _clock != null;
+
+/// Causes all future calls to [newTimer] to return mock [Timer] objects that
+/// are controlled by the returned [Clock]. This may only be called once.
+Clock mock() {
+ if (_mocked) {
+ throw new StateError("mock_clock.mock() has already been called.");
+ }
+
+ _clock = new Clock._();
+ return _clock;
+}
+
+typedef void TimerCallback(Timer timer);
+
+/// Returns a new (possibly mocked) [Timer]. Works the same as [new Timer].
+Timer newTimer(Duration duration, TimerCallback callback) =>
+ _mocked ? new _MockTimer(duration, callback) : new Timer(duration, callback);
+
+/// A clock that controls when mocked [Timer]s move forward in time. It starts
+/// at time 0 and advances forward millisecond-by-millisecond, broadcasting each
+/// tick on the [onTick] stream.
+class Clock {
+ /// The current time of the clock, in milliseconds. Starts at 0.
+ int get time => _time;
+ int _time = 0;
+
+ /// The stream of millisecond ticks of the clock.
+ Stream<int> get onTick => _onTickController.stream;
+ final _onTickController = new StreamController<int>.broadcast();
+
+ Clock._();
+
+ /// Advances the clock forward by [milliseconds]. This works like synchronous
+ /// code that takes [milliseconds] to execute; any [Timer]s that are scheduled
+ /// to fire during the interval will do so asynchronously once control returns
+ /// to the event loop.
+ void tick([int milliseconds=1]) {
+ for (var i = 0; i < milliseconds; i++) {
+ var tickTime = ++_time;
+ new Future.immediate(null).then((_) => _onTickController.add(tickTime));
+ }
+ }
+
+ /// Automatically progresses forward in time as long as there are still
+ /// subscribers to [onTick] (that is, [Timer]s waiting to fire). After each
+ /// tick, this pumps the event loop repeatedly so that all non-clock-dependent
+ /// code runs before the next tick.
+ void run() {
+ pumpEventQueue().then((_) {
+ if (!_onTickController.hasSubscribers) return;
+ tick();
+ return run();
+ });
+ }
+}
+
+/// A mock implementation of [Timer] that uses [Clock] to keep time, rather than
+/// the system clock.
+class _MockTimer implements Timer {
+ /// The time at which the timer should fire.
+ final int _time;
+
+ /// The callback to run when the timer fires.
+ final TimerCallback _callback;
+
+ /// The subscription to the [Clock.onTick] stream.
+ StreamSubscription _subscription;
+
+ // TODO(nweiz): Remove this when issue 8512 is fixed.
+ var _cancelled = false;
+
+ _MockTimer(Duration duration, this._callback)
+ : _time = _clock.time + duration.inMilliseconds {
+ _subscription = _clock.onTick.listen((time) {
+ if (_cancelled || time < _time) return;
+ _subscription.cancel();
+ _callback(this);
+ });
+ }
+
+ void cancel() {
+ _cancelled = true;
+ _subscription.cancel();
+ }
+}
« no previous file with comments | « pkg/scheduled_test/lib/scheduled_test.dart ('k') | pkg/scheduled_test/lib/src/schedule.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698