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

Unified Diff: tests/language/async_await_test.dart

Issue 968963002: Add some async/await tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update more test expectations. Created 5 years, 9 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
Index: tests/language/async_await_test.dart
diff --git a/tests/language/async_await_test.dart b/tests/language/async_await_test.dart
new file mode 100644
index 0000000000000000000000000000000000000000..705c0a3042cba8f152754219a1b61c7d1ad432ca
--- /dev/null
+++ b/tests/language/async_await_test.dart
@@ -0,0 +1,2006 @@
+// Copyright (c) 2015, 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 async_await_test;
+
+import "package:unittest/unittest.dart";
+import "dart:async";
+
+main() {
+ bool checkedMode = false;
+ assert((checkedMode = true));
+
+ group("basic", () {
+ test("async w/o await", () {
+ f() async { return id(42); }
+ return expect42(f());
+ });
+
+ test("async waits", () {
+ // Calling an "async" function won't do anything immediately.
+ var result = [];
+ f() async {
+ result.add(1);
+ return id(42);
+ };
+ var future = f();
+ result.add(0);
+ return future.whenComplete(() {
+ expect(result, equals([0, 1]));
+ });
+ });
+
+ test("async throws", () {
+ f() async {
+ throw "err";
+ return id(42);
+ }
+ return throwsErr(f());
+ });
+
+ test("await future", () {
+ f() async {
+ var v = await new Future.value(42);
+ return v;
+ };
+ return expect42(f());
+ });
+
+ test("await value", () {
+ f() async {
+ var v = await id(42);
+ return v;
+ };
+ return expect42(f());
+ });
+
+ test("await null", () {
+ f() async {
+ var v = await null;
+ expect(v, equals(null));
+ };
+ return f();
+ });
+
+ test("await await", () {
+ f() async {
+ return await await new Future.value(42);
+ }
+ return expect42(f());
+ });
+
+ test("await fake value future", () {
+ f() async {
+ return await new FakeValueFuture(42);
+ }
+ return expect42(f());
+ });
+
+ test("await fake error future", () {
+ f() async {
+ return await new FakeErrorFuture("err");
+ }
+ return throwsErr(f());
+ });
+
+ test("await value is delayed", () {
+ f() async {
+ bool x = false;
+ scheduleMicrotask(() { x = true; });
+ var y = await true;
+ expect(x, equals(y));
+ }
+ return f();
+ });
+
+ test("await throw", () {
+ f() async {
+ await (throw "err"); // Check grammar: Are parentheses necessary?
+ return id(42);
+ }
+ return throwsErr(f());
+ });
+
+ test("throw before await", () {
+ f() async {
+ var x = throw "err";
+ await x; // Check grammar: Are parentheses necessary?
+ return id(42);
+ }
+ return throwsErr(f());
+ });
+
+ if (checkedMode) {
+ test("assert before await", () {
+ f(v) async {
+ assert(v == 87);
+ return await new Future.microtask(() => 42);
+ }
+ return f(42).then((_) {
+ fail("assert didn't throw");
+ }, onError: (e, s) {
+ expect(e is AssertionError, isTrue);
+ });
+ });
+
+ test("assert after await", () {
+ f(v) async {
+ var x = await new Future.microtask(() => 42);
+ assert(v == 87);
+ return x;
+ }
+ return f(42).then((_) {
+ fail("assert didn't throw");
+ }, onError: (e, s) {
+ expect(e is AssertionError, isTrue);
+ });
+ });
+ }
+
+ test("async await error", () {
+ f() async {
+ await new Future.error("err");
+ return id(42);
+ }
+ return throwsErr(f());
+ });
+
+ test("async flattens futures", () {
+ f() async {
+ return new Future.value(42); // Not awaited.
+ };
+ return f().then((v) {
+ expect(v, equals(42)); // And not a Future with value 42.
+ });
+ });
+
+ test("async flattens futures, error", () {
+ f() async {
+ return new Future.error("err"); // Not awaited.
+ };
+ return throwsErr(f());
+ });
+
+ test("await for", () {
+ f(s) async {
+ int i = 0;
+ await for (int v in s) {
+ i += v;
+ }
+ return i;
+ }
+ return f(mkStream()).then((v) {
+ expect(v, equals(45)); // 0 + 1 + ... + 9
+ });
+ });
+
+ test("await for w/ await", () {
+ f(s) async {
+ int i = 0;
+ await for (int v in s) {
+ i += await new Future.value(v);
+ }
+ return i;
+ }
+ return f(mkStream()).then((v) {
+ expect(v, equals(45)); // 0 + 1 + ... + 9
+ });
+ });
+
+ test("await for empty", () {
+ f(s) async {
+ int v = 0;
+ await for (int i in s) {
+ v += i;
+ }
+ return v;
+ }
+ var s = (new StreamController()..close()).stream;
+ return f(s).then((v) {
+ expect(v, equals(0));
+ });
+ });
+
+ if (checkedMode) {
+ test("await for w/ await, asseert", () {
+ f(s) async {
+ int i = 0;
+ await for (int v in s) {
+ i += await new Future.microtask(() => v);
+ assert(v < 8);
+ }
+ return i;
+ }
+ return f(mkStream()).then((v) {
+ fail("assert didn't throw");
+ }, onError: (e, s) {
+ expect(e is AssertionError, isTrue);
+ });
+ });
+ }
+ });
+
+ group("for", () {
+ test("await in for-loop", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i++) {
+ v += await new Future.value(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * id(42)));
+ });
+ });
+
+ test("await in for-init", () {
+ f() async {
+ int v = 0;
+ for (int i = await new Future.value(42); i >= 0; i -= 10) {
+ v += 10;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * 5));
+ });
+ });
+
+ test("await in for-test", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < await new Future.value(42); i += 10) {
+ v += 10;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * 5));
+ });
+ });
+
+ test("await in for-incr", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 100; i += await new Future.value(42)) {
+ v += 10;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * 3));
+ });
+ });
+
+ test("await err in for-loop", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i++) {
+ v += await new Future.error("err");
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("await err in for-init", () {
+ f() async {
+ int v = 0;
+ for (int i = await new Future.error("err"); i >= 0; i -= 10) {
+ v += 10;
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("await err in for-test", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < await new Future.error("err"); i += 10) {
+ v += 10;
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("await err in for-incr", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 100; i += await new Future.error("err")) {
+ v += 10;
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("await in empty for-loop", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i > 0; i += 1) {
+ v += await new Future.value(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(0));
+ });
+ });
+
+ test("await in empty for-loop 2", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i > 0; i += await new Future.value(1)) {
+ v += 1;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(0));
+ });
+ });
+
+ test("break before await in for-loop", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i += 1) {
+ if (i == 2) break;
+ v += await new Future.value(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 2));
+ });
+ });
+
+ test("break before await in for-loop 2", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i += await new Future.value(1)) {
+ if (i == 2) break;
+ v += id(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 2));
+ });
+ });
+
+ test("continue before await", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i += 1) {
+ if (i == 2) continue;
+ v += await new Future.value(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+
+ test("continue after await", () {
+ f() async {
+ int v = 0;
+ for (int i = 0; i < 10; i += 1) {
+ var j = await new Future.value(42);
+ if (i == 2) continue;
+ v += j;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+ });
+
+ group("while", () {
+ test("await in while-loop", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ v += await new Future.value(42);
+ i++;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * id(42)));
+ });
+ });
+
+ test("await in while-test", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < await new Future.value(42)) {
+ v += 10;
+ i += 10;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * 5));
+ });
+ });
+
+ test("await err in loop", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ v += await new Future.error("err");
+ i++;
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("await err in test", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < await new Future.error("err")) {
+ v += 10;
+ i += 10;
+ }
+ return v;
+ }
+ return throwsErr(f());
+ });
+
+ test("break before await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ if (i == 2) break;
+ v += await new Future.value(42);
+ i += 1;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 2));
+ });
+ });
+
+ test("break after await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ v += await new Future.value(42);
+ if (i == 2) break;
+ i += 1;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 3));
+ });
+ });
+
+ test("continue before await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ i += 1;
+ if (i == 2) continue;
+ v += await new Future.value(42);
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+
+ test("continue after await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ while (i < 10) {
+ i += 1;
+ int j = await new Future.value(42);
+ if (i == 2) continue;
+ v += j;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+ });
+
+ group("do-while", () {
+ test("await in loop", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ v += await new Future.value(42);
+ i++;
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * id(42)));
+ });
+ });
+
+ test("await in test", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ v += 10;
+ i += 10;
+ } while (i < await new Future.value(42));
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(10 * 5));
+ });
+ });
+
+ test("await err in loop", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ v += await new Future.error("err");
+ i++;
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("await err in test", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ v += 10;
+ i += 10;
+ } while (i < await new Future.error("err"));
+ return v;
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("break before await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ if (i == 2) break;
+ v += await new Future.value(42);
+ i += 1;
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 2));
+ });
+ });
+
+ test("break after await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ v += await new Future.value(42);
+ if (i == 2) break;
+ i += 1;
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 3));
+ });
+ });
+
+ test("continue before await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ i += 1;
+ if (i == 2) continue;
+ v += await new Future.value(42);
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+
+ test("continue after await", () {
+ f() async {
+ int v = 0;
+ int i = 0;
+ do {
+ i += 1;
+ int j = await new Future.value(42);
+ if (i == 2) continue;
+ v += j;
+ } while (i < 10);
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(42 * 9));
+ });
+ });
+ });
+
+ group("for-in", () {
+ test("await in for-in", () {
+ f() async {
+ var v = 0;
+ for (var fut in [1, 2, 3].map((v) => new Future.value(v))) {
+ v += await fut;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(6));
+ });
+ });
+
+ test("await in for-in iterable", () {
+ f() async {
+ var v = 0;
+ for (var i in await new Future.value([1, 2, 3])) {
+ v += i;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(6));
+ });
+ });
+
+ test("await err in for-in", () {
+ f() async {
+ var v = 0;
+ for (var fut in [1, 2, 3].map((v) => (v != 1)
+ ? new Future.value(v)
+ : new Future.error("err"))) {
+ v += await fut;
+ }
+ return v;
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("await err in for-in iterable", () {
+ f() async {
+ var v = 0;
+ for (var i in await new Future.error("err")) {
+ v += i;
+ }
+ return v;
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("break before await in for-in", () {
+ f() async {
+ var v = 0;
+ for (var fut in [1, 2, 3].map((v) => new Future.value(v))) {
+ if (v == 3) break;
+ v += await fut;
+ }
+ return v;
+ }
+ return f().then((v) {
+ expect(v, equals(3));
+ });
+ });
+ });
+
+ group("try-catch", () {
+ test("try-no-catch", () {
+ f() async {
+ try {
+ return await id(42);
+ } catch(e) {
+ return 37;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in body", () {
+ f() async {
+ try {
+ await new Future.error(42);
+ } catch(e) {
+ return e;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("throw before await in body", () {
+ int i = id(0);
+ f() async {
+ try {
+ if (i >= 0) throw id(42);
+ return await new Future.value(10);
+ } catch(e) {
+ return e;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("try-catch await in catch", () {
+ f() async {
+ try {
+ throw id(42);
+ } catch(e) {
+ return await new Future.value(e);
+ }
+ }
+ return expect42(f());
+ });
+
+ test("try-catch await error in catch", () {
+ f() async {
+ try {
+ throw id(42);
+ } catch(e) {
+ await new Future.error("err");
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("try-catch-rethrow", () {
+ f() async {
+ try {
+ await new Future.error("err");
+ } catch(e) {
+ if (e == id(42)) return;
+ rethrow;
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+ });
+
+ group("try-finally", () {
+ test("await in body", () {
+ f() async {
+ try {
+ return await new Future.value(42);
+ } finally {
+ // Don't do anything.
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in finally", () {
+ var x = 0;
+ f() async {
+ try {
+ return id(42);
+ } finally {
+ x = await new Future.value(37);
+ }
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(37));
+ });
+ });
+
+ test("await err in body", () {
+ f() async {
+ try {
+ return await new Future.error("err");
+ } finally {
+ // Don't do anything.
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("await err in finally", () {
+ f() async {
+ try {
+ return id(42);
+ } finally {
+ await new Future.error("err");
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("await err in both", () {
+ f() async {
+ try {
+ await new Future.error("not err");
+ } finally {
+ await new Future.error("err");
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+ });
+
+ test("await err in body, override in finally", () {
+ f() async {
+ try {
+ return await new Future.error("err");
+ } finally {
+ return id(42);
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in body, override in finally", () {
+ f() async {
+ label: try {
+ return await new Future.value(37);
+ } finally {
+ break label;
+ }
+ return id(42);
+ }
+ return expect42(f());
+ });
+
+ test("await, override in finally", () {
+ var x = 0;
+ f() async {
+ label: try {
+ return 87;
+ } finally {
+ x = await new Future.value(37);
+ break label;
+ }
+ return id(42);
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(37));
+ });
+ });
+
+ test("throw in body, await, override in finally 3", () {
+ var x = 0;
+ f() async {
+ label: try {
+ throw "err";
+ } finally {
+ x = await new Future.value(37);
+ break label;
+ }
+ return id(42);
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(37));
+ });
+ });
+
+ test("await err in body, override in finally 2", () {
+ f() async {
+ label: try {
+ return await new Future.error("err");
+ } finally {
+ break label;
+ }
+ return id(42);
+ }
+ return expect42(f());
+ });
+
+ test("await in body, no-exit in finally", () {
+ f() async {
+ for (int i = 0; i < 10; i++) {
+ try {
+ return await i;
+ } finally {
+ continue;
+ }
+ }
+ return id(42);
+ }
+ return expect42(f());
+ });
+
+ test("no-exit after await in finally", () {
+ f() async {
+ int i = 0;
+ for (; i < 10; i++) {
+ try {
+ break;
+ } finally {
+ await new Future.value(42);
+ continue;
+ }
+ }
+ return id(i);
+ }
+ return f().then((v) {
+ expect(v, equals(10));
+ });
+ });
+
+ test("exit after continue, await in finally", () {
+ f() async {
+ int i = 0;
+ for (; i < 10; i++) {
+ try {
+ continue;
+ } finally {
+ await new Future.value(42);
+ break;
+ }
+ }
+ return id(i);
+ }
+ return f().then((v) {
+ expect(v, equals(0));
+ });
+ });
+
+ test("no-exit before await in finally 2", () {
+ f() async {
+ for (int i = 0; i < 10; i++) {
+ try {
+ return i;
+ } finally {
+ if (i >= 0) continue;
+ await new Future.value(42);
+ }
+ }
+ return id(42);
+ }
+ return expect42(f());
+ });
+
+ test("no-exit after await in finally", () {
+ f() async {
+ for (int i = 0; i < 10; i++) {
+ try {
+ return i;
+ } finally {
+ await new Future.value(42);
+ continue;
+ }
+ }
+ return id(42);
+ }
+ return expect42(f());
+ });
+
+ test("nested finallies", () {
+ var x = 0;
+ f() async {
+ try {
+ try {
+ return 42;
+ } finally {
+ x = await new Future.value(37);
+ }
+ } finally {
+ x += await new Future.value(37);
+ }
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(74));
+ });
+ });
+
+ test("nested finallies 2", () {
+ var x = 0;
+ f() async {
+ label: try {
+ try {
+ break label;
+ } finally {
+ x = await new Future.value(37);
+ }
+ } finally {
+ x += await new Future.value(37);
+ }
+ return 42;
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(74));
+ });
+ });
+
+ test("nested finallies 3", () {
+ var x = 0;
+ f() async {
+ label: try {
+ try {
+ break label;
+ } finally {
+ return await new Future.value(42);
+ }
+ } finally {
+ break label;
+ }
+ return 42;
+ }
+ return expect42(f());
+ });
+
+ test("nested finallies, throw", () {
+ var x = 0;
+ f() async {
+ try {
+ try {
+ throw "err";
+ } finally {
+ x = await new Future.value(37);
+ }
+ } finally {
+ x += await new Future.value(37);
+ }
+ }
+ return f().then((v) { fail("didn't throw"); },
+ onError: (e) {
+ expect(e, equals("err"));
+ expect(x, equals(2 * 37));
+ });
+ });
+ });
+
+ group("try-catch-finally", () {
+ test("await in body", () {
+ f() async {
+ try {
+ return await new Future.value(42);
+ } catch (e) {
+ throw null;
+ } finally {
+ if (id(42) == id(10)) return 10;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in catch, not hit", () {
+ f() async {
+ try {
+ return id(42);
+ } catch (e) {
+ await new Future.error("err");
+ } finally {
+ if (id(42) == id(10)) return 10;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in catch, hit", () {
+ f() async {
+ try {
+ return throw id(42);
+ } catch (e) {
+ return await new Future.value(e);
+ } finally {
+ if (id(42) == id(10)) return 10;
+ }
+ }
+ return expect42(f());
+ });
+
+ test("await in finally", () {
+ var x = 0;
+ f() async {
+ try {
+ return id(42);
+ } catch (e) {
+ throw null;
+ } finally {
+ x = await new Future.value(37);
+ if (id(42) == id(10)) return 10;
+ }
+ }
+ return f().then((v) {
+ expect(v, equals(42));
+ expect(x, equals(37));
+ });
+ });
+ });
+
+ group("switch", () {
+ test("await in expression", () {
+ f(v) async {
+ switch (await new Future.value(v)) {
+ case 1: return 1;
+ case 2: return 42;
+ default: return 3;
+ }
+ return null;
+ }
+ return expect42(f(2));
+ });
+
+ test("await err in expression", () {
+ f(v) async {
+ switch (await new Future.error("err")) {
+ case 1: return 1;
+ case 2: return 42;
+ default: return 3;
+ }
+ return null;
+ }
+ return throwsErr(f(2));
+ });
+
+ test("await in case", () {
+ f(v) async {
+ switch (v) {
+ case 1: return 1;
+ case 2: return await new Future.value(42);
+ default: return 3;
+ }
+ return null;
+ }
+ return expect42(f(2));
+ });
+
+ test("await err in case", () {
+ f(v) async {
+ switch (v) {
+ case 1: return 1;
+ case 2: return await new Future.error("err");
+ default: return 3;
+ }
+ return null;
+ }
+ return throwsErr(f(2));
+ });
+
+ test("continue before await in case", () {
+ f(v) async {
+ switch (v) {
+ label:
+ case 1: return 42;
+ case 2:
+ if (v <= 2) continue label;
+ return await new Future.value(10);
+ default: return 3;
+ }
+ return null;
+ }
+ return expect42(f(2));
+ });
+
+ test("continue after await in case", () {
+ f(v) async {
+ switch (v) {
+ label:
+ case 1: return 42;
+ case 2:
+ await new Future.value(10);
+ continue label;
+ default: return 3;
+ }
+ return null;
+ }
+ return expect42(f(2));
+ });
+ });
+
+ group("if", () {
+ test("await in test", () {
+ f(v) async {
+ if (await new Future.value(v)) {
+ return 42;
+ } else {
+ return 37;
+ }
+ }
+ return expect42(f(true));
+ });
+
+ test("await err in test", () {
+ f(v) async {
+ if (await new Future.error("err")) {
+ return 42;
+ } else {
+ return 37;
+ }
+ }
+ return throwsErr(f(true));
+ });
+
+ test("await in then", () {
+ f(v) async {
+ if (v) {
+ return await new Future.value(42);
+ }
+ return 37;
+ }
+ return expect42(f(true));
+ });
+
+ test("await err in then", () {
+ f(v) async {
+ if (v) {
+ return await new Future.error("err");
+ }
+ return 37;
+ }
+ return throwsErr(f(true));
+ });
+
+ test("await in then with else", () {
+ f(v) async {
+ if (v) {
+ return await new Future.value(42);
+ } else {
+ return 87;
+ }
+ return 37;
+ }
+ return expect42(f(true));
+ });
+
+ test("await err in then with else", () {
+ f(v) async {
+ if (v) {
+ return await new Future.error("err");
+ } else {
+ return 87;
+ }
+ return 37;
+ }
+ return throwsErr(f(true));
+ });
+
+ test("await in else", () {
+ f(v) async {
+ if (v) {
+ return 37;
+ } else {
+ return await new Future.value(42);
+ }
+ return 87;
+ }
+ return expect42(f(false));
+ });
+
+ test("await err in else", () {
+ f(v) async {
+ if (v) {
+ return 37;
+ } else {
+ return await new Future.error("err");
+ }
+ return 87;
+ }
+ return throwsErr(f(false));
+ });
+
+ test("await in else-if test", () {
+ f(v) async {
+ if (v) {
+ return 37;
+ } else if (!await new Future.value(v)) {
+ return 42;
+ } else {
+ return 37;
+ }
+ return 87;
+ }
+ return expect42(f(false));
+ });
+
+ test("await in else-if then", () {
+ f(v) async {
+ if (v) {
+ return 37;
+ } else if (!v) {
+ return await new Future.value(42);
+ } else {
+ return 37;
+ }
+ return 87;
+ }
+ return expect42(f(false));
+ });
+ });
+
+ group("conditional operator", () {
+ test("await in test", () {
+ f(v) async {
+ return (await new Future.value(v)) ? 42 : 37;
+ }
+ return expect42(f(true));
+ });
+
+ test("await err in test", () {
+ f(v) async {
+ return (await new Future.error("err")) ? 42 : 37;
+ }
+ return throwsErr(f(true));
+ });
+
+ test("await in then", () {
+ f(v) async {
+ return v ? (await new Future.value(42)) : 37;
+ }
+ return expect42(f(true));
+ });
+
+ test("await err in then", () {
+ f(v) async {
+ return v ? (await new Future.error("err")) : 37;
+ }
+ return throwsErr(f(true));
+ });
+
+ test("await in else", () {
+ f(v) async {
+ return v ? 37 : (await new Future.value(42));
+ }
+ return expect42(f(false));
+ });
+
+ test("await err in else", () {
+ f(v) async {
+ return v ? 37 : (await new Future.error("err"));
+ }
+ return throwsErr(f(false));
+ });
+ });
+
+ group("async declarations", () {
+ var f42 = new Future.value(42);
+
+ // Top-level declarations or local declarations in top-level functions.
+ test("topMethod", () {
+ return expect42(topMethod(f42));
+ });
+
+ test("topArrowMethod", () {
+ return expect42(topArrowMethod(f42));
+ });
+
+ test("topGetter", () {
+ return expect42(topGetter);
+ });
+
+ test("topArrowGetter", () {
+ return expect42(topArrowGetter);
+ });
+
+ test("topLocal", () {
+ return expect42(topLocal(f42));
+ });
+
+ test("topArrowLocal", () {
+ return expect42(topArrowLocal(f42));
+ });
+
+ test("topExpression", () {
+ return expect42(topExpression(f42));
+ });
+
+ test("topArrowExpression", () {
+ return expect42(topArrowExpression(f42));
+ });
+
+ test("topVarExpression", () {
+ return expect42(topVarExpression(f42));
+ });
+
+ test("topVarArrowExpression", () {
+ return expect42(topVarArrowExpression(f42));
+ });
+
+ // Static declarations or local declarations in static functions.
+ test("staticMethod", () {
+ return expect42(Async.staticMethod(f42));
+ });
+
+ test("staticArrowMethod", () {
+ return expect42(Async.staticArrowMethod(f42));
+ });
+
+ test("staticGetter", () {
+ return expect42(Async.staticGetter);
+ });
+
+ test("staticArrowGetter", () {
+ return expect42(Async.staticArrowGetter);
+ });
+
+ test("staticLocal", () {
+ return expect42(Async.staticLocal(f42));
+ });
+
+ test("staticArrowLocal", () {
+ return expect42(Async.staticArrowLocal(f42));
+ });
+
+ test("staticExpression", () {
+ return expect42(Async.staticExpression(f42));
+ });
+
+ test("staticArrowExpression", () {
+ return expect42(Async.staticArrowExpression(f42));
+ });
+
+ test("staticVarExpression", () {
+ return expect42(Async.staticVarExpression(f42));
+ });
+
+ test("staticVarArrowExpression", () {
+ return expect42(Async.staticVarArrowExpression(f42));
+ });
+
+ // Instance declarations or local declarations in instance functions.
+ var async = new Async();
+
+ test("instanceMethod", () {
+ return expect42(async.instanceMethod(f42));
+ });
+
+ test("instanceArrowMethod", () {
+ return expect42(async.instanceArrowMethod(f42));
+ });
+
+ test("instanceGetter", () {
+ return expect42(async.instanceGetter);
+ });
+
+ test("instanceArrowGetter", () {
+ return expect42(async.instanceArrowGetter);
+ });
+
+ test("instanceLocal", () {
+ return expect42(async.instanceLocal(f42));
+ });
+
+ test("instanceArrowLocal", () {
+ return expect42(async.instanceArrowLocal(f42));
+ });
+
+ test("instanceExpression", () {
+ return expect42(async.instanceExpression(f42));
+ });
+
+ test("instanceArrowExpression", () {
+ return expect42(async.instanceArrowExpression(f42));
+ });
+
+ test("instanceVarExpression", () {
+ return expect42(async.instanceVarExpression(f42));
+ });
+
+ test("instanceVarArrowExpression", () {
+ return expect42(async.instanceVarArrowExpression(f42));
+ });
+
+ // Local functions in constructor initializer list.
+ test("initializerExpression", () {
+ var async = new Async.initializer(f42);
+ return expect42(async.initValue);
+ });
+
+ test("initializerArrowExpression", () {
+ var async = new Async.initializerArrow(f42);
+ return expect42(async.initValue);
+ });
+
+ test("async in async", () {
+ return expect42(asyncInAsync(f42));
+ });
+
+ test("sync in async", () {
+ return expect42(syncInAsync(f42));
+ });
+
+ test("async in sync", () {
+ return expect42(asyncInSync(f42));
+ });
+
+ // Equality and identity.
+ test("Identical and equals", () {
+ expect(async.instanceMethod, equals(async.instanceMethod));
+ expect(Async.staticMethod, same(Async.staticMethod));
+ expect(topMethod, same(topMethod));
+ });
+ });
+
+ group("await expression", () {
+ const c42 = 42;
+ final v42 = 42;
+
+ test("local variable", () {
+ var l42 = 42;
+ f() async {
+ return await l42;
+ }
+ return expect42(f());
+ });
+
+ test("parameter", () {
+ f(p) async {
+ return await p;
+ }
+ return expect42(f(42));
+ });
+
+ test("final local variable", () {
+ f() async {
+ return await v42;
+ }
+ return expect42(f());
+ });
+
+ test("const local variable", () {
+ f() async {
+ return await c42;
+ }
+ return expect42(f());
+ });
+
+ test("unary prefix operator", () {
+ f() async {
+ return -await -42;
+ }
+ return expect42(f());
+ });
+
+ test("suffix operator", () {
+ f() async {
+ var v = [42];
+ return await v[0];
+ }
+ return expect42(f());
+ });
+
+ test("unary postfix operator", () {
+ f() async {
+ var x = 42;
+ return await x++;
+ }
+ return expect42(f());
+ });
+
+ test("suffix operator + increment", () {
+ f() async {
+ var v = [42];
+ return await v[0]++;
+ }
+ return expect42(f());
+ });
+
+ test("suffix operator + increment 2", () {
+ f() async {
+ var v = [42];
+ return await v[await 0]++;
+ }
+ return expect42(f());
+ });
+
+ test("unary pre-increment operator", () {
+ f() async {
+ var x = 41;
+ return await ++x;
+ }
+ return expect42(f());
+ });
+
+ test("suffix operator + pre-increment", () {
+ f() async {
+ var v = [41];
+ return await ++v[0];
+ }
+ return expect42(f());
+ });
+
+ test("assignment operator", () {
+ f() async {
+ var x = 37;
+ return await (x = 42);
+ }
+ return expect42(f());
+ });
+
+ test("assignment-op operator", () {
+ f() async {
+ var x = 37;
+ return await (x += 5);
+ }
+ return expect42(f());
+ });
+
+ test("binary operator", () {
+ f() async {
+ return await (10 + 11) + await (10 + 11);
+ }
+ return expect42(f());
+ });
+
+ test("ternary operator", () {
+ f(v) async {
+ return await ((v == 10) ? new Future.value(42) : 37);
+ }
+ return expect42(f(10));
+ });
+
+ test("top-level function call", () {
+ f() async {
+ return await topMethod(42);
+ }
+ return expect42(f());
+ });
+
+ test("static function call", () {
+ f() async {
+ return await Async.staticMethod(42);
+ }
+ return expect42(f());
+ });
+
+ test("instance function call", () {
+ f() async {
+ var a = new Async();
+ return await a.instanceMethod(42);
+ }
+ return expect42(f());
+ });
+
+ test("top-level function call w/ await", () {
+ f() async {
+ return await topMethod(await 42);
+ }
+ return expect42(f());
+ });
+
+ test("static function call w/ await", () {
+ f() async {
+ return await Async.staticMethod(await 42);
+ }
+ return expect42(f());
+ });
+
+ test("instance function call w/ await", () {
+ f() async {
+ var a = new Async();
+ return await a.instanceMethod(await 42);
+ }
+ return expect42(f());
+ });
+
+ test("top-level getter call", () {
+ f() async {
+ return await topGetter;
+ }
+ return expect42(f());
+ });
+
+ test("static getter call", () {
+ f() async {
+ return await Async.staticGetter;
+ }
+ return expect42(f());
+ });
+
+ test("top-level getter call", () {
+ f() async {
+ var a = new Async();
+ return await a.instanceGetter;
+ }
+ return expect42(f());
+ });
+
+ test("inside assert, true", () { /// 03: ok
+ f() async { /// 03: continued
+ assert(await new Future.microtask(() => true)); /// 03: continued
+ return 42; /// 03: continued
+ } /// 03: continued
+ return expect42(f()); /// 03: continued
+ }); /// 03: continued
+
+ test("inside assert, false", () { /// 03: continued
+ f() async { /// 03: continued
+ assert(await new Future.microtask(() => false)); /// 03: continued
+ return 42; /// 03: continued
+ } /// 03: continued
+ return f().then((_) { /// 03: continued
+ fail("assert didn't throw"); /// 03: continued
+ }, onError: (e, s) { /// 03: continued
+ expect(e is AssertionError, isTrue); /// 03: continued
+ }); /// 03: continued
+ }); /// 03: continued
+
+ test("inside assert, function -> false", () { /// 03: continued
+ f() async { /// 03: continued
+ assert(await new Future.microtask(() => false)); /// 03: continued
+ return 42; /// 03: continued
+ } /// 03: continued
+ return f().then((_) { /// 03: continued
+ fail("assert didn't throw"); /// 03: continued
+ }, onError: (e, s) { /// 03: continued
+ expect(e is AssertionError, isTrue); /// 03: continued
+ }); /// 03: continued
+ }); /// 03: continued
+
+ });
+
+ group("syntax", () {
+ test("async as variable", () {
+ // Valid identifiers outside of async function.
+ var async = 42;
+ expect(async, equals(42));
+ });
+
+ test("await as variable", () { /// 02: ok
+ // Valid identifiers outside of async function. /// 02: continued
+ var await = 42; /// 02: continued
+ expect(await, equals(42)); /// 02: continued
+ }); /// 02: continued
+
+ test("yield as variable", () {
+ // Valid identifiers outside of async function.
+ var yield = 42;
+ expect(yield, equals(42));
+ });
+ });
+}
+
+
+// Attempt to obfuscates value to avoid too much constant folding.
+id(v) {
+ try {
+ if (v != null) throw v;
+ } catch (e) {
+ return e;
+ }
+ return null;
+}
+
+// Create a stream for testing "async for-in".
+Stream mkStream() {
+ var c;
+ int i = 0;
+ next() {
+ c.add(i++);
+ if (i == 10) {
+ c.close();
+ } else {
+ scheduleMicrotask(next);
+ }
+ }
+ c = new StreamController(onListen: () {
+ scheduleMicrotask(next);
+ });
+ return c.stream;
+}
+
+// Check that future contains the error "err".
+Future throwsErr(Future future) {
+ return future.then((v) { fail("didn't throw"); },
+ onError: (e) { expect(e, equals("err")); });
+}
+
+// Check that future contains the value 42.
+Future expect42(Future future) {
+ return future.then((v) {
+ expect(v, equals(42));
+ });
+}
+
+
+// Various async declarations.
+
+Future topMethod(f) async { return await f; }
+
+Future topArrowMethod(f) async => await f;
+
+Future get topGetter async {
+ return await new Future.value(42);
+}
+
+Future get topArrowGetter async => await new Future.value(42);
+
+Future topLocal(f) {
+ local() async { return await f; }
+ return local();
+}
+
+Future topArrowLocal(f) {
+ local() async => await f;
+ return local();
+}
+
+Future topExpression(f) {
+ return () async { return await f; } ();
+}
+
+Future topArrowExpression(f) {
+ return (() async => await f) ();
+}
+
+var topVarExpression = (f) async { return await f; };
+
+var topVarArrowExpression = (f) async => await f;
+
+class Async {
+ var initValue;
+ Async();
+
+ Async.initializer(f) : initValue = (() async { return await f; } ());
+
+ Async.initializerArrow(f) : initValue = ((() async => await f) ());
+
+ /* static */
+ static Future staticMethod(f) async { return await f; }
+
+ static Future staticArrowMethod(f) async => await f;
+
+ static Future get staticGetter async {
+ return await new Future.value(42);
+ }
+
+ static Future get staticArrowGetter async => await new Future.value(42);
+
+ static Future staticLocal(f) {
+ local() async { return await f; }
+ return local();
+ }
+
+ static Future staticArrowLocal(f) {
+ local() async => await f;
+ return local();
+ }
+
+ static Future staticExpression(f) {
+ return () async { return await f; } ();
+ }
+
+ static Future staticArrowExpression(f) {
+ return (() async => await f) ();
+ }
+
+ static var staticVarExpression = (f) async { return await f; };
+
+ static var staticVarArrowExpression = (f) async => await f;
+
+ /* instance */
+ Future instanceMethod(f) async { return await f; }
+
+ Future instanceArrowMethod(f) async => await f;
+
+ Future get instanceGetter async {
+ return await new Future.value(42);
+ }
+
+ Future get instanceArrowGetter async => await new Future.value(42);
+
+ Future instanceLocal(f) {
+ local() async { return await f; }
+ return local();
+ }
+
+ Future instanceArrowLocal(f) {
+ local() async => await f;
+ return local();
+ }
+
+ Future instanceExpression(f) {
+ return () async { return await f; } ();
+ }
+
+ Future instanceArrowExpression(f) {
+ return (() async => await f) ();
+ }
+
+ var instanceVarExpression = (f) async { return await f; };
+
+ var instanceVarArrowExpression = (f) async => await f;
+}
+
+Future asyncInAsync(f) async {
+ inner(f) async {
+ return await f;
+ }
+ return await inner(f);
+}
+
+Future asyncInSync(f) {
+ inner(f) async {
+ return await f;
+ }
+ return inner(f);
+}
+
+Future syncInAsync(f) async {
+ inner(f) {
+ return f;
+ }
+ return await inner(f);
+}
+
+/**
+ * A non-standard implementation of Future with a value.
+ */
+class FakeValueFuture implements Future {
+ final _value;
+ FakeValueFuture(this._value);
+ Future then(callback(value), {Function onError}) {
+ return new Future.microtask(() => callback(_value));
+ }
+ Future whenComplete(callback()) {
+ return new Future.microtask(() { callback(); });
+ }
+ Future catchError(Function onError, {bool test(error)}) => this;
+ Stream asStream() => (new StreamController()..add(_value)..close()).stream;
+ Future timeout(Duration duration, {onTimeout}) => this;
+}
+
+typedef BinaryFunction(a, b);
+
+/**
+ * A non-standard implementation of Future with an error.
+ */
+class FakeErrorFuture implements Future {
+ final _error;
+ FakeErrorFuture(this._error);
+ Future then(callback(value), {Function onError}) {
+ if (onError != null) {
+ if (onError is BinaryFunction) {
+ return new Future.microtask(() => onError(_error, null));
+ }
+ return new Future.microtask(() => onError(_error));
+ }
+ return this;
+ }
+ Future whenComplete(callback()) {
+ return new Future.microtask(() { callback(); }).then((_) => this);
+ }
+ Future catchError(Function onError, {bool test(error)}) {
+ return new Future.microtask(() {
+ if (test != null && !test(_error)) return this;
+ if (onError is BinaryFunction) {
+ return onError(_error, null);
+ }
+ return onError(_error);
+ });
+ }
+ Stream asStream() =>
+ (new StreamController()..addError(_error)..close()).stream;
+ Future timeout(Duration duration, {onTimeout}) => this;
+}

Powered by Google App Engine
This is Rietveld 408576698