Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(537)

Unified Diff: tests/lib_strong/async/future_test.dart

Issue 2802973005: Migrate async tests to strong (Closed)
Patch Set: Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tests/lib_strong/async/future_or_strong_test.dart ('k') | tests/lib_strong/async/future_timeout_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tests/lib_strong/async/future_test.dart
diff --git a/tests/lib_strong/async/future_test.dart b/tests/lib_strong/async/future_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..4c46e3f79c94230c15da2e6a59c30e340e724c79
--- /dev/null
+++ b/tests/lib_strong/async/future_test.dart
@@ -0,0 +1,1240 @@
+// 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;
+ }
+}
« no previous file with comments | « tests/lib_strong/async/future_or_strong_test.dart ('k') | tests/lib_strong/async/future_timeout_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698