| Index: mojo/public/dart/third_party/analyzer/test/cancelable_future_test.dart
|
| diff --git a/mojo/public/dart/third_party/analyzer/test/cancelable_future_test.dart b/mojo/public/dart/third_party/analyzer/test/cancelable_future_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b28c0f9482c1b99dcf41960b58bc9c4965ff6bec
|
| --- /dev/null
|
| +++ b/mojo/public/dart/third_party/analyzer/test/cancelable_future_test.dart
|
| @@ -0,0 +1,411 @@
|
| +// Copyright (c) 2014, 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 test.cancelable_future;
|
| +
|
| +import 'dart:async';
|
| +
|
| +import 'package:analyzer/src/cancelable_future.dart';
|
| +import 'package:unittest/unittest.dart';
|
| +import 'package:watcher/src/utils.dart';
|
| +
|
| +import 'reflective_tests.dart';
|
| +import 'utils.dart';
|
| +
|
| +void main() {
|
| + initializeTestEnvironment();
|
| + runReflectiveTests(CancelableCompleterTests);
|
| + runReflectiveTests(CancelableFutureTests);
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class CancelableCompleterTests {
|
| + CancelableCompleter<Object> completer;
|
| + int cancelCount = 0;
|
| +
|
| + void setUp() {
|
| + completer = new CancelableCompleter<Object>(() {
|
| + cancelCount++;
|
| + });
|
| + }
|
| +
|
| + Future test_cancel_after_cancel() {
|
| + // It is permissible to cancel multiple times, but only the first
|
| + // cancellation has any effect.
|
| + expect(cancelCount, 0);
|
| + completer.future.cancel();
|
| + expect(cancelCount, 1);
|
| + completer.future.cancel();
|
| + expect(cancelCount, 1);
|
| + // Make sure the future still completes with error.
|
| + return completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 1);
|
| + });
|
| + }
|
| +
|
| + Future test_cancel_after_chaining() {
|
| + bool callbackInvoked = false;
|
| + completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + callbackInvoked = true;
|
| + });
|
| + expect(cancelCount, 0);
|
| + completer.future.cancel();
|
| + // The cancel callback should have been invoked immediately.
|
| + expect(cancelCount, 1);
|
| + // But the completer should remain in the "not completed" state.
|
| + expect(completer.isCompleted, isFalse);
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 1);
|
| + });
|
| + }
|
| +
|
| + Future test_cancel_after_complete() {
|
| + Object obj = new Object();
|
| + completer.complete(obj);
|
| + completer.future.cancel();
|
| + // The cancel callback should not have been invoked, because it was too
|
| + // late to cancel.
|
| + expect(cancelCount, 0);
|
| + // Make sure the future still completes with the object.
|
| + return completer.future.then((result) {
|
| + expect(result, same(obj));
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 0);
|
| + });
|
| + }
|
| +
|
| + Future test_cancel_before_chaining() {
|
| + completer.future.cancel();
|
| + // The cancel callback should have been invoked immediately.
|
| + expect(cancelCount, 1);
|
| + // But the completer should remain in the "not completed" state.
|
| + expect(completer.isCompleted, isFalse);
|
| + bool callbackInvoked = false;
|
| + completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + callbackInvoked = true;
|
| + });
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + expect(completer.isCompleted, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 1);
|
| + });
|
| + }
|
| +
|
| + Future test_complete_after_cancel() {
|
| + completer.future.cancel();
|
| + // The cancel callback should have been invoked immediately.
|
| + expect(cancelCount, 1);
|
| + // Completing should have no effect other than to set the isCompleted
|
| + // flag.
|
| + expect(completer.isCompleted, isFalse);
|
| + Object obj = new Object();
|
| + completer.complete(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + // Make sure the future still completer with error.
|
| + return completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 1);
|
| + });
|
| + }
|
| +
|
| + Future test_complete_after_chaining() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + completer.future.then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(completer.isCompleted, isFalse);
|
| + // Running the event loop should have no effect since the completer hasn't
|
| + // been completed yet.
|
| + return pumpEventQueue().then((_) {
|
| + completer.complete(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 0);
|
| + });
|
| + }
|
| +
|
| + void test_complete_after_complete() {
|
| + // As with an ordinary Completer, calling complete() (or completeError)
|
| + // after calling complete() should throw an exception.
|
| + completer.complete();
|
| + expect(() {
|
| + completer.complete();
|
| + }, throws);
|
| + expect(() {
|
| + completer.completeError(new Object());
|
| + }, throws);
|
| + }
|
| +
|
| + void test_complete_after_completeError() {
|
| + // As with an ordinary Completer, calling complete() (or completeError)
|
| + // after calling completeError() should throw an exception.
|
| + completer.completeError(new Object());
|
| + expect(() {
|
| + completer.complete();
|
| + }, throws);
|
| + expect(() {
|
| + completer.completeError(new Object());
|
| + }, throws);
|
| + // Now absorb the error that's in the completer's future.
|
| + completer.future.catchError((_) => null);
|
| + }
|
| +
|
| + Future test_complete_before_chaining() {
|
| + Object obj = new Object();
|
| + completer.complete(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + bool callbackInvoked = false;
|
| + completer.future.then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + expect(completer.isCompleted, isTrue);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 0);
|
| + });
|
| + }
|
| +
|
| + Future test_completeError_after_cancel() {
|
| + completer.future.cancel();
|
| + // The cancel callback should have been invoked immediately.
|
| + expect(cancelCount, 1);
|
| + // Completing should have no effect other than to set the isCompleted
|
| + // flag.
|
| + expect(completer.isCompleted, isFalse);
|
| + Object obj = new Object();
|
| + completer.completeError(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + // Make sure the future still completes with error.
|
| + return completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 1);
|
| + });
|
| + }
|
| +
|
| + Future test_completeError_after_chaining() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(error, same(obj));
|
| + callbackInvoked = true;
|
| + });
|
| + expect(completer.isCompleted, isFalse);
|
| + // Running the event loop should have no effect since the completer hasn't
|
| + // been completed yet.
|
| + return pumpEventQueue().then((_) {
|
| + completer.completeError(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 0);
|
| + });
|
| + }
|
| +
|
| + Future test_completeError_before_chaining() {
|
| + Object obj = new Object();
|
| + completer.completeError(obj);
|
| + expect(completer.isCompleted, isTrue);
|
| + bool callbackInvoked = false;
|
| + completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(error, same(obj));
|
| + callbackInvoked = true;
|
| + });
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + expect(completer.isCompleted, isTrue);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 0);
|
| + });
|
| + }
|
| +
|
| + void test_initialState() {
|
| + expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 0);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class CancelableFutureTests {
|
| + Future test_defaultConstructor_returnFuture() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture(() => new Future(() => obj)).then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_defaultConstructor_returnValue() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture(() => obj).then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_defaultConstructor_throwException() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture(() {
|
| + throw obj;
|
| + }).then((result) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(error, same(obj));
|
| + callbackInvoked = true;
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_delayed_noCallback() {
|
| + DateTime start = new DateTime.now();
|
| + return new CancelableFuture.delayed(new Duration(seconds: 1))
|
| + .then((result) {
|
| + DateTime end = new DateTime.now();
|
| + expect(result, isNull);
|
| + expect(end.difference(start).inMilliseconds > 900, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_delayed_withCallback() {
|
| + Object obj = new Object();
|
| + DateTime start = new DateTime.now();
|
| + return new CancelableFuture.delayed(new Duration(seconds: 1), () {
|
| + DateTime end = new DateTime.now();
|
| + expect(end.difference(start).inMilliseconds > 900, isTrue);
|
| + return obj;
|
| + }).then((result) {
|
| + expect(result, same(obj));
|
| + });
|
| + }
|
| +
|
| + Future test_error() {
|
| + Object obj = new Object();
|
| + return new CancelableFuture.error(obj).then((result) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| + expect(error, same(obj));
|
| + });
|
| + }
|
| +
|
| + Future test_microtask() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture.microtask(() => obj).then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_sync() {
|
| + Object obj = new Object();
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture.sync(() => obj).then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| + });
|
| + }
|
| +
|
| + Future test_value() {
|
| + Object obj = new Object();
|
| + return new CancelableFuture.value(obj).then((result) {
|
| + expect(result, same(obj));
|
| + }, onError: (error) {
|
| + fail('Expected successful completion');
|
| + });
|
| + }
|
| +}
|
|
|