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