OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012, 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 future_test; |
| 6 |
| 7 import 'package:async_helper/async_helper.dart'; |
| 8 import "package:expect/expect.dart"; |
| 9 import 'dart:async'; |
| 10 |
| 11 const Duration MS = const Duration(milliseconds: 1); |
| 12 |
| 13 void testValue() { |
| 14 final future = new Future<String>.value("42"); |
| 15 asyncStart(); |
| 16 future.then((x) { |
| 17 Expect.equals("42", x); |
| 18 asyncEnd(); |
| 19 }); |
| 20 } |
| 21 |
| 22 void testSync() { |
| 23 compare(func) { |
| 24 // Compare the results of the following two futures. |
| 25 Future f1 = new Future.sync(func); |
| 26 Future f2 = new Future.value().then((_) => func()); |
| 27 f2.catchError((_) {}); // I'll get the error later. |
| 28 f1.then((v1) { |
| 29 f2.then((v2) { |
| 30 Expect.equals(v1, v2); |
| 31 }); |
| 32 }, onError: (e1) { |
| 33 f2.then((_) { |
| 34 Expect.fail("Expected error"); |
| 35 }, onError: (e2) { |
| 36 Expect.equals(e1, e2); |
| 37 }); |
| 38 }); |
| 39 } |
| 40 |
| 41 Future val = new Future.value(42); |
| 42 Future err1 = new Future.error("Error")..catchError((_) {}); |
| 43 try { |
| 44 throw new List(0); |
| 45 } catch (e, st) { |
| 46 Future err2 = new Future.error(e, st)..catchError((_) {}); |
| 47 } |
| 48 compare(() => 42); |
| 49 compare(() => val); |
| 50 compare(() { |
| 51 throw "Flif"; |
| 52 }); |
| 53 compare(() => err1); |
| 54 bool hasExecuted = false; |
| 55 compare(() { |
| 56 hasExecuted = true; |
| 57 return 499; |
| 58 }); |
| 59 Expect.isTrue(hasExecuted); |
| 60 } |
| 61 |
| 62 void testNeverComplete() { |
| 63 final completer = new Completer<int>(); |
| 64 final future = completer.future; |
| 65 future.then((v) => Expect.fail("Value not expected")); |
| 66 future.catchError((e) => Expect.fail("Value not expected")); |
| 67 } |
| 68 |
| 69 void testComplete() { |
| 70 final completer = new Completer<int>(); |
| 71 final future = completer.future; |
| 72 Expect.isFalse(completer.isCompleted); |
| 73 |
| 74 completer.complete(3); |
| 75 Expect.isTrue(completer.isCompleted); |
| 76 |
| 77 future.then((v) => Expect.equals(3, v)); |
| 78 } |
| 79 |
| 80 // Tests for [then] |
| 81 |
| 82 void testCompleteWithSuccessHandlerBeforeComplete() { |
| 83 final completer = new Completer<int>(); |
| 84 final future = completer.future; |
| 85 |
| 86 int after; |
| 87 |
| 88 asyncStart(); |
| 89 future.then((int v) { |
| 90 after = v; |
| 91 }).then((_) { |
| 92 Expect.equals(3, after); |
| 93 asyncEnd(); |
| 94 }); |
| 95 |
| 96 completer.complete(3); |
| 97 Expect.isNull(after); |
| 98 } |
| 99 |
| 100 void testCompleteWithSuccessHandlerAfterComplete() { |
| 101 final completer = new Completer<int>(); |
| 102 final future = completer.future; |
| 103 |
| 104 int after; |
| 105 completer.complete(3); |
| 106 Expect.isNull(after); |
| 107 |
| 108 asyncStart(); |
| 109 future.then((int v) { |
| 110 after = v; |
| 111 }).then((_) { |
| 112 Expect.equals(3, after); |
| 113 asyncEnd(); |
| 114 }); |
| 115 } |
| 116 |
| 117 void testCompleteManySuccessHandlers() { |
| 118 final completer = new Completer<int>(); |
| 119 final future = completer.future; |
| 120 int before; |
| 121 int after1; |
| 122 int after2; |
| 123 |
| 124 var futures = []; |
| 125 futures.add(future.then((int v) { |
| 126 before = v; |
| 127 })); |
| 128 completer.complete(3); |
| 129 futures.add(future.then((int v) { |
| 130 after1 = v; |
| 131 })); |
| 132 futures.add(future.then((int v) { |
| 133 after2 = v; |
| 134 })); |
| 135 |
| 136 asyncStart(); |
| 137 Future.wait(futures).then((_) { |
| 138 Expect.equals(3, before); |
| 139 Expect.equals(3, after1); |
| 140 Expect.equals(3, after2); |
| 141 asyncEnd(); |
| 142 }); |
| 143 } |
| 144 |
| 145 // Tests for [catchError] |
| 146 |
| 147 void testException() { |
| 148 final completer = new Completer<int>(); |
| 149 final future = completer.future; |
| 150 final ex = new Exception(); |
| 151 |
| 152 asyncStart(); |
| 153 future.then((v) { |
| 154 throw "Value not expected"; |
| 155 }).catchError((error) { |
| 156 Expect.equals(error, ex); |
| 157 asyncEnd(); |
| 158 }, test: (e) => e == ex); |
| 159 completer.completeError(ex); |
| 160 } |
| 161 |
| 162 void testExceptionHandler() { |
| 163 final completer = new Completer<int>(); |
| 164 final future = completer.future; |
| 165 final ex = new Exception(); |
| 166 |
| 167 var ex2; |
| 168 var done = future.catchError((error) { |
| 169 ex2 = error; |
| 170 }); |
| 171 |
| 172 Expect.isFalse(completer.isCompleted); |
| 173 completer.completeError(ex); |
| 174 Expect.isTrue(completer.isCompleted); |
| 175 |
| 176 asyncStart(); |
| 177 done.then((_) { |
| 178 Expect.equals(ex, ex2); |
| 179 asyncEnd(); |
| 180 }); |
| 181 } |
| 182 |
| 183 void testExceptionHandlerReturnsTrue() { |
| 184 final completer = new Completer<int>(); |
| 185 final future = completer.future; |
| 186 final ex = new Exception(); |
| 187 |
| 188 bool reached = false; |
| 189 future.catchError((e) {}); |
| 190 future.catchError((e) { |
| 191 reached = true; |
| 192 }, test: (e) => false).catchError((e) {}); |
| 193 Expect.isFalse(completer.isCompleted); |
| 194 completer.completeError(ex); |
| 195 Expect.isTrue(completer.isCompleted); |
| 196 Expect.isFalse(reached); |
| 197 } |
| 198 |
| 199 void testExceptionHandlerReturnsTrue2() { |
| 200 final completer = new Completer<int>(); |
| 201 final future = completer.future; |
| 202 final ex = new Exception(); |
| 203 |
| 204 bool reached = false; |
| 205 var done = future.catchError((e) {}, test: (e) => false).catchError((e) { |
| 206 reached = true; |
| 207 }); |
| 208 completer.completeError(ex); |
| 209 |
| 210 asyncStart(); |
| 211 done.then((_) { |
| 212 Expect.isTrue(reached); |
| 213 asyncEnd(); |
| 214 }); |
| 215 } |
| 216 |
| 217 void testExceptionHandlerReturnsFalse() { |
| 218 final completer = new Completer<int>(); |
| 219 final future = completer.future; |
| 220 final ex = new Exception(); |
| 221 |
| 222 bool reached = false; |
| 223 |
| 224 future.catchError((e) {}); |
| 225 |
| 226 future.catchError((e) { |
| 227 reached = true; |
| 228 }, test: (e) => false).catchError((e) {}); |
| 229 |
| 230 completer.completeError(ex); |
| 231 |
| 232 Expect.isFalse(reached); |
| 233 } |
| 234 |
| 235 void testFutureAsStreamCompleteAfter() { |
| 236 var completer = new Completer(); |
| 237 bool gotValue = false; |
| 238 asyncStart(); |
| 239 completer.future.asStream().listen((data) { |
| 240 Expect.isFalse(gotValue); |
| 241 gotValue = true; |
| 242 Expect.equals("value", data); |
| 243 }, onDone: () { |
| 244 Expect.isTrue(gotValue); |
| 245 asyncEnd(); |
| 246 }); |
| 247 completer.complete("value"); |
| 248 } |
| 249 |
| 250 void testFutureAsStreamCompleteBefore() { |
| 251 var completer = new Completer(); |
| 252 bool gotValue = false; |
| 253 asyncStart(); |
| 254 completer.complete("value"); |
| 255 completer.future.asStream().listen((data) { |
| 256 Expect.isFalse(gotValue); |
| 257 gotValue = true; |
| 258 Expect.equals("value", data); |
| 259 }, onDone: () { |
| 260 Expect.isTrue(gotValue); |
| 261 asyncEnd(); |
| 262 }); |
| 263 } |
| 264 |
| 265 void testFutureAsStreamCompleteImmediate() { |
| 266 bool gotValue = false; |
| 267 asyncStart(); |
| 268 new Future.value("value").asStream().listen((data) { |
| 269 Expect.isFalse(gotValue); |
| 270 gotValue = true; |
| 271 Expect.equals("value", data); |
| 272 }, onDone: () { |
| 273 Expect.isTrue(gotValue); |
| 274 asyncEnd(); |
| 275 }); |
| 276 } |
| 277 |
| 278 void testFutureAsStreamCompleteErrorAfter() { |
| 279 var completer = new Completer(); |
| 280 bool gotError = false; |
| 281 asyncStart(); |
| 282 completer.future.asStream().listen((data) { |
| 283 Expect.fail("Unexpected data"); |
| 284 }, onError: (error) { |
| 285 Expect.isFalse(gotError); |
| 286 gotError = true; |
| 287 Expect.equals("error", error); |
| 288 }, onDone: () { |
| 289 Expect.isTrue(gotError); |
| 290 asyncEnd(); |
| 291 }); |
| 292 completer.completeError("error"); |
| 293 } |
| 294 |
| 295 void testFutureAsStreamWrapper() { |
| 296 var completer = new Completer(); |
| 297 bool gotValue = false; |
| 298 asyncStart(); |
| 299 completer.complete("value"); |
| 300 completer.future |
| 301 .catchError((_) { |
| 302 throw "not possible"; |
| 303 }) // Returns a future wrapper. |
| 304 .asStream() |
| 305 .listen((data) { |
| 306 Expect.isFalse(gotValue); |
| 307 gotValue = true; |
| 308 Expect.equals("value", data); |
| 309 }, onDone: () { |
| 310 Expect.isTrue(gotValue); |
| 311 asyncEnd(); |
| 312 }); |
| 313 } |
| 314 |
| 315 void testFutureWhenCompleteValue() { |
| 316 asyncStart(); |
| 317 int counter = 2; |
| 318 countDown() { |
| 319 if (--counter == 0) asyncEnd(); |
| 320 } |
| 321 |
| 322 var completer = new Completer(); |
| 323 Future future = completer.future; |
| 324 Future later = future.whenComplete(countDown); |
| 325 later.then((v) { |
| 326 Expect.equals(42, v); |
| 327 countDown(); |
| 328 }); |
| 329 completer.complete(42); |
| 330 } |
| 331 |
| 332 void testFutureWhenCompleteError() { |
| 333 asyncStart(); |
| 334 int counter = 2; |
| 335 countDown() { |
| 336 if (--counter == 0) asyncEnd(); |
| 337 } |
| 338 |
| 339 var completer = new Completer(); |
| 340 Future future = completer.future; |
| 341 Future later = future.whenComplete(countDown); |
| 342 later.catchError((error) { |
| 343 Expect.equals("error", error); |
| 344 countDown(); |
| 345 }); |
| 346 completer.completeError("error"); |
| 347 } |
| 348 |
| 349 void testFutureWhenCompleteValueNewError() { |
| 350 asyncStart(); |
| 351 int counter = 2; |
| 352 countDown() { |
| 353 if (--counter == 0) asyncEnd(); |
| 354 } |
| 355 |
| 356 var completer = new Completer(); |
| 357 Future future = completer.future; |
| 358 Future later = future.whenComplete(() { |
| 359 countDown(); |
| 360 throw "new error"; |
| 361 }); |
| 362 later.catchError((error) { |
| 363 Expect.equals("new error", error); |
| 364 countDown(); |
| 365 }); |
| 366 completer.complete(42); |
| 367 } |
| 368 |
| 369 void testFutureWhenCompleteErrorNewError() { |
| 370 asyncStart(); |
| 371 int counter = 2; |
| 372 countDown() { |
| 373 if (--counter == 0) asyncEnd(); |
| 374 } |
| 375 |
| 376 var completer = new Completer(); |
| 377 Future future = completer.future; |
| 378 Future later = future.whenComplete(() { |
| 379 countDown(); |
| 380 throw "new error"; |
| 381 }); |
| 382 later.catchError((error) { |
| 383 Expect.equals("new error", error); |
| 384 countDown(); |
| 385 }); |
| 386 completer.completeError("error"); |
| 387 } |
| 388 |
| 389 void testFutureWhenCompletePreValue() { |
| 390 asyncStart(); |
| 391 int counter = 2; |
| 392 countDown() { |
| 393 if (--counter == 0) asyncEnd(); |
| 394 } |
| 395 |
| 396 var completer = new Completer(); |
| 397 Future future = completer.future; |
| 398 completer.complete(42); |
| 399 Timer.run(() { |
| 400 Future later = future.whenComplete(countDown); |
| 401 later.then((v) { |
| 402 Expect.equals(42, v); |
| 403 countDown(); |
| 404 }); |
| 405 }); |
| 406 } |
| 407 |
| 408 void testFutureWhenValueFutureValue() { |
| 409 asyncStart(); |
| 410 int counter = 3; |
| 411 countDown(int expect) { |
| 412 Expect.equals(expect, counter); |
| 413 if (--counter == 0) asyncEnd(); |
| 414 } |
| 415 |
| 416 var completer = new Completer(); |
| 417 completer.future.whenComplete(() { |
| 418 countDown(3); |
| 419 var completer2 = new Completer(); |
| 420 new Timer(MS * 10, () { |
| 421 countDown(2); |
| 422 completer2.complete(37); |
| 423 }); |
| 424 return completer2.future; |
| 425 }).then((v) { |
| 426 Expect.equals(42, v); |
| 427 countDown(1); |
| 428 }); |
| 429 |
| 430 completer.complete(42); |
| 431 } |
| 432 |
| 433 void testFutureWhenValueFutureError() { |
| 434 asyncStart(); |
| 435 int counter = 3; |
| 436 countDown(int expect) { |
| 437 Expect.equals(expect, counter); |
| 438 if (--counter == 0) asyncEnd(); |
| 439 } |
| 440 |
| 441 var completer = new Completer(); |
| 442 completer.future.whenComplete(() { |
| 443 countDown(3); |
| 444 var completer2 = new Completer(); |
| 445 new Timer(MS * 10, () { |
| 446 countDown(2); |
| 447 completer2.completeError("Fail"); |
| 448 }); |
| 449 return completer2.future; |
| 450 }).then((v) { |
| 451 Expect.fail("should fail async"); |
| 452 }, onError: (error) { |
| 453 Expect.equals("Fail", error); |
| 454 countDown(1); |
| 455 }); |
| 456 |
| 457 completer.complete(42); |
| 458 } |
| 459 |
| 460 void testFutureWhenErrorFutureValue() { |
| 461 asyncStart(); |
| 462 int counter = 3; |
| 463 countDown(int expect) { |
| 464 Expect.equals(expect, counter); |
| 465 if (--counter == 0) asyncEnd(); |
| 466 } |
| 467 |
| 468 var completer = new Completer(); |
| 469 completer.future.whenComplete(() { |
| 470 countDown(3); |
| 471 var completer2 = new Completer(); |
| 472 new Timer(MS * 10, () { |
| 473 countDown(2); |
| 474 completer2.complete(37); |
| 475 }); |
| 476 return completer2.future; |
| 477 }).then((v) { |
| 478 Expect.fail("should fail async"); |
| 479 }, onError: (error) { |
| 480 Expect.equals("Error", error); |
| 481 countDown(1); |
| 482 }); |
| 483 |
| 484 completer.completeError("Error"); |
| 485 } |
| 486 |
| 487 void testFutureWhenErrorFutureError() { |
| 488 asyncStart(); |
| 489 int counter = 3; |
| 490 countDown(int expect) { |
| 491 Expect.equals(expect, counter); |
| 492 if (--counter == 0) asyncEnd(); |
| 493 } |
| 494 |
| 495 var completer = new Completer(); |
| 496 completer.future.whenComplete(() { |
| 497 countDown(3); |
| 498 var completer2 = new Completer(); |
| 499 new Timer(MS * 10, () { |
| 500 countDown(2); |
| 501 completer2.completeError("Fail"); |
| 502 }); |
| 503 return completer2.future; |
| 504 }).then((v) { |
| 505 Expect.fail("should fail async"); |
| 506 }, onError: (error) { |
| 507 Expect.equals("Fail", error); |
| 508 countDown(1); |
| 509 }); |
| 510 |
| 511 completer.completeError("Error"); |
| 512 } |
| 513 |
| 514 void testFutureThenThrowsAsync() { |
| 515 final completer = new Completer<int>(); |
| 516 final future = completer.future; |
| 517 int error = 42; |
| 518 |
| 519 asyncStart(); |
| 520 future.then((v) { |
| 521 throw error; |
| 522 }).catchError((e) { |
| 523 Expect.identical(error, e); |
| 524 asyncEnd(); |
| 525 }); |
| 526 completer.complete(0); |
| 527 } |
| 528 |
| 529 void testFutureCatchThrowsAsync() { |
| 530 final completer = new Completer<int>(); |
| 531 final future = completer.future; |
| 532 int error = 42; |
| 533 |
| 534 asyncStart(); |
| 535 future.catchError((e) { |
| 536 throw error; |
| 537 }).catchError((e) { |
| 538 Expect.identical(error, e); |
| 539 asyncEnd(); |
| 540 }); |
| 541 completer.completeError(0); |
| 542 } |
| 543 |
| 544 void testFutureCatchRethrowsAsync() { |
| 545 final completer = new Completer<int>(); |
| 546 final future = completer.future; |
| 547 var error; |
| 548 |
| 549 asyncStart(); |
| 550 future.catchError((e) { |
| 551 error = e; |
| 552 throw e; |
| 553 }).catchError((e) { |
| 554 Expect.identical(error, e); |
| 555 asyncEnd(); |
| 556 }); |
| 557 completer.completeError(0); |
| 558 } |
| 559 |
| 560 void testFutureWhenThrowsAsync() { |
| 561 final completer = new Completer<int>(); |
| 562 final future = completer.future; |
| 563 var error = 42; |
| 564 |
| 565 asyncStart(); |
| 566 future.whenComplete(() { |
| 567 throw error; |
| 568 }).catchError((e) { |
| 569 Expect.identical(error, e); |
| 570 asyncEnd(); |
| 571 }); |
| 572 completer.complete(0); |
| 573 } |
| 574 |
| 575 void testCompleteWithError() { |
| 576 final completer = new Completer<int>(); |
| 577 final future = completer.future; |
| 578 var error = 42; |
| 579 |
| 580 asyncStart(); |
| 581 future.catchError((e) { |
| 582 Expect.identical(error, e); |
| 583 asyncEnd(); |
| 584 }); |
| 585 |
| 586 completer.completeError(error); |
| 587 } |
| 588 |
| 589 void testCompleteWithFutureSuccess() { |
| 590 asyncStart(); |
| 591 final completer = new Completer<int>(); |
| 592 final completer2 = new Completer<int>(); |
| 593 completer.complete(completer2.future); |
| 594 completer.future.then((v) { |
| 595 Expect.equals(42, v); |
| 596 asyncEnd(); |
| 597 }); |
| 598 completer2.complete(42); |
| 599 } |
| 600 |
| 601 void testCompleteWithFutureSuccess2() { |
| 602 asyncStart(); |
| 603 final completer = new Completer<int>(); |
| 604 Future result = new Future.value(42); |
| 605 completer.complete(result); |
| 606 completer.future.then((v) { |
| 607 Expect.equals(42, v); |
| 608 asyncEnd(); |
| 609 }); |
| 610 } |
| 611 |
| 612 void testCompleteWithFutureError() { |
| 613 asyncStart(); |
| 614 final completer = new Completer<int>(); |
| 615 final completer2 = new Completer<int>(); |
| 616 completer.complete(completer2.future); |
| 617 completer.future.then((v) { |
| 618 Expect.fail("Should not happen"); |
| 619 asyncEnd(); |
| 620 }, onError: (e) { |
| 621 Expect.equals("ERROR-tcwfe", e); |
| 622 asyncEnd(); |
| 623 }); |
| 624 completer2.completeError("ERROR-tcwfe"); |
| 625 } |
| 626 |
| 627 void testCompleteWithFutureError2() { |
| 628 asyncStart(); |
| 629 final completer = new Completer<int>(); |
| 630 Future result = new Future.error("ERROR-tcwfe2"); |
| 631 completer.complete(result); |
| 632 completer.future.then((v) { |
| 633 Expect.fail("Should not happen"); |
| 634 asyncEnd(); |
| 635 }, onError: (e) { |
| 636 Expect.equals("ERROR-tcwfe2", e); |
| 637 asyncEnd(); |
| 638 }); |
| 639 } |
| 640 |
| 641 void testCompleteErrorWithFuture() { |
| 642 asyncStart(); |
| 643 final completer = new Completer<int>(); |
| 644 completer.completeError(new Future.value(42)); |
| 645 completer.future.then((_) { |
| 646 Expect.fail("Shouldn't happen"); |
| 647 }, onError: (e, s) { |
| 648 Future f = e; |
| 649 f.then((v) { |
| 650 Expect.equals(42, v); |
| 651 asyncEnd(); |
| 652 }); |
| 653 }); |
| 654 } |
| 655 |
| 656 void testCompleteWithCustomFutureSuccess() { |
| 657 asyncStart(); |
| 658 final completer = new Completer<int>(); |
| 659 final completer2 = new Completer<int>(); |
| 660 completer.complete(new CustomFuture(completer2.future)); |
| 661 completer.future.then((v) { |
| 662 Expect.equals(42, v); |
| 663 asyncEnd(); |
| 664 }); |
| 665 completer2.complete(42); |
| 666 } |
| 667 |
| 668 void testCompleteWithCustomFutureError() { |
| 669 asyncStart(); |
| 670 final completer = new Completer<int>(); |
| 671 final completer2 = new Completer<int>(); |
| 672 completer.complete(new CustomFuture(completer2.future)); |
| 673 completer.future.then((v) { |
| 674 Expect.fail("Should not happen"); |
| 675 asyncEnd(); |
| 676 }, onError: (e) { |
| 677 Expect.equals("ERROR-tcwcfe", e); |
| 678 asyncEnd(); |
| 679 }); |
| 680 completer2.completeError("ERROR-tcwcfe"); |
| 681 } |
| 682 |
| 683 void testCompleteErrorWithCustomFuture() { |
| 684 asyncStart(); |
| 685 final completer = new Completer<int>(); |
| 686 var future = new CustomFuture(new Future.value(42)); |
| 687 completer.completeError(future); |
| 688 completer.future.then((_) { |
| 689 Expect.fail("Shouldn't happen"); |
| 690 }, onError: (Future f) { |
| 691 f.then((v) { |
| 692 Expect.equals(42, v); |
| 693 asyncEnd(); |
| 694 }); |
| 695 }); |
| 696 } |
| 697 |
| 698 void testCompleteErrorWithNull() { |
| 699 asyncStart(); |
| 700 final completer = new Completer<int>(); |
| 701 completer.future.catchError((e) { |
| 702 Expect.isTrue(e is NullThrownError); |
| 703 asyncEnd(); |
| 704 }); |
| 705 completer.completeError(null); |
| 706 } |
| 707 |
| 708 void testChainedFutureValue() { |
| 709 final completer = new Completer(); |
| 710 final future = completer.future; |
| 711 asyncStart(); |
| 712 |
| 713 future.then((v) => new Future.value(v * 2)).then((v) { |
| 714 Expect.equals(42, v); |
| 715 asyncEnd(); |
| 716 }); |
| 717 completer.complete(21); |
| 718 } |
| 719 |
| 720 void testChainedFutureValueDelay() { |
| 721 final completer = new Completer(); |
| 722 final future = completer.future; |
| 723 asyncStart(); |
| 724 |
| 725 future |
| 726 .then((v) => |
| 727 new Future.delayed(const Duration(milliseconds: 10), () => v * 2)) |
| 728 .then((v) { |
| 729 Expect.equals(42, v); |
| 730 asyncEnd(); |
| 731 }); |
| 732 completer.complete(21); |
| 733 } |
| 734 |
| 735 void testChainedFutureValue2Delay() { |
| 736 asyncStart(); |
| 737 |
| 738 new Future.delayed(const Duration(milliseconds: 10)).then((v) { |
| 739 Expect.isNull(v); |
| 740 asyncEnd(); |
| 741 }); |
| 742 } |
| 743 |
| 744 void testChainedFutureError() { |
| 745 final completer = new Completer(); |
| 746 final future = completer.future; |
| 747 asyncStart(); |
| 748 |
| 749 future.then((v) => new Future.error("Fehler")).then((v) { |
| 750 Expect.fail("unreachable!"); |
| 751 }, onError: (error) { |
| 752 Expect.equals("Fehler", error); |
| 753 asyncEnd(); |
| 754 }); |
| 755 completer.complete(21); |
| 756 } |
| 757 |
| 758 void testSyncFuture_i13368() { |
| 759 asyncStart(); |
| 760 |
| 761 final future = new Future<int>.sync(() { |
| 762 return new Future<int>.value(42); |
| 763 }); |
| 764 |
| 765 future.then((int val) { |
| 766 Expect.equals(val, 42); |
| 767 asyncEnd(); |
| 768 }); |
| 769 } |
| 770 |
| 771 void testWaitCleanUp() { |
| 772 asyncStart(); |
| 773 // Creates three futures with different completion times, and where some fail. |
| 774 // The `mask` specifies which futures fail (values 1-7), |
| 775 // and `permute` defines the order of completion. values 0-5. |
| 776 void doTest(int mask, int permute) { |
| 777 asyncStart(); |
| 778 String stringId = "waitCleanup-$mask-$permute"; |
| 779 List futures = new List(3); |
| 780 List cleanup = new List(3); |
| 781 int permuteTmp = permute; |
| 782 for (int i = 0; i < 3; i++) { |
| 783 bool throws = (mask & (1 << i)) != 0; |
| 784 var future = new Future.delayed(new Duration(milliseconds: 100 * (i + 1)), |
| 785 () => (throws ? throw "Error $i($mask-$permute)" : i)); |
| 786 int mod = 3 - i; |
| 787 int position = permuteTmp % mod; |
| 788 permuteTmp = permuteTmp ~/ mod; |
| 789 while (futures[position] != null) position++; |
| 790 futures[position] = future; |
| 791 cleanup[i] = throws; |
| 792 } |
| 793 void cleanUp(index) { |
| 794 Expect.isFalse(cleanup[index]); |
| 795 cleanup[index] = true; |
| 796 } |
| 797 |
| 798 Future.wait(futures, cleanUp: cleanUp).then((_) { |
| 799 Expect.fail("No error: $stringId"); |
| 800 }, onError: (e, s) { |
| 801 Expect.listEquals([true, true, true], cleanup); |
| 802 asyncEnd(); |
| 803 }); |
| 804 } |
| 805 |
| 806 for (int i = 1; i < 8; i++) { |
| 807 for (int j = 0; j < 6; j++) { |
| 808 doTest(i, j); |
| 809 } |
| 810 } |
| 811 asyncEnd(); |
| 812 } |
| 813 |
| 814 void testWaitCleanUpEager() { |
| 815 asyncStart(); |
| 816 // Creates three futures with different completion times, and where some fail. |
| 817 // The `mask` specifies which futures fail (values 1-7), |
| 818 // and `permute` defines the order of completion. values 0-5. |
| 819 void doTest(int mask, int permute) { |
| 820 asyncStart(); |
| 821 asyncStart(); |
| 822 bool done = false; |
| 823 String stringId = "waitCleanup-$mask-$permute"; |
| 824 List futures = new List(3); |
| 825 List cleanup = new List(3); |
| 826 int permuteTmp = permute; |
| 827 for (int i = 0; i < 3; i++) { |
| 828 bool throws = (mask & (1 << i)) != 0; |
| 829 var future = new Future.delayed(new Duration(milliseconds: 100 * (i + 1)), |
| 830 () => (throws ? throw "Error $i($mask-$permute)" : i)); |
| 831 int mod = 3 - i; |
| 832 int position = permuteTmp % mod; |
| 833 permuteTmp = permuteTmp ~/ mod; |
| 834 while (futures[position] != null) position++; |
| 835 futures[position] = future; |
| 836 cleanup[i] = throws; |
| 837 } |
| 838 void checkDone() { |
| 839 if (done) return; |
| 840 if (cleanup.every((v) => v)) { |
| 841 done = true; |
| 842 asyncEnd(); |
| 843 } |
| 844 } |
| 845 |
| 846 void cleanUp(index) { |
| 847 Expect.isFalse(cleanup[index]); |
| 848 cleanup[index] = true; |
| 849 // Cleanup might happen before and after the wait().then() callback. |
| 850 checkDone(); |
| 851 } |
| 852 |
| 853 Future.wait(futures, eagerError: true, cleanUp: cleanUp).then((_) { |
| 854 Expect.fail("No error: $stringId"); |
| 855 }, onError: (e, s) { |
| 856 asyncEnd(); |
| 857 checkDone(); |
| 858 }); |
| 859 } |
| 860 |
| 861 for (int i = 1; i < 8; i++) { |
| 862 for (int j = 0; j < 6; j++) { |
| 863 doTest(i, j); |
| 864 } |
| 865 } |
| 866 asyncEnd(); |
| 867 } |
| 868 |
| 869 void testWaitCleanUpError() { |
| 870 var cms = const Duration(milliseconds: 100); |
| 871 var cleanups = new List.filled(3, false); |
| 872 var uncaughts = new List.filled(3, false); |
| 873 asyncStart(); |
| 874 asyncStart(); |
| 875 asyncStart(); |
| 876 runZoned(() { |
| 877 Future.wait([ |
| 878 new Future.delayed(cms, () => 0), |
| 879 new Future.delayed(cms * 2, () => throw 1), |
| 880 new Future.delayed(cms * 3, () => 2) |
| 881 ], cleanUp: (index) { |
| 882 Expect.isTrue(index == 0 || index == 2, "$index"); |
| 883 Expect.isFalse(cleanups[index]); |
| 884 cleanups[index] = true; |
| 885 throw index; |
| 886 }).catchError((e) { |
| 887 Expect.equals(e, 1); |
| 888 asyncEnd(); |
| 889 }); |
| 890 }, onError: (int index, s) { |
| 891 Expect.isTrue(index == 0 || index == 2, "$index"); |
| 892 Expect.isFalse(uncaughts[index]); |
| 893 uncaughts[index] = true; |
| 894 asyncEnd(); |
| 895 }); |
| 896 } |
| 897 |
| 898 void testWaitSyncError() { |
| 899 var cms = const Duration(milliseconds: 100); |
| 900 var cleanups = new List.filled(3, false); |
| 901 asyncStart(); |
| 902 asyncStart(); |
| 903 runZoned(() { |
| 904 Future.wait( |
| 905 new Iterable.generate(5, (i) { |
| 906 if (i != 3) return new Future.delayed(cms * (i + 1), () => i); |
| 907 throw "throwing synchronously in iterable"; |
| 908 }), cleanUp: (index) { |
| 909 Expect.isFalse(cleanups[index]); |
| 910 cleanups[index] = true; |
| 911 if (cleanups.every((x) => x)) asyncEnd(); |
| 912 }); |
| 913 }, onError: (e, s) { |
| 914 asyncEnd(); |
| 915 }); |
| 916 } |
| 917 |
| 918 void testWaitSyncError2() { |
| 919 asyncStart(); |
| 920 Future.wait([null]).catchError((e, st) { |
| 921 // Makes sure that the `catchError` is invoked. |
| 922 // Regression test: an earlier version of `Future.wait` would propagate |
| 923 // the error too soon for the code to install an error handler. |
| 924 // `testWaitSyncError` didn't show this problem, because the `runZoned` |
| 925 // was already installed. |
| 926 asyncEnd(); |
| 927 }); |
| 928 } |
| 929 |
| 930 // Future.wait transforms synchronous errors into asynchronous ones. |
| 931 // This function tests that zones can intercept them. |
| 932 void testWaitSyncError3() { |
| 933 var caughtError; |
| 934 var count = 0; |
| 935 |
| 936 AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, |
| 937 Object error, StackTrace stackTrace) { |
| 938 Expect.equals(0, count); |
| 939 count++; |
| 940 caughtError = error; |
| 941 return parent.errorCallback(zone, error, stackTrace); |
| 942 } |
| 943 |
| 944 asyncStart(); |
| 945 runZoned(() { |
| 946 Future.wait([null]).catchError((e, st) { |
| 947 Expect.identical(e, caughtError); |
| 948 Expect.equals(1, count); |
| 949 asyncEnd(); |
| 950 }); |
| 951 }, zoneSpecification: new ZoneSpecification(errorCallback: errorCallback)); |
| 952 } |
| 953 |
| 954 void testBadFuture() { |
| 955 var bad = new BadFuture(); |
| 956 // Completing with bad future (then call throws) puts error in result. |
| 957 asyncStart(); |
| 958 Completer completer = new Completer(); |
| 959 completer.complete(bad); |
| 960 completer.future.then((_) { |
| 961 Expect.fail("unreachable"); |
| 962 }, onError: (e, s) { |
| 963 Expect.isTrue(completer.isCompleted); |
| 964 asyncEnd(); |
| 965 }); |
| 966 |
| 967 asyncStart(); |
| 968 var f = new Future.value().then((_) => bad); |
| 969 f.then((_) { |
| 970 Expect.fail("unreachable"); |
| 971 }, onError: (e, s) { |
| 972 asyncEnd(); |
| 973 }); |
| 974 } |
| 975 |
| 976 void testTypes() { |
| 977 // Test that future is a Future<int> and not something less precise. |
| 978 testType(name, future, [depth = 2]) { |
| 979 var desc = "$name${".whenComplete"*(2-depth)}"; |
| 980 Expect.isTrue(future is Future<int>, "$desc is Future<int>"); |
| 981 Expect.isFalse(future is Future<String>, "$desc is! Future<String>"); |
| 982 var stream = future.asStream(); |
| 983 Expect.isTrue(stream is Stream<int>, "$desc.asStream() is Stream<int>"); |
| 984 Expect.isFalse( |
| 985 stream is Stream<String>, "$desc.asStream() is! Stream<String>"); |
| 986 if (depth > 0) { |
| 987 testType(name, future.whenComplete(() {}), depth - 1); |
| 988 } |
| 989 } |
| 990 |
| 991 for (var value in [42, null]) { |
| 992 testType("Future($value)", new Future<int>(() => value)); |
| 993 testType("Future.delayed($value)", |
| 994 new Future<int>.delayed(Duration.ZERO, () => value)); |
| 995 testType( |
| 996 "Future.microtask($value)", new Future<int>.microtask(() => value)); |
| 997 testType("Future.sync($value)", new Future<int>.sync(() => value)); //# 01:
ok |
| 998 testType("Future.sync(future($value))", // //# 01:
continued |
| 999 new Future<int>.sync(() => new Future<int>.value(value))); //# 01:
continued |
| 1000 testType("Future.value($value)", new Future<int>.value(value)); |
| 1001 } |
| 1002 testType("Completer.future", new Completer<int>().future); |
| 1003 testType("Future.error", new Future<int>.error("ERR")..catchError((_) {})); |
| 1004 } |
| 1005 |
| 1006 void testAnyValue() { |
| 1007 asyncStart(); |
| 1008 var cs = new List.generate(3, (_) => new Completer()); |
| 1009 var result = Future.any(cs.map((x) => x.future)); |
| 1010 |
| 1011 result.then((v) { |
| 1012 Expect.equals(42, v); |
| 1013 asyncEnd(); |
| 1014 }, onError: (e, s) { |
| 1015 Expect.fail("Unexpected error: $e"); |
| 1016 }); |
| 1017 |
| 1018 cs[1].complete(42); |
| 1019 cs[2].complete(10); |
| 1020 cs[0].complete(20); |
| 1021 } |
| 1022 |
| 1023 void testAnyError() { |
| 1024 asyncStart(); |
| 1025 var cs = new List.generate(3, (_) => new Completer()); |
| 1026 var result = Future.any(cs.map((x) => x.future)); |
| 1027 |
| 1028 result.then((v) { |
| 1029 Expect.fail("Unexpected value: $v"); |
| 1030 }, onError: (e, s) { |
| 1031 Expect.equals(42, e); |
| 1032 asyncEnd(); |
| 1033 }); |
| 1034 |
| 1035 cs[1].completeError(42); |
| 1036 cs[2].complete(10); |
| 1037 cs[0].complete(20); |
| 1038 } |
| 1039 |
| 1040 void testAnyIgnoreIncomplete() { |
| 1041 asyncStart(); |
| 1042 var cs = new List.generate(3, (_) => new Completer()); |
| 1043 var result = Future.any(cs.map((x) => x.future)); |
| 1044 |
| 1045 result.then((v) { |
| 1046 Expect.equals(42, v); |
| 1047 asyncEnd(); |
| 1048 }, onError: (e, s) { |
| 1049 Expect.fail("Unexpected error: $e"); |
| 1050 }); |
| 1051 |
| 1052 cs[1].complete(42); |
| 1053 // The other two futures never complete. |
| 1054 } |
| 1055 |
| 1056 void testAnyIgnoreError() { |
| 1057 asyncStart(); |
| 1058 var cs = new List.generate(3, (_) => new Completer()); |
| 1059 var result = Future.any(cs.map((x) => x.future)); |
| 1060 |
| 1061 result.then((v) { |
| 1062 Expect.equals(42, v); |
| 1063 asyncEnd(); |
| 1064 }, onError: (e, s) { |
| 1065 Expect.fail("Unexpected error: $e"); |
| 1066 }); |
| 1067 |
| 1068 cs[1].complete(42); |
| 1069 // The errors are ignored, not uncaught. |
| 1070 cs[2].completeError("BAD"); |
| 1071 cs[0].completeError("BAD"); |
| 1072 } |
| 1073 |
| 1074 void testFutureResult() { |
| 1075 asyncStart(); |
| 1076 () async { |
| 1077 var f = new UglyFuture(5); |
| 1078 // Sanity check that our future is as mis-behaved as we think. |
| 1079 f.then((v) { |
| 1080 Expect.isTrue(v is Future); |
| 1081 }); |
| 1082 |
| 1083 var v = await f; |
| 1084 // The static type of await is Flatten(static-type-of-expression), so it |
| 1085 // suggests that it flattens. In practice it currently doesn't. |
| 1086 // The specification doesn't say anything special, so v should be the |
| 1087 // completion value of the UglyFuture future which is a future. |
| 1088 Expect.isTrue(v is Future); |
| 1089 |
| 1090 // This used to hit an assert in checked mode. |
| 1091 // The CL adding this test changed the behavior to actually flatten the |
| 1092 // the future returned by the then-callback. |
| 1093 var w = new Future.value(42).then((_) => f); |
| 1094 Expect.equals(42, await w); |
| 1095 asyncEnd(); |
| 1096 }(); |
| 1097 } |
| 1098 |
| 1099 main() { |
| 1100 asyncStart(); |
| 1101 |
| 1102 testValue(); |
| 1103 testSync(); |
| 1104 testNeverComplete(); |
| 1105 |
| 1106 testComplete(); |
| 1107 testCompleteWithSuccessHandlerBeforeComplete(); |
| 1108 testCompleteWithSuccessHandlerAfterComplete(); |
| 1109 testCompleteManySuccessHandlers(); |
| 1110 testCompleteWithError(); |
| 1111 |
| 1112 testCompleteWithFutureSuccess(); |
| 1113 testCompleteWithFutureSuccess2(); |
| 1114 testCompleteWithFutureError(); |
| 1115 testCompleteWithFutureError2(); |
| 1116 testCompleteErrorWithFuture(); |
| 1117 testCompleteWithCustomFutureSuccess(); |
| 1118 testCompleteWithCustomFutureError(); |
| 1119 testCompleteErrorWithCustomFuture(); |
| 1120 testCompleteErrorWithNull(); |
| 1121 |
| 1122 testException(); |
| 1123 testExceptionHandler(); |
| 1124 testExceptionHandlerReturnsTrue(); |
| 1125 testExceptionHandlerReturnsTrue2(); |
| 1126 testExceptionHandlerReturnsFalse(); |
| 1127 |
| 1128 testFutureAsStreamCompleteAfter(); |
| 1129 testFutureAsStreamCompleteBefore(); |
| 1130 testFutureAsStreamCompleteImmediate(); |
| 1131 testFutureAsStreamCompleteErrorAfter(); |
| 1132 testFutureAsStreamWrapper(); |
| 1133 |
| 1134 testFutureWhenCompleteValue(); |
| 1135 testFutureWhenCompleteError(); |
| 1136 testFutureWhenCompleteValueNewError(); |
| 1137 testFutureWhenCompleteErrorNewError(); |
| 1138 |
| 1139 testFutureWhenValueFutureValue(); |
| 1140 testFutureWhenErrorFutureValue(); |
| 1141 testFutureWhenValueFutureError(); |
| 1142 testFutureWhenErrorFutureError(); |
| 1143 |
| 1144 testFutureThenThrowsAsync(); |
| 1145 testFutureCatchThrowsAsync(); |
| 1146 testFutureWhenThrowsAsync(); |
| 1147 testFutureCatchRethrowsAsync(); |
| 1148 |
| 1149 testChainedFutureValue(); |
| 1150 testChainedFutureValueDelay(); |
| 1151 testChainedFutureError(); |
| 1152 |
| 1153 testSyncFuture_i13368(); |
| 1154 |
| 1155 testWaitCleanUp(); |
| 1156 testWaitCleanUpError(); |
| 1157 testWaitSyncError(); |
| 1158 testWaitSyncError2(); |
| 1159 testWaitSyncError3(); |
| 1160 |
| 1161 testBadFuture(); |
| 1162 |
| 1163 testTypes(); |
| 1164 |
| 1165 testAnyValue(); |
| 1166 testAnyError(); |
| 1167 testAnyIgnoreIncomplete(); |
| 1168 testAnyIgnoreError(); |
| 1169 |
| 1170 testFutureResult(); |
| 1171 |
| 1172 asyncEnd(); |
| 1173 } |
| 1174 |
| 1175 /// A well-behaved Future that isn't recognizable as a _Future. |
| 1176 class CustomFuture<T> implements Future<T> { |
| 1177 Future _realFuture; |
| 1178 CustomFuture(this._realFuture); |
| 1179 Future then(action(result), {Function onError}) => |
| 1180 _realFuture.then(action, onError: onError); |
| 1181 Future catchError(Function onError, {bool test(e)}) => |
| 1182 _realFuture.catchError(onError, test: test); |
| 1183 Future whenComplete(action()) => _realFuture.whenComplete(action); |
| 1184 Future timeout(Duration timeLimit, {void onTimeout()}) => |
| 1185 _realFuture.timeout(timeLimit, onTimeout: onTimeout); |
| 1186 Stream asStream() => _realFuture.asStream(); |
| 1187 String toString() => "CustomFuture@${_realFuture.hashCode}"; |
| 1188 int get hashCode => _realFuture.hashCode; |
| 1189 } |
| 1190 |
| 1191 /// A bad future that throws on every method. |
| 1192 class BadFuture<T> implements Future<T> { |
| 1193 Future then(action(T result), {Function onError}) { |
| 1194 throw "then GOTCHA!"; |
| 1195 } |
| 1196 |
| 1197 Future catchError(Function onError, {bool test(e)}) { |
| 1198 throw "catch GOTCHA!"; |
| 1199 } |
| 1200 |
| 1201 Future whenComplete(action()) { |
| 1202 throw "finally GOTCHA!"; |
| 1203 } |
| 1204 |
| 1205 Stream<T> asStream() { |
| 1206 throw "asStream GOTCHA!"; |
| 1207 } |
| 1208 |
| 1209 Future timeout(Duration duration, {onTimeout()}) { |
| 1210 throw "timeout GOTCHA!"; |
| 1211 } |
| 1212 } |
| 1213 |
| 1214 // An evil future that completes with another future. |
| 1215 class UglyFuture implements Future<dynamic> { |
| 1216 final _result; |
| 1217 UglyFuture(int badness) |
| 1218 : _result = (badness == 0) ? 42 : new UglyFuture(badness - 1); |
| 1219 Future then(action(value), {onError(error, StackTrace stack)}) { |
| 1220 var c = new Completer(); |
| 1221 c.complete(new Future.microtask(() => action(_result))); |
| 1222 return c.future; |
| 1223 } |
| 1224 |
| 1225 Future catchError(onError, {test}) => this; // Never an error. |
| 1226 Future whenComplete(action()) { |
| 1227 return new Future.microtask(action).then((_) => this); |
| 1228 } |
| 1229 |
| 1230 Stream asStream() { |
| 1231 return (new StreamController() |
| 1232 ..add(_result) |
| 1233 ..close()) |
| 1234 .stream; |
| 1235 } |
| 1236 |
| 1237 Future timeout(Duration duration, {onTimeout()}) { |
| 1238 return this; |
| 1239 } |
| 1240 } |
OLD | NEW |