OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | |
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. | |
4 | |
5 library async_start_test; | |
6 | |
7 import "package:unittest/unittest.dart"; | |
ahe
2015/08/18 13:55:09
This means that the package unittest cannot use th
| |
8 import "dart:async"; | |
9 | |
10 main() { | |
11 group("basic", () { | |
12 test("empty", () { | |
13 f() async* {} | |
14 return f().toList().then((v) { | |
15 expect(v, equals([])); | |
16 }); | |
17 }); | |
18 | |
19 test("single", () { | |
20 f() async* { yield 42; } | |
21 return f().toList().then((v) { | |
22 expect(v, equals([42])); | |
23 }); | |
24 }); | |
25 | |
26 test("call delays", () { | |
27 var list = []; | |
28 f() async* { list.add(1); yield 2; } | |
29 var res = f().forEach(list.add); | |
30 list.add(0); | |
31 return res.whenComplete(() { | |
32 expect(list, equals([0, 1, 2])); | |
33 }); | |
34 }); | |
35 | |
36 test("throws", () { | |
37 f() async* { yield 1; throw 2; } | |
38 var completer = new Completer(); | |
39 var list = []; | |
40 f().listen(list.add, | |
41 onError: (v) => list.add("$v"), | |
42 onDone: completer.complete); | |
43 return completer.future.whenComplete(() { | |
44 expect(list, equals([1, "2"])); | |
45 }); | |
46 }); | |
47 | |
48 test("multiple", () { | |
49 f() async* { | |
50 for (int i = 0; i < 10; i++) { | |
51 yield i; | |
52 } | |
53 } | |
54 return expectList(f(), new List.generate(10, id)); | |
55 }); | |
56 | |
57 test("allows await", () { | |
58 f() async* { | |
59 var x = await new Future.value(42); | |
60 yield x; | |
61 x = await new Future.value(42); | |
62 } | |
63 return expectList(f(), [42]); | |
64 }); | |
65 | |
66 test("allows await in loop", () { | |
67 f() async* { | |
68 for (int i = 0; i < 10; i++) { | |
69 yield await i; | |
70 } | |
71 } | |
72 return expectList(f(), new List.generate(10, id)); | |
73 }); | |
74 | |
75 test("allows yield*", () { | |
76 f() async* { | |
77 yield* new Stream.fromIterable([1, 2, 3]); | |
78 } | |
79 return expectList(f(), [1, 2, 3]); | |
80 }); | |
81 | |
82 test("allows yield* of async*", () { | |
83 f(n) async* { | |
84 yield n; | |
85 if (n == 0) return; | |
86 yield* f(n - 1); | |
87 yield n; | |
88 } | |
89 return expectList(f(3), [3, 2, 1, 0, 1, 2, 3]); | |
90 }); | |
91 | |
92 test("Cannot yield* non-stream", () { | |
93 f(s) async* { | |
94 yield* s; | |
95 } | |
96 return f(42).transform(getErrors).single.then((v) { | |
97 // Not implementing Stream. | |
98 expect(v is Error, isTrue); | |
99 }); | |
100 }); | |
101 | |
102 test("Cannot yield* non-stream", () { | |
103 f(s) async* { | |
104 yield* s; | |
105 } | |
106 return f(new NotAStream()).transform(getErrors).single.then((v) { | |
107 // Not implementing Stream. | |
108 expect(v is Error, isTrue); | |
109 }); | |
110 }); | |
111 }); | |
112 | |
113 group("yield statement context", () { | |
114 test("plain", () { | |
115 f() async* { | |
116 yield 0; | |
117 } | |
118 return expectList(f(), [0]); | |
119 }); | |
120 | |
121 test("if-then-else", () { | |
122 f(b) async* { | |
123 if (b) yield 0; else yield 1; | |
124 } | |
125 return expectList(f(true), [0]).whenComplete(() { | |
126 expectList(f(false), [1]); | |
127 }); | |
128 }); | |
129 | |
130 test("block", () { | |
131 f() async* { | |
132 yield 0; | |
133 { yield 1; } | |
134 yield 2; | |
135 } | |
136 return expectList(f(), [0, 1, 2]); | |
137 }); | |
138 | |
139 test("labeled", () { | |
140 f() async* { | |
141 label1: yield 0; | |
142 } | |
143 return expectList(f(), [0]); | |
144 }); | |
145 | |
146 // VM issue 2238 | |
147 test("labeled 2", () { /// 01: ok | |
148 f() async* { /// 01: continued | |
149 label1: label2: yield 0; /// 01: continued | |
150 } /// 01: continued | |
151 return expectList(f(), [0]); /// 01: continued | |
152 }); /// 01: continued | |
153 | |
154 test("for-loop", () { | |
155 f() async* { | |
156 for (int i = 0; i < 3; i++) yield i; | |
157 } | |
158 return expectList(f(), [0, 1, 2]); | |
159 }); | |
160 | |
161 test("for-in-loop", () { | |
162 f() async* { | |
163 for (var i in [0, 1, 2]) yield i; | |
164 } | |
165 return expectList(f(), [0, 1, 2]); | |
166 }); | |
167 | |
168 test("await for-in-loop", () { | |
169 f() async* { | |
170 await for (var i in new Stream.fromIterable([0, 1, 2])) yield i; | |
171 } | |
172 return expectList(f(), [0, 1, 2]); | |
173 }); | |
174 | |
175 test("while-loop", () { | |
176 f() async* { | |
177 int i = 0; | |
178 while (i < 3) yield i++; | |
179 } | |
180 return expectList(f(), [0, 1, 2]); | |
181 }); | |
182 | |
183 test("do-while-loop", () { | |
184 f() async* { | |
185 int i = 0; | |
186 do yield i++; while (i < 3); | |
187 } | |
188 return expectList(f(), [0, 1, 2]); | |
189 }); | |
190 | |
191 test("try-catch-finally", () { | |
192 f() async* { | |
193 try { yield 0; } catch (e) { yield 1; } finally { yield 2; } | |
194 } | |
195 return expectList(f(), [0, 2]); | |
196 }); | |
197 | |
198 test("try-catch-finally 2", () { | |
199 f() async* { | |
200 try { yield throw 0; } catch (e) { yield 1; } finally { yield 2; } | |
201 } | |
202 return expectList(f(), [1, 2]); | |
203 }); | |
204 | |
205 test("switch-case", () { | |
206 f(v) async* { | |
207 switch (v) { | |
208 case 0: | |
209 yield 0; | |
210 continue label1; | |
211 label1: | |
212 case 1: | |
213 yield 1; | |
214 break; | |
215 default: | |
216 yield 2; | |
217 } | |
218 } | |
219 return expectList(f(0), [0, 1]).whenComplete(() { | |
220 return expectList(f(1), [1]); | |
221 }).whenComplete(() { | |
222 return expectList(f(2), [2]); | |
223 }); | |
224 }); | |
225 | |
226 test("dead-code return", () { | |
227 f() async* { | |
228 return; | |
229 yield 1; | |
230 } | |
231 return expectList(f(), []); | |
232 }); | |
233 | |
234 test("dead-code throw", () { | |
235 f() async* { | |
236 try { | |
237 throw 0; | |
238 yield 1; | |
239 } catch (_) {} | |
240 } | |
241 return expectList(f(), []); | |
242 }); | |
243 | |
244 test("dead-code break", () { | |
245 f() async* { | |
246 while (true) { | |
247 break; | |
248 yield 1; | |
249 } | |
250 } | |
251 return expectList(f(), []); | |
252 }); | |
253 | |
254 test("dead-code break 2", () { | |
255 f() async* { | |
256 label: { | |
257 break label; | |
258 yield 1; | |
259 } | |
260 } | |
261 return expectList(f(), []); | |
262 }); | |
263 | |
264 test("dead-code continue", () { | |
265 f() async* { | |
266 do { | |
267 continue; | |
268 yield 1; | |
269 } while (false); | |
270 } | |
271 return expectList(f(), []); | |
272 }); | |
273 }); | |
274 | |
275 group("yield expressions", () { | |
276 test("local variable", () { | |
277 f() async* { | |
278 var x = 42; | |
279 yield x; | |
280 } | |
281 return expectList(f(), [42]); | |
282 }); | |
283 | |
284 test("constant variable", () { | |
285 f() async* { | |
286 const x = 42; | |
287 yield x; | |
288 } | |
289 return expectList(f(), [42]); | |
290 }); | |
291 | |
292 test("function call", () { | |
293 g() => 42; | |
294 f() async* { | |
295 yield g(); | |
296 } | |
297 return expectList(f(), [42]); | |
298 }); | |
299 | |
300 test("unary operator", () { | |
301 f() async* { | |
302 var x = -42; | |
303 yield -x; | |
304 } | |
305 return expectList(f(), [42]); | |
306 }); | |
307 | |
308 test("binary operator", () { | |
309 f() async* { | |
310 var x = 21; | |
311 yield x + x; | |
312 } | |
313 return expectList(f(), [42]); | |
314 }); | |
315 | |
316 test("ternary operator", () { | |
317 f() async* { | |
318 var x = 21; | |
319 yield x == 21 ? x + x : x; | |
320 } | |
321 return expectList(f(), [42]); | |
322 }); | |
323 | |
324 test("suffix post-increment", () { | |
325 f() async* { | |
326 var x = 42; | |
327 yield x++; | |
328 } | |
329 return expectList(f(), [42]); | |
330 }); | |
331 | |
332 test("suffix pre-increment", () { | |
333 f() async* { | |
334 var x = 41; | |
335 yield ++x; | |
336 } | |
337 return expectList(f(), [42]); | |
338 }); | |
339 | |
340 test("assignment", () { | |
341 f() async* { | |
342 var x = 37; | |
343 yield x = 42; | |
344 } | |
345 return expectList(f(), [42]); | |
346 }); | |
347 | |
348 test("assignment op", () { | |
349 f() async* { | |
350 var x = 41; | |
351 yield x += 1; | |
352 } | |
353 return expectList(f(), [42]); | |
354 }); | |
355 | |
356 test("await", () { | |
357 f() async* { | |
358 yield await new Future.value(42); | |
359 } | |
360 return expectList(f(), [42]); | |
361 }); | |
362 | |
363 test("index operator", () { | |
364 f() async* { | |
365 var x = [42]; | |
366 yield x[0]; | |
367 } | |
368 return expectList(f(), [42]); | |
369 }); | |
370 | |
371 test("function expression block", () { | |
372 var o = new Object(); | |
373 f() async* { | |
374 yield () { return o; }; | |
375 } | |
376 return f().first.then((v) { | |
377 expect(v(), same(o)); | |
378 }); | |
379 }); | |
380 | |
381 test("function expression arrow", () { | |
382 var o = new Object(); | |
383 f() async* { | |
384 yield () => o; | |
385 } | |
386 return f().first.then((v) { | |
387 expect(v(), same(o)); | |
388 }); | |
389 }); | |
390 | |
391 test("function expression block async", () { | |
392 var o = new Object(); | |
393 f() async* { | |
394 yield () async { return o; }; | |
395 } | |
396 return f().first.then((v) => v()).then((v) { | |
397 expect(v, same(o)); | |
398 }); | |
399 }); | |
400 | |
401 test("function expression arrow async", () { | |
402 var o = new Object(); | |
403 f() async* { | |
404 yield () async => o; | |
405 } | |
406 return f().first.then((v) => v()).then((v) { | |
407 expect(v, same(o)); | |
408 }); | |
409 }); | |
410 | |
411 test("function expression block async*", () { | |
412 var o = new Object(); | |
413 f() async* { | |
414 yield () async* { yield o; }; | |
415 } | |
416 return f().first.then((v) => v().first).then((v) { | |
417 expect(v, same(o)); | |
418 }); | |
419 }); | |
420 }); | |
421 | |
422 group("loops", () { | |
423 test("simple yield", () { | |
424 f() async* { | |
425 for (int i = 0; i < 3; i++) { | |
426 yield i; | |
427 } | |
428 } | |
429 return expectList(f(), [0, 1, 2]); | |
430 }); | |
431 | |
432 test("yield in double loop", () { | |
433 f() async* { | |
434 for (int i = 0; i < 3; i++) { | |
435 for (int j = 0; j < 2; j++) { | |
436 yield i * 2 + j; | |
437 } | |
438 } | |
439 } | |
440 return expectList(f(), [0, 1, 2, 3, 4, 5]); | |
441 }); | |
442 | |
443 test("yield in try body", () { | |
444 var list = []; | |
445 f() async* { | |
446 for (int i = 0; i < 3; i++) { | |
447 try { | |
448 yield i; | |
449 } finally { | |
450 list.add("$i"); | |
451 } | |
452 } | |
453 } | |
454 return expectList(f(), [0, 1, 2]).whenComplete(() { | |
455 expect(list, equals(["0", "1", "2"])); | |
456 }); | |
457 }); | |
458 | |
459 test("yield in catch", () { | |
460 var list = []; | |
461 f() async* { | |
462 for (int i = 0; i < 3; i++) { | |
463 try { | |
464 throw i; | |
465 } catch (e) { | |
466 yield e; | |
467 } finally { | |
468 list.add("$i"); | |
469 } | |
470 } | |
471 } | |
472 return expectList(f(), [0, 1, 2]).whenComplete(() { | |
473 expect(list, equals(["0", "1", "2"])); | |
474 }); | |
475 }); | |
476 | |
477 test("yield in finally", () { | |
478 var list = []; | |
479 f() async* { | |
480 for (int i = 0; i < 3; i++) { | |
481 try { | |
482 throw i; | |
483 } finally { | |
484 yield i; | |
485 list.add("$i"); | |
486 continue; | |
487 } | |
488 } | |
489 } | |
490 return expectList(f(), [0, 1, 2]).whenComplete(() { | |
491 expect(list, equals(["0", "1", "2"])); | |
492 }); | |
493 }); | |
494 | |
495 test("keep yielding after cancel", () { | |
496 f() async* { | |
497 for (int i = 0; i < 10; i++) { | |
498 try { | |
499 yield i; | |
500 } finally { | |
501 continue; | |
502 } | |
503 } | |
504 } | |
505 return expectList(f().take(3), [0, 1, 2]); | |
506 }); | |
507 }); | |
508 | |
509 group("canceling", () { | |
510 // Stream.take(n) automatically cancels after seeing the n'th value. | |
511 | |
512 test("cancels at yield", () { | |
513 Completer exits = new Completer(); | |
514 var list = []; | |
515 f() async* { | |
516 try { | |
517 list.add(0); | |
518 yield list.add(1); | |
519 list.add(2); | |
520 } finally { | |
521 exits.complete(3); | |
522 } | |
523 } | |
524 // No events must be fired synchronously in response to a listen. | |
525 var subscription = f().listen((v) { fail("Received event $v"); }, | |
526 onDone: () { fail("Received done"); }); | |
527 // No events must be delivered after a cancel. | |
528 subscription.cancel(); | |
529 return exits.future.then((v) { | |
530 expect(v, equals(3)); | |
531 expect(list, equals([0, 1])); | |
532 }); | |
533 }); | |
534 | |
535 test("does cancel eventually", () { | |
536 var exits = new Completer(); | |
537 var list = []; | |
538 f() async* { | |
539 int i = 0; | |
540 try { | |
541 while (true) yield i++; | |
542 } finally { | |
543 list.add("a"); | |
544 exits.complete(i); | |
545 } | |
546 } | |
547 return expectList(f().take(5), [0, 1, 2, 3, 4]) | |
548 .then((_) => exits.future) | |
549 .then((v) { | |
550 expect(v, greaterThan(4)); | |
551 expect(list, ["a"]); | |
552 }); | |
553 }); | |
554 | |
555 group("at index", () { | |
556 f() async* { | |
557 try { | |
558 yield await new Future.microtask(() => 1); | |
559 } finally { | |
560 try { | |
561 yield await new Future.microtask(() => 2); | |
562 } finally { | |
563 yield await new Future.microtask(() => 3); | |
564 } | |
565 } | |
566 } | |
567 test("- all, sanity check", () { | |
568 return expectList(f(), [1, 2, 3]); | |
569 }); | |
570 test("after end", () { | |
571 return expectList(f().take(4), [1, 2, 3]); | |
572 }); | |
573 test("at end", () { | |
574 return expectList(f().take(3), [1, 2, 3]); | |
575 }); | |
576 test("before end", () { | |
577 return expectList(f().take(2), [1, 2]); | |
578 }); | |
579 test("early", () { | |
580 return expectList(f().take(1), [1]); | |
581 }); | |
582 test("at start", () { | |
583 return expectList(f().take(0), []); | |
584 }); | |
585 }); | |
586 | |
587 // Crashes dart2js. | |
588 // test("regression-fugl/fisk", () { | |
589 // var res = []; | |
590 // fisk() async* { | |
591 // res.add("+fisk"); | |
592 // try { | |
593 // for (int i = 0; i < 2; i++) { | |
594 // yield await new Future.microtask(() => i); | |
595 // } | |
596 // } finally { | |
597 // res.add("-fisk"); | |
598 // } | |
599 // } | |
600 | |
601 // fugl(int count) async { | |
602 // res.add("fisk $count"); | |
603 // try { | |
604 // await for(int i in fisk().take(count)) res.add(i); | |
605 // } finally { | |
606 // res.add("done"); | |
607 // } | |
608 // } | |
609 | |
610 // return fugl(3).whenComplete(() => fugl(2)) | |
611 // .whenComplete(() => fugl(1)) | |
612 // .whenComplete(() { | |
613 // expect(res, ["fisk 3", "+fisk", 0, 1, "-fisk", "done", | |
614 // "fisk 2", "+fisk", 0, 1, "-fisk", "done", | |
615 // "fisk 1", "+fisk", 0, "done", "-fisk", ]); | |
616 // }); | |
617 // }); | |
618 | |
619 }); | |
620 | |
621 group("pausing", () { | |
622 test("pauses execution at yield for at least a microtask", () { | |
623 var list = []; | |
624 f() async* { | |
625 list.add(1); | |
626 yield 2; | |
627 list.add(3); | |
628 yield 4; | |
629 list.add(5); | |
630 } | |
631 var done = new Completer(); | |
632 var sub = f().listen((v) { | |
633 if (v == 2) { | |
634 expect(list, equals([1])); | |
635 } else if (v == 4) { | |
636 expect(list, equals([1, 3])); | |
637 } else { | |
638 fail("Unexpected value $v"); | |
639 } | |
640 }, onDone: () { | |
641 expect(list, equals([1, 3, 5])); | |
642 done.complete(); | |
643 }); | |
644 return done.future; | |
645 }); | |
646 | |
647 test("pause stops execution at yield", () { | |
648 var list = []; | |
649 f() async* { | |
650 list.add(1); | |
651 yield 2; | |
652 list.add(3); | |
653 yield 4; | |
654 list.add(5); | |
655 } | |
656 var done = new Completer(); | |
657 var sub; | |
658 sub = f().listen((v) { | |
659 if (v == 2) { | |
660 expect(list, equals([1])); | |
661 sub.pause(); | |
662 new Timer(MS * 300, () { | |
663 expect(list.length, lessThan(3)); | |
664 sub.resume(); | |
665 }); | |
666 } else if (v == 4) { | |
667 expect(list, equals([1, 3])); | |
668 } else { | |
669 fail("Unexpected value $v"); | |
670 } | |
671 }, onDone: () { | |
672 expect(list, equals([1, 3, 5])); | |
673 done.complete(); | |
674 }); | |
675 return done.future; | |
676 }); | |
677 | |
678 test("pause stops execution at yield 2", () { | |
679 var list = []; | |
680 f() async* { | |
681 int i = 0; | |
682 while (true) { | |
683 yield i; | |
684 list.add(i); | |
685 i++; | |
686 } | |
687 } | |
688 int expected = 0; | |
689 var done = new Completer(); | |
690 var sub; | |
691 sub = f().listen((v) { | |
692 expect(v, equals(expected++)); | |
693 if (v % 5 == 0) { | |
694 sub.pause(new Future.delayed(MS * 300)); | |
695 } else if (v == 17) { | |
696 sub.cancel(); | |
697 done.complete(); | |
698 } | |
699 }, onDone: () { | |
700 fail("Unexpected done!"); | |
701 }); | |
702 return done.future.whenComplete(() { | |
703 expect(list.length == 18 || list.length == 19, isTrue); | |
704 }); | |
705 }); | |
706 | |
707 test("multiple pauses, cancel while paused", () { | |
708 var list = []; | |
709 f() async* { | |
710 int i = 0; | |
711 while (true) { | |
712 yield i; | |
713 list.add(i); | |
714 i++; | |
715 await null; // extra pause for good measure. | |
716 } | |
717 } | |
718 int expected = 0; | |
719 var done = new Completer(); | |
720 var sub; | |
721 sub = f().listen((v) { | |
722 expect(v, equals(expected++)); | |
723 if (v == 5) { | |
724 scheduleMicrotask(() { | |
725 sub.pause(); | |
726 sub.resume(); | |
727 sub.pause(); | |
728 sub.resume(); | |
729 sub.pause(); | |
730 sub.resume(); | |
731 }); | |
732 } else if (v == 6) { | |
733 sub.pause(); | |
734 new Timer(MS * 300, () { | |
735 expect(list.length, lessThan(8)); | |
736 sub.cancel(); | |
737 done.complete(); | |
738 }); | |
739 } | |
740 }, onDone: () { | |
741 fail("Unexpected done"); | |
742 }); | |
743 }); | |
744 | |
745 test("canceling while paused at yield", () { /// 02: ok | |
746 var list = []; /// 02: contin ued | |
747 var sync = new Sync(); /// 02: contin ued | |
748 f() async* { /// 02: contin ued | |
749 list.add("*1"); /// 02: contin ued | |
750 yield 1; /// 02: contin ued | |
751 await sync.wait(); /// 02: contin ued | |
752 sync.release(); /// 02: contin ued | |
753 list.add("*2"); /// 02: contin ued | |
754 yield 2; /// 02: contin ued | |
755 list.add("*3"); /// 02: contin ued | |
756 }; /// 02: contin ued | |
757 var stream = f(); /// 02: contin ued | |
758 var sub = stream.listen(list.add); /// 02: contin ued | |
759 return sync.wait().whenComplete(() { /// 02: contin ued | |
760 expect(list, equals(["*1", 1])); /// 02: contin ued | |
761 sub.pause(); /// 02: contin ued | |
762 return sync.wait(); /// 02: contin ued | |
763 }).whenComplete(() { /// 02: contin ued | |
764 expect(list, equals(["*1", 1, "*2"])); /// 02: contin ued | |
765 sub.cancel(); /// 02: contin ued | |
766 return new Future.delayed(MS * 200, () { /// 02: contin ued | |
767 // Should not have yielded 2 or added *3 while paused. /// 02: contin ued | |
768 expect(list, equals(["*1", 1, "*2"])); /// 02: contin ued | |
769 }); /// 02: contin ued | |
770 }); /// 02: contin ued | |
771 }); /// 02: contin ued | |
772 }); | |
773 | |
774 group("await for", () { | |
775 mkStream(int n) async* { | |
776 for (int i = 0; i < n; i++) yield i; | |
777 } | |
778 | |
779 test("simple stream", () { | |
780 f(s) async { | |
781 var r = 0; | |
782 await for(var v in s) r += v; | |
783 return r; | |
784 } | |
785 return f(mkStream(5)).then((v) { | |
786 expect(v, equals(10)); | |
787 }); | |
788 }); | |
789 | |
790 test("simple stream, await", () { | |
791 f(s) async { | |
792 var r = 0; | |
793 await for(var v in s) r += await new Future.microtask(() => v); | |
794 return r; | |
795 } | |
796 return f(mkStream(5)).then((v) { | |
797 expect(v, equals(10)); | |
798 }); | |
799 }); | |
800 | |
801 test("simple stream - take", () { /// 03: ok | |
802 f(s) async { /// 03: continued | |
803 var r = 0; /// 03: continued | |
804 await for(var v in s.take(5)) r += v; /// 03: continued | |
805 return r; /// 03: continued | |
806 } /// 03: continued | |
807 return f(mkStream(10)).then((v) { /// 03: continued | |
808 expect(v, equals(10)); /// 03: continued | |
809 }); /// 03: continued | |
810 }); /// 03: continued | |
811 | |
812 test("simple stream reyield", () { | |
813 f(s) async* { | |
814 var r = 0; | |
815 await for(var v in s) yield r += v; | |
816 } | |
817 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); | |
818 }); | |
819 | |
820 test("simple stream, await, reyield", () { | |
821 f(s) async* { | |
822 var r = 0; | |
823 await for(var v in s) yield r += await new Future.microtask(() => v); | |
824 } | |
825 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); | |
826 }); | |
827 | |
828 test("simple stream - take, reyield", () { /// 04: ok | |
829 f(s) async* { /// 04: continued | |
830 var r = 0; /// 04: continued | |
831 await for(var v in s.take(5)) yield r += v; /// 04: continued | |
832 } /// 04: continued | |
833 return expectList(f(mkStream(10)), [0, 1, 3, 6, 10]); /// 04: continued | |
834 }); /// 04: continued | |
835 | |
836 test("nested", () { | |
837 f() async { | |
838 var r = 0; | |
839 await for (var i in mkStream(5)) { | |
840 await for (var j in mkStream(3)) { | |
841 r += i * j; | |
842 } | |
843 } | |
844 return r; | |
845 } | |
846 return f().then((v) { | |
847 expect(v, equals((1 + 2 + 3 + 4) * (1 + 2))); | |
848 }); | |
849 }); | |
850 | |
851 test("nested, await", () { | |
852 f() async { | |
853 var r = 0; | |
854 await for (var i in mkStream(5)) { | |
855 await for (var j in mkStream(3)) { | |
856 r += await new Future.microtask(() => i * j); | |
857 } | |
858 } | |
859 return r; | |
860 } | |
861 return f().then((v) { | |
862 expect(v, equals((1 + 2 + 3 + 4) * (1 + 2))); | |
863 }); | |
864 }); | |
865 | |
866 test("nested, await * 2", () { | |
867 f() async { | |
868 var r = 0; | |
869 await for (var i in mkStream(5)) { | |
870 var ai = await new Future.microtask(() => i); | |
871 await for (var j in mkStream(3)) { | |
872 r += await new Future.microtask(() => ai * j); | |
873 } | |
874 } | |
875 return r; | |
876 } | |
877 return f().then((v) { | |
878 expect(v, equals((1 + 2 + 3 + 4) * (1 + 2))); | |
879 }); | |
880 }); | |
881 | |
882 test("await pauses loop", () { /// 05: ok | |
883 var sc; /// 05: con tinued | |
884 var i = 0; /// 05: con tinued | |
885 void send() { /// 05: con tinued | |
886 if (i == 5) { /// 05: con tinued | |
887 sc.close(); /// 05: con tinued | |
888 } else { /// 05: con tinued | |
889 sc.add(i++); /// 05: con tinued | |
890 } /// 05: con tinued | |
891 } /// 05: con tinued | |
892 sc = new StreamController(onListen: send, onResume: send); /// 05: con tinued | |
893 f(s) async { /// 05: con tinued | |
894 var r = 0; /// 05: con tinued | |
895 await for (var i in s) { /// 05: con tinued | |
896 r += await new Future.delayed(MS * 10, () => i); /// 05: con tinued | |
897 } /// 05: con tinued | |
898 return r; /// 05: con tinued | |
899 } /// 05: con tinued | |
900 return f(sc.stream).then((v) { /// 05: con tinued | |
901 expect(v, equals(10)); /// 05: con tinued | |
902 }); /// 05: con tinued | |
903 }); /// 05: con tinued | |
904 }); | |
905 } | |
906 | |
907 // Obscuring identity function. | |
908 id(x) { | |
909 try { | |
910 if (x != null) throw x; | |
911 } catch (e) { | |
912 return e; | |
913 } | |
914 return null; | |
915 } | |
916 | |
917 expectList(stream, list) { | |
918 return stream.toList().then((v) { | |
919 expect(v, equals(list)); | |
920 }); | |
921 } | |
922 | |
923 const MS = const Duration(milliseconds: 1); | |
924 | |
925 var getErrors = new StreamTransformer.fromHandlers( | |
926 handleData:(data, sink) { fail("Unexpected value"); }, | |
927 handleError: (e, s, sink) { sink.add(e); }, | |
928 handleDone: (sink) { sink.close(); }); | |
929 | |
930 class NotAStream { | |
931 listen(oData, {onError, onDone, cancelOnError}) { | |
932 fail("Not implementing Stream."); | |
933 } | |
934 } | |
935 | |
936 /** | |
937 * Allows two asynchronous executions to synchronize. | |
938 * | |
939 * Calling [wait] and waiting for the returned future to complete will | |
940 * wait for the other executions to call [wait] again. At that point, | |
941 * the waiting execution is allowed to continue (the returned future completes), | |
942 * and the more resent call to [wait] is now the waiting execution. | |
943 */ | |
944 class Sync { | |
945 Completer _completer = null; | |
946 // Release whoever is currently waiting and start waiting yourself. | |
947 Future wait([v]) { | |
948 if (_completer != null) _completer.complete(v); | |
949 _completer = new Completer(); | |
950 return _completer.future; | |
951 } | |
952 | |
953 // Release whoever is currently waiting. | |
954 void release([v]) { | |
955 if (_completer != null) { | |
956 _completer.complete(v); | |
957 _completer = null; | |
958 } | |
959 } | |
960 } | |
OLD | NEW |