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

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

Issue 12377093: Add a ScheduledProcess class to pkg/scheduled_test. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 9 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 library utils; 5 library utils;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 /// A pair of values.
10 class Pair<E, F> {
11 E first;
12 F last;
13
14 Pair(this.first, this.last);
15
16 String toString() => '($first, $last)';
17
18 bool operator==(other) {
19 if (other is! Pair) return false;
20 return other.first == first && other.last == last;
21 }
22
23 int get hashCode => first.hashCode ^ last.hashCode;
24 }
25
9 /// Configures [future] so that its result (success or exception) is passed on 26 /// Configures [future] so that its result (success or exception) is passed on
10 /// to [completer]. 27 /// to [completer].
11 void chainToCompleter(Future future, Completer completer) { 28 void chainToCompleter(Future future, Completer completer) {
12 future.then((value) => completer.complete(value), 29 future.then((value) => completer.complete(value),
13 onError: (e) => completer.completeError(e.error, e.stackTrace)); 30 onError: (e) => completer.completeError(e));
14 } 31 }
15 32
16 /// Prepends each line in [text] with [prefix]. 33 /// Prepends each line in [text] with [prefix].
17 String prefixLines(String text, {String prefix: '| '}) => 34 String prefixLines(String text, {String prefix: '| '}) =>
18 text.split('\n').map((line) => '$prefix$line').join('\n'); 35 text.split('\n').map((line) => '$prefix$line').join('\n');
19 36
20 /// Returns a [Future] that completes after pumping the event queue [times] 37 /// Returns a [Future] that completes after pumping the event queue [times]
21 /// times. By default, this should pump the event queue enough times to allow 38 /// times. By default, this should pump the event queue enough times to allow
22 /// any code to run, as long as it's not waiting on some external event. 39 /// any code to run, as long as it's not waiting on some external event.
23 Future pumpEventQueue([int times=20]) { 40 Future pumpEventQueue([int times=20]) {
(...skipping 29 matching lines...) Expand all
53 stream.listen( 70 stream.listen(
54 controller.add, 71 controller.add,
55 onError: (error) => controller.signalError(error), 72 onError: (error) => controller.signalError(error),
56 onDone: controller.close); 73 onDone: controller.close);
57 }).catchError((e) { 74 }).catchError((e) {
58 controller.signalError(e); 75 controller.signalError(e);
59 controller.close(); 76 controller.close();
60 }); 77 });
61 return controller.stream; 78 return controller.stream;
62 } 79 }
80
81 // TODO(nweiz): remove this when issue 7964 is fixed.
82 /// Returns a [Future] that will complete to the first element of [stream].
83 /// Unlike [Stream.first], this is safe to use with single-subscription streams.
84 Future streamFirst(Stream stream) {
85 // TODO(nweiz): remove this when issue 8512 is fixed.
86 var cancelled = false;
87 var completer = new Completer();
88 var subscription;
89 subscription = stream.listen((value) {
90 if (!cancelled) {
91 cancelled = true;
92 subscription.cancel();
93 completer.complete(value);
94 }
95 }, onError: (e) {
96 if (!cancelled) {
97 completer.completeError(e.error, e.stackTrace);
98 }
99 }, onDone: () {
100 if (!cancelled) {
101 completer.completeError(new StateError("No elements"));
102 }
103 }, unsubscribeOnError: true);
104 return completer.future;
105 }
106
107 /// Returns a wrapped version of [stream] along with a [StreamSubscription] that
108 /// can be used to control the wrapped stream.
109 Pair<Stream, StreamSubscription> streamWithSubscription(Stream stream) {
110 var controller = stream.isBroadcast ?
111 new StreamController.broadcast() :
112 new StreamController();
113 var subscription = stream.listen(controller.add,
114 onError: controller.signalError,
115 onDone: controller.close);
116 return new Pair<Stream, StreamSubscription>(controller.stream, subscription);
117 }
118
119 // TODO(nweiz): remove this when issue 7787 is fixed.
120 /// Creates two single-subscription [Stream]s that each emit all values and
121 /// errors from [stream]. This is useful if [stream] is single-subscription but
122 /// multiple subscribers are necessary.
123 Pair<Stream, Stream> tee(Stream stream) {
124 var controller1 = new StreamController();
125 var controller2 = new StreamController();
126 stream.listen((value) {
127 controller1.add(value);
128 controller2.add(value);
129 }, onError: (error) {
130 controller1.signalError(error);
131 controller2.signalError(error);
132 }, onDone: () {
133 controller1.close();
134 controller2.close();
135 });
136 return new Pair<Stream, Stream>(controller1.stream, controller2.stream);
137 }
138
139 /// Takes a simple data structure (composed of [Map]s, [List]s, scalar objects,
140 /// and [Future]s) and recursively resolves all the [Future]s contained within.
141 /// Completes with the fully resolved structure.
142 Future awaitObject(object) {
143 // Unroll nested futures.
144 if (object is Future) return object.then(awaitObject);
145 if (object is Collection) {
Bob Nystrom 2013/03/04 23:52:00 Iterable?
nweiz 2013/03/05 02:16:09 Done.
146 return Future.wait(object.map(awaitObject).toList());
147 }
148 if (object is! Map) return new Future.immediate(object);
149
150 var pairs = <Future<Pair>>[];
151 object.forEach((key, value) {
152 pairs.add(awaitObject(value)
153 .then((resolved) => new Pair(key, resolved)));
154 });
155 return Future.wait(pairs).then((resolvedPairs) {
156 var map = {};
157 for (var pair in resolvedPairs) {
158 map[pair.first] = pair.last;
159 }
160 return map;
161 });
162 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698