| 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 |