From 6928e0ec4c4663131596ae18eb3db66f383c7c36 Mon Sep 17 00:00:00 2001 From: huhaosumail <995483610@qq.com> Date: Thu, 11 Jul 2024 16:18:12 +0800 Subject: [PATCH] feat: implement `allSuccess*` methods in `CompletableFutureUtils` (#197) --- .../cffu/CompletableFutureUtils.java | 456 +++++++++++++++++- .../cffu/CompletableFutureUtilsTest.java | 79 +++ 2 files changed, 533 insertions(+), 2 deletions(-) diff --git a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index 362ad82e..c9028a7f 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -73,6 +73,57 @@ public static CompletableFuture> mSupplyFastFailAsync( return allResultsFastFailOf(wrapSuppliers(executor, suppliers)); } + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the CompletableFuture's default asynchronous execution facility + * with the most values obtained by calling the given Suppliers + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param valueIfNotSuccess the value to return if not completed successfully + * @param suppliers the suppliers returning the value to be used to complete the returned CompletableFuture + * @param the suppliers' return type + * @return the new CompletableFuture + * @see #mostSuccessResultsOf(Object, long, TimeUnit, CompletionStage[]) + * @see CompletableFuture#supplyAsync(Supplier) + */ + @SafeVarargs + public static CompletableFuture> mSupplyAllSuccessAsync( + @Nullable T valueIfNotSuccess, Supplier... suppliers) { + return mSupplyAllSuccessAsync(valueIfNotSuccess, ASYNC_POOL, suppliers); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the given Executor with the most values obtained by calling the given Suppliers + * in the given time({@code timeout}, aka as many results as possible in the given time) + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param valueIfNotSuccess the value to return if not completed successfully + * @param executor the executor to use for asynchronous execution + * @param suppliers the suppliers returning the value to be used to complete the returned CompletableFuture + * @param the suppliers' return type + * @return the new CompletableFuture + * @see #mostSuccessResultsOf(Object, Executor, long, TimeUnit, CompletionStage[]) + * @see CompletableFuture#supplyAsync(Supplier, Executor) + */ + @SafeVarargs + public static CompletableFuture> mSupplyAllSuccessAsync( + @Nullable T valueIfNotSuccess, Executor executor, + Supplier... suppliers) { + requireNonNull(executor, "executor is null"); + requireArrayAndEleNonNull("supplier", suppliers); + + return allSuccessResultsOf(valueIfNotSuccess, wrapSuppliers(executor, suppliers)); + } + + /** * Returns a new CompletableFuture that is asynchronously completed * by tasks running in the CompletableFuture's default asynchronous execution facility @@ -566,6 +617,153 @@ private static T tupleOf0(Object... elements) { return (T) ret; } + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the CompletableFuture's default asynchronous execution facility + * with all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Supplier supplier1, Supplier supplier2) { + return tupleMSupplyAllSuccessAsync(ASYNC_POOL, supplier1, supplier2); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed by tasks running in the given Executor + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Executor executor, Supplier supplier1, Supplier supplier2) { + requireNonNull(executor, "executor is null"); + Supplier[] suppliers = requireArrayAndEleNonNull("supplier", supplier1, supplier2); + + return allSuccessTupleOf(wrapSuppliers(executor, suppliers)); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the CompletableFuture's default asynchronous execution facility + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Supplier supplier1, Supplier supplier2, Supplier supplier3) { + return tupleMSupplyAllSuccessAsync(ASYNC_POOL, supplier1, supplier2, supplier3); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed by tasks running in the given Executor + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Executor executor, + Supplier supplier1, Supplier supplier2, Supplier supplier3) { + requireNonNull(executor, "executor is null"); + Supplier[] suppliers = requireArrayAndEleNonNull("supplier", supplier1, supplier2, supplier3); + + return allSuccessTupleOf(wrapSuppliers(executor, suppliers)); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the CompletableFuture's default asynchronous execution facility + * with the most values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Supplier supplier1, Supplier supplier2, + Supplier supplier3, Supplier supplier4) { + return tupleMSupplyAllSuccessAsync(ASYNC_POOL, supplier1, supplier2, supplier3, supplier4); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed by tasks running in the given Executor + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Executor executor, Supplier supplier1, + Supplier supplier2, Supplier supplier3, Supplier supplier4) { + requireNonNull(executor, "executor is null"); + Supplier[] suppliers = requireArrayAndEleNonNull("supplier", supplier1, supplier2, supplier3, supplier4); + + return allSuccessTupleOf(wrapSuppliers(executor, suppliers)); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed + * by tasks running in the CompletableFuture's default asynchronous execution facility + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Supplier supplier1, + Supplier supplier2, Supplier supplier3, + Supplier supplier4, Supplier supplier5) { + return tupleMSupplyAllSuccessAsync(ASYNC_POOL, supplier1, supplier2, supplier3, supplier4, supplier5); + } + + /** + * Returns a new CompletableFuture that is asynchronously completed by tasks running in the given Executor + * with the all values obtained by calling the given Suppliers + * in the same order of the given Suppliers arguments. + *

+ * If the given supplier is successful in the given time, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> tupleMSupplyAllSuccessAsync( + Executor executor, Supplier supplier1, + Supplier supplier2, Supplier supplier3, + Supplier supplier4, Supplier supplier5) { + requireNonNull(executor, "executor is null"); + Supplier[] suppliers = requireArrayAndEleNonNull("supplier", supplier1, supplier2, supplier3, supplier4, supplier5); + + return allSuccessTupleOf(wrapSuppliers(executor, suppliers)); + } + /** * Returns a new CompletableFuture that is asynchronously completed * by tasks running in the CompletableFuture's default asynchronous execution facility @@ -744,6 +942,13 @@ public static CompletableFuture> return mostSuccessTupleOf0(executor, timeout, unit, wrapSuppliers(executor, suppliers)); } + private static CompletableFuture allSuccessTupleOf(CompletionStage... css) { + // MUST be *Non-Minimal* CF instances in order to read results(`getSuccessNow`), + // otherwise UnsupportedOperationException + final CompletableFuture[] cfArray = toNonMinCfArray(css); + return CompletableFuture.allOf(cfArray).handle((unused, ex) -> tupleOf0(MGetSuccessNow0(null, cfArray))); + } + private static CompletableFuture mostSuccessTupleOf0( Executor executorWhenTimeout, long timeout, TimeUnit unit, CompletionStage... css) { requireNonNull(executorWhenTimeout, "executorWhenTimeout is null"); @@ -1007,6 +1212,35 @@ public static CompletableFuture> mostSuccessResultsOf( .handle((unused, ex) -> arrayList(MGetSuccessNow0(valueIfNotSuccess, cfArray))); } + /** + * Returns a new CompletableFuture with all the results in the same order of + *

+ * If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. + * + * @param valueIfNotSuccess the value to return if not completed successfully + * @param cfs the stages + * @see #getSuccessNow(CompletableFuture, Object) + */ + @Contract(pure = true) + @SafeVarargs + public static CompletableFuture> allSuccessResultsOf( + @Nullable T valueIfNotSuccess, CompletionStage... cfs) { + requireNonNull(cfs, "cfs is null"); + + if (cfs.length == 0) return completedFuture(arrayList()); + if (cfs.length == 1) { + // Defensive copy input cf to non-minimal-stage instance in order to + // 1. ensure that the returned cf is not minimal-stage CF instance(UnsupportedOperationException) + final CompletableFuture f = toNonMinCfCopy(requireNonNull(cfs[0], "cf1 is null")); + return f.handle((unused, ex) -> arrayList(getSuccessNow(f, valueIfNotSuccess))).exceptionally(ex -> reportException("Exception occurred in handle of executor hop", ex)); + } + + // MUST be non-minimal-stage CF instances in order to read results(`getSuccessNow`), + // otherwise UnsupportedOperationException + final CompletableFuture[] cfArray = toNonMinCfArray(cfs); + return f_cast(CompletableFuture.allOf(cfArray).handle((unused, ex) -> arrayList(MGetSuccessNow0(valueIfNotSuccess, cfArray)))); + } + /** * Returns a new CompletableFuture with the results in the same order of the given stages arguments, * the new CompletableFuture is completed when all the given stages complete; @@ -1149,8 +1383,7 @@ private static List arrayList(T... elements) { * Returns a cf array whose elements do the result collection. */ private static CompletableFuture[] createResultSetterCfs(CompletionStage[] css, T[] result) { - @SuppressWarnings("unchecked") - final CompletableFuture[] resultSetterCfs = new CompletableFuture[result.length]; + @SuppressWarnings("unchecked") final CompletableFuture[] resultSetterCfs = new CompletableFuture[result.length]; for (int i = 0; i < result.length; i++) { final int index = i; resultSetterCfs[index] = f_toCf(css[index]).thenAccept(v -> result[index] = v); @@ -1767,6 +2000,55 @@ public static CompletableFuture> thenMApplyFastFailAsync( return cfThis.thenCompose(v -> allResultsFastFailOf(wrapFunctions(executor, v, fns))); } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful, the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param valueIfNotSuccess the value to return if not completed successfully + * @param fns the functions to use to compute the values of the returned CompletableFuture + * @param the functions' return type + * @return the new CompletableFuture + */ + @SafeVarargs + public static CompletableFuture> thenMApplyAllSuccessAsync( + CompletableFuture cfThis, @Nullable U valueIfNotSuccess, + Function... fns) { + return thenMApplyAllSuccessAsync(cfThis, valueIfNotSuccess, ASYNC_POOL, fns); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the given Executor, with the most values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param valueIfNotSuccess the value to return if not completed successfully + * @param executor the executor to use for asynchronous execution + * @param fns the functions to use to compute the values of the returned CompletableFuture + * @param the functions' return type + * @return the new CompletableFuture + */ + @SafeVarargs + public static CompletableFuture> thenMApplyAllSuccessAsync( + CompletableFuture cfThis, @Nullable U valueIfNotSuccess, + Executor executor, Function... fns) { + requireNonNull(cfThis, "cfThis is null"); + requireNonNull(executor, "executor is null"); + requireArrayAndEleNonNull("fn", fns); + + return cfThis.thenCompose(v -> allSuccessResultsOf(valueIfNotSuccess, wrapFunctions(executor, v, fns))); + } + /** * Returns a new CompletableFuture that, when the given stage completes normally, * is executed using the CompletableFuture's default asynchronous execution facility, @@ -2356,6 +2638,176 @@ public static CompletableFuture allTupleOf0(true, wrapFunctions(executor, v, fns))); } + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful,the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, + Function fn1, Function fn2) { + return thenTupleMApplyAllSuccessAsync(cfThis, ASYNC_POOL, fn1, fn2); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the given Executor, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful , the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Executor executor, + Function fn1, Function fn2) { + requireNonNull(cfThis, "cfThis is null"); + requireNonNull(executor, "executor is null"); + Function[] fns = requireArrayAndEleNonNull("fn", fn1, fn2); + + return cfThis.thenCompose(v -> allSuccessTupleOf(wrapFunctions(executor, v, fns))); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Function fn1, + Function fn2, Function fn3) { + return thenTupleMApplyAllSuccessAsync(cfThis, ASYNC_POOL, fn1, fn2, fn3); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the given Executor, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful,the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Executor executor, + Function fn1, Function fn2, + Function fn3) { + requireNonNull(cfThis, "cfThis is null"); + requireNonNull(executor, "executor is null"); + Function[] fns = requireArrayAndEleNonNull("fn", fn1, fn2, fn3); + + return cfThis.thenCompose(v -> allSuccessTupleOf(wrapFunctions(executor, v, fns))); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful ,the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, + Function fn1, Function fn2, + Function fn3, Function fn4) { + return thenTupleMApplyAllSuccessAsync(cfThis, ASYNC_POOL, fn1, fn2, fn3, fn4); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the given Executor, + * with the a;; values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful , the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Executor executor, + Function fn1, Function fn2, + Function fn3, Function fn4) { + requireNonNull(cfThis, "cfThis is null"); + requireNonNull(executor, "executor is null"); + Function[] fns = requireArrayAndEleNonNull("fn", fn1, fn2, fn3, fn4); + + return cfThis.thenCompose(v -> allSuccessTupleOf(wrapFunctions(executor, v, fns))); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the CompletableFuture's default asynchronous execution facility, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful , the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Function fn1, + Function fn2, Function fn3, + Function fn4, Function fn5) { + return thenTupleMApplyAllSuccessAsync(cfThis, ASYNC_POOL, fn1, fn2, fn3, fn4, fn5); + } + + /** + * Returns a new CompletableFuture that, when the given stage completes normally, + * is executed using the given Executor, + * with the all values obtained by calling the given Functions + * (with the given stage's result as the argument to the given functions) + * in the same order of the given Functions arguments. + *

+ * If the given function is successful , the return result is the completed value; + * Otherwise the given valueIfNotSuccess. + * + * @param executor the executor to use for asynchronous execution + * @return the new CompletableFuture + */ + public static CompletableFuture> thenTupleMApplyAllSuccessAsync( + CompletableFuture cfThis, Executor executor, + Function fn1, Function fn2, + Function fn3, Function fn4, + Function fn5) { + requireNonNull(cfThis, "cfThis is null"); + requireNonNull(executor, "executor is null"); + Function[] fns = requireArrayAndEleNonNull("fn", fn1, fn2, fn3, fn4, fn5); + + return cfThis.thenCompose(v -> allSuccessTupleOf(wrapFunctions(executor, v, fns))); + } + + /** * Returns a new CompletableFuture that, when the given stage completes normally, * is executed using the CompletableFuture's default asynchronous execution facility, diff --git a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java index 6722f383..ac76b05b 100644 --- a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java +++ b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java @@ -76,6 +76,8 @@ void test_mSupply() throws Exception { mSupplyFastFailAsync(executorService, supplier, supplier), mSupplyMostSuccessAsync(anotherN, 500, TimeUnit.MILLISECONDS, supplier, supplier), mSupplyMostSuccessAsync(anotherN, executorService, 500, TimeUnit.MILLISECONDS, supplier, supplier), + mSupplyAllSuccessAsync(anotherN, supplier, supplier), + mSupplyAllSuccessAsync(anotherN, executorService, supplier, supplier), }; assertTrue(System.currentTimeMillis() - tick < 50); @@ -842,6 +844,43 @@ void test_tupleMSupplyMostSuccessAsync() throws Exception { } + @Test + void test_tupleMSupplyAllSuccessAsync() throws Exception { + final Supplier supplier_n = () -> { + sleep(10); + return n; + }; + final Supplier supplier_s = () -> { + sleep(10); + return s; + }; + + final Supplier supplier_d = () -> { + sleep(10); + return d; + }; + final Supplier supplier_an = () -> { + sleep(10); + return anotherN; + }; + final Supplier supplier_nn = () -> { + sleep(10); + return n + n; + }; + assertEquals(Tuple2.of(n, s), tupleMSupplyAllSuccessAsync(supplier_n, supplier_s).get()); + assertEquals(Tuple2.of(n, s), tupleMSupplyAllSuccessAsync(defaultExecutor(), supplier_n, supplier_s).get()); + + assertEquals(Tuple3.of(n, s, d), tupleMSupplyAllSuccessAsync(supplier_n, supplier_s, supplier_d).get()); + assertEquals(Tuple3.of(n, s, d), tupleMSupplyAllSuccessAsync(defaultExecutor(), supplier_n, supplier_s, supplier_d).get()); + + assertEquals(Tuple4.of(n, s, d, anotherN), tupleMSupplyAllSuccessAsync(supplier_n, supplier_s, supplier_d, supplier_an).get()); + assertEquals(Tuple4.of(n, s, d, anotherN), tupleMSupplyAllSuccessAsync(defaultExecutor(), supplier_n, supplier_s, supplier_d, supplier_an).get()); + + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), tupleMSupplyAllSuccessAsync(supplier_n, supplier_s, supplier_d, supplier_an, supplier_nn).get()); + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), tupleMSupplyAllSuccessAsync(defaultExecutor(), supplier_n, supplier_s, supplier_d, supplier_an, supplier_nn).get()); + } + + @Test void test_tupleMApplyMostSuccessAsync() throws Exception { final CompletableFuture completed = completedFuture(n); @@ -881,6 +920,44 @@ void test_tupleMApplyMostSuccessAsync() throws Exception { } + @Test + void test_thenTupleMApplyAllSuccessAsync() throws Exception { + final CompletableFuture completed = completedFuture(n); + final Function function_n = (x) -> { + sleep(100); + return n; + }; + + final Function function_s = (x) -> { + sleep(100); + return s; + }; + + final Function function_d = (x) -> { + sleep(100); + return d; + }; + final Function function_an = (x) -> { + sleep(100); + return anotherN; + }; + final Function function_nn = (x) -> { + sleep(100); + return n + n; + }; + assertEquals(Tuple2.of(n, s), thenTupleMApplyAllSuccessAsync(completed, function_n, function_s).get()); + assertEquals(Tuple2.of(n, s), thenTupleMApplyAllSuccessAsync(completed, defaultExecutor(), function_n, function_s).get()); + + assertEquals(Tuple3.of(n, s, d), thenTupleMApplyAllSuccessAsync(completed, function_n, function_s, function_d).get()); + assertEquals(Tuple3.of(n, s, d), thenTupleMApplyAllSuccessAsync(completed, defaultExecutor(), function_n, function_s, function_d).get()); + + assertEquals(Tuple4.of(n, s, d, anotherN), thenTupleMApplyAllSuccessAsync(completed, function_n, function_s, function_d, function_an).get()); + assertEquals(Tuple4.of(n, s, d, anotherN), thenTupleMApplyAllSuccessAsync(completed, defaultExecutor(), function_n, function_s, function_d, function_an).get()); + + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), thenTupleMApplyAllSuccessAsync(completed, function_n, function_s, function_d, function_an, function_nn).get()); + assertEquals(Tuple5.of(n, s, d, anotherN, n + n), thenTupleMApplyAllSuccessAsync(completed, defaultExecutor(), function_n, function_s, function_d, function_an, function_nn).get()); + } + @Test void test_thenTupleMApplyAsync() throws Exception { final CompletableFuture completed = completedFuture(n); @@ -1052,6 +1129,8 @@ void test_thenMApply() throws Exception { thenMApplyFastFailAsync(completed, executorService, supplier, supplier), thenMApplyMostSuccessAsync(completed, anotherN, 500, TimeUnit.MILLISECONDS, supplier, supplier), thenMApplyMostSuccessAsync(completed, anotherN, executorService, 500, TimeUnit.MILLISECONDS, supplier, supplier), + thenMApplyAllSuccessAsync(completed, anotherN, supplier, supplier), + thenMApplyAllSuccessAsync(completed, anotherN, executorService, supplier, supplier), }; assertTrue(System.currentTimeMillis() - tick < 50);