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