Index: packages/async/test/future_group_test.dart |
diff --git a/packages/async/test/future_group_test.dart b/packages/async/test/future_group_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..09ea29a0abd0a364fce633b92c92c9d6dc5835de |
--- /dev/null |
+++ b/packages/async/test/future_group_test.dart |
@@ -0,0 +1,220 @@ |
+// 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. |
+ |
+import 'dart:async'; |
+ |
+import 'package:async/src/future_group.dart'; |
+import 'package:test/test.dart'; |
+ |
+import 'utils.dart'; |
+ |
+void main() { |
+ var futureGroup; |
+ setUp(() { |
+ futureGroup = new FutureGroup(); |
+ }); |
+ |
+ group("with no futures", () { |
+ test("never completes if nothing happens", () async { |
+ var completed = false; |
+ futureGroup.future.then((_) => completed = true); |
+ |
+ await flushMicrotasks(); |
+ expect(completed, isFalse); |
+ }); |
+ |
+ test("completes once it's closed", () { |
+ expect(futureGroup.future, completion(isEmpty)); |
+ futureGroup.close(); |
+ }); |
+ }); |
+ |
+ group("with a future that already completed", () { |
+ test("never completes if nothing happens", () async { |
+ futureGroup.add(new Future.value()); |
+ await flushMicrotasks(); |
+ |
+ var completed = false; |
+ futureGroup.future.then((_) => completed = true); |
+ |
+ await flushMicrotasks(); |
+ expect(completed, isFalse); |
+ }); |
+ |
+ test("completes once it's closed", () async { |
+ futureGroup.add(new Future.value()); |
+ await flushMicrotasks(); |
+ |
+ expect(futureGroup.future, completes); |
+ futureGroup.close(); |
+ }); |
+ |
+ test("completes to that future's value", () { |
+ futureGroup.add(new Future.value(1)); |
+ futureGroup.close(); |
+ expect(futureGroup.future, completion(equals([1]))); |
+ }); |
+ |
+ test("completes to that future's error, even if it's not closed", () { |
+ futureGroup.add(new Future.error("error")); |
+ expect(futureGroup.future, throwsA("error")); |
+ }); |
+ }); |
+ |
+ test("completes once all contained futures complete", () async { |
+ var completer1 = new Completer(); |
+ var completer2 = new Completer(); |
+ var completer3 = new Completer(); |
+ |
+ futureGroup.add(completer1.future); |
+ futureGroup.add(completer2.future); |
+ futureGroup.add(completer3.future); |
+ futureGroup.close(); |
+ |
+ var completed = false; |
+ futureGroup.future.then((_) => completed = true); |
+ |
+ completer1.complete(); |
+ await flushMicrotasks(); |
+ expect(completed, isFalse); |
+ |
+ completer2.complete(); |
+ await flushMicrotasks(); |
+ expect(completed, isFalse); |
+ |
+ completer3.complete(); |
+ await flushMicrotasks(); |
+ expect(completed, isTrue); |
+ }); |
+ |
+ test("completes to the values of the futures in order of addition", () { |
+ var completer1 = new Completer(); |
+ var completer2 = new Completer(); |
+ var completer3 = new Completer(); |
+ |
+ futureGroup.add(completer1.future); |
+ futureGroup.add(completer2.future); |
+ futureGroup.add(completer3.future); |
+ futureGroup.close(); |
+ |
+ // Complete the completers in reverse order to prove that that doesn't |
+ // affect the result order. |
+ completer3.complete(3); |
+ completer2.complete(2); |
+ completer1.complete(1); |
+ expect(futureGroup.future, completion(equals([1, 2, 3]))); |
+ }); |
+ |
+ test("completes to the first error to be emitted, even if it's not closed", |
+ () { |
+ var completer1 = new Completer(); |
+ var completer2 = new Completer(); |
+ var completer3 = new Completer(); |
+ |
+ futureGroup.add(completer1.future); |
+ futureGroup.add(completer2.future); |
+ futureGroup.add(completer3.future); |
+ |
+ completer2.completeError("error 2"); |
+ completer1.completeError("error 1"); |
+ expect(futureGroup.future, throwsA("error 2")); |
+ }); |
+ |
+ group("onIdle:", () { |
+ test("emits an event when the last pending future completes", () async { |
+ var idle = false; |
+ futureGroup.onIdle.listen((_) => idle = true); |
+ |
+ var completer1 = new Completer(); |
+ var completer2 = new Completer(); |
+ var completer3 = new Completer(); |
+ |
+ futureGroup.add(completer1.future); |
+ futureGroup.add(completer2.future); |
+ futureGroup.add(completer3.future); |
+ |
+ await flushMicrotasks(); |
+ expect(idle, isFalse); |
+ expect(futureGroup.isIdle, isFalse); |
+ |
+ completer1.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isFalse); |
+ expect(futureGroup.isIdle, isFalse); |
+ |
+ completer2.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isFalse); |
+ expect(futureGroup.isIdle, isFalse); |
+ |
+ completer3.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isTrue); |
+ expect(futureGroup.isIdle, isTrue); |
+ }); |
+ |
+ test("emits an event each time it becomes idle", () async { |
+ var idle = false; |
+ futureGroup.onIdle.listen((_) => idle = true); |
+ |
+ var completer = new Completer(); |
+ futureGroup.add(completer.future); |
+ |
+ completer.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isTrue); |
+ expect(futureGroup.isIdle, isTrue); |
+ |
+ idle = false; |
+ completer = new Completer(); |
+ futureGroup.add(completer.future); |
+ |
+ await flushMicrotasks(); |
+ expect(idle, isFalse); |
+ expect(futureGroup.isIdle, isFalse); |
+ |
+ completer.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isTrue); |
+ expect(futureGroup.isIdle, isTrue); |
+ }); |
+ |
+ test("emits an event when the group closes", () async { |
+ // It's important that the order of events here stays consistent over |
+ // time, since code may rely on it in subtle ways. |
+ var idle = false; |
+ var onIdleDone = false; |
+ var futureFired = false; |
+ |
+ futureGroup.onIdle.listen(expectAsync((_) { |
+ expect(futureFired, isFalse); |
+ idle = true; |
+ }), onDone: expectAsync(() { |
+ expect(idle, isTrue); |
+ expect(futureFired, isFalse); |
+ onIdleDone = true; |
+ })); |
+ |
+ futureGroup.future.then(expectAsync((_) { |
+ expect(idle, isTrue); |
+ expect(onIdleDone, isTrue); |
+ futureFired = true; |
+ })); |
+ |
+ var completer = new Completer(); |
+ futureGroup.add(completer.future); |
+ futureGroup.close(); |
+ |
+ await flushMicrotasks(); |
+ expect(idle, isFalse); |
+ expect(futureGroup.isIdle, isFalse); |
+ |
+ completer.complete(); |
+ await flushMicrotasks(); |
+ expect(idle, isTrue); |
+ expect(futureGroup.isIdle, isTrue); |
+ expect(futureFired, isTrue); |
+ }); |
+ }); |
+} |