OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 async_start_test; | 5 library async_start_test; |
6 | 6 |
7 import "package:unittest/unittest.dart"; | 7 import "package:unittest/unittest.dart"; |
8 import "dart:async"; | 8 import "dart:async"; |
9 | 9 |
10 main() { | 10 main() { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 return expectList(f(), [0, 1, 2]); | 136 return expectList(f(), [0, 1, 2]); |
137 }); | 137 }); |
138 | 138 |
139 test("labeled", () { | 139 test("labeled", () { |
140 f() async* { | 140 f() async* { |
141 label1: yield 0; | 141 label1: yield 0; |
142 } | 142 } |
143 return expectList(f(), [0]); | 143 return expectList(f(), [0]); |
144 }); | 144 }); |
145 | 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", () { | 146 test("for-loop", () { |
155 f() async* { | 147 f() async* { |
156 for (int i = 0; i < 3; i++) yield i; | 148 for (int i = 0; i < 3; i++) yield i; |
157 } | 149 } |
158 return expectList(f(), [0, 1, 2]); | 150 return expectList(f(), [0, 1, 2]); |
159 }); | 151 }); |
160 | 152 |
161 test("for-in-loop", () { | 153 test("for-in-loop", () { |
162 f() async* { | 154 f() async* { |
163 for (var i in [0, 1, 2]) yield i; | 155 for (var i in [0, 1, 2]) yield i; |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 test("before end", () { | 568 test("before end", () { |
577 return expectList(f().take(2), [1, 2]); | 569 return expectList(f().take(2), [1, 2]); |
578 }); | 570 }); |
579 test("early", () { | 571 test("early", () { |
580 return expectList(f().take(1), [1]); | 572 return expectList(f().take(1), [1]); |
581 }); | 573 }); |
582 test("at start", () { | 574 test("at start", () { |
583 return expectList(f().take(0), []); | 575 return expectList(f().take(0), []); |
584 }); | 576 }); |
585 }); | 577 }); |
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 }); | 578 }); |
620 | 579 |
621 group("pausing", () { | 580 group("pausing", () { |
622 test("pauses execution at yield for at least a microtask", () { | 581 test("pauses execution at yield for at least a microtask", () { |
623 var list = []; | 582 var list = []; |
624 f() async* { | 583 f() async* { |
625 list.add(1); | 584 list.add(1); |
626 yield 2; | 585 yield 2; |
627 list.add(3); | 586 list.add(3); |
628 yield 4; | 587 yield 4; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
696 sub.cancel(); | 655 sub.cancel(); |
697 done.complete(); | 656 done.complete(); |
698 } | 657 } |
699 }, onDone: () { | 658 }, onDone: () { |
700 fail("Unexpected done!"); | 659 fail("Unexpected done!"); |
701 }); | 660 }); |
702 return done.future.whenComplete(() { | 661 return done.future.whenComplete(() { |
703 expect(list.length == 18 || list.length == 19, isTrue); | 662 expect(list.length == 18 || list.length == 19, isTrue); |
704 }); | 663 }); |
705 }); | 664 }); |
706 | |
707 test("canceling while paused at yield", () { /// 02: ok | |
708 var list = []; /// 02: contin
ued | |
709 var sync = new Sync(); /// 02: contin
ued | |
710 f() async* { /// 02: contin
ued | |
711 list.add("*1"); /// 02: contin
ued | |
712 yield 1; /// 02: contin
ued | |
713 await sync.wait(); /// 02: contin
ued | |
714 sync.release(); /// 02: contin
ued | |
715 list.add("*2"); /// 02: contin
ued | |
716 yield 2; /// 02: contin
ued | |
717 list.add("*3"); /// 02: contin
ued | |
718 }; /// 02: contin
ued | |
719 var stream = f(); /// 02: contin
ued | |
720 var sub = stream.listen(list.add); /// 02: contin
ued | |
721 return sync.wait().whenComplete(() { /// 02: contin
ued | |
722 expect(list, equals(["*1", 1])); /// 02: contin
ued | |
723 sub.pause(); /// 02: contin
ued | |
724 return sync.wait(); /// 02: contin
ued | |
725 }).whenComplete(() { /// 02: contin
ued | |
726 expect(list, equals(["*1", 1, "*2"])); /// 02: contin
ued | |
727 sub.cancel(); /// 02: contin
ued | |
728 return new Future.delayed(MS * 200, () { /// 02: contin
ued | |
729 // Should not have yielded 2 or added *3 while paused. /// 02: contin
ued | |
730 expect(list, equals(["*1", 1, "*2"])); /// 02: contin
ued | |
731 }); /// 02: contin
ued | |
732 }); /// 02: contin
ued | |
733 }); /// 02: contin
ued | |
734 }); | 665 }); |
735 | 666 |
736 group("await for", () { | 667 group("await for", () { |
737 mkStream(int n) async* { | 668 mkStream(int n) async* { |
738 for (int i = 0; i < n; i++) yield i; | 669 for (int i = 0; i < n; i++) yield i; |
739 } | 670 } |
740 | 671 |
741 test("simple stream", () { | 672 test("simple stream", () { |
742 f(s) async { | 673 f(s) async { |
743 var r = 0; | 674 var r = 0; |
744 await for(var v in s) r += v; | 675 await for(var v in s) r += v; |
745 return r; | 676 return r; |
746 } | 677 } |
747 return f(mkStream(5)).then((v) { | 678 return f(mkStream(5)).then((v) { |
748 expect(v, equals(10)); | 679 expect(v, equals(10)); |
749 }); | 680 }); |
750 }); | 681 }); |
751 | 682 |
752 test("simple stream, await", () { | 683 test("simple stream, await", () { |
753 f(s) async { | 684 f(s) async { |
754 var r = 0; | 685 var r = 0; |
755 await for(var v in s) r += await new Future.microtask(() => v); | 686 await for(var v in s) r += await new Future.microtask(() => v); |
756 return r; | 687 return r; |
757 } | 688 } |
758 return f(mkStream(5)).then((v) { | 689 return f(mkStream(5)).then((v) { |
759 expect(v, equals(10)); | 690 expect(v, equals(10)); |
760 }); | 691 }); |
761 }); | 692 }); |
762 | 693 |
763 test("simple stream - take", () { /// 03: ok | |
764 f(s) async { /// 03: continued | |
765 var r = 0; /// 03: continued | |
766 await for(var v in s.take(5)) r += v; /// 03: continued | |
767 return r; /// 03: continued | |
768 } /// 03: continued | |
769 return f(mkStream(10)).then((v) { /// 03: continued | |
770 expect(v, equals(10)); /// 03: continued | |
771 }); /// 03: continued | |
772 }); /// 03: continued | |
773 | |
774 test("simple stream reyield", () { | 694 test("simple stream reyield", () { |
775 f(s) async* { | 695 f(s) async* { |
776 var r = 0; | 696 var r = 0; |
777 await for(var v in s) yield r += v; | 697 await for(var v in s) yield r += v; |
778 } | 698 } |
779 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); | 699 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); |
780 }); | 700 }); |
781 | 701 |
782 test("simple stream, await, reyield", () { | 702 test("simple stream, await, reyield", () { |
783 f(s) async* { | 703 f(s) async* { |
784 var r = 0; | 704 var r = 0; |
785 await for(var v in s) yield r += await new Future.microtask(() => v); | 705 await for(var v in s) yield r += await new Future.microtask(() => v); |
786 } | 706 } |
787 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); | 707 return expectList(f(mkStream(5)), [0, 1, 3, 6, 10]); |
788 }); | 708 }); |
789 | 709 |
790 test("simple stream - take, reyield", () { /// 04: ok | |
791 f(s) async* { /// 04: continued | |
792 var r = 0; /// 04: continued | |
793 await for(var v in s.take(5)) yield r += v; /// 04: continued | |
794 } /// 04: continued | |
795 return expectList(f(mkStream(10)), [0, 1, 3, 6, 10]); /// 04: continued | |
796 }); /// 04: continued | |
797 | |
798 test("nested", () { | 710 test("nested", () { |
799 f() async { | 711 f() async { |
800 var r = 0; | 712 var r = 0; |
801 await for (var i in mkStream(5)) { | 713 await for (var i in mkStream(5)) { |
802 await for (var j in mkStream(3)) { | 714 await for (var j in mkStream(3)) { |
803 r += i * j; | 715 r += i * j; |
804 } | 716 } |
805 } | 717 } |
806 return r; | 718 return r; |
807 } | 719 } |
(...skipping 25 matching lines...) Expand all Loading... |
833 await for (var j in mkStream(3)) { | 745 await for (var j in mkStream(3)) { |
834 r += await new Future.microtask(() => ai * j); | 746 r += await new Future.microtask(() => ai * j); |
835 } | 747 } |
836 } | 748 } |
837 return r; | 749 return r; |
838 } | 750 } |
839 return f().then((v) { | 751 return f().then((v) { |
840 expect(v, equals((1 + 2 + 3 + 4) * (1 + 2))); | 752 expect(v, equals((1 + 2 + 3 + 4) * (1 + 2))); |
841 }); | 753 }); |
842 }); | 754 }); |
843 | |
844 test("await pauses loop", () { /// 05: ok | |
845 var sc; /// 05: con
tinued | |
846 var i = 0; /// 05: con
tinued | |
847 void send() { /// 05: con
tinued | |
848 if (i == 5) { /// 05: con
tinued | |
849 sc.close(); /// 05: con
tinued | |
850 } else { /// 05: con
tinued | |
851 sc.add(i++); /// 05: con
tinued | |
852 } /// 05: con
tinued | |
853 } /// 05: con
tinued | |
854 sc = new StreamController(onListen: send, onResume: send); /// 05: con
tinued | |
855 f(s) async { /// 05: con
tinued | |
856 var r = 0; /// 05: con
tinued | |
857 await for (var i in s) { /// 05: con
tinued | |
858 r += await new Future.delayed(MS * 10, () => i); /// 05: con
tinued | |
859 } /// 05: con
tinued | |
860 return r; /// 05: con
tinued | |
861 } /// 05: con
tinued | |
862 return f(sc.stream).then((v) { /// 05: con
tinued | |
863 expect(v, equals(10)); /// 05: con
tinued | |
864 }); /// 05: con
tinued | |
865 }); /// 05: con
tinued | |
866 }); | 755 }); |
867 } | 756 } |
868 | 757 |
869 // Obscuring identity function. | 758 // Obscuring identity function. |
870 id(x) { | 759 id(x) { |
871 try { | 760 try { |
872 if (x != null) throw x; | 761 if (x != null) throw x; |
873 } catch (e) { | 762 } catch (e) { |
874 return e; | 763 return e; |
875 } | 764 } |
(...skipping 11 matching lines...) Expand all Loading... |
887 var getErrors = new StreamTransformer.fromHandlers( | 776 var getErrors = new StreamTransformer.fromHandlers( |
888 handleData:(data, sink) { fail("Unexpected value"); }, | 777 handleData:(data, sink) { fail("Unexpected value"); }, |
889 handleError: (e, s, sink) { sink.add(e); }, | 778 handleError: (e, s, sink) { sink.add(e); }, |
890 handleDone: (sink) { sink.close(); }); | 779 handleDone: (sink) { sink.close(); }); |
891 | 780 |
892 class NotAStream { | 781 class NotAStream { |
893 listen(oData, {onError, onDone, cancelOnError}) { | 782 listen(oData, {onError, onDone, cancelOnError}) { |
894 fail("Not implementing Stream."); | 783 fail("Not implementing Stream."); |
895 } | 784 } |
896 } | 785 } |
897 | |
898 /** | |
899 * Allows two asynchronous executions to synchronize. | |
900 * | |
901 * Calling [wait] and waiting for the returned future to complete will | |
902 * wait for the other executions to call [wait] again. At that point, | |
903 * the waiting execution is allowed to continue (the returned future completes), | |
904 * and the more resent call to [wait] is now the waiting execution. | |
905 */ | |
906 class Sync { | |
907 Completer _completer = null; | |
908 // Release whoever is currently waiting and start waiting yourself. | |
909 Future wait([v]) { | |
910 if (_completer != null) _completer.complete(v); | |
911 _completer = new Completer(); | |
912 return _completer.future; | |
913 } | |
914 | |
915 // Release whoever is currently waiting. | |
916 void release([v]) { | |
917 if (_completer != null) { | |
918 _completer.complete(v); | |
919 _completer = null; | |
920 } | |
921 } | |
922 } | |
OLD | NEW |