| // Copyright (c) 2020, 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. | |
| // Checks that `Future<Future<int>>` is a valid type | |
| // and that futures can contain and complete other futures. | |
| // This essentially checks that `FutureOr<X>` is treated correctly depending | |
| // on what `X` is. | |
| import 'dart:async'; | |
| import 'package:expect/async_helper.dart'; | |
| import "package:expect/expect.dart"; | |
| main() { | |
| asyncStart(); | |
| // Helper values and factories. | |
| Future<Null> nullFuture = Future<Null>.value(null); | |
| var stack = StackTrace.current; | |
| var error = ArgumentError("yep"); | |
| Future<Null> errorFuture = Future<Null>.error(error, stack) | |
| ..catchError((_) => null); | |
| Future<int> fi(int n) => Future<int>.value(n); | |
| Future<Future<int>> ffi(n) => Future<Future<int>>.value(fi(n)); | |
| // Tests that `Future<Future<int>>` can be created. | |
| asyncTest(() { | |
| return expectFutureFutureInt(ffi(0), 0); | |
| }); | |
| // Check `Future.then`'s callback. | |
| asyncTest(() { | |
| Future<int> future = nullFuture.then<int>((_) => fi(1)); | |
| return expectFutureInt(future, 1); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> future = nullFuture.then<Future<int>>((_) => fi(2)); | |
| return expectFutureFutureInt(future, 2); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> future = nullFuture.then<Future<int>>((_) => ffi(3)); | |
| return expectFutureFutureInt(future, 3); | |
| }); | |
| // Check `Future.then`'s `onError`. | |
| asyncTest(() { | |
| Future<int> future = errorFuture.then<int>( | |
| (_) => -1, | |
| onError: (_) => fi(4), | |
| ); | |
| return expectFutureInt(future, 4); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> future = errorFuture.then<Future<int>>( | |
| (_) => fi(-1), | |
| onError: (_) => fi(5), | |
| ); | |
| return expectFutureFutureInt(future, 5); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> future = errorFuture.then<Future<int>>( | |
| (_) => fi(-1), | |
| onError: (_) => ffi(6), | |
| ); | |
| return expectFutureFutureInt(future, 6); | |
| }); | |
| // Check `Future.catchError`. | |
| // Its implied `FutureOr` return type is based on the original future's type. | |
| asyncTest(() { | |
| Future<int> errorFuture = Future<int>.error(error, stack); | |
| Future<int> future = errorFuture.catchError((_) => fi(7)); | |
| return expectFutureInt(future, 7); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack); | |
| Future<Future<int>> future = errorFuture.catchError((_) => fi(8)); | |
| return expectFutureFutureInt(future, 8); | |
| }); | |
| asyncTest(() { | |
| Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack); | |
| Future<Future<int>> future = errorFuture.catchError((_) => ffi(9)); | |
| return expectFutureFutureInt(future, 9); | |
| }); | |
| // Check `Completer.complete`. | |
| asyncTest(() { | |
| var completer = Completer<int>()..complete(fi(10)); | |
| return expectFutureInt(completer.future, 10); | |
| }); | |
| asyncTest(() { | |
| var completer = Completer<Future<int>>()..complete(fi(11)); | |
| return expectFutureFutureInt(completer.future, 11); | |
| }); | |
| asyncTest(() { | |
| var completer = Completer<Future<int>>()..complete(ffi(12)); | |
| return expectFutureFutureInt(completer.future, 12); | |
| }); | |
| // Future<Object> works correctly when Object is another Future. | |
| asyncTest(() { | |
| Future<Object> future = nullFuture.then<Object>((_) => fi(13)); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| return future.then<void>((o) { | |
| Expect.equals(13, o); | |
| }); | |
| }); | |
| asyncTest(() { | |
| Future<Object> future = nullFuture.then<Object>((_) => ffi(14)); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| Expect.notType<Future<Future<int>>>(future); | |
| return future.then<void>((v) => expectFutureInt(v, 14)); | |
| }); | |
| asyncTest(() { | |
| Future<Object> future = errorFuture.then<Object>( | |
| (_) => -1, | |
| onError: (_) => fi(15), | |
| ); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| return future.then<void>((o) { | |
| Expect.equals(15, o); | |
| }); | |
| }); | |
| asyncTest(() { | |
| Future<Object> future = errorFuture.then<Object>( | |
| (_) => -1, | |
| onError: (_) => ffi(16), | |
| ); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| Expect.notType<Future<Future<int>>>(future); | |
| return future.then<void>((v) => expectFutureInt(v, 16)); | |
| }); | |
| asyncTest(() { | |
| Future<Object> errorFuture = Future<Object>.error(error, stack); | |
| Future<Object> future = errorFuture.catchError((_) => fi(17)); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| return future.then<void>((o) { | |
| Expect.equals(17, o); | |
| }); | |
| }); | |
| asyncTest(() { | |
| Future<Object> errorFuture = Future<Object>.error(error, stack); | |
| Future<Object> future = errorFuture.catchError((_) => ffi(18)); | |
| Expect.type<Future<Object>>(future); | |
| Expect.notType<Future<int>>(future); | |
| Expect.notType<Future<Future<int>>>(future); | |
| return future.then<void>((v) => expectFutureInt(v, 18)); | |
| }); | |
| asyncEnd(); | |
| } | |
| // Checks that future is a Future<Future<int>> containing the value Future<int> | |
| // which then contains the value 42. | |
| Future<void> expectFutureFutureInt(dynamic future, int n) { | |
| Expect.type<Future<Future<int>>>(future); | |
| asyncStart(); | |
| return future.then<void>((dynamic v) { | |
| Expect.type<Future<int>>(v, "$n"); | |
| return expectFutureInt(v, n).then(asyncSuccess); | |
| }); | |
| } | |
| Future<void> expectFutureInt(dynamic future, int n) { | |
| Expect.type<Future<int>>(future); | |
| asyncStart(); | |
| return future.then<void>((dynamic v) { | |
| Expect.type<int>(v, "$n"); | |
| Expect.equals(n, v); | |
| asyncEnd(); | |
| }); | |
| } |