Index: tests/lib/async/future_test.dart |
diff --git a/tests/lib/async/future_test.dart b/tests/lib/async/future_test.dart |
deleted file mode 100644 |
index 4c46e3f79c94230c15da2e6a59c30e340e724c79..0000000000000000000000000000000000000000 |
--- a/tests/lib/async/future_test.dart |
+++ /dev/null |
@@ -1,1240 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library future_test; |
- |
-import 'package:async_helper/async_helper.dart'; |
-import "package:expect/expect.dart"; |
-import 'dart:async'; |
- |
-const Duration MS = const Duration(milliseconds: 1); |
- |
-void testValue() { |
- final future = new Future<String>.value("42"); |
- asyncStart(); |
- future.then((x) { |
- Expect.equals("42", x); |
- asyncEnd(); |
- }); |
-} |
- |
-void testSync() { |
- compare(func) { |
- // Compare the results of the following two futures. |
- Future f1 = new Future.sync(func); |
- Future f2 = new Future.value().then((_) => func()); |
- f2.catchError((_) {}); // I'll get the error later. |
- f1.then((v1) { |
- f2.then((v2) { |
- Expect.equals(v1, v2); |
- }); |
- }, onError: (e1) { |
- f2.then((_) { |
- Expect.fail("Expected error"); |
- }, onError: (e2) { |
- Expect.equals(e1, e2); |
- }); |
- }); |
- } |
- |
- Future val = new Future.value(42); |
- Future err1 = new Future.error("Error")..catchError((_) {}); |
- try { |
- throw new List(0); |
- } catch (e, st) { |
- Future err2 = new Future.error(e, st)..catchError((_) {}); |
- } |
- compare(() => 42); |
- compare(() => val); |
- compare(() { |
- throw "Flif"; |
- }); |
- compare(() => err1); |
- bool hasExecuted = false; |
- compare(() { |
- hasExecuted = true; |
- return 499; |
- }); |
- Expect.isTrue(hasExecuted); |
-} |
- |
-void testNeverComplete() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- future.then((v) => Expect.fail("Value not expected")); |
- future.catchError((e) => Expect.fail("Value not expected")); |
-} |
- |
-void testComplete() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- Expect.isFalse(completer.isCompleted); |
- |
- completer.complete(3); |
- Expect.isTrue(completer.isCompleted); |
- |
- future.then((v) => Expect.equals(3, v)); |
-} |
- |
-// Tests for [then] |
- |
-void testCompleteWithSuccessHandlerBeforeComplete() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- |
- int after; |
- |
- asyncStart(); |
- future.then((int v) { |
- after = v; |
- }).then((_) { |
- Expect.equals(3, after); |
- asyncEnd(); |
- }); |
- |
- completer.complete(3); |
- Expect.isNull(after); |
-} |
- |
-void testCompleteWithSuccessHandlerAfterComplete() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- |
- int after; |
- completer.complete(3); |
- Expect.isNull(after); |
- |
- asyncStart(); |
- future.then((int v) { |
- after = v; |
- }).then((_) { |
- Expect.equals(3, after); |
- asyncEnd(); |
- }); |
-} |
- |
-void testCompleteManySuccessHandlers() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- int before; |
- int after1; |
- int after2; |
- |
- var futures = []; |
- futures.add(future.then((int v) { |
- before = v; |
- })); |
- completer.complete(3); |
- futures.add(future.then((int v) { |
- after1 = v; |
- })); |
- futures.add(future.then((int v) { |
- after2 = v; |
- })); |
- |
- asyncStart(); |
- Future.wait(futures).then((_) { |
- Expect.equals(3, before); |
- Expect.equals(3, after1); |
- Expect.equals(3, after2); |
- asyncEnd(); |
- }); |
-} |
- |
-// Tests for [catchError] |
- |
-void testException() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- final ex = new Exception(); |
- |
- asyncStart(); |
- future.then((v) { |
- throw "Value not expected"; |
- }).catchError((error) { |
- Expect.equals(error, ex); |
- asyncEnd(); |
- }, test: (e) => e == ex); |
- completer.completeError(ex); |
-} |
- |
-void testExceptionHandler() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- final ex = new Exception(); |
- |
- var ex2; |
- var done = future.catchError((error) { |
- ex2 = error; |
- }); |
- |
- Expect.isFalse(completer.isCompleted); |
- completer.completeError(ex); |
- Expect.isTrue(completer.isCompleted); |
- |
- asyncStart(); |
- done.then((_) { |
- Expect.equals(ex, ex2); |
- asyncEnd(); |
- }); |
-} |
- |
-void testExceptionHandlerReturnsTrue() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- final ex = new Exception(); |
- |
- bool reached = false; |
- future.catchError((e) {}); |
- future.catchError((e) { |
- reached = true; |
- }, test: (e) => false).catchError((e) {}); |
- Expect.isFalse(completer.isCompleted); |
- completer.completeError(ex); |
- Expect.isTrue(completer.isCompleted); |
- Expect.isFalse(reached); |
-} |
- |
-void testExceptionHandlerReturnsTrue2() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- final ex = new Exception(); |
- |
- bool reached = false; |
- var done = future.catchError((e) {}, test: (e) => false).catchError((e) { |
- reached = true; |
- }); |
- completer.completeError(ex); |
- |
- asyncStart(); |
- done.then((_) { |
- Expect.isTrue(reached); |
- asyncEnd(); |
- }); |
-} |
- |
-void testExceptionHandlerReturnsFalse() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- final ex = new Exception(); |
- |
- bool reached = false; |
- |
- future.catchError((e) {}); |
- |
- future.catchError((e) { |
- reached = true; |
- }, test: (e) => false).catchError((e) {}); |
- |
- completer.completeError(ex); |
- |
- Expect.isFalse(reached); |
-} |
- |
-void testFutureAsStreamCompleteAfter() { |
- var completer = new Completer(); |
- bool gotValue = false; |
- asyncStart(); |
- completer.future.asStream().listen((data) { |
- Expect.isFalse(gotValue); |
- gotValue = true; |
- Expect.equals("value", data); |
- }, onDone: () { |
- Expect.isTrue(gotValue); |
- asyncEnd(); |
- }); |
- completer.complete("value"); |
-} |
- |
-void testFutureAsStreamCompleteBefore() { |
- var completer = new Completer(); |
- bool gotValue = false; |
- asyncStart(); |
- completer.complete("value"); |
- completer.future.asStream().listen((data) { |
- Expect.isFalse(gotValue); |
- gotValue = true; |
- Expect.equals("value", data); |
- }, onDone: () { |
- Expect.isTrue(gotValue); |
- asyncEnd(); |
- }); |
-} |
- |
-void testFutureAsStreamCompleteImmediate() { |
- bool gotValue = false; |
- asyncStart(); |
- new Future.value("value").asStream().listen((data) { |
- Expect.isFalse(gotValue); |
- gotValue = true; |
- Expect.equals("value", data); |
- }, onDone: () { |
- Expect.isTrue(gotValue); |
- asyncEnd(); |
- }); |
-} |
- |
-void testFutureAsStreamCompleteErrorAfter() { |
- var completer = new Completer(); |
- bool gotError = false; |
- asyncStart(); |
- completer.future.asStream().listen((data) { |
- Expect.fail("Unexpected data"); |
- }, onError: (error) { |
- Expect.isFalse(gotError); |
- gotError = true; |
- Expect.equals("error", error); |
- }, onDone: () { |
- Expect.isTrue(gotError); |
- asyncEnd(); |
- }); |
- completer.completeError("error"); |
-} |
- |
-void testFutureAsStreamWrapper() { |
- var completer = new Completer(); |
- bool gotValue = false; |
- asyncStart(); |
- completer.complete("value"); |
- completer.future |
- .catchError((_) { |
- throw "not possible"; |
- }) // Returns a future wrapper. |
- .asStream() |
- .listen((data) { |
- Expect.isFalse(gotValue); |
- gotValue = true; |
- Expect.equals("value", data); |
- }, onDone: () { |
- Expect.isTrue(gotValue); |
- asyncEnd(); |
- }); |
-} |
- |
-void testFutureWhenCompleteValue() { |
- asyncStart(); |
- int counter = 2; |
- countDown() { |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- Future future = completer.future; |
- Future later = future.whenComplete(countDown); |
- later.then((v) { |
- Expect.equals(42, v); |
- countDown(); |
- }); |
- completer.complete(42); |
-} |
- |
-void testFutureWhenCompleteError() { |
- asyncStart(); |
- int counter = 2; |
- countDown() { |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- Future future = completer.future; |
- Future later = future.whenComplete(countDown); |
- later.catchError((error) { |
- Expect.equals("error", error); |
- countDown(); |
- }); |
- completer.completeError("error"); |
-} |
- |
-void testFutureWhenCompleteValueNewError() { |
- asyncStart(); |
- int counter = 2; |
- countDown() { |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- Future future = completer.future; |
- Future later = future.whenComplete(() { |
- countDown(); |
- throw "new error"; |
- }); |
- later.catchError((error) { |
- Expect.equals("new error", error); |
- countDown(); |
- }); |
- completer.complete(42); |
-} |
- |
-void testFutureWhenCompleteErrorNewError() { |
- asyncStart(); |
- int counter = 2; |
- countDown() { |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- Future future = completer.future; |
- Future later = future.whenComplete(() { |
- countDown(); |
- throw "new error"; |
- }); |
- later.catchError((error) { |
- Expect.equals("new error", error); |
- countDown(); |
- }); |
- completer.completeError("error"); |
-} |
- |
-void testFutureWhenCompletePreValue() { |
- asyncStart(); |
- int counter = 2; |
- countDown() { |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- Future future = completer.future; |
- completer.complete(42); |
- Timer.run(() { |
- Future later = future.whenComplete(countDown); |
- later.then((v) { |
- Expect.equals(42, v); |
- countDown(); |
- }); |
- }); |
-} |
- |
-void testFutureWhenValueFutureValue() { |
- asyncStart(); |
- int counter = 3; |
- countDown(int expect) { |
- Expect.equals(expect, counter); |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- completer.future.whenComplete(() { |
- countDown(3); |
- var completer2 = new Completer(); |
- new Timer(MS * 10, () { |
- countDown(2); |
- completer2.complete(37); |
- }); |
- return completer2.future; |
- }).then((v) { |
- Expect.equals(42, v); |
- countDown(1); |
- }); |
- |
- completer.complete(42); |
-} |
- |
-void testFutureWhenValueFutureError() { |
- asyncStart(); |
- int counter = 3; |
- countDown(int expect) { |
- Expect.equals(expect, counter); |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- completer.future.whenComplete(() { |
- countDown(3); |
- var completer2 = new Completer(); |
- new Timer(MS * 10, () { |
- countDown(2); |
- completer2.completeError("Fail"); |
- }); |
- return completer2.future; |
- }).then((v) { |
- Expect.fail("should fail async"); |
- }, onError: (error) { |
- Expect.equals("Fail", error); |
- countDown(1); |
- }); |
- |
- completer.complete(42); |
-} |
- |
-void testFutureWhenErrorFutureValue() { |
- asyncStart(); |
- int counter = 3; |
- countDown(int expect) { |
- Expect.equals(expect, counter); |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- completer.future.whenComplete(() { |
- countDown(3); |
- var completer2 = new Completer(); |
- new Timer(MS * 10, () { |
- countDown(2); |
- completer2.complete(37); |
- }); |
- return completer2.future; |
- }).then((v) { |
- Expect.fail("should fail async"); |
- }, onError: (error) { |
- Expect.equals("Error", error); |
- countDown(1); |
- }); |
- |
- completer.completeError("Error"); |
-} |
- |
-void testFutureWhenErrorFutureError() { |
- asyncStart(); |
- int counter = 3; |
- countDown(int expect) { |
- Expect.equals(expect, counter); |
- if (--counter == 0) asyncEnd(); |
- } |
- |
- var completer = new Completer(); |
- completer.future.whenComplete(() { |
- countDown(3); |
- var completer2 = new Completer(); |
- new Timer(MS * 10, () { |
- countDown(2); |
- completer2.completeError("Fail"); |
- }); |
- return completer2.future; |
- }).then((v) { |
- Expect.fail("should fail async"); |
- }, onError: (error) { |
- Expect.equals("Fail", error); |
- countDown(1); |
- }); |
- |
- completer.completeError("Error"); |
-} |
- |
-void testFutureThenThrowsAsync() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- int error = 42; |
- |
- asyncStart(); |
- future.then((v) { |
- throw error; |
- }).catchError((e) { |
- Expect.identical(error, e); |
- asyncEnd(); |
- }); |
- completer.complete(0); |
-} |
- |
-void testFutureCatchThrowsAsync() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- int error = 42; |
- |
- asyncStart(); |
- future.catchError((e) { |
- throw error; |
- }).catchError((e) { |
- Expect.identical(error, e); |
- asyncEnd(); |
- }); |
- completer.completeError(0); |
-} |
- |
-void testFutureCatchRethrowsAsync() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- var error; |
- |
- asyncStart(); |
- future.catchError((e) { |
- error = e; |
- throw e; |
- }).catchError((e) { |
- Expect.identical(error, e); |
- asyncEnd(); |
- }); |
- completer.completeError(0); |
-} |
- |
-void testFutureWhenThrowsAsync() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- var error = 42; |
- |
- asyncStart(); |
- future.whenComplete(() { |
- throw error; |
- }).catchError((e) { |
- Expect.identical(error, e); |
- asyncEnd(); |
- }); |
- completer.complete(0); |
-} |
- |
-void testCompleteWithError() { |
- final completer = new Completer<int>(); |
- final future = completer.future; |
- var error = 42; |
- |
- asyncStart(); |
- future.catchError((e) { |
- Expect.identical(error, e); |
- asyncEnd(); |
- }); |
- |
- completer.completeError(error); |
-} |
- |
-void testCompleteWithFutureSuccess() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- final completer2 = new Completer<int>(); |
- completer.complete(completer2.future); |
- completer.future.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- completer2.complete(42); |
-} |
- |
-void testCompleteWithFutureSuccess2() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- Future result = new Future.value(42); |
- completer.complete(result); |
- completer.future.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
-} |
- |
-void testCompleteWithFutureError() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- final completer2 = new Completer<int>(); |
- completer.complete(completer2.future); |
- completer.future.then((v) { |
- Expect.fail("Should not happen"); |
- asyncEnd(); |
- }, onError: (e) { |
- Expect.equals("ERROR-tcwfe", e); |
- asyncEnd(); |
- }); |
- completer2.completeError("ERROR-tcwfe"); |
-} |
- |
-void testCompleteWithFutureError2() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- Future result = new Future.error("ERROR-tcwfe2"); |
- completer.complete(result); |
- completer.future.then((v) { |
- Expect.fail("Should not happen"); |
- asyncEnd(); |
- }, onError: (e) { |
- Expect.equals("ERROR-tcwfe2", e); |
- asyncEnd(); |
- }); |
-} |
- |
-void testCompleteErrorWithFuture() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- completer.completeError(new Future.value(42)); |
- completer.future.then((_) { |
- Expect.fail("Shouldn't happen"); |
- }, onError: (e, s) { |
- Future f = e; |
- f.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- }); |
-} |
- |
-void testCompleteWithCustomFutureSuccess() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- final completer2 = new Completer<int>(); |
- completer.complete(new CustomFuture(completer2.future)); |
- completer.future.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- completer2.complete(42); |
-} |
- |
-void testCompleteWithCustomFutureError() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- final completer2 = new Completer<int>(); |
- completer.complete(new CustomFuture(completer2.future)); |
- completer.future.then((v) { |
- Expect.fail("Should not happen"); |
- asyncEnd(); |
- }, onError: (e) { |
- Expect.equals("ERROR-tcwcfe", e); |
- asyncEnd(); |
- }); |
- completer2.completeError("ERROR-tcwcfe"); |
-} |
- |
-void testCompleteErrorWithCustomFuture() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- var future = new CustomFuture(new Future.value(42)); |
- completer.completeError(future); |
- completer.future.then((_) { |
- Expect.fail("Shouldn't happen"); |
- }, onError: (Future f) { |
- f.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- }); |
-} |
- |
-void testCompleteErrorWithNull() { |
- asyncStart(); |
- final completer = new Completer<int>(); |
- completer.future.catchError((e) { |
- Expect.isTrue(e is NullThrownError); |
- asyncEnd(); |
- }); |
- completer.completeError(null); |
-} |
- |
-void testChainedFutureValue() { |
- final completer = new Completer(); |
- final future = completer.future; |
- asyncStart(); |
- |
- future.then((v) => new Future.value(v * 2)).then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- completer.complete(21); |
-} |
- |
-void testChainedFutureValueDelay() { |
- final completer = new Completer(); |
- final future = completer.future; |
- asyncStart(); |
- |
- future |
- .then((v) => |
- new Future.delayed(const Duration(milliseconds: 10), () => v * 2)) |
- .then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }); |
- completer.complete(21); |
-} |
- |
-void testChainedFutureValue2Delay() { |
- asyncStart(); |
- |
- new Future.delayed(const Duration(milliseconds: 10)).then((v) { |
- Expect.isNull(v); |
- asyncEnd(); |
- }); |
-} |
- |
-void testChainedFutureError() { |
- final completer = new Completer(); |
- final future = completer.future; |
- asyncStart(); |
- |
- future.then((v) => new Future.error("Fehler")).then((v) { |
- Expect.fail("unreachable!"); |
- }, onError: (error) { |
- Expect.equals("Fehler", error); |
- asyncEnd(); |
- }); |
- completer.complete(21); |
-} |
- |
-void testSyncFuture_i13368() { |
- asyncStart(); |
- |
- final future = new Future<int>.sync(() { |
- return new Future<int>.value(42); |
- }); |
- |
- future.then((int val) { |
- Expect.equals(val, 42); |
- asyncEnd(); |
- }); |
-} |
- |
-void testWaitCleanUp() { |
- asyncStart(); |
- // Creates three futures with different completion times, and where some fail. |
- // The `mask` specifies which futures fail (values 1-7), |
- // and `permute` defines the order of completion. values 0-5. |
- void doTest(int mask, int permute) { |
- asyncStart(); |
- String stringId = "waitCleanup-$mask-$permute"; |
- List futures = new List(3); |
- List cleanup = new List(3); |
- int permuteTmp = permute; |
- for (int i = 0; i < 3; i++) { |
- bool throws = (mask & (1 << i)) != 0; |
- var future = new Future.delayed(new Duration(milliseconds: 100 * (i + 1)), |
- () => (throws ? throw "Error $i($mask-$permute)" : i)); |
- int mod = 3 - i; |
- int position = permuteTmp % mod; |
- permuteTmp = permuteTmp ~/ mod; |
- while (futures[position] != null) position++; |
- futures[position] = future; |
- cleanup[i] = throws; |
- } |
- void cleanUp(index) { |
- Expect.isFalse(cleanup[index]); |
- cleanup[index] = true; |
- } |
- |
- Future.wait(futures, cleanUp: cleanUp).then((_) { |
- Expect.fail("No error: $stringId"); |
- }, onError: (e, s) { |
- Expect.listEquals([true, true, true], cleanup); |
- asyncEnd(); |
- }); |
- } |
- |
- for (int i = 1; i < 8; i++) { |
- for (int j = 0; j < 6; j++) { |
- doTest(i, j); |
- } |
- } |
- asyncEnd(); |
-} |
- |
-void testWaitCleanUpEager() { |
- asyncStart(); |
- // Creates three futures with different completion times, and where some fail. |
- // The `mask` specifies which futures fail (values 1-7), |
- // and `permute` defines the order of completion. values 0-5. |
- void doTest(int mask, int permute) { |
- asyncStart(); |
- asyncStart(); |
- bool done = false; |
- String stringId = "waitCleanup-$mask-$permute"; |
- List futures = new List(3); |
- List cleanup = new List(3); |
- int permuteTmp = permute; |
- for (int i = 0; i < 3; i++) { |
- bool throws = (mask & (1 << i)) != 0; |
- var future = new Future.delayed(new Duration(milliseconds: 100 * (i + 1)), |
- () => (throws ? throw "Error $i($mask-$permute)" : i)); |
- int mod = 3 - i; |
- int position = permuteTmp % mod; |
- permuteTmp = permuteTmp ~/ mod; |
- while (futures[position] != null) position++; |
- futures[position] = future; |
- cleanup[i] = throws; |
- } |
- void checkDone() { |
- if (done) return; |
- if (cleanup.every((v) => v)) { |
- done = true; |
- asyncEnd(); |
- } |
- } |
- |
- void cleanUp(index) { |
- Expect.isFalse(cleanup[index]); |
- cleanup[index] = true; |
- // Cleanup might happen before and after the wait().then() callback. |
- checkDone(); |
- } |
- |
- Future.wait(futures, eagerError: true, cleanUp: cleanUp).then((_) { |
- Expect.fail("No error: $stringId"); |
- }, onError: (e, s) { |
- asyncEnd(); |
- checkDone(); |
- }); |
- } |
- |
- for (int i = 1; i < 8; i++) { |
- for (int j = 0; j < 6; j++) { |
- doTest(i, j); |
- } |
- } |
- asyncEnd(); |
-} |
- |
-void testWaitCleanUpError() { |
- var cms = const Duration(milliseconds: 100); |
- var cleanups = new List.filled(3, false); |
- var uncaughts = new List.filled(3, false); |
- asyncStart(); |
- asyncStart(); |
- asyncStart(); |
- runZoned(() { |
- Future.wait([ |
- new Future.delayed(cms, () => 0), |
- new Future.delayed(cms * 2, () => throw 1), |
- new Future.delayed(cms * 3, () => 2) |
- ], cleanUp: (index) { |
- Expect.isTrue(index == 0 || index == 2, "$index"); |
- Expect.isFalse(cleanups[index]); |
- cleanups[index] = true; |
- throw index; |
- }).catchError((e) { |
- Expect.equals(e, 1); |
- asyncEnd(); |
- }); |
- }, onError: (int index, s) { |
- Expect.isTrue(index == 0 || index == 2, "$index"); |
- Expect.isFalse(uncaughts[index]); |
- uncaughts[index] = true; |
- asyncEnd(); |
- }); |
-} |
- |
-void testWaitSyncError() { |
- var cms = const Duration(milliseconds: 100); |
- var cleanups = new List.filled(3, false); |
- asyncStart(); |
- asyncStart(); |
- runZoned(() { |
- Future.wait( |
- new Iterable.generate(5, (i) { |
- if (i != 3) return new Future.delayed(cms * (i + 1), () => i); |
- throw "throwing synchronously in iterable"; |
- }), cleanUp: (index) { |
- Expect.isFalse(cleanups[index]); |
- cleanups[index] = true; |
- if (cleanups.every((x) => x)) asyncEnd(); |
- }); |
- }, onError: (e, s) { |
- asyncEnd(); |
- }); |
-} |
- |
-void testWaitSyncError2() { |
- asyncStart(); |
- Future.wait([null]).catchError((e, st) { |
- // Makes sure that the `catchError` is invoked. |
- // Regression test: an earlier version of `Future.wait` would propagate |
- // the error too soon for the code to install an error handler. |
- // `testWaitSyncError` didn't show this problem, because the `runZoned` |
- // was already installed. |
- asyncEnd(); |
- }); |
-} |
- |
-// Future.wait transforms synchronous errors into asynchronous ones. |
-// This function tests that zones can intercept them. |
-void testWaitSyncError3() { |
- var caughtError; |
- var count = 0; |
- |
- AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, |
- Object error, StackTrace stackTrace) { |
- Expect.equals(0, count); |
- count++; |
- caughtError = error; |
- return parent.errorCallback(zone, error, stackTrace); |
- } |
- |
- asyncStart(); |
- runZoned(() { |
- Future.wait([null]).catchError((e, st) { |
- Expect.identical(e, caughtError); |
- Expect.equals(1, count); |
- asyncEnd(); |
- }); |
- }, zoneSpecification: new ZoneSpecification(errorCallback: errorCallback)); |
-} |
- |
-void testBadFuture() { |
- var bad = new BadFuture(); |
- // Completing with bad future (then call throws) puts error in result. |
- asyncStart(); |
- Completer completer = new Completer(); |
- completer.complete(bad); |
- completer.future.then((_) { |
- Expect.fail("unreachable"); |
- }, onError: (e, s) { |
- Expect.isTrue(completer.isCompleted); |
- asyncEnd(); |
- }); |
- |
- asyncStart(); |
- var f = new Future.value().then((_) => bad); |
- f.then((_) { |
- Expect.fail("unreachable"); |
- }, onError: (e, s) { |
- asyncEnd(); |
- }); |
-} |
- |
-void testTypes() { |
- // Test that future is a Future<int> and not something less precise. |
- testType(name, future, [depth = 2]) { |
- var desc = "$name${".whenComplete"*(2-depth)}"; |
- Expect.isTrue(future is Future<int>, "$desc is Future<int>"); |
- Expect.isFalse(future is Future<String>, "$desc is! Future<String>"); |
- var stream = future.asStream(); |
- Expect.isTrue(stream is Stream<int>, "$desc.asStream() is Stream<int>"); |
- Expect.isFalse( |
- stream is Stream<String>, "$desc.asStream() is! Stream<String>"); |
- if (depth > 0) { |
- testType(name, future.whenComplete(() {}), depth - 1); |
- } |
- } |
- |
- for (var value in [42, null]) { |
- testType("Future($value)", new Future<int>(() => value)); |
- testType("Future.delayed($value)", |
- new Future<int>.delayed(Duration.ZERO, () => value)); |
- testType( |
- "Future.microtask($value)", new Future<int>.microtask(() => value)); |
- testType("Future.sync($value)", new Future<int>.sync(() => value)); //# 01: ok |
- testType("Future.sync(future($value))", // //# 01: continued |
- new Future<int>.sync(() => new Future<int>.value(value))); //# 01: continued |
- testType("Future.value($value)", new Future<int>.value(value)); |
- } |
- testType("Completer.future", new Completer<int>().future); |
- testType("Future.error", new Future<int>.error("ERR")..catchError((_) {})); |
-} |
- |
-void testAnyValue() { |
- asyncStart(); |
- var cs = new List.generate(3, (_) => new Completer()); |
- var result = Future.any(cs.map((x) => x.future)); |
- |
- result.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }, onError: (e, s) { |
- Expect.fail("Unexpected error: $e"); |
- }); |
- |
- cs[1].complete(42); |
- cs[2].complete(10); |
- cs[0].complete(20); |
-} |
- |
-void testAnyError() { |
- asyncStart(); |
- var cs = new List.generate(3, (_) => new Completer()); |
- var result = Future.any(cs.map((x) => x.future)); |
- |
- result.then((v) { |
- Expect.fail("Unexpected value: $v"); |
- }, onError: (e, s) { |
- Expect.equals(42, e); |
- asyncEnd(); |
- }); |
- |
- cs[1].completeError(42); |
- cs[2].complete(10); |
- cs[0].complete(20); |
-} |
- |
-void testAnyIgnoreIncomplete() { |
- asyncStart(); |
- var cs = new List.generate(3, (_) => new Completer()); |
- var result = Future.any(cs.map((x) => x.future)); |
- |
- result.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }, onError: (e, s) { |
- Expect.fail("Unexpected error: $e"); |
- }); |
- |
- cs[1].complete(42); |
- // The other two futures never complete. |
-} |
- |
-void testAnyIgnoreError() { |
- asyncStart(); |
- var cs = new List.generate(3, (_) => new Completer()); |
- var result = Future.any(cs.map((x) => x.future)); |
- |
- result.then((v) { |
- Expect.equals(42, v); |
- asyncEnd(); |
- }, onError: (e, s) { |
- Expect.fail("Unexpected error: $e"); |
- }); |
- |
- cs[1].complete(42); |
- // The errors are ignored, not uncaught. |
- cs[2].completeError("BAD"); |
- cs[0].completeError("BAD"); |
-} |
- |
-void testFutureResult() { |
- asyncStart(); |
- () async { |
- var f = new UglyFuture(5); |
- // Sanity check that our future is as mis-behaved as we think. |
- f.then((v) { |
- Expect.isTrue(v is Future); |
- }); |
- |
- var v = await f; |
- // The static type of await is Flatten(static-type-of-expression), so it |
- // suggests that it flattens. In practice it currently doesn't. |
- // The specification doesn't say anything special, so v should be the |
- // completion value of the UglyFuture future which is a future. |
- Expect.isTrue(v is Future); |
- |
- // This used to hit an assert in checked mode. |
- // The CL adding this test changed the behavior to actually flatten the |
- // the future returned by the then-callback. |
- var w = new Future.value(42).then((_) => f); |
- Expect.equals(42, await w); |
- asyncEnd(); |
- }(); |
-} |
- |
-main() { |
- asyncStart(); |
- |
- testValue(); |
- testSync(); |
- testNeverComplete(); |
- |
- testComplete(); |
- testCompleteWithSuccessHandlerBeforeComplete(); |
- testCompleteWithSuccessHandlerAfterComplete(); |
- testCompleteManySuccessHandlers(); |
- testCompleteWithError(); |
- |
- testCompleteWithFutureSuccess(); |
- testCompleteWithFutureSuccess2(); |
- testCompleteWithFutureError(); |
- testCompleteWithFutureError2(); |
- testCompleteErrorWithFuture(); |
- testCompleteWithCustomFutureSuccess(); |
- testCompleteWithCustomFutureError(); |
- testCompleteErrorWithCustomFuture(); |
- testCompleteErrorWithNull(); |
- |
- testException(); |
- testExceptionHandler(); |
- testExceptionHandlerReturnsTrue(); |
- testExceptionHandlerReturnsTrue2(); |
- testExceptionHandlerReturnsFalse(); |
- |
- testFutureAsStreamCompleteAfter(); |
- testFutureAsStreamCompleteBefore(); |
- testFutureAsStreamCompleteImmediate(); |
- testFutureAsStreamCompleteErrorAfter(); |
- testFutureAsStreamWrapper(); |
- |
- testFutureWhenCompleteValue(); |
- testFutureWhenCompleteError(); |
- testFutureWhenCompleteValueNewError(); |
- testFutureWhenCompleteErrorNewError(); |
- |
- testFutureWhenValueFutureValue(); |
- testFutureWhenErrorFutureValue(); |
- testFutureWhenValueFutureError(); |
- testFutureWhenErrorFutureError(); |
- |
- testFutureThenThrowsAsync(); |
- testFutureCatchThrowsAsync(); |
- testFutureWhenThrowsAsync(); |
- testFutureCatchRethrowsAsync(); |
- |
- testChainedFutureValue(); |
- testChainedFutureValueDelay(); |
- testChainedFutureError(); |
- |
- testSyncFuture_i13368(); |
- |
- testWaitCleanUp(); |
- testWaitCleanUpError(); |
- testWaitSyncError(); |
- testWaitSyncError2(); |
- testWaitSyncError3(); |
- |
- testBadFuture(); |
- |
- testTypes(); |
- |
- testAnyValue(); |
- testAnyError(); |
- testAnyIgnoreIncomplete(); |
- testAnyIgnoreError(); |
- |
- testFutureResult(); |
- |
- asyncEnd(); |
-} |
- |
-/// A well-behaved Future that isn't recognizable as a _Future. |
-class CustomFuture<T> implements Future<T> { |
- Future _realFuture; |
- CustomFuture(this._realFuture); |
- Future then(action(result), {Function onError}) => |
- _realFuture.then(action, onError: onError); |
- Future catchError(Function onError, {bool test(e)}) => |
- _realFuture.catchError(onError, test: test); |
- Future whenComplete(action()) => _realFuture.whenComplete(action); |
- Future timeout(Duration timeLimit, {void onTimeout()}) => |
- _realFuture.timeout(timeLimit, onTimeout: onTimeout); |
- Stream asStream() => _realFuture.asStream(); |
- String toString() => "CustomFuture@${_realFuture.hashCode}"; |
- int get hashCode => _realFuture.hashCode; |
-} |
- |
-/// A bad future that throws on every method. |
-class BadFuture<T> implements Future<T> { |
- Future then(action(T result), {Function onError}) { |
- throw "then GOTCHA!"; |
- } |
- |
- Future catchError(Function onError, {bool test(e)}) { |
- throw "catch GOTCHA!"; |
- } |
- |
- Future whenComplete(action()) { |
- throw "finally GOTCHA!"; |
- } |
- |
- Stream<T> asStream() { |
- throw "asStream GOTCHA!"; |
- } |
- |
- Future timeout(Duration duration, {onTimeout()}) { |
- throw "timeout GOTCHA!"; |
- } |
-} |
- |
-// An evil future that completes with another future. |
-class UglyFuture implements Future<dynamic> { |
- final _result; |
- UglyFuture(int badness) |
- : _result = (badness == 0) ? 42 : new UglyFuture(badness - 1); |
- Future then(action(value), {onError(error, StackTrace stack)}) { |
- var c = new Completer(); |
- c.complete(new Future.microtask(() => action(_result))); |
- return c.future; |
- } |
- |
- Future catchError(onError, {test}) => this; // Never an error. |
- Future whenComplete(action()) { |
- return new Future.microtask(action).then((_) => this); |
- } |
- |
- Stream asStream() { |
- return (new StreamController() |
- ..add(_result) |
- ..close()) |
- .stream; |
- } |
- |
- Future timeout(Duration duration, {onTimeout()}) { |
- return this; |
- } |
-} |