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

Side by Side Diff: pkg/scheduled_test/lib/src/mock_clock.dart

Issue 14753009: Make StreamSubscription be the active part of a stream. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// A library that wraps [Timer] in a way that can be mocked out in test code. 5 /// A library that wraps [Timer] in a way that can be mocked out in test code.
6 /// Application code only needs to use [newTimer] to get an instance of [Timer]. 6 /// Application code only needs to use [newTimer] to get an instance of [Timer].
7 /// Then test code can call [mock] to mock out all new [Timer] instances so that 7 /// Then test code can call [mock] to mock out all new [Timer] instances so that
8 /// they're controllable by a returned [Clock] object. 8 /// they're controllable by a returned [Clock] object.
9 library mock_clock; 9 library mock_clock;
10 10
(...skipping 26 matching lines...) Expand all
37 _mocked ? new _MockTimer(duration, callback) : new Timer(duration, callback); 37 _mocked ? new _MockTimer(duration, callback) : new Timer(duration, callback);
38 38
39 /// A clock that controls when mocked [Timer]s move forward in time. It starts 39 /// A clock that controls when mocked [Timer]s move forward in time. It starts
40 /// at time 0 and advances forward millisecond-by-millisecond, broadcasting each 40 /// at time 0 and advances forward millisecond-by-millisecond, broadcasting each
41 /// tick on the [onTick] stream. 41 /// tick on the [onTick] stream.
42 class Clock { 42 class Clock {
43 /// The current time of the clock, in milliseconds. Starts at 0. 43 /// The current time of the clock, in milliseconds. Starts at 0.
44 int get time => _time; 44 int get time => _time;
45 int _time = 0; 45 int _time = 0;
46 46
47 /// Collection of controllers of all subscribed listeners.
48 Set<StreamController> _subscriptions = new Set<StreamController>();
49
50 Clock._();
51
47 /// The stream of millisecond ticks of the clock. 52 /// The stream of millisecond ticks of the clock.
48 Stream<int> get onTick { 53 Stream<int> get onTick {
49 if (_onTickControllerStream == null) { 54 StreamController<int> controller;
floitsch 2013/05/23 18:38:23 We should really provide a StreamController that d
50 _onTickControllerStream = _onTickController.stream.asBroadcastStream(); 55 controller = new StreamController<int>(
51 } 56 onListen: () {
52 return _onTickControllerStream; 57 _subscriptions.add(controller);
58 },
59 onCancel: () {
60 _subscriptions.remove(controller);
61 });
62 return controller.stream;
53 } 63 }
54 64
55 final _onTickController = new StreamController<int>();
56 Stream<int> _onTickControllerStream;
57
58 Clock._();
59 65
60 /// Advances the clock forward by [milliseconds]. This works like synchronous 66 /// Advances the clock forward by [milliseconds]. This works like synchronous
61 /// code that takes [milliseconds] to execute; any [Timer]s that are scheduled 67 /// code that takes [milliseconds] to execute; any [Timer]s that are scheduled
62 /// to fire during the interval will do so asynchronously once control returns 68 /// to fire during the interval will do so asynchronously once control returns
63 /// to the event loop. 69 /// to the event loop.
64 void tick([int milliseconds=1]) { 70 void tick([int milliseconds = 1]) {
65 for (var i = 0; i < milliseconds; i++) { 71 for (var i = 0; i < milliseconds; i++) {
66 var tickTime = ++_time; 72 var tickTime = ++_time;
67 new Future.value().then((_) => _onTickController.add(tickTime)); 73 runAsync(() {
74 List<StreamController> controllers = _subscriptions.toList();
75 for (StreamController controller in controllers) {
76 if (controller in _subscriptions) {
77 controller.add(tickTime);
78 }
79 }
80 });
68 } 81 }
69 } 82 }
70 83
71 /// Automatically progresses forward in time as long as there are still 84 /// Automatically progresses forward in time as long as there are still
72 /// subscribers to [onTick] (that is, [Timer]s waiting to fire). After each 85 /// subscribers to [onTick] (that is, [Timer]s waiting to fire). After each
73 /// tick, this pumps the event loop repeatedly so that all non-clock-dependent 86 /// tick, this pumps the event loop repeatedly so that all non-clock-dependent
74 /// code runs before the next tick. 87 /// code runs before the next tick.
75 void run() { 88 void run() {
76 pumpEventQueue().then((_) { 89 pumpEventQueue().then((_) {
77 if (!_onTickController.hasListener) return; 90 if (_subscriptions.isEmpty) return;
78 tick(); 91 tick();
79 return run(); 92 return run();
80 }); 93 });
81 } 94 }
82 } 95 }
83 96
84 /// A mock implementation of [Timer] that uses [Clock] to keep time, rather than 97 /// A mock implementation of [Timer] that uses [Clock] to keep time, rather than
85 /// the system clock. 98 /// the system clock.
86 class _MockTimer implements Timer { 99 class _MockTimer implements Timer {
87 /// The time at which the timer should fire. 100 /// The time at which the timer should fire.
88 final int _time; 101 final int _time;
89 102
90 /// The callback to run when the timer fires. 103 /// The callback to run when the timer fires.
91 final TimerCallback _callback; 104 final TimerCallback _callback;
92 105
93 /// The subscription to the [Clock.onTick] stream. 106 /// The subscription to the [Clock.onTick] stream.
94 StreamSubscription _subscription; 107 StreamSubscription _subscription;
95 108
96 _MockTimer(Duration duration, this._callback) 109 _MockTimer(Duration duration, this._callback)
97 : _time = _clock.time + duration.inMilliseconds { 110 : _time = _clock.time + duration.inMilliseconds {
98 _subscription = _clock.onTick.listen((time) { 111 _subscription = _clock.onTick.listen((time) {
99 if (time < _time) return; 112 if (time < _time) return;
100 _subscription.cancel(); 113 _subscription.cancel();
101 _callback(); 114 _callback();
102 }); 115 });
103 } 116 }
104 117
105 void cancel() => _subscription.cancel(); 118 void cancel() => _subscription.cancel();
106 } 119 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698