| // 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/async.dart'; |
| import 'package:test/test.dart'; |
| |
| import 'utils.dart'; |
| |
| void main() { |
| group("without being canceled", () { |
| CancelableCompleter completer; |
| setUp(() { |
| completer = |
| new CancelableCompleter(onCancel: expectAsync0(() {}, count: 0)); |
| }); |
| |
| test("sends values to the future", () { |
| expect(completer.operation.value, completion(equals(1))); |
| expect(completer.isCompleted, isFalse); |
| completer.complete(1); |
| expect(completer.isCompleted, isTrue); |
| }); |
| |
| test("sends errors to the future", () { |
| expect(completer.operation.value, throwsA("error")); |
| expect(completer.isCompleted, isFalse); |
| completer.completeError("error"); |
| expect(completer.isCompleted, isTrue); |
| }); |
| |
| test("sends values in a future to the future", () { |
| expect(completer.operation.value, completion(equals(1))); |
| expect(completer.isCompleted, isFalse); |
| completer.complete(new Future.value(1)); |
| expect(completer.isCompleted, isTrue); |
| }); |
| |
| test("sends errors in a future to the future", () { |
| expect(completer.operation.value, throwsA("error")); |
| expect(completer.isCompleted, isFalse); |
| completer.complete(new Future.error("error")); |
| expect(completer.isCompleted, isTrue); |
| }); |
| |
| test("sends values to valueOrCancellation", () { |
| expect(completer.operation.valueOrCancellation(), completion(equals(1))); |
| completer.complete(1); |
| }); |
| |
| test("sends errors to valueOrCancellation", () { |
| expect(completer.operation.valueOrCancellation(), throwsA("error")); |
| completer.completeError("error"); |
| }); |
| |
| group("throws a StateError if completed", () { |
| test("successfully twice", () { |
| completer.complete(1); |
| expect(() => completer.complete(1), throwsStateError); |
| }); |
| |
| test("successfully then unsuccessfully", () { |
| completer.complete(1); |
| expect(() => completer.completeError("error"), throwsStateError); |
| }); |
| |
| test("unsuccessfully twice", () { |
| expect(completer.operation.value, throwsA("error")); |
| completer.completeError("error"); |
| expect(() => completer.completeError("error"), throwsStateError); |
| }); |
| |
| test("successfully then with a future", () { |
| completer.complete(1); |
| expect( |
| () => completer.complete(new Completer().future), throwsStateError); |
| }); |
| |
| test("with a future then successfully", () { |
| completer.complete(new Completer().future); |
| expect(() => completer.complete(1), throwsStateError); |
| }); |
| |
| test("with a future twice", () { |
| completer.complete(new Completer().future); |
| expect( |
| () => completer.complete(new Completer().future), throwsStateError); |
| }); |
| }); |
| |
| group("CancelableOperation.fromFuture", () { |
| test("forwards values", () { |
| var operation = new CancelableOperation.fromFuture(new Future.value(1)); |
| expect(operation.value, completion(equals(1))); |
| }); |
| |
| test("forwards errors", () { |
| var operation = |
| new CancelableOperation.fromFuture(new Future.error("error")); |
| expect(operation.value, throwsA("error")); |
| }); |
| }); |
| }); |
| |
| group("when canceled", () { |
| test("causes the future never to fire", () async { |
| var completer = new CancelableCompleter(); |
| completer.operation.value.whenComplete(expectAsync0(() {}, count: 0)); |
| completer.operation.cancel(); |
| |
| // Give the future plenty of time to fire if it's going to. |
| await flushMicrotasks(); |
| completer.complete(); |
| await flushMicrotasks(); |
| }); |
| |
| test("fires onCancel", () { |
| var canceled = false; |
| CancelableCompleter completer; |
| completer = new CancelableCompleter(onCancel: expectAsync0(() { |
| expect(completer.isCanceled, isTrue); |
| canceled = true; |
| })); |
| |
| expect(canceled, isFalse); |
| expect(completer.isCanceled, isFalse); |
| expect(completer.isCompleted, isFalse); |
| completer.operation.cancel(); |
| expect(canceled, isTrue); |
| expect(completer.isCanceled, isTrue); |
| expect(completer.isCompleted, isFalse); |
| }); |
| |
| test("returns the onCancel future each time cancel is called", () { |
| var completer = new CancelableCompleter(onCancel: expectAsync0(() { |
| return new Future.value(1); |
| })); |
| expect(completer.operation.cancel(), completion(equals(1))); |
| expect(completer.operation.cancel(), completion(equals(1))); |
| expect(completer.operation.cancel(), completion(equals(1))); |
| }); |
| |
| test("returns a future even if onCancel doesn't", () { |
| var completer = new CancelableCompleter(onCancel: expectAsync0(() {})); |
| expect(completer.operation.cancel(), completes); |
| }); |
| |
| test("doesn't call onCancel if the completer has completed", () { |
| var completer = |
| new CancelableCompleter(onCancel: expectAsync0(() {}, count: 0)); |
| completer.complete(1); |
| expect(completer.operation.value, completion(equals(1))); |
| expect(completer.operation.cancel(), completes); |
| }); |
| |
| test( |
| "does call onCancel if the completer has completed to an unfired " |
| "Future", () { |
| var completer = new CancelableCompleter(onCancel: expectAsync0(() {})); |
| completer.complete(new Completer().future); |
| expect(completer.operation.cancel(), completes); |
| }); |
| |
| test( |
| "doesn't call onCancel if the completer has completed to a fired " |
| "Future", () async { |
| var completer = |
| new CancelableCompleter(onCancel: expectAsync0(() {}, count: 0)); |
| completer.complete(new Future.value(1)); |
| await completer.operation.value; |
| expect(completer.operation.cancel(), completes); |
| }); |
| |
| test("can be completed once after being canceled", () async { |
| var completer = new CancelableCompleter(); |
| completer.operation.value.whenComplete(expectAsync0(() {}, count: 0)); |
| await completer.operation.cancel(); |
| completer.complete(1); |
| expect(() => completer.complete(1), throwsStateError); |
| }); |
| |
| test("fires valueOrCancellation with the given value", () { |
| var completer = new CancelableCompleter(); |
| expect(completer.operation.valueOrCancellation(1), completion(equals(1))); |
| completer.operation.cancel(); |
| }); |
| |
| test("pipes an error through valueOrCancellation", () { |
| var completer = new CancelableCompleter(onCancel: () { |
| throw "error"; |
| }); |
| expect(completer.operation.valueOrCancellation(1), throwsA("error")); |
| completer.operation.cancel(); |
| }); |
| |
| test("valueOrCancellation waits on the onCancel future", () async { |
| var innerCompleter = new Completer(); |
| var completer = |
| new CancelableCompleter(onCancel: () => innerCompleter.future); |
| |
| var fired = false; |
| completer.operation.valueOrCancellation().then((_) { |
| fired = true; |
| }); |
| |
| completer.operation.cancel(); |
| await flushMicrotasks(); |
| expect(fired, isFalse); |
| |
| innerCompleter.complete(); |
| await flushMicrotasks(); |
| expect(fired, isTrue); |
| }); |
| }); |
| |
| group("asStream()", () { |
| test("emits a value and then closes", () { |
| var completer = new CancelableCompleter(); |
| expect(completer.operation.asStream().toList(), completion(equals([1]))); |
| completer.complete(1); |
| }); |
| |
| test("emits an error and then closes", () { |
| var completer = new CancelableCompleter(); |
| var queue = new StreamQueue(completer.operation.asStream()); |
| expect(queue.next, throwsA("error")); |
| expect(queue.hasNext, completion(isFalse)); |
| completer.completeError("error"); |
| }); |
| |
| test("cancels the completer when the subscription is canceled", () { |
| var completer = new CancelableCompleter(onCancel: expectAsync0(() {})); |
| var sub = |
| completer.operation.asStream().listen(expectAsync1((_) {}, count: 0)); |
| completer.operation.value.whenComplete(expectAsync0(() {}, count: 0)); |
| sub.cancel(); |
| expect(completer.isCanceled, isTrue); |
| }); |
| }); |
| } |