OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2016, 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 import "dart:async"; |
| 6 import "package:async_helper/async_helper.dart"; |
| 7 |
| 8 /// This test verifies that an await for loop sends the correct |
| 9 /// signals to the stream it iterates over: |
| 10 /// 1) A listen event. |
| 11 /// 2) A pause event when the loop body is awaiting something, |
| 12 /// and more elements arrive on the stream. See issue |
| 13 /// https://github.com/dart-lang/sdk/issues/23996 . |
| 14 /// 3) A resume event, when the loop is again ready to iterate. |
| 15 main() { |
| 16 Completer listenEventReceived = new Completer(); |
| 17 Completer pauseEventReceived = new Completer(); |
| 18 Completer resumeEventReceived = new Completer(); |
| 19 StreamController controller = new StreamController( |
| 20 onListen: () => listenEventReceived.complete(), |
| 21 onPause: () => pauseEventReceived.complete(), |
| 22 onResume: () => resumeEventReceived.complete()); |
| 23 |
| 24 Completer forLoopEntered = new Completer(); |
| 25 |
| 26 /// The send function puts items on the stream. It waits for a |
| 27 /// listener, puts "first" on the stream, waits for the for loop |
| 28 /// to start (and eventually block), puts "second" on the stream |
| 29 /// multiple times, letting the event loop run, until the for loop |
| 30 /// pauses the stream because it it blocked. |
| 31 /// The for loop unblocks after the pause message is received, and |
| 32 /// reads the stream items, sending a stream resume message when it |
| 33 /// is ready for more. |
| 34 /// Then the send function puts a final "third" on the stream, and |
| 35 /// closes the stream. |
| 36 send() async { |
| 37 await listenEventReceived.future; |
| 38 controller.add('first'); |
| 39 await forLoopEntered.future; |
| 40 var timer = new Timer.periodic(new Duration(milliseconds: 10), (timer) { |
| 41 controller.add('second'); |
| 42 }); |
| 43 await pauseEventReceived.future; |
| 44 // pauseEventReceived.future completes when controller.stream is |
| 45 // paused by the await-for loop below. What's specified is that |
| 46 // await-for must pause immediately on an "await", but instead |
| 47 // the implementations agree on not pausing until receiving the |
| 48 // next event. For this reason, [timer] will call its callback at |
| 49 // least once before we cancel it again. |
| 50 timer.cancel(); |
| 51 await resumeEventReceived.future; |
| 52 controller.add('third'); |
| 53 controller.close(); |
| 54 } |
| 55 |
| 56 receive() async { |
| 57 bool thirdReceived = false; |
| 58 await for (var entry in controller.stream) { |
| 59 if (entry == 'first') { |
| 60 forLoopEntered.complete(); |
| 61 await pauseEventReceived.future; |
| 62 } else if (entry == 'third') { |
| 63 thirdReceived = true; |
| 64 } |
| 65 } |
| 66 if (!thirdReceived) { |
| 67 throw "Error in await-for loop: 'third' not received"; |
| 68 } |
| 69 } |
| 70 |
| 71 asyncTest(() async { |
| 72 // We need to start both functions in parallel, and wait on them both. |
| 73 var f = send(); |
| 74 await receive(); |
| 75 await f; |
| 76 }); |
| 77 } |
OLD | NEW |