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

Side by Side Diff: tests/lib/async/stream_state_helper.dart

Issue 16125005: Make new StreamController be async by default. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review comments Created 7 years, 6 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 stream_state_helper; 5 library stream_state_helper;
6 6
7 import "../../../pkg/unittest/lib/unittest.dart"; 7 import "../../../pkg/unittest/lib/unittest.dart";
8 import "dart:async"; 8 import "dart:async";
9 import "dart:collection"; 9 import "dart:collection";
10 10
11 class SubscriptionProtocolTest {
12 final StreamProtocolTest _streamTest;
13 final int id;
14 StreamSubscription _subscription;
15
16 SubscriptionProtocolTest(this.id, this._subscription, this._streamTest);
17
18 void pause([Future resumeSignal]) {
19 if (_subscription == null) throw new StateError("Not subscribed");
20 _subscription.pause(resumeSignal);
21 }
22
23 void resume() {
24 if (_subscription == null) throw new StateError("Not subscribed");
25 _subscription.resume();
26 }
27
28 void cancel() {
29 if (_subscription == null) throw new StateError("Not subscribed");
30 _subscription.cancel();
31 _subscription = null;
32 }
33
34 void expectData(var data, [void action()]) {
35 _streamTest._expectData(this, data, action);
36 }
37
38 void expectError(var error, [void action()]) {
39 _streamTest._expectError(this, error, action);
40 }
41
42 void expectDone([void action()]) {
43 _streamTest._expectDone(this, action);
44 }
45 }
46
11 class StreamProtocolTest { 47 class StreamProtocolTest {
12 bool trace = false; 48 bool trace = false;
49 // If not a broadcast stream, the onComplete is called automatically by
50 // the first onCancel.
51 bool isBroadcast;
13 StreamController _controller; 52 StreamController _controller;
14 Stream _controllerStream; 53 Stream _controllerStream;
15 StreamSubscription _subscription; 54 // Most recent subscription created. Used as default for pause/resume.
55 SubscriptionProtocolTest _latestSubscription;
16 List<Event> _expectations = new List<Event>(); 56 List<Event> _expectations = new List<Event>();
17 int _nextExpectationIndex = 0; 57 int _nextExpectationIndex = 0;
58 int _subscriptionIdCounter = 0;
18 Function _onComplete; 59 Function _onComplete;
19 60
20 StreamProtocolTest([bool broadcast = false]) { 61 StreamProtocolTest.broadcast({ bool sync: false })
62 : isBroadcast = true {
63 _controller = new StreamController.broadcast(
64 sync: sync,
65 onListen: _onListen,
66 onCancel: _onCancel);
67 _controllerStream = _controller.stream;
68 _onComplete = expectAsync0((){
69 _onComplete = null; // Being null marks the test as being complete.
70 });
71 }
72
73 StreamProtocolTest({ bool broadcast: false, bool sync: false })
74 : isBroadcast = false {
21 _controller = new StreamController( 75 _controller = new StreamController(
22 onListen: _onSubcription, 76 sync: sync,
23 onPause: _onPause, 77 onListen: _onListen,
24 onResume: _onResume, 78 onPause: _onPause,
25 onCancel: _onCancel); 79 onResume: _onResume,
80 onCancel: _onCancel);
26 if (broadcast) { 81 if (broadcast) {
27 _controllerStream = _controller.stream.asBroadcastStream(); 82 _controllerStream = _controller.stream.asBroadcastStream();
28 } else { 83 } else {
29 _controllerStream = _controller.stream; 84 _controllerStream = _controller.stream;
30 } 85 }
31 _onComplete = expectAsync0((){ 86 _onComplete = expectAsync0((){
32 _onComplete = null; // Being null marks the test to be complete. 87 _onComplete = null; // Being null marks the test as being complete.
33 }); 88 });
34 } 89 }
35 90
36 // Actions on the stream and controller. 91 // Actions on the stream and controller.
37 void add(var data) { _controller.add(data); } 92 void add(var data) { _controller.add(data); }
38 void error(var error) { _controller.addError(error); } 93 void error(var error) { _controller.addError(error); }
39 void close() { _controller.close(); } 94 void close() { _controller.close(); }
40 95
41 void subscribe({bool cancelOnError : false}) { 96 SubscriptionProtocolTest listen({bool cancelOnError : false}) {
42 // TODO(lrn): Handle more subscriptions (e.g., a subscription-id 97 int subscriptionId = _subscriptionIdCounter++;
43 // per subscription, and an id on event _expectations). 98
44 if (_subscription != null) throw new StateError("Already subscribed"); 99 StreamSubscription subscription = _controllerStream.listen(
45 _subscription = _controllerStream.listen(_onData, 100 (var data) { _onData(subscriptionId, data); },
46 onError: _onError, 101 onError: (Object error) { _onError(subscriptionId, error); },
47 onDone: _onDone, 102 onDone: () { _onDone(subscriptionId); },
48 cancelOnError: 103 cancelOnError: cancelOnError);
49 cancelOnError); 104 _latestSubscription =
105 new SubscriptionProtocolTest(subscriptionId, subscription, this);
106 if (trace) {
107 print("[Listen #$subscriptionId(#${_latestSubscription.hashCode})]");
108 }
109 return _latestSubscription;
50 } 110 }
51 111
112 // Actions on the most recently created subscription.
52 void pause([Future resumeSignal]) { 113 void pause([Future resumeSignal]) {
53 if (_subscription == null) throw new StateError("Not subscribed"); 114 _latestSubscription.pause(resumeSignal);
54 _subscription.pause(resumeSignal);
55 } 115 }
56 116
57 void resume() { 117 void resume() {
58 if (_subscription == null) throw new StateError("Not subscribed"); 118 _latestSubscription.resume();
59 _subscription.resume();
60 } 119 }
61 120
62 void cancel() { 121 void cancel() {
63 if (_subscription == null) throw new StateError("Not subscribed"); 122 _latestSubscription.cancel();
64 _subscription.cancel(); 123 _latestSubscription = null;
65 _subscription = null; 124 }
125
126 // End the test now. There must be no open expectations, and no furter
127 // expectations will be allowed.
128 // Called automatically by an onCancel event on a non-broadcast stream.
129 void terminate() {
130 if (_nextExpectationIndex != _expectations.length) {
131 _withNextExpectation((Event expect) {
132 _fail("Expected: $expect\n"
133 "Found : Early termination.\n${expect._stackTrace}");
134 });
135 }
136 _onComplete();
66 } 137 }
67 138
68 // Handling of stream events. 139 // Handling of stream events.
69 void _onData(var data) { 140 void _onData(int id, var data) {
70 if (trace) print("[Data : $data]"); 141 if (trace) print("[Data#$id : $data]");
71 _withNextExpectation((Event expect) { 142 _withNextExpectation((Event expect) {
72 if (!expect.matchData(data)) { 143 if (!expect.matchData(id, data)) {
73 _fail("Expected: $expect\n" 144 _fail("Expected: $expect\n"
74 "Found : [Data: $data]"); 145 "Found : [Data#$id: $data]\n${expect._stackTrace}");
75 } 146 }
76 }); 147 });
77 } 148 }
78 149
79 void _onError(error) { 150 void _onError(int id, Object error) {
80 if (trace) print("[Error : $error]"); 151 if (trace) print("[Error#$id : $error]");
81 _withNextExpectation((Event expect) { 152 _withNextExpectation((Event expect) {
82 if (!expect.matchError(error)) { 153 if (!expect.matchError(id, error)) {
83 _fail("Expected: $expect\n" 154 _fail("Expected: $expect\n"
84 "Found : [Error: ${error}]"); 155 "Found : [Error#$id: ${error}]\n${expect._stackTrace}");
85 } 156 }
86 }); 157 });
87 } 158 }
88 159
89 void _onDone() { 160 void _onDone(int id) {
90 if (trace) print("[Done]"); 161 if (trace) print("[Done#$id]");
91 _subscription = null;
92 _withNextExpectation((Event expect) { 162 _withNextExpectation((Event expect) {
93 if (!expect.matchDone()) { 163 if (!expect.matchDone(id)) {
94 _fail("Expected: $expect\n" 164 _fail("Expected: $expect\n"
95 "Found : [Done]"); 165 "Found : [Done#$id]\n${expect._stackTrace}");
96 } 166 }
97 }); 167 });
98 } 168 }
99 169
100 void _onPause() { 170 void _onPause() {
101 if (trace) print("[Pause]"); 171 if (trace) print("[Pause]");
102 _withNextExpectation((Event expect) { 172 _withNextExpectation((Event expect) {
103 if (!expect.matchPause()) { 173 if (!expect.matchPause()) {
104 _fail("Expected: $expect\n" 174 _fail("Expected: $expect\n"
105 "Found : [Paused]"); 175 "Found : [Paused]\n${expect._stackTrace}");
106 } 176 }
107 }); 177 });
108 } 178 }
109 179
110 void _onResume() { 180 void _onResume() {
111 if (trace) print("[Resumed]"); 181 if (trace) print("[Resumed]");
112 _withNextExpectation((Event expect) { 182 _withNextExpectation((Event expect) {
113 if (!expect.matchResume()) { 183 if (!expect.matchResume()) {
114 _fail("Expected: $expect\n" 184 _fail("Expected: $expect\n"
115 "Found : [Resumed]"); 185 "Found : [Resumed]\n${expect._stackTrace}");
116 } 186 }
117 }); 187 });
118 } 188 }
119 189
120 void _onSubcription() { 190 void _onListen() {
121 if (trace) print("[Subscribed]"); 191 if (trace) print("[Subscribed]");
122 _withNextExpectation((Event expect) { 192 _withNextExpectation((Event expect) {
123 if (!expect.matchSubscribe()) { 193 if (!expect.matchSubscribe()) {
124 _fail("Expected: $expect\n" 194 _fail("Expected: $expect\n"
125 "Found: [Subscribed]"); 195 "Found: [Subscribed]\n${expect._stackTrace}");
126 } 196 }
127 }); 197 });
128 } 198 }
129 199
130 void _onCancel() { 200 void _onCancel() {
131 if (trace) print("[Cancelled]"); 201 if (trace) print("[Cancelled]");
132 _withNextExpectation((Event expect) { 202 _withNextExpectation((Event expect) {
133 if (!expect.matchCancel()) { 203 if (!expect.matchCancel()) {
134 _fail("Expected: $expect\n" 204 _fail("Expected: $expect\n"
135 "Found: [Cancelled]"); 205 "Found: [Cancelled]\n${expect._stackTrace}");
136 } 206 }
137 }); 207 });
208 if (!isBroadcast) terminate();
138 } 209 }
139 210
140 void _withNextExpectation(void action(Event expect)) { 211 void _withNextExpectation(void action(Event expect)) {
141 if (_nextExpectationIndex == _expectations.length) { 212 if (_nextExpectationIndex == _expectations.length) {
213 _nextExpectationIndex++;
142 action(new MismatchEvent()); 214 action(new MismatchEvent());
143 } else { 215 } else {
144 Event next = _expectations[_nextExpectationIndex]; 216 Event next = _expectations[_nextExpectationIndex++];
145 action(next); 217 action(next);
146 } 218 }
147 _nextExpectationIndex++;
148 _checkDone();
149 } 219 }
150 220
151 void _checkDone() {
152 if (_nextExpectationIndex == _expectations.length) {
153 _onComplete();
154 }
155 }
156
157
158 // Adds _expectations. 221 // Adds _expectations.
159 void expectAny([void action()]) { 222 void expectAny([void action()]) {
160 if (_onComplete == null) { 223 if (_onComplete == null) {
161 _fail("Adding expectation after completing"); 224 _fail("Adding expectation after completing");
162 } 225 }
163 _expectations.add(new LogAnyEvent(action)); 226 _expectations.add(new LogAnyEvent(action));
164 } 227 }
228
165 void expectData(var data, [void action()]) { 229 void expectData(var data, [void action()]) {
230 _expectData(null, data, action);
231 }
232
233 void _expectData(SubscriptionProtocolTest sub, var data, void action()) {
166 if (_onComplete == null) { 234 if (_onComplete == null) {
167 _fail("Adding expectation after completing"); 235 _fail("Adding expectation after completing");
168 } 236 }
169 _expectations.add(new DataEvent(data, action)); 237 _expectations.add(new DataEvent(sub, data, action));
170 } 238 }
239
171 void expectError(var error, [void action()]) { 240 void expectError(var error, [void action()]) {
241 _expectError(null, error, action);
242 }
243
244 void _expectError(SubscriptionProtocolTest sub, var error, void action()) {
172 if (_onComplete == null) { 245 if (_onComplete == null) {
173 _fail("Adding expectation after completing"); 246 _fail("Adding expectation after completing");
174 } 247 }
175 _expectations.add(new ErrorEvent(error, action)); 248 _expectations.add(new ErrorEvent(sub, error, action));
176 } 249 }
250
177 void expectDone([void action()]) { 251 void expectDone([void action()]) {
252 _expectDone(null, action);
253 }
254
255 void _expectDone(SubscriptionProtocolTest sub, [void action()]) {
178 if (_onComplete == null) { 256 if (_onComplete == null) {
179 _fail("Adding expectation after completing"); 257 _fail("Adding expectation after completing");
180 } 258 }
181 _expectations.add(new DoneEvent(action)); 259 _expectations.add(new DoneEvent(sub, action));
182 } 260 }
261
183 void expectPause([void action()]) { 262 void expectPause([void action()]) {
184 if (_onComplete == null) { 263 if (_onComplete == null) {
185 _fail("Adding expectation after completing"); 264 _fail("Adding expectation after completing");
186 } 265 }
187 _expectations.add(new PauseCallbackEvent(action)); 266 _expectations.add(new PauseCallbackEvent(action));
188 } 267 }
268
189 void expectResume([void action()]) { 269 void expectResume([void action()]) {
190 if (_onComplete == null) { 270 if (_onComplete == null) {
191 _fail("Adding expectation after completing"); 271 _fail("Adding expectation after completing");
192 } 272 }
193 _expectations.add(new ResumeCallbackEvent(action)); 273 _expectations.add(new ResumeCallbackEvent(action));
194 } 274 }
195 void expectSubscription([void action()]) { 275
276 void expectListen([void action()]) {
196 if (_onComplete == null) { 277 if (_onComplete == null) {
197 _fail("Adding expectation after completing"); 278 _fail("Adding expectation after completing");
198 } 279 }
199 _expectations.add( 280 _expectations.add(
200 new SubscriptionCallbackEvent(action)); 281 new SubscriptionCallbackEvent(action));
201 } 282 }
283
202 void expectCancel([void action()]) { 284 void expectCancel([void action()]) {
203 if (_onComplete == null) { 285 if (_onComplete == null) {
204 _fail("Adding expectation after completing"); 286 _fail("Adding expectation after completing");
205 } 287 }
206 _expectations.add( 288 _expectations.add(
207 new CancelCallbackEvent(action)); 289 new CancelCallbackEvent(action));
208 } 290 }
209 291
210 void _fail(String message) { 292 void _fail(String message) {
211 if (_nextExpectationIndex == 0) { 293 if (_nextExpectationIndex == 0) {
212 throw "Unexpected event:\n$message\nNo earlier events matched."; 294 throw "Unexpected event:\n$message\nNo earlier events matched.";
213 } 295 }
214 throw "Unexpected event:\n$message\nMatched so far:\n" 296 StringBuffer buf = new StringBuffer();
215 " ${_expectations.take(_nextExpectationIndex).join("\n ")}"; 297 for (int i = 0; i < _expectations.length; i++) {
298 if (i == _nextExpectationIndex - 1) {
299 buf.write("->");
300 } else {
301 buf.write(" ");
302 }
303 buf.write(_expectations[i]);
304 buf.write("\n");
305 }
306 throw "Unexpected event:\n$message\nAll expectations:\n$buf";
216 } 307 }
217 } 308 }
218 309
219 class Event { 310 class Event {
220 Function _action; 311 Function _action;
221 Event(void this._action()); 312 StackTrace _stackTrace;
313 Event(void action())
314 : _action = (action == null) ? null : expectAsync0(action) {
315 try { throw 0; } catch (_, s) { _stackTrace = s; }
316 }
222 317
223 bool matchData(var data) { 318 bool matchData(int id, var data) {
224 if (!_testData(data)) return false; 319 return false;
225 if (_action != null) _action();
226 return true;
227 } 320 }
228 bool matchError(e) { 321
229 if (!_testError(e)) return false; 322 bool matchError(int id, e) {
230 if (_action != null) _action(); 323 return false;
231 return true;
232 } 324 }
233 bool matchDone() { 325
234 if (!_testDone()) return false; 326 bool matchDone(int id) {
235 if (_action != null) _action(); 327 return false;
236 return true;
237 } 328 }
329
238 bool matchPause() { 330 bool matchPause() {
239 if (!_testPause()) return false; 331 if (!_testPause()) return false;
240 if (_action != null) _action(); 332 if (_action != null) _action();
241 return true; 333 return true;
242 } 334 }
335
243 bool matchResume() { 336 bool matchResume() {
244 if (!_testResume()) return false; 337 if (!_testResume()) return false;
245 if (_action != null) _action(); 338 if (_action != null) _action();
246 return true; 339 return true;
247 } 340 }
341
248 bool matchSubscribe() { 342 bool matchSubscribe() {
249 if (!_testSubscribe()) return false; 343 if (!_testSubscribe()) return false;
250 if (_action != null) _action(); 344 if (_action != null) _action();
251 return true; 345 return true;
252 } 346 }
347
253 bool matchCancel() { 348 bool matchCancel() {
254 if (!_testCancel()) return false; 349 if (!_testCancel()) return false;
255 if (_action != null) _action(); 350 if (_action != null) _action();
256 return true; 351 return true;
257 } 352 }
258 353
259 bool _testData(_) => false; 354 bool _testData(_) => false;
260 bool _testError(_) => false; 355 bool _testError(_) => false;
261 bool _testDone() => false; 356 bool _testDone() => false;
262 bool _testPause() => false; 357 bool _testPause() => false;
263 bool _testResume() => false; 358 bool _testResume() => false;
264 bool _testSubscribe() => false; 359 bool _testSubscribe() => false;
265 bool _testCancel() => false; 360 bool _testCancel() => false;
266 } 361 }
267 362
363 class SubscriptionEvent extends Event {
364 SubscriptionProtocolTest subscription;
365 SubscriptionEvent(this.subscription, void action()) : super(action);
366
367 bool matchData(int id, var data) {
368 if (subscription != null && subscription.id != id) return false;
369 if (!_testData(data)) return false;
370 if (_action != null) _action();
371 return true;
372 }
373
374 bool matchError(int id, e) {
375 if (subscription != null && subscription.id != id) return false;
376 if (!_testError(e)) return false;
377 if (_action != null) _action();
378 return true;
379 }
380
381 bool matchDone(int id) {
382 if (subscription != null && subscription.id != id) return false;
383 if (!_testDone()) return false;
384 if (_action != null) _action();
385 return true;
386 }
387
388 String get _id => (subscription == null) ? "" : "#${subscription.id}";
389 }
390
268 class MismatchEvent extends Event { 391 class MismatchEvent extends Event {
269 MismatchEvent() : super(null); 392 MismatchEvent() : super(null);
270 toString() => "[No event expected]"; 393 toString() => "[No event expected]";
271 } 394 }
272 395
273 class DataEvent extends Event { 396 class DataEvent extends SubscriptionEvent {
274 final data; 397 final data;
275 DataEvent(this.data, void action()) : super(action); 398 DataEvent(SubscriptionProtocolTest sub, this.data, void action())
399 : super(sub, action);
276 bool _testData(var data) => this.data == data; 400 bool _testData(var data) => this.data == data;
277 String toString() => "[Data: $data]"; 401 String toString() => "[Data$_id: $data]";
278 } 402 }
279 403
280 class ErrorEvent extends Event { 404 class ErrorEvent extends SubscriptionEvent {
281 final error; 405 final error;
282 ErrorEvent(this.error, void action()) : super(action); 406 ErrorEvent(SubscriptionProtocolTest sub, this.error, void action())
407 : super(sub, action);
283 bool _testError(error) => this.error == error; 408 bool _testError(error) => this.error == error;
284 String toString() => "[Error: $error]"; 409 String toString() => "[Error$_id: $error]";
285 } 410 }
286 411
287 class DoneEvent extends Event { 412 class DoneEvent extends SubscriptionEvent {
288 DoneEvent(void action()) : super(action); 413 DoneEvent(SubscriptionProtocolTest sub, void action()) : super(sub, action);
289 bool _testDone() => true; 414 bool _testDone() => true;
290 String toString() => "[Done]"; 415 String toString() => "[Done$_id]";
291 } 416 }
292 417
293 class PauseCallbackEvent extends Event { 418 class PauseCallbackEvent extends Event {
294 PauseCallbackEvent(void action()) : super(action); 419 PauseCallbackEvent(void action()) : super(action);
295 bool _testPause() => true; 420 bool _testPause() => true;
296 String toString() => "[Paused]"; 421 String toString() => "[Paused]";
297 } 422 }
298 423
299 class ResumeCallbackEvent extends Event { 424 class ResumeCallbackEvent extends Event {
300 ResumeCallbackEvent(void action()) : super(action); 425 ResumeCallbackEvent(void action()) : super(action);
301 bool _testResume() => true; 426 bool _testResume() => true;
302 String toString() => "[Resumed]"; 427 String toString() => "[Resumed]";
303 } 428 }
304 429
305 class SubscriptionCallbackEvent extends Event { 430 class SubscriptionCallbackEvent extends Event {
306 SubscriptionCallbackEvent(void action()) : super(action); 431 SubscriptionCallbackEvent(void action()) : super(action);
307 bool _testSubscribe() => true; 432 bool _testSubscribe() => true;
308 String toString() => "[Subscribed]"; 433 String toString() => "[Subscribed]";
309 } 434 }
310 435
311 class CancelCallbackEvent extends Event { 436 class CancelCallbackEvent extends Event {
312 CancelCallbackEvent(void action()) : super(action); 437 CancelCallbackEvent(void action()) : super(action);
313 bool _testCancel() => true; 438 bool _testCancel() => true;
314 String toString() => "[Cancelled]"; 439 String toString() => "[Cancelled]";
315 } 440 }
316 441
317 442 /** Event matcher that matches any other event. */
318 class LogAnyEvent extends Event { 443 class LogAnyEvent extends Event {
319 String _actual = "*Not matched yet*"; 444 String _actual = "*Not matched yet*";
445
320 LogAnyEvent(void action()) : super(action); 446 LogAnyEvent(void action()) : super(action);
447
321 bool _testData(var data) { 448 bool _testData(var data) {
322 _actual = "*[Data $data]"; 449 _actual = "*[Data $data]";
323 return true; 450 return true;
324 } 451 }
452
325 bool _testError(error) { 453 bool _testError(error) {
326 _actual = "*[Error ${error}]"; 454 _actual = "*[Error ${error}]";
327 return true; 455 return true;
328 } 456 }
457
329 bool _testDone() { 458 bool _testDone() {
330 _actual = "*[Done]"; 459 _actual = "*[Done]";
331 return true; 460 return true;
332 } 461 }
462
333 bool _testPause() { 463 bool _testPause() {
334 _actual = "*[Paused]"; 464 _actual = "*[Paused]";
335 return true; 465 return true;
336 } 466 }
467
337 bool _testResume() { 468 bool _testResume() {
338 _actual = "*[Resumed]"; 469 _actual = "*[Resumed]";
339 return true; 470 return true;
340 } 471 }
472
341 bool _testSubcribe() { 473 bool _testSubcribe() {
342 _actual = "*[Subscribed]"; 474 _actual = "*[Subscribed]";
343 return true; 475 return true;
344 } 476 }
477
345 bool _testCancel() { 478 bool _testCancel() {
346 _actual = "*[Cancelled]"; 479 _actual = "*[Cancelled]";
347 return true; 480 return true;
348 } 481 }
349 482
483 /** Returns a representation of the event it was tested against. */
350 String toString() => _actual; 484 String toString() => _actual;
351 } 485 }
OLDNEW
« no previous file with comments | « tests/lib/async/stream_single_to_multi_subscriber_test.dart ('k') | tests/lib/async/stream_state_nonzero_timer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698