| Index: pkg/analyzer/test/cancelable_future_test.dart
|
| diff --git a/pkg/analyzer/test/cancelable_future_test.dart b/pkg/analyzer/test/cancelable_future_test.dart
|
| index c9d88f29ccbd0d23845a075952ca34486991538c..b28c0f9482c1b99dcf41960b58bc9c4965ff6bec 100644
|
| --- a/pkg/analyzer/test/cancelable_future_test.dart
|
| +++ b/pkg/analyzer/test/cancelable_future_test.dart
|
| @@ -4,157 +4,162 @@
|
|
|
| library test.cancelable_future;
|
|
|
| -import 'reflective_tests.dart';
|
| -import 'package:analyzer/src/cancelable_future.dart';
|
| 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() {
|
| - groupSep = ' | ';
|
| + initializeTestEnvironment();
|
| runReflectiveTests(CancelableCompleterTests);
|
| runReflectiveTests(CancelableFutureTests);
|
| }
|
|
|
| @reflectiveTest
|
| -class CancelableFutureTests {
|
| - 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);
|
| +class CancelableCompleterTests {
|
| + CancelableCompleter<Object> completer;
|
| + int cancelCount = 0;
|
| +
|
| + void setUp() {
|
| + completer = new CancelableCompleter<Object>(() {
|
| + cancelCount++;
|
| });
|
| }
|
|
|
| - 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;
|
| + 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) {
|
| - fail('Expected successful completion');
|
| - });
|
| - expect(callbackInvoked, isFalse);
|
| - return pumpEventQueue().then((_) {
|
| - expect(callbackInvoked, isTrue);
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 1);
|
| });
|
| }
|
|
|
| - Future test_defaultConstructor_throwException() {
|
| - Object obj = new Object();
|
| + Future test_cancel_after_chaining() {
|
| bool callbackInvoked = false;
|
| - new CancelableFuture(() {
|
| - throw obj;
|
| - }).then((result) {
|
| + completer.future.then((_) {
|
| fail('Expected error completion');
|
| }, onError: (error) {
|
| expect(callbackInvoked, isFalse);
|
| - expect(error, same(obj));
|
| + 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_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() {
|
| + Future test_cancel_after_complete() {
|
| 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) {
|
| + 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_error() {
|
| - Object obj = new Object();
|
| - return new CancelableFuture.error(obj).then((result) {
|
| + 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(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));
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| callbackInvoked = true;
|
| - }, onError: (error) {
|
| - fail('Expected successful completion');
|
| });
|
| + // 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_sync() {
|
| + 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();
|
| - bool callbackInvoked = false;
|
| - new CancelableFuture.sync(() => obj).then((result) {
|
| - expect(callbackInvoked, isFalse);
|
| - expect(result, same(obj));
|
| - callbackInvoked = true;
|
| + 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) {
|
| - fail('Expected successful completion');
|
| - });
|
| - expect(callbackInvoked, isFalse);
|
| - return pumpEventQueue().then((_) {
|
| - expect(callbackInvoked, isTrue);
|
| + expect(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| + expect(completer.isCompleted, isTrue);
|
| + expect(cancelCount, 1);
|
| });
|
| }
|
|
|
| - Future test_value() {
|
| + Future test_complete_after_chaining() {
|
| Object obj = new Object();
|
| - return new CancelableFuture.value(obj).then((result) {
|
| + bool callbackInvoked = false;
|
| + completer.future.then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| expect(result, same(obj));
|
| + callbackInvoked = true;
|
| }, onError: (error) {
|
| fail('Expected successful completion');
|
| });
|
| - }
|
| -}
|
| -
|
| -@reflectiveTest
|
| -class CancelableCompleterTests {
|
| - CancelableCompleter<Object> completer;
|
| - int cancelCount = 0;
|
| -
|
| - void setUp() {
|
| - completer = new CancelableCompleter<Object>(() {
|
| - cancelCount++;
|
| - });
|
| - }
|
| -
|
| - void test_initialState() {
|
| expect(completer.isCompleted, isFalse);
|
| - expect(cancelCount, 0);
|
| + // 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() {
|
| @@ -205,43 +210,43 @@ class CancelableCompleterTests {
|
| });
|
| }
|
|
|
| - Future test_completeError_before_chaining() {
|
| + 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);
|
| - bool callbackInvoked = false;
|
| - completer.future.then((_) {
|
| + // Make sure the future still completes with error.
|
| + return 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(error, new isInstanceOf<FutureCanceledError>());
|
| + // And make sure nothing else happens.
|
| + }).then((_) => pumpEventQueue()).then((_) {
|
| expect(completer.isCompleted, isTrue);
|
| - expect(cancelCount, 0);
|
| + expect(cancelCount, 1);
|
| });
|
| }
|
|
|
| - Future test_complete_after_chaining() {
|
| + Future test_completeError_after_chaining() {
|
| Object obj = new Object();
|
| bool callbackInvoked = false;
|
| - completer.future.then((result) {
|
| + completer.future.then((_) {
|
| + fail('Expected error completion');
|
| + }, onError: (error) {
|
| expect(callbackInvoked, isFalse);
|
| - expect(result, same(obj));
|
| + expect(error, 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);
|
| + completer.completeError(obj);
|
| expect(completer.isCompleted, isTrue);
|
| // The callback should be deferred to a microtask.
|
| expect(callbackInvoked, isFalse);
|
| @@ -252,8 +257,10 @@ class CancelableCompleterTests {
|
| });
|
| }
|
|
|
| - Future test_completeError_after_chaining() {
|
| + 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');
|
| @@ -262,147 +269,143 @@ class CancelableCompleterTests {
|
| 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.
|
| + // The callback should be deferred to a microtask.
|
| + expect(callbackInvoked, isFalse);
|
| + expect(completer.isCompleted, isTrue);
|
| 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_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.
|
| + void test_initialState() {
|
| expect(completer.isCompleted, isFalse);
|
| + expect(cancelCount, 0);
|
| + }
|
| +}
|
| +
|
| +@reflectiveTest
|
| +class CancelableFutureTests {
|
| + Future test_defaultConstructor_returnFuture() {
|
| + Object obj = new Object();
|
| bool callbackInvoked = false;
|
| - completer.future.then((_) {
|
| - fail('Expected error completion');
|
| + 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(error, new isInstanceOf<FutureCanceledError>());
|
| + 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, isFalse);
|
| return pumpEventQueue().then((_) {
|
| expect(callbackInvoked, isTrue);
|
| - expect(completer.isCompleted, isFalse);
|
| - expect(cancelCount, 1);
|
| });
|
| }
|
|
|
| - Future test_cancel_after_chaining() {
|
| + Future test_defaultConstructor_throwException() {
|
| + Object obj = new Object();
|
| bool callbackInvoked = false;
|
| - completer.future.then((_) {
|
| + new CancelableFuture(() {
|
| + throw obj;
|
| + }).then((result) {
|
| fail('Expected error completion');
|
| }, onError: (error) {
|
| expect(callbackInvoked, isFalse);
|
| - expect(error, new isInstanceOf<FutureCanceledError>());
|
| + expect(error, same(obj));
|
| 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() {
|
| + 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();
|
| - 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) {
|
| + 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));
|
| - // And make sure nothing else happens.
|
| - }).then((_) => pumpEventQueue()).then((_) {
|
| - expect(completer.isCompleted, isTrue);
|
| - expect(cancelCount, 0);
|
| });
|
| }
|
|
|
| - 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);
|
| + Future test_error() {
|
| Object obj = new Object();
|
| - completer.complete(obj);
|
| - expect(completer.isCompleted, isTrue);
|
| - // Make sure the future still completer with error.
|
| - return completer.future.then((_) {
|
| + return new CancelableFuture.error(obj).then((result) {
|
| 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);
|
| + expect(error, same(obj));
|
| });
|
| }
|
|
|
| - 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);
|
| + Future test_microtask() {
|
| 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');
|
| + bool callbackInvoked = false;
|
| + new CancelableFuture.microtask(() => obj).then((result) {
|
| + expect(callbackInvoked, isFalse);
|
| + expect(result, same(obj));
|
| + callbackInvoked = true;
|
| }, onError: (error) {
|
| - expect(error, new isInstanceOf<FutureCanceledError>());
|
| - // And make sure nothing else happens.
|
| - }).then((_) => pumpEventQueue()).then((_) {
|
| - expect(completer.isCompleted, isTrue);
|
| - expect(cancelCount, 1);
|
| + fail('Expected successful completion');
|
| + });
|
| + expect(callbackInvoked, isFalse);
|
| + return pumpEventQueue().then((_) {
|
| + expect(callbackInvoked, isTrue);
|
| });
|
| }
|
|
|
| - 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');
|
| + 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) {
|
| - expect(error, new isInstanceOf<FutureCanceledError>());
|
| - // And make sure nothing else happens.
|
| - }).then((_) => pumpEventQueue()).then((_) {
|
| - expect(completer.isCompleted, isFalse);
|
| - expect(cancelCount, 1);
|
| + 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');
|
| });
|
| }
|
| }
|
|
|