From 107ca6504c19dc4a45d716a212ae6ee9866ee301 Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Mon, 17 Apr 2023 01:21:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20add=20`CffuFactory.allOfFastFail`and=20?= =?UTF-8?q?related=20kotlin=20extension=20methods=20=F0=9F=8D=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/foldright/cffu/CffuFactory.java | 141 +++++- .../cffu/CompletableFutureUtils.java | 12 +- .../foldright/cffu/kotlin/CffuExtensions.kt | 459 +++++++----------- .../kotlin/CompletableFutureExtensions.kt | 386 +++++++++++++++ .../io/foldright/cffu/CffuFactoryTest.java | 210 ++++++-- .../cffu/kotlin/CffuExtensionsTest.kt | 414 +++++++--------- .../kotlin/CompletableFutureExtensionsTest.kt | 234 +++++++++ 7 files changed, 1279 insertions(+), 577 deletions(-) create mode 100644 src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt create mode 100644 src/test/java/io/foldright/cffu/kotlin/CompletableFutureExtensionsTest.kt diff --git a/src/main/java/io/foldright/cffu/CffuFactory.java b/src/main/java/io/foldright/cffu/CffuFactory.java index ef4e6e27..cc07df3e 100644 --- a/src/main/java/io/foldright/cffu/CffuFactory.java +++ b/src/main/java/io/foldright/cffu/CffuFactory.java @@ -13,6 +13,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; +import java.util.Collections; import java.util.List; import java.util.concurrent.*; import java.util.function.Supplier; @@ -313,7 +314,13 @@ public final Cffu[] asCffuArray(CompletionStage... stages) { } //////////////////////////////////////////////////////////////////////////////// - //# allOf / anyOf methods, equivalent to same name static methods of CompletableFuture + //# allOf / anyOf methods, without return result type enhancement + // - allOf*, return Cffu, equivalent to same name methods: + // - CompletableFuture.allOf() + // - CompletableFutureUtils.allOfFastFail() + // - anyOf*, return Cffu, equivalent to same name methods: + // - CompletableFuture.anyOf() + // - CompletableFutureUtils.anyOfSuccess() //////////////////////////////////////////////////////////////////////////////// /** @@ -352,9 +359,16 @@ public Cffu allOf(Cffu... cfs) { } /** + * Returns a new Cffu that is completed when all the given CompletableFutures complete. + * If any of the given CompletableFuture complete exceptionally, then the returned + * Cffu also does so, with a CompletionException holding this exception as its cause.
+ * Otherwise, the results, if any, of the given CompletableFutures are not reflected in + * the returned Cffu({@code Cffu}), but may be obtained by inspecting them individually.
+ * If no CompletableFutures are provided, returns a Cffu completed with the value {@code null}. + *

* Same as {@link #allOf(Cffu[])} with overloaded argument type {@link CompletableFuture}. *

- * if you need the results of given Cffus, prefer below methods: + * if you need the results of given CompletableFutures, prefer below methods: *

    *
  1. {@link #cffuAllOf(CompletableFuture[])} *
  2. {@link #cffuCombine(CompletableFuture, CompletableFuture)}/{@link #cffuCombine(CompletableFuture, CompletableFuture, CompletableFuture, CompletableFuture, CompletableFuture)} @@ -389,6 +403,61 @@ public Cffu allOf() { return dummy(); } + /** + * Returns a new Cffu that success when all the given Cffus success, + * the results({@code Cffu}) of the given Cffus are not reflected + * in the returned Cffu, but may be obtained by inspecting them individually. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no Cffus are provided, returns a Cffu completed with the value {@code null}. + * + * @param cfs the Cffus + * @return a new Cffu that success when all the given Cffus success + * @throws NullPointerException if the array or any of its elements are {@code null} + * @see CompletableFutureUtils#allOfFastFail(CompletableFuture[]) + */ + @Contract(pure = true) + @SuppressWarnings("unchecked") + public Cffu allOfFastFail(Cffu... cfs) { + return allOfFastFail(toCompletableFutureArray((Cffu[]) cfs)); + } + + /** + * Returns a new Cffu that success when all the given CompletableFutures success, + * the results({@code Cffu}) of the given CompletableFutures are not reflected + * in the returned Cffu, but may be obtained by inspecting them individually. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed with the value {@code null}. + *

    + * Same as {@link #allOfFastFail(Cffu[])} with overloaded argument type {@link CompletableFuture}. + * + * @param cfs the CompletableFutures + * @return a new Cffu that success when all the given CompletableFutures success + * @throws NullPointerException if the array or any of its elements are {@code null} + * @see #allOfFastFail(Cffu[]) + * @see #cffuAllOfFastFail(CompletableFuture[]) + * @see CompletableFutureUtils#allOfFastFail(CompletableFuture[]) + */ + @Contract(pure = true) + public Cffu allOfFastFail(CompletableFuture... cfs) { + return new0(CompletableFutureUtils.allOfFastFail(cfs)); + } + + /** + * Provided this overloaded method just for resolving "allOfFastFail is ambiguous" problem + * when call {@code allOfFastFail} with empty arguments: {@code cffuFactory.allOfFastFail()}. + * + * @see #allOfFastFail(Cffu[]) + * @see #allOfFastFail(CompletableFuture[]) + */ + @Contract(pure = true) + public Cffu allOfFastFail() { + return new0(CompletableFutureUtils.allOfFastFail()); + } + /** * Returns a new Cffu that is completed when any of the given Cffus complete, with the same result.
    * Otherwise, if it completed exceptionally, the returned Cffu also does so, @@ -542,7 +611,7 @@ public Executor delayedExecutor(long delay, TimeUnit unit, Executor executor) { //////////////////////////////////////////////////////////////////////////////// /** - * Returns a new Cffu with the result of all the given Cffus, + * Returns a new Cffu with the results of all the given Cffus, * the new Cffu is completed when all the given Cffus complete. * Returns a new Cffu that is completed when all the given Cffus complete. * If any of the given Cffus complete exceptionally, then the returned Cffu @@ -565,7 +634,7 @@ public final Cffu> cffuAllOf(Cffu... cfs) { } /** - * Returns a new Cffu with the result of all the given CompletableFutures, + * Returns a new Cffu with the results of all the given CompletableFutures, * the new Cffu is completed when all the given CompletableFutures complete. * If any of the given CompletableFutures complete exceptionally, then the returned Cffu * also does so, with a CompletionException holding this exception as its cause. @@ -590,11 +659,69 @@ public final Cffu> cffuAllOf(CompletableFuture... cfs) { * when call {@code cffuAllOf} with empty arguments: {@code cffuFactory.cffuAllOf()}. * * @see #cffuAllOf(Cffu[]) - * @see #cffuAllOf(Cffu[]) + * @see #cffuAllOf(CompletableFuture[]) */ @Contract(pure = true) public Cffu> cffuAllOf() { - return dummy(); + return new0(CompletableFutureUtils.allOfWithResult()); + } + + /** + * Returns a new Cffu with the result of all the given Cffus, + * the new Cffu success when all the given Cffus success. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value {@link Collections#emptyList() emptyList}. + *

    + * Same as {@link #cffuAllOfFastFail(Cffu[])} with overloaded argument type {@link CompletableFuture}. + * + * @param cfs the CompletableFutures + * @return a new CompletableFuture that success when all the given CompletableFutures success + * @throws NullPointerException if the array or any of its elements are {@code null} + * @see CompletableFutureUtils#allOfFastFail(CompletableFuture[]) + * @see #cffuAllOfFastFail(Cffu[]) + */ + @Contract(pure = true) + @SafeVarargs + public final Cffu> cffuAllOfFastFail(Cffu... cfs) { + return cffuAllOfFastFail(toCompletableFutureArray(cfs)); + } + + /** + * Returns a new Cffu with the result of all the given CompletableFutures, + * the new Cffu success when all the given CompletableFutures success. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value {@link Collections#emptyList() emptyList}. + *

    + * Same as {@link #cffuAllOfFastFail(Cffu[])} with overloaded argument type {@link CompletableFuture}. + * + * @param cfs the CompletableFutures + * @return a new CompletableFuture that success when all the given CompletableFutures success + * @throws NullPointerException if the array or any of its elements are {@code null} + * @see CompletableFutureUtils#allOfFastFail(CompletableFuture[]) + * @see #cffuAllOfFastFail(Cffu[]) + */ + @Contract(pure = true) + @SafeVarargs + public final Cffu> cffuAllOfFastFail(CompletableFuture... cfs) { + return new0(CompletableFutureUtils.allOfFastFailWithResult(cfs)); + } + + /** + * Provided this overloaded method just for resolving "cffuAllOfFastFail is ambiguous" problem + * when call {@code cffuAllOfFastFail} with empty arguments: {@code cffuFactory.cffuAllOfFastFail()}. + * + * @see #cffuAllOfFastFail(Cffu[]) + * @see #cffuAllOfFastFail(CompletableFuture[]) + */ + @Contract(pure = true) + public Cffu> cffuAllOfFastFail() { + return new0(CompletableFutureUtils.allOfFastFailWithResult()); } /** @@ -668,6 +795,8 @@ public final Cffu cffuAnyOfSuccess(Cffu... cfs) { * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, * returns a new Cffu that is already completed exceptionally * with a CompletionException holding a {@link NoCfsProvidedException} as its cause. + *

    + * Same as {@link #cffuAnyOfSuccess(Cffu[])} with overloaded argument type {@link CompletableFuture}. * * @param cfs the CompletableFutures * @return a new Cffu diff --git a/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index d3194386..8eddc42e 100644 --- a/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -30,7 +30,7 @@ public final class CompletableFutureUtils { //////////////////////////////////////////////////////////////////////////////// /** - * Returns a new CompletableFuture with the result of all the given CompletableFutures, + * Returns a new CompletableFuture with the results of all the given CompletableFutures, * the new CompletableFuture is completed when all the given CompletableFutures complete. * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture * also does so, with a CompletionException holding this exception as its cause. @@ -67,12 +67,12 @@ public static CompletableFuture> allOfWithResult(CompletableFuture}) of the given CompletableFutures are not reflected + * in the returned CompletableFuture, but may be obtained by inspecting them individually. * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture * also does so *without* waiting other incomplete given CompletableFutures, * with a CompletionException holding this exception as its cause. - * Otherwise, the results, if any, of the given CompletableFutures are not reflected in - * the returned CompletableFuture, but may be obtained by inspecting them individually. * If no CompletableFutures are provided, returns a CompletableFuture completed with the value {@code null}. * * @param cfs the CompletableFutures @@ -101,13 +101,11 @@ public static CompletableFuture allOfFastFail(CompletableFuture... cfs) } /** - * Returns a new CompletableFuture with the result of all the given CompletableFutures, + * Returns a new CompletableFuture with the results of all the given CompletableFutures, * the new CompletableFuture success when all the given CompletableFutures success. * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture * also does so *without* waiting other incomplete given CompletableFutures, * with a CompletionException holding this exception as its cause. - * Otherwise, the results, if any, of the given CompletableFutures are not reflected in - * the returned CompletableFuture, but may be obtained by inspecting them individually. * If no CompletableFutures are provided, returns a CompletableFuture completed * with the value {@link Collections#emptyList() emptyList}. *

    diff --git a/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt b/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt index 0b4b0411..f6e2581d 100644 --- a/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt +++ b/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt @@ -2,277 +2,17 @@ package io.foldright.cffu.kotlin import io.foldright.cffu.Cffu import io.foldright.cffu.CffuFactory -import io.foldright.cffu.CompletableFutureUtils -import io.foldright.cffu.tuple.Tuple2 -import io.foldright.cffu.tuple.Tuple3 -import io.foldright.cffu.tuple.Tuple4 -import io.foldright.cffu.tuple.Tuple5 import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletionStage -//////////////////////////////////////////////////////////////////////////////// -//# Extension methods for CompletableFuture -//////////////////////////////////////////////////////////////////////////////// - -//////////////////////////////////////// -// - allOfCompletableFuture -// - allOfCompletableFutureVoid -//////////////////////////////////////// - -/** - * Returns a new CompletableFuture with the result of all the given CompletableFutures, - * the returned new CompletableFuture is completed when all the given CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding this exception as its cause. - * If no CompletableFutures are provided, returns a CompletableFuture completed - * with the value [emptyList][java.util.Collections.emptyList]. - * - * Same as [allOfCompletableFutureVoid], - * but the returned CompletableFuture contains the results of input CompletableFutures. - * - * @see allOfCffu - * @see allOfCompletableFutureVoid - */ -fun Collection>.allOfCompletableFuture(): CompletableFuture> = - CompletableFutureUtils.allOfWithResult(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture with the result of all the given CompletableFutures, - * the returned new CompletableFuture is completed when all the given CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding this exception as its cause. - * If no CompletableFutures are provided, returns a CompletableFuture completed - * with the value [emptyList][java.util.Collections.emptyList]. - * - * Same as [allOfCompletableFutureVoid], - * but the returned CompletableFuture contains the results of input CompletableFutures. - * - * @see allOfCffu - * @see allOfCompletableFutureVoid - */ -fun Array>.allOfCompletableFuture(): CompletableFuture> = - CompletableFutureUtils.allOfWithResult(*this) - -/** - * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. - * - * Same as [CompletableFuture.allOf], providing this method is convenient for method chaining. - * - * @see allOfCffu - * @see allOfCffuVoid - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun Collection>.allOfCompletableFutureVoid(): CompletableFuture = - CompletableFuture.allOf(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. - * - * Same as [CompletableFuture.allOf], providing this method is convenient for method chaining. - * - * @see allOfCffu - * @see allOfCffuVoid - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun Array>.allOfCompletableFutureVoid(): CompletableFuture = - CompletableFuture.allOf(*this) - -//////////////////////////////////////// -// - anyOfCompletableFuture -// - anyOfCompletableFutureAny -//////////////////////////////////////// - -/** - * Returns a new CompletableFuture that is completed - * when any of the given CompletableFutures complete, with the same result. - * - * Same as [anyOfCompletableFutureAny], but return result type is specified type instead of type `Any`. - * - * @see anyOfCffu - * @see anyOfCompletableFutureAny - */ -fun Collection>.anyOfCompletableFuture(): CompletableFuture = - CompletableFutureUtils.anyOfWithType(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture that is completed - * when any of the given CompletableFutures complete, with the same result. - * - * Same as [anyOfCompletableFutureAny], but return result type is specified type instead of type `Any`. - * - * @see anyOfCffu - * @see anyOfCompletableFutureAny - */ -fun Array>.anyOfCompletableFuture(): CompletableFuture = - CompletableFutureUtils.anyOfWithType(*this) - -/** - * Returns a new CompletableFuture that is completed - * when any of the given CompletableFutures complete, with the same result. - * - * Same as [CompletableFuture.anyOf], providing this method is convenient for method chaining. - * - * @see anyOfCffu - * @see anyOfCffuAny - * @see anyOfCompletableFuture - * @see CompletableFuture.anyOf - */ -fun Collection>.anyOfCompletableFutureAny(): CompletableFuture = - CompletableFuture.anyOf(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture that is completed - * when any of the given CompletableFutures complete, with the same result. - * - * Same as [CompletableFuture.anyOf], providing this method is convenient for method chaining. - * - * @see anyOfCffu - * @see anyOfCffuAny - * @see anyOfCompletableFuture - * @see CompletableFuture.anyOf - */ -fun Array>.anyOfCompletableFutureAny(): CompletableFuture = - CompletableFuture.anyOf(*this) - -/** - * Returns a new CompletableFuture that success when any of the given CompletableFutures success, - * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, - * the returned CompletableFuture also does so, with a CompletionException holding - * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, - * returns a new CompletableFuture that is already completed exceptionally with a CompletionException - * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. - * - * Same as [CompletableFutureUtils.anyOfSuccessWithType], providing this method is convenient for method chaining. - * - * @see anyOfCompletableFuture - * @see CompletableFutureUtils.anyOfSuccessWithType - */ -fun Collection>.anyOfSuccessCompletableFuture(): CompletableFuture = - CompletableFutureUtils.anyOfSuccessWithType(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture that success when any of the given CompletableFutures success, - * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, - * the returned CompletableFuture also does so, with a CompletionException holding - * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, - * returns a new CompletableFuture that is already completed exceptionally with a CompletionException - * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. - * - * Same as [CompletableFutureUtils.anyOfSuccess], providing this method is convenient for method chaining. - * - * @see anyOfCompletableFuture - * @see CompletableFutureUtils.anyOfSuccessWithType - */ -fun Array>.anyOfSuccessCompletableFuture(): CompletableFuture = - CompletableFutureUtils.anyOfSuccessWithType(*this) - -/** - * Returns a new CompletableFuture that success when any of the given CompletableFutures success, - * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, - * the returned CompletableFuture also does so, with a CompletionException holding - * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, - * returns a new CompletableFuture that is already completed exceptionally with a CompletionException - * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. - * - * Same as [CompletableFutureUtils.anyOfSuccess], providing this method is convenient for method chaining. - * - * @see anyOfSuccessCffu - * @see anyOfCompletableFuture - * @see CompletableFutureUtils.anyOfSuccessWithType - */ -fun Collection>.anyOfSuccessCompletableFutureAny(): CompletableFuture = - CompletableFutureUtils.anyOfSuccess(*this.toTypedArray()) - -/** - * Returns a new CompletableFuture that success when any of the given CompletableFutures success, - * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, - * the returned CompletableFuture also does so, with a CompletionException holding - * an exception CompletableFuture any of the given CompletableFutures as its cause. If no CompletableFutures are provided, - * returns a new Cffu that is already completed exceptionally with a CompletionException - * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. - * - * Same as [CompletableFutureUtils.anyOfSuccessWithType], providing this method is convenient for method chaining. - * - * @see anyOfSuccessCffu - * @see anyOfCompletableFuture - * @see CompletableFutureUtils.anyOfSuccessWithType - */ -fun Array>.anyOfSuccessCompletableFutureAny(): CompletableFuture = - CompletableFutureUtils.anyOfSuccess(*this) - -//////////////////////////////////////// -// combine -//////////////////////////////////////// - -/** - * Returns a new CompletableFuture that is completed when the given two CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding this exception as its cause. - * - * @return a new CompletableFuture that is completed when the given 2 CompletableFutures complete - * @throws NullPointerException if any input CompletableFutures are `null` - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun CompletableFuture.combine(cf2: CompletableFuture): CompletableFuture> = - CompletableFutureUtils.combine(this, cf2) - -/** - * Returns a new CompletableFuture that is completed when the given three CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding this exception as its cause. - * - * @return a new CompletableFuture that is completed when the given 3 CompletableFutures complete - * @throws NullPointerException if any input CompletableFutures are `null` - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun CompletableFuture.combine( - cf2: CompletableFuture, cf3: CompletableFuture -): CompletableFuture> = - CompletableFutureUtils.combine(this, cf2, cf3) - -/** - * Returns a new CompletableFuture that is completed when the given 4 CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding this exception as its cause. - * - * @return a new CompletableFuture that is completed when the given 4 CompletableFutures complete - * @throws NullPointerException if any input CompletableFutures are `null` - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun CompletableFuture.combine( - cf2: CompletableFuture, cf3: CompletableFuture, cf4: CompletableFuture -): CompletableFuture> = - CompletableFutureUtils.combine(this, cf2, cf3, cf4) - -/** - * Returns a new CompletableFuture that is completed when the given 5 CompletableFutures complete. - * If any of the given CompletableFutures complete exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding this exception as its cause. - * - * @return a new CompletableFuture that is completed when the given 5 CompletableFutures complete - * @throws NullPointerException if any input CompletableFutures are `null` - * @see allOfCompletableFuture - * @see CompletableFuture.allOf - */ -fun CompletableFuture.combine( - cf2: CompletableFuture, cf3: CompletableFuture, - cf4: CompletableFuture, cf5: CompletableFuture -): CompletableFuture> = - CompletableFutureUtils.combine(this, cf2, cf3, cf4, cf5) - - //////////////////////////////////////////////////////////////////////////////// //# Extension methods for Cffu +// output(return type) is Cffu //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// -// asCffu +// asCffu methods //////////////////////////////////////// /** @@ -307,8 +47,12 @@ fun > Array.asCffu(cffuFactory: CffuFactory): Arr cffuFactory.asCffuArray(*this) //////////////////////////////////////// -// - allOfCffu -// - allOfCffuVoid +// allOf* methods +// +// - allOfCffu +// - allOfCffuVoid +// - allOfFastFailCffu +// - allOfFastFailCffuVoid //////////////////////////////////////// /** @@ -342,7 +86,6 @@ fun Collection>.allOfCffu(cffuFactory: CffuFactory): Cffu> = * @see allOfCffuVoid * @see CffuFactory.cffuAllOf */ - fun Array>.allOfCffu(cffuFactory: CffuFactory): Cffu> = cffuFactory.cffuAllOf(*this) @@ -382,8 +125,12 @@ fun Array>.allOfCffu(cffuFactory: CffuFactory): Cffu

  3. `), but may be obtained by inspecting them individually. + * If no Cffus are provided, returns a Cffu completed with the value `null`. * * Same as [CffuFactory.allOf], providing this method is convenient for method chaining. * @@ -394,8 +141,12 @@ fun Collection>.allOfCffuVoid(cffuFactory: CffuFactory): Cffu = cffuFactory.allOf(*this.toTypedArray()) /** - * Returns a new Cffu with the result of all the given Cffus, - * the new Cffu is completed when all the given Cffus complete. + * Returns a new Cffu that is completed when all the given Cffus complete. + * If any of the given Cffu complete exceptionally, then the returned + * Cffu also does so, with a CompletionException holding this exception as its cause. + * Otherwise, the results, if any, of the given Cffus are not reflected in + * the returned Cffu(`Cffu`), but may be obtained by inspecting them individually. + * If no Cffus are provided, returns a Cffu completed with the value `null`. * * Same as [CffuFactory.allOf], providing this method is convenient for method chaining. * @@ -407,8 +158,12 @@ fun Array>.allOfCffuVoid(cffuFactory: CffuFactory): Cffu = cffuFactory.allOf(*this) /** - * Returns a new Cffu with the result of all the given CompletableFutures, - * the new Cffu is completed when all the given CompletableFutures complete. + * Returns a new Cffu that is completed when all the given CompletableFutures complete. + * If any of the given Cffu complete exceptionally, then the returned + * Cffu also does so, with a CompletionException holding this exception as its cause. + * Otherwise, the results, if any, of the given CompletableFutures are not reflected in + * the returned Cffu(`Cffu`), but may be obtained by inspecting them individually. + * If no CompletableFutures are provided, returns a Cffu completed with the value `null`. * * Same as [CffuFactory.allOf], providing this method is convenient for method chaining. * @@ -420,8 +175,12 @@ fun Collection>.allOfCffuVoid(cffuFactory: CffuFactory): Cf cffuFactory.allOf(*this.toTypedArray()) /** - * Returns a new Cffu with the result of all the given CompletableFutures, - * the new Cffu is completed when all the given CompletableFutures complete. + * Returns a new Cffu that is completed when all the given CompletableFutures complete. + * If any of the given Cffu complete exceptionally, then the returned + * Cffu also does so, with a CompletionException holding this exception as its cause. + * Otherwise, the results, if any, of the given CompletableFutures are not reflected in + * the returned Cffu(`Cffu`), but may be obtained by inspecting them individually. + * If no CompletableFutures are provided, returns a Cffu completed with the value `null`. * * Same as [CffuFactory.allOf], providing this method is convenient for method chaining. * @@ -431,9 +190,155 @@ fun Collection>.allOfCffuVoid(cffuFactory: CffuFactory): Cf fun Array>.allOfCffuVoid(cffuFactory: CffuFactory): Cffu = cffuFactory.allOf(*this) +/** + * Returns a new Cffu with the result of all the given Cffus, + * the new Cffu success when all the given Cffus success. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCffuVoid], but the returned Cffu contains the results of input Cffus. + * Same as [CffuFactory.cffuAllOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffuVoid + * @see CffuFactory.cffuAllOfFastFail + */ +fun Collection>.allOfFastFailCffu(cffuFactory: CffuFactory): Cffu> = + cffuFactory.cffuAllOfFastFail(*this.toTypedArray()) + +/** + * Returns a new Cffu with the result of all the given Cffus, + * the new Cffu success when all the given Cffus success. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCffuVoid], but the returned Cffu contains the results of input Cffus. + * Same as [CffuFactory.cffuAllOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffuVoid + * @see CffuFactory.cffuAllOfFastFail + */ +fun Array>.allOfFastFailCffu(cffuFactory: CffuFactory): Cffu> = + cffuFactory.cffuAllOfFastFail(*this) + +/** + * Returns a new Cffu with the result of all the given CompletableFutures, + * the new Cffu success when all the given CompletableFutures success. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCffuVoid], but the returned Cffu contains the results of input Cffus. + * Same as [CffuFactory.cffuAllOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffuVoid + * @see CffuFactory.cffuAllOfFastFail + */ +@JvmName("allOfFastFailCffuCf") +fun Collection>.allOfFastFailCffu(cffuFactory: CffuFactory): Cffu> = + cffuFactory.cffuAllOfFastFail(*this.toTypedArray()) + +/** + * Returns a new Cffu with the result of all the given CompletableFutures, + * the new Cffu success when all the given CompletableFutures success. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCffuVoid], but the returned Cffu contains the results of input Cffus. + * Same as [CffuFactory.cffuAllOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffuVoid + * @see CffuFactory.cffuAllOfFastFail + */ +fun Array>.allOfFastFailCffu(cffuFactory: CffuFactory): Cffu> = + cffuFactory.cffuAllOfFastFail(*this) + +/** + * Returns a new Cffu that success when all the given Cffus success, + * the results(`Cffu`) of the given Cffus are not reflected in the returned Cffu, + * but may be obtained by inspecting them individually. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no Cffus are provided, returns a Cffu completed with the value `null`. + * + * Same as [CffuFactory.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see CffuFactory.allOfFastFail + */ +fun Collection>.allOfFastFailCffuVoid(cffuFactory: CffuFactory): Cffu = + cffuFactory.allOfFastFail(*this.toTypedArray()) + +/** + * Returns a new Cffu that success when all the given Cffus success, + * the results(`Cffu`) of the given Cffus are not reflected in the returned Cffu, + * but may be obtained by inspecting them individually. + * If any of the given Cffus complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given Cffus, + * with a CompletionException holding this exception as its cause. + * If no Cffus are provided, returns a Cffu completed with the value `null`. + * + * Same as [CffuFactory.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see CffuFactory.allOfFastFail + */ +fun Array>.allOfFastFailCffuVoid(cffuFactory: CffuFactory): Cffu = + cffuFactory.allOfFastFail(*this) + +/** + * Returns a new Cffu that success when all the given CompletableFutures success, + * the results(`Cffu`) of the given CompletableFutures are not reflected in the returned Cffu, + * but may be obtained by inspecting them individually. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed with the value `null`. + * + * Same as [CffuFactory.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see CffuFactory.allOfFastFail + */ +@JvmName("allOfFastFailCffuVoidCf") +fun Collection>.allOfFastFailCffuVoid(cffuFactory: CffuFactory): Cffu = + cffuFactory.allOfFastFail(*this.toTypedArray()) + +/** + * Returns a new Cffu that success when all the given CompletableFutures success, + * the results(`Cffu`) of the given CompletableFutures are not reflected in the returned Cffu, + * but may be obtained by inspecting them individually. + * If any of the given CompletableFutures complete exceptionally, then the returned Cffu + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a Cffu completed with the value `null`. + * + * Same as [CffuFactory.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see CffuFactory.allOfFastFail + */ +fun Array>.allOfFastFailCffuVoid(cffuFactory: CffuFactory): Cffu = + cffuFactory.allOfFastFail(*this) + //////////////////////////////////////// -// - anyOfCffu -// - anyOfCffuAny +// anyOf* methods +// +// - anyOfCffu +// - anyOfCffuAny +// - anyOfSuccessCffu +// - anyOfSuccessCffuAny //////////////////////////////////////// /** @@ -661,7 +566,7 @@ fun Array>.anyOfSuccessCffuAny(cffuFactory: CffuFactory): C cffuFactory.anyOfSuccess(*this) //////////////////////////////////////// -// toCompletableFuture +// toCompletableFuture methods //////////////////////////////////////// /** @@ -685,7 +590,7 @@ fun > Array.toCompletableFuture(): Array Collection>.allOfCompletableFuture(): CompletableFuture> = + CompletableFutureUtils.allOfWithResult(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture with the result of all the given CompletableFutures, + * the returned new CompletableFuture is completed when all the given CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so, with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a CompletableFuture completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfCompletableFutureVoid], + * but the returned CompletableFuture contains the results of input CompletableFutures. + * Same as [CompletableFutureUtils.allOfWithResult], providing this method is convenient for method chaining. + * + * @see allOfCffu + * @see allOfCompletableFutureVoid + */ +fun Array>.allOfCompletableFuture(): CompletableFuture> = + CompletableFutureUtils.allOfWithResult(*this) + +/** + * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so, with a CompletionException holding this exception as its cause. + * Otherwise, the results, if any, of the given CompletableFutures are not reflected in the returned + * CompletableFuture, but may be obtained by inspecting them individually. + * If no CompletableFutures are provided, returns a CompletableFuture completed with the value `null`. + * + * Among the applications of this method is to await completion of a set of independent CompletableFutures + * before continuing a program, as in: `CompletableFuture.allOf(c1, c2, c3).join();`. + * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. + * + * Same as [CompletableFuture.allOf], providing this method is convenient for method chaining. + * + * @see allOfCffu + * @see allOfCffuVoid + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun Collection>.allOfCompletableFutureVoid(): CompletableFuture = + CompletableFuture.allOf(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so, with a CompletionException holding this exception as its cause. + * Otherwise, the results, if any, of the given CompletableFutures are not reflected in the returned + * CompletableFuture, but may be obtained by inspecting them individually. + * If no CompletableFutures are provided, returns a CompletableFuture completed with the value `null`. + * + * Among the applications of this method is to await completion of a set of independent CompletableFutures + * before continuing a program, as in: `CompletableFuture.allOf(c1, c2, c3).join();`. + * Returns a new CompletableFuture that is completed when all the given CompletableFutures complete. + * + * Same as [CompletableFuture.allOf], providing this method is convenient for method chaining. + * + * @see allOfCffu + * @see allOfCffuVoid + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun Array>.allOfCompletableFutureVoid(): CompletableFuture = + CompletableFuture.allOf(*this) + +/** + * Returns a new CompletableFuture with the results of all the given CompletableFutures, + * the new CompletableFuture success when all the given CompletableFutures success. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a CompletableFuture completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCompletableFutureVoid], + * but the returned CompletableFuture contains the results of input CompletableFutures. + * Same as [CompletableFutureUtils.allOfFastFailWithResult], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see allOfFastFailCompletableFutureVoid + */ +fun Collection>.allOfFastFailCompletableFuture(): CompletableFuture> = + CompletableFutureUtils.allOfFastFailWithResult(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture with the results of all the given CompletableFutures, + * the new CompletableFuture success when all the given CompletableFutures success. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a CompletableFuture completed + * with the value [emptyList][java.util.Collections.emptyList]. + * + * Same as [allOfFastFailCompletableFutureVoid], + * but the returned CompletableFuture contains the results of input CompletableFutures. + * Same as [CompletableFutureUtils.allOfFastFailWithResult], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see allOfFastFailCompletableFutureVoid + */ +fun Array>.allOfFastFailCompletableFuture(): CompletableFuture> = + CompletableFutureUtils.allOfFastFailWithResult(*this) + +/** + * Returns a new CompletableFuture that success when all the given CompletableFutures success, + * the results(`CompletableFuture`) of the given CompletableFutures are not reflected in the returned CompletableFuture, + * but may be obtained by inspecting them individually. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a CompletableFuture completed with the value `null`. + * + * Same as [CompletableFutureUtils.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see allOfFastFailCffuVoid + * @see allOfFastFailCompletableFuture + * @see CompletableFutureUtils.allOfFastFail + */ +fun Collection>.allOfFastFailCompletableFutureVoid(): CompletableFuture = + CompletableFutureUtils.allOfFastFail(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that success when all the given CompletableFutures success, + * the results(`CompletableFuture`) of the given CompletableFutures are not reflected in the returned CompletableFuture, + * but may be obtained by inspecting them individually. + * If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture + * also does so *without* waiting other incomplete given CompletableFutures, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns a CompletableFuture completed with the value `null`. + * + * Same as [CompletableFutureUtils.allOfFastFail], providing this method is convenient for method chaining. + * + * @see allOfFastFailCffu + * @see allOfFastFailCffuVoid + * @see allOfFastFailCompletableFuture + * @see CompletableFutureUtils.allOfFastFail + */ +fun Array>.allOfFastFailCompletableFutureVoid(): CompletableFuture = + CompletableFutureUtils.allOfFastFail(*this) + + +//////////////////////////////////////// +// anyOf* methods +// +// - anyOfCompletableFuture +// - anyOfCompletableFutureAny +// - anyOfSuccessCompletableFuture +// - anyOfSuccessCompletableFutureAny +//////////////////////////////////////// + +/** + * Returns a new CompletableFuture that is completed + * when any of the given CompletableFutures complete, with the same result. + * Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns an incomplete CompletableFuture. + * + * Same as [anyOfCompletableFutureAny], but return result type is specified type instead of type `Any`. + * Same as [CompletableFutureUtils.anyOfWithType], providing this method is convenient for method chaining. + * + * @see anyOfCffu + * @see anyOfCompletableFutureAny + */ +fun Collection>.anyOfCompletableFuture(): CompletableFuture = + CompletableFutureUtils.anyOfWithType(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that is completed + * when any of the given CompletableFutures complete, with the same result. + * Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns an incomplete CompletableFuture. + * + * Same as [anyOfCompletableFutureAny], but return result type is specified type instead of type `Any`. + * Same as [CompletableFutureUtils.anyOfWithType], providing this method is convenient for method chaining. + * + * @see anyOfCffu + * @see anyOfCompletableFutureAny + */ +fun Array>.anyOfCompletableFuture(): CompletableFuture = + CompletableFutureUtils.anyOfWithType(*this) + +/** + * Returns a new CompletableFuture that is completed + * when any of the given CompletableFutures complete, with the same result. + * Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns an incomplete CompletableFuture. + * + * Same as [CompletableFuture.anyOf], providing this method is convenient for method chaining. + * + * @see anyOfCffu + * @see anyOfCffuAny + * @see anyOfCompletableFuture + * @see CompletableFuture.anyOf + */ +fun Collection>.anyOfCompletableFutureAny(): CompletableFuture = + CompletableFuture.anyOf(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that is completed + * when any of the given CompletableFutures complete, with the same result. + * Otherwise, if it completed exceptionally, the returned CompletableFuture also does so, + * with a CompletionException holding this exception as its cause. + * If no CompletableFutures are provided, returns an incomplete CompletableFuture. + * + * Same as [CompletableFuture.anyOf], providing this method is convenient for method chaining. + * + * @see anyOfCffu + * @see anyOfCffuAny + * @see anyOfCompletableFuture + * @see CompletableFuture.anyOf + */ +fun Array>.anyOfCompletableFutureAny(): CompletableFuture = + CompletableFuture.anyOf(*this) + +/** + * Returns a new CompletableFuture that success when any of the given CompletableFutures success, + * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, + * the returned CompletableFuture also does so, with a CompletionException holding + * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, + * returns a new CompletableFuture that is already completed exceptionally with a CompletionException + * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. + * + * Same as [anyOfSuccessCompletableFutureAny], but return result type is specified type instead of type `Any`. + * Same as [CompletableFutureUtils.anyOfSuccessWithType], providing this method is convenient for method chaining. + * + * @see anyOfCompletableFuture + * @see CompletableFutureUtils.anyOfSuccessWithType + */ +fun Collection>.anyOfSuccessCompletableFuture(): CompletableFuture = + CompletableFutureUtils.anyOfSuccessWithType(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that success when any of the given CompletableFutures success, + * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, + * the returned CompletableFuture also does so, with a CompletionException holding + * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, + * returns a new CompletableFuture that is already completed exceptionally with a CompletionException + * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. + * + * Same as [anyOfSuccessCompletableFutureAny], but return result type is specified type instead of type `Any`. + * Same as [CompletableFutureUtils.anyOfSuccessWithType], providing this method is convenient for method chaining. + * + * @see anyOfCompletableFuture + * @see CompletableFutureUtils.anyOfSuccessWithType + */ +fun Array>.anyOfSuccessCompletableFuture(): CompletableFuture = + CompletableFutureUtils.anyOfSuccessWithType(*this) + +/** + * Returns a new CompletableFuture that success when any of the given CompletableFutures success, + * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, + * the returned CompletableFuture also does so, with a CompletionException holding + * an exception from any of the given CompletableFutures as its cause. If no CompletableFutures are provided, + * returns a new CompletableFuture that is already completed exceptionally with a CompletionException + * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. + * + * Same as [CompletableFutureUtils.anyOfSuccess], providing this method is convenient for method chaining. + * + * @see anyOfSuccessCffu + * @see anyOfCompletableFuture + * @see CompletableFutureUtils.anyOfSuccess + */ +fun Collection>.anyOfSuccessCompletableFutureAny(): CompletableFuture = + CompletableFutureUtils.anyOfSuccess(*this.toTypedArray()) + +/** + * Returns a new CompletableFuture that success when any of the given CompletableFutures success, + * with the same result. Otherwise, all the given CompletableFutures complete exceptionally, + * the returned CompletableFuture also does so, with a CompletionException holding + * an exception CompletableFuture any of the given CompletableFutures as its cause. If no CompletableFutures are provided, + * returns a new Cffu that is already completed exceptionally with a CompletionException + * holding a [NoCfsProvidedException][io.foldright.cffu.NoCfsProvidedException] as its cause. + * + * Same as [CompletableFutureUtils.anyOfSuccess], providing this method is convenient for method chaining. + * + * @see anyOfSuccessCffu + * @see anyOfCompletableFuture + * @see CompletableFutureUtils.anyOfSuccess + */ +fun Array>.anyOfSuccessCompletableFutureAny(): CompletableFuture = + CompletableFutureUtils.anyOfSuccess(*this) + +//////////////////////////////////////// +// combine methods +//////////////////////////////////////// + +/** + * Returns a new CompletableFuture that is completed when the given two CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned + * CompletableFuture also does so, with a CompletionException holding this exception as its cause. + * + * @return a new CompletableFuture that is completed when the given 2 CompletableFutures complete + * @throws NullPointerException if any input CompletableFutures are `null` + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun CompletableFuture.combine(cf2: CompletableFuture): CompletableFuture> = + CompletableFutureUtils.combine(this, cf2) + +/** + * Returns a new CompletableFuture that is completed when the given three CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned + * CompletableFuture also does so, with a CompletionException holding this exception as its cause. + * + * @return a new CompletableFuture that is completed when the given 3 CompletableFutures complete + * @throws NullPointerException if any input CompletableFutures are `null` + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun CompletableFuture.combine( + cf2: CompletableFuture, cf3: CompletableFuture +): CompletableFuture> = + CompletableFutureUtils.combine(this, cf2, cf3) + +/** + * Returns a new CompletableFuture that is completed when the given 4 CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned + * CompletableFuture also does so, with a CompletionException holding this exception as its cause. + * + * @return a new CompletableFuture that is completed when the given 4 CompletableFutures complete + * @throws NullPointerException if any input CompletableFutures are `null` + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun CompletableFuture.combine( + cf2: CompletableFuture, cf3: CompletableFuture, cf4: CompletableFuture +): CompletableFuture> = + CompletableFutureUtils.combine(this, cf2, cf3, cf4) + +/** + * Returns a new CompletableFuture that is completed when the given 5 CompletableFutures complete. + * If any of the given CompletableFutures complete exceptionally, then the returned + * CompletableFuture also does so, with a CompletionException holding this exception as its cause. + * + * @return a new CompletableFuture that is completed when the given 5 CompletableFutures complete + * @throws NullPointerException if any input CompletableFutures are `null` + * @see allOfCompletableFuture + * @see CompletableFuture.allOf + */ +fun CompletableFuture.combine( + cf2: CompletableFuture, cf3: CompletableFuture, + cf4: CompletableFuture, cf5: CompletableFuture +): CompletableFuture> = + CompletableFutureUtils.combine(this, cf2, cf3, cf4, cf5) diff --git a/src/test/java/io/foldright/cffu/CffuFactoryTest.java b/src/test/java/io/foldright/cffu/CffuFactoryTest.java index a9fb21c2..2728f915 100644 --- a/src/test/java/io/foldright/cffu/CffuFactoryTest.java +++ b/src/test/java/io/foldright/cffu/CffuFactoryTest.java @@ -12,6 +12,7 @@ import org.junit.jupiter.api.condition.JRE; import java.util.Arrays; +import java.util.Collections; import java.util.concurrent.*; import java.util.function.Function; @@ -180,48 +181,171 @@ void test_asCffuArray() throws Exception { @Test void test_allOf_CompletableFuture() throws Exception { - Cffu cffus = cffuFactory.allOf(CompletableFuture.completedFuture(n), CompletableFuture.completedFuture(another_n)); - cffus.get(); + cffuFactory.allOf( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(another_n) + ).get(); + cffuFactory.allOf( + CompletableFuture.completedFuture(another_n) + ).get(); + + assertNull(cffuFactory.allOf().get()); + + //////////////////////////////////////// + + cffuFactory.allOfFastFail( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(another_n) + ).get(); + cffuFactory.allOfFastFail( + CompletableFuture.completedFuture(another_n) + ).get(); + + assertNull(cffuFactory.allOfFastFail().get()); + + cffuFactory.allOfFastFail( + cffuFactory.completedFuture(n), + cffuFactory.completedFuture(another_n) + ).get(); + cffuFactory.allOfFastFail( + cffuFactory.completedFuture(another_n) + ).get(); } @Test void test_anyOf_CompletableFuture() throws Exception { - Cffu cffus = cffuFactory.anyOf(CompletableFuture.completedFuture(n), CompletableFuture.completedFuture(another_n)); - cffus.get(); + cffuFactory.anyOf( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(another_n) + ).get(); + assertEquals(another_n, cffuFactory.anyOf( + CompletableFuture.completedFuture(another_n) + ).get()); + + assertFalse(cffuFactory.anyOf().isDone()); + + //////////////////////////////////////// + + cffuFactory.anyOfSuccess( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(another_n) + ).get(); + assertEquals(another_n, cffuFactory.anyOfSuccess( + CompletableFuture.completedFuture(another_n) + ).get()); + + try { + cffuFactory.anyOfSuccess().get(); + fail(); + } catch (ExecutionException expected) { + assertSame(NoCfsProvidedException.class, expected.getCause().getClass()); + } + + cffuFactory.anyOfSuccess( + cffuFactory.completedFuture(n), + cffuFactory.completedFuture(another_n) + ).get(); + assertEquals(another_n, cffuFactory.anyOfSuccess( + cffuFactory.completedFuture(another_n) + ).get()); } //////////////////////////////////////////////////////////////////////////////// - // new methods of CompletableFuture missing functions + //# Delay Execution, equivalent to same name static methods of CompletableFuture + // + // - delayedExecutor + //////////////////////////////////////////////////////////////////////////////// + + // ... + + //////////////////////////////////////////////////////////////////////////////// + //# New type-safe allOf/anyOf Factory Methods + // method name prefix with `cffu` + // + // - cffuAllOf + // - cffuAnyOf //////////////////////////////////////////////////////////////////////////////// @Test void test_cffuAllOf() throws Exception { - assertEquals(Arrays.asList(n, n + 1, n + 2), + assertEquals(Arrays.asList(n, n + 1), + cffuFactory.cffuAllOf( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(n + 1) + ).get() + ); + assertEquals(Collections.singletonList(n), cffuFactory.cffuAllOf( - CompletableFuture.completedFuture(n), - CompletableFuture.completedFuture(n + 1), - CompletableFuture.completedFuture(n + 2)) - .get() + CompletableFuture.completedFuture(n) + ).get() + ); + + assertEquals(Collections.emptyList(), + cffuFactory.cffuAllOf().get() ); - assertEquals(Arrays.asList(n, n + 1, n + 2), + assertEquals(Arrays.asList(n, n + 1), cffuFactory.cffuAllOf( - cffuFactory.completedFuture(n), - cffuFactory.completedFuture(n + 1), - cffuFactory.completedFuture(n + 2)) - .get() + cffuFactory.completedFuture(n), + cffuFactory.completedFuture(n + 1) + ).get() + ); + assertEquals(Collections.singletonList(n), + cffuFactory.cffuAllOf( + cffuFactory.completedFuture(n) + ).get() + ); + + //////////////////////////////////////// + + assertEquals(Arrays.asList(n, n + 1), + cffuFactory.cffuAllOfFastFail( + CompletableFuture.completedFuture(n), + CompletableFuture.completedFuture(n + 1) + ).get() + ); + assertEquals(Collections.singletonList(n), + cffuFactory.cffuAllOfFastFail( + CompletableFuture.completedFuture(n) + ).get() + ); + + assertEquals(Collections.emptyList(), + cffuFactory.cffuAllOfFastFail().get() ); - assertTrue(cffuFactory.cffuAllOf().isDone()); + assertEquals(Arrays.asList(n, n + 1), + cffuFactory.cffuAllOfFastFail( + cffuFactory.completedFuture(n), + cffuFactory.completedFuture(n + 1) + ).get() + ); + assertEquals(Collections.singletonList(n), + cffuFactory.cffuAllOfFastFail( + cffuFactory.completedFuture(n) + ).get() + ); } @Test void test_cffuAllOf_exceptionally() throws Exception { try { cffuFactory.cffuAllOf( - CompletableFuture.completedFuture(n), - createFailedFuture(rte), - CompletableFuture.completedFuture(s) + cffuFactory.completedFuture(n), + cffuFactory.failedFuture(rte), + cffuFactory.completedFuture(s) + ).get(); + + fail(); + } catch (ExecutionException expected) { + assertSame(rte, expected.getCause()); + } + + try { + cffuFactory.cffuAllOfFastFail( + cffuFactory.completedFuture(n), + cffuFactory.failedFuture(rte), + cffuFactory.completedFuture(s) ).get(); fail(); @@ -234,17 +358,41 @@ void test_cffuAllOf_exceptionally() throws Exception { void test_cffuAnyOf() throws Exception { assertEquals(n, cffuFactory.cffuAnyOf( createIncompleteFuture(), - createIncompleteFuture(), CompletableFuture.completedFuture(n) ).get()); + assertEquals(n, cffuFactory.cffuAnyOf( + CompletableFuture.completedFuture(n) + ).get()); + + assertFalse(cffuFactory.cffuAnyOf().isDone()); assertEquals(n, cffuFactory.cffuAnyOf( - cffuFactory.newIncompleteCffu(), cffuFactory.completedFuture(n), cffuFactory.newIncompleteCffu() ).get()); + assertEquals(n, cffuFactory.cffuAnyOf( + cffuFactory.completedFuture(n) + ).get()); - assertFalse(cffuFactory.cffuAnyOf().isDone()); + //////////////////////////////////////// + + assertEquals(n, cffuFactory.cffuAnyOfSuccess( + createIncompleteFuture(), + CompletableFuture.completedFuture(n) + ).get()); + assertEquals(n, cffuFactory.cffuAnyOfSuccess( + CompletableFuture.completedFuture(n) + ).get()); + + assertSame(NoCfsProvidedException.class, cffuFactory.cffuAnyOfSuccess().exceptionNow().getClass()); + + assertEquals(n, cffuFactory.cffuAnyOfSuccess( + cffuFactory.completedFuture(n), + cffuFactory.newIncompleteCffu() + ).get()); + assertEquals(n, cffuFactory.cffuAnyOfSuccess( + cffuFactory.completedFuture(n) + ).get()); } @Test @@ -351,24 +499,6 @@ void test_cffuAnyOfSuccess__trivial_case() throws Exception { assertSame(NoCfsProvidedException.class, cffuFactory.cffuAnyOfSuccess().exceptionNow().getClass()); } - //////////////////////////////////////////////////////////////////////////////// - //# Delay Execution, equivalent to same name static methods of CompletableFuture - // - // - delayedExecutor - //////////////////////////////////////////////////////////////////////////////// - - // ... - - //////////////////////////////////////////////////////////////////////////////// - //# New type-safe allOf/anyOf Factory Methods - // method name prefix with `cffu` - // - // - cffuAllOf - // - cffuAnyOf - //////////////////////////////////////////////////////////////////////////////// - - // ... - //////////////////////////////////////////////////////////////////////////////// //# New type-safe cffuCombine Factory Methods // support 2~5 input arguments, method name prefix with `cffu` diff --git a/src/test/java/io/foldright/cffu/kotlin/CffuExtensionsTest.kt b/src/test/java/io/foldright/cffu/kotlin/CffuExtensionsTest.kt index 3d42d5e7..74496df8 100644 --- a/src/test/java/io/foldright/cffu/kotlin/CffuExtensionsTest.kt +++ b/src/test/java/io/foldright/cffu/kotlin/CffuExtensionsTest.kt @@ -3,10 +3,6 @@ package io.foldright.cffu.kotlin import io.foldright.cffu.Cffu import io.foldright.cffu.CffuFactoryBuilder.newCffuFactoryBuilder import io.foldright.cffu.NoCfsProvidedException -import io.foldright.cffu.tuple.Tuple2 -import io.foldright.cffu.tuple.Tuple3 -import io.foldright.cffu.tuple.Tuple4 -import io.foldright.cffu.tuple.Tuple5 import io.foldright.test_utils.testCffuFactory import io.foldright.test_utils.testForkJoinPoolExecutor import io.foldright.test_utils.testThreadPoolExecutor @@ -23,174 +19,12 @@ import kotlinx.coroutines.future.await import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletionStage -class CffuExtensionsTest : FunSpec({ - val n = 42 - val anotherN = 4242 - val s = "43" - val d = 44.0 - - //////////////////////////////////////////////////////////////////////////////// - //# Extension methods for CompletableFuture - //////////////////////////////////////////////////////////////////////////////// - - //////////////////////////////////////// - // - allOfCompletableFuture - // - anyOfCompletableFuture - //////////////////////////////////////// - - test("allOfCompletableFuture / anyOfCompletableFuture - collection") { - listOf( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture(43), - CompletableFuture.completedFuture(44), - ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) - - setOf( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture(43), - CompletableFuture.completedFuture(44), - ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) - - listOf( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfCompletableFuture().await() shouldBe 42 - - setOf( - CompletableFuture(), - CompletableFuture.completedFuture(42), - CompletableFuture(), - ).anyOfCompletableFutureAny().await() shouldBe 42 - } - - test("allOfCompletableFuture / anyOfCompletableFuture - array") { - arrayOf( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture(43), - CompletableFuture.completedFuture(44), - ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) - - arrayOf( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfCompletableFuture().await() shouldBe 42 - } - - //////////////////////////////////////// - // - allOfCompletableFutureVoid - // - anyOfCompletableFutureAny - //////////////////////////////////////// - - test("allOfCompletableFutureVoid / anyOfCompletableFutureAny - collection") { - listOf( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture("42"), - CompletableFuture.completedFuture(42.0), - ).allOfCompletableFutureVoid().await().shouldBeNull() - - setOf( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture("42"), - CompletableFuture.completedFuture(42.0), - ).allOfCompletableFutureVoid().await().shouldBeNull() - - listOf( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfCompletableFutureAny().await() shouldBe 42 - - setOf( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfCompletableFutureAny().await() shouldBe 42 - } - - test("allOfCompletableFutureVoid / anyOfCompletableFutureAny - array") { - // FIXME: Need Type arguments for array... - - arrayOf>( - CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture("42"), - CompletableFuture.completedFuture(42.0), - ).allOfCompletableFutureVoid().await().shouldBeNull() - - arrayOf>( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfCompletableFutureAny().await() shouldBe 42 - } - - //////////////////////////////////////// - // - anyOfSuccessCompletableFuture - //////////////////////////////////////// - - test("anyOfSuccessCompletableFuture - collection") { - listOf( - CompletableFuture(), - CompletableFuture(), - CompletableFuture.completedFuture(42), - ).anyOfSuccessCompletableFuture().await() shouldBe 42 - - setOf( - CompletableFuture(), - CompletableFuture.completedFuture(42), - CompletableFuture(), - ).anyOfSuccessCompletableFuture().await() shouldBe 42 - - shouldThrow { - listOf>().anyOfSuccessCompletableFuture().await() - }.shouldBeTypeOf() - } - - test("anyOfSuccessCompletableFuture - array") { - arrayOf( - CompletableFuture(), - CompletableFuture.completedFuture(42), - CompletableFuture(), - ).anyOfSuccessCompletableFuture().await() shouldBe 42 - - shouldThrow { - arrayOf>().anyOfSuccessCompletableFuture().await() - }.shouldBeTypeOf() - } - - //////////////////////////////////////// - // combine - //////////////////////////////////////// - - test("combine - CompletableFuture") { - CompletableFuture.completedFuture(n).combine( - CompletableFuture.completedFuture(s) - ).get() shouldBe Tuple2.of(n, s) - - CompletableFuture.completedFuture(n).combine( - CompletableFuture.completedFuture(s), - CompletableFuture.completedFuture(d) - ).get() shouldBe Tuple3.of(n, s, d) - - CompletableFuture.completedFuture(n).combine( - CompletableFuture.completedFuture(s), - CompletableFuture.completedFuture(d), - CompletableFuture.completedFuture(anotherN) - ).get() shouldBe Tuple4.of(n, s, d, anotherN) - - CompletableFuture.completedFuture(n).combine( - CompletableFuture.completedFuture(s), - CompletableFuture.completedFuture(d), - CompletableFuture.completedFuture(anotherN), - CompletableFuture.completedFuture(n + n) - ).get() shouldBe Tuple5.of(n, s, d, anotherN, n + n) - } - - //////////////////////////////////////////////////////////////////////////////// - //# Extension methods for Cffu - //////////////////////////////////////////////////////////////////////////////// +const val n = 42 +const val anotherN = 4242 +const val s = "43" +const val d = 44.0 +class CffuExtensionsTest : FunSpec({ //////////////////////////////////////// // asCffu //////////////////////////////////////// @@ -239,12 +73,7 @@ class CffuExtensionsTest : FunSpec({ } } - //////////////////////////////////////// - // - allOfCffu - // - anyOfCffu - //////////////////////////////////////// - - test("allOfCffu/anyOfCffu for collection") { + test("allOf*") { listOf( testCffuFactory.completedFuture(42), testCffuFactory.completedFuture(43), @@ -269,127 +98,199 @@ class CffuExtensionsTest : FunSpec({ CompletableFuture.completedFuture(44), ).allOfCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + arrayOf( + testCffuFactory.completedFuture(42), + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + + arrayOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + + //////////////////////////////////////// + listOf( - testCffuFactory.newIncompleteCffu(), - testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() setOf( - testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), - testCffuFactory.newIncompleteCffu(), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() listOf( - CompletableFuture(), - CompletableFuture(), CompletableFuture.completedFuture(42), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() setOf( - CompletableFuture(), CompletableFuture.completedFuture(42), - CompletableFuture(), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 - } + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() - test("allOfCffu/anyOfCffu for array") { - arrayOf( + // FIXME: Need Type arguments for array... + arrayOf>( testCffuFactory.completedFuture(42), testCffuFactory.completedFuture(43), testCffuFactory.completedFuture(44), - ).allOfCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() - arrayOf( + arrayOf>( CompletableFuture.completedFuture(42), CompletableFuture.completedFuture(43), CompletableFuture.completedFuture(44), - ).allOfCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + + //////////////////////////////////////// + + listOf( + testCffuFactory.completedFuture(42), + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + + setOf( + testCffuFactory.completedFuture(42), + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + + listOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) + + setOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) arrayOf( - testCffuFactory.newIncompleteCffu(), - testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) arrayOf( - CompletableFuture(), - CompletableFuture(), CompletableFuture.completedFuture(42), - ).anyOfCffu(testCffuFactory).await() shouldBe 42 - } + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCffu(testCffuFactory).await() shouldBe listOf(42, 43, 44) - //////////////////////////////////////// - // - allOfCffuVoid - // - anyOfCffuAny - //////////////////////////////////////// + //////////////////////////////////////// - test("allOfCffuVoid/anyOfCffuAny for collection") { listOf( testCffuFactory.completedFuture(42), testCffuFactory.completedFuture(43), testCffuFactory.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() setOf( testCffuFactory.completedFuture(42), testCffuFactory.completedFuture(43), testCffuFactory.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() listOf( CompletableFuture.completedFuture(42), CompletableFuture.completedFuture(43), CompletableFuture.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() setOf( CompletableFuture.completedFuture(42), CompletableFuture.completedFuture(43), CompletableFuture.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() + + // FIXME: Need Type arguments for array... + arrayOf>( + testCffuFactory.completedFuture(42), + testCffuFactory.completedFuture(43), + testCffuFactory.completedFuture(44), + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() + arrayOf>( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCffuVoid(testCffuFactory).await().shouldBeNull() + } + + test("anyOf*") { listOf( testCffuFactory.newIncompleteCffu(), testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), - ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + ).anyOfCffu(testCffuFactory).await() shouldBe 42 setOf( testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), testCffuFactory.newIncompleteCffu(), - ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + ).anyOfCffu(testCffuFactory).await() shouldBe 42 listOf( CompletableFuture(), CompletableFuture(), CompletableFuture.completedFuture(42), - ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + ).anyOfCffu(testCffuFactory).await() shouldBe 42 setOf( CompletableFuture(), CompletableFuture.completedFuture(42), CompletableFuture(), - ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 - } + ).anyOfCffu(testCffuFactory).await() shouldBe 42 - test("allOfCffuVoid/anyOfCffuAny for array") { - // FIXME: Need Type arguments for array... + arrayOf( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.newIncompleteCffu(), + testCffuFactory.completedFuture(42), + ).anyOfCffu(testCffuFactory).await() shouldBe 42 - arrayOf>( + arrayOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCffu(testCffuFactory).await() shouldBe 42 + + //////////////////////////////////////// + + listOf( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), - testCffuFactory.completedFuture(43), - testCffuFactory.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 - arrayOf>( + setOf( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.completedFuture(42), + testCffuFactory.newIncompleteCffu(), + ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + + listOf( + CompletableFuture(), + CompletableFuture(), CompletableFuture.completedFuture(42), - CompletableFuture.completedFuture(43), - CompletableFuture.completedFuture(44), - ).allOfCffuVoid(testCffuFactory).await().shouldBeNull() + ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + setOf( + CompletableFuture(), + CompletableFuture.completedFuture(42), + CompletableFuture(), + ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 + + // FIXME: Need Type arguments for array... arrayOf>( testCffuFactory.newIncompleteCffu(), testCffuFactory.newIncompleteCffu(), @@ -401,13 +302,9 @@ class CffuExtensionsTest : FunSpec({ CompletableFuture(), CompletableFuture.completedFuture(42), ).anyOfCffuAny(testCffuFactory).await() shouldBe 42 - } - //////////////////////////////////////// - // - anyOfSuccessCffu - //////////////////////////////////////// + //////////////////////////////////////// - test("anyOfSuccessCffu for collection") { listOf( testCffuFactory.newIncompleteCffu(), testCffuFactory.newIncompleteCffu(), @@ -420,12 +317,6 @@ class CffuExtensionsTest : FunSpec({ testCffuFactory.newIncompleteCffu(), ).anyOfSuccessCffu(testCffuFactory).await() shouldBe 42 - shouldThrow { - listOf>().anyOfSuccessCffu(testCffuFactory).await() - }.shouldBeTypeOf() - - ////////////////////////////////////////////////////////////////////////////// - listOf( CompletableFuture(), CompletableFuture(), @@ -438,22 +329,12 @@ class CffuExtensionsTest : FunSpec({ CompletableFuture(), ).anyOfSuccessCffu(testCffuFactory).await() shouldBe 42 - shouldThrow { - listOf>().anyOfSuccessCffu(testCffuFactory).await() - }.shouldBeTypeOf() - } - - test("anyOfSuccessCffu for array") { arrayOf( testCffuFactory.newIncompleteCffu(), testCffuFactory.newIncompleteCffu(), testCffuFactory.completedFuture(42), ).anyOfSuccessCffu(testCffuFactory).await() shouldBe 42 - shouldThrow { - arrayOf>().anyOfSuccessCffu(testCffuFactory).await() - }.shouldBeTypeOf() - arrayOf( CompletableFuture(), CompletableFuture(), @@ -463,6 +344,45 @@ class CffuExtensionsTest : FunSpec({ shouldThrow { arrayOf>().anyOfSuccessCffu(testCffuFactory).await() }.shouldBeTypeOf() + + //////////////////////////////////////// + + listOf( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.newIncompleteCffu(), + testCffuFactory.completedFuture(42), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 + + setOf( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.completedFuture(42), + testCffuFactory.newIncompleteCffu(), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 + + listOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 + + setOf( + CompletableFuture(), + CompletableFuture.completedFuture(42), + CompletableFuture(), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 + + // FIXME: Need Type arguments for array... + arrayOf>( + testCffuFactory.newIncompleteCffu(), + testCffuFactory.newIncompleteCffu(), + testCffuFactory.completedFuture(42), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 + + arrayOf>( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCffuAny(testCffuFactory).await() shouldBe 42 } //////////////////////////////////////// diff --git a/src/test/java/io/foldright/cffu/kotlin/CompletableFutureExtensionsTest.kt b/src/test/java/io/foldright/cffu/kotlin/CompletableFutureExtensionsTest.kt new file mode 100644 index 00000000..48c56d9e --- /dev/null +++ b/src/test/java/io/foldright/cffu/kotlin/CompletableFutureExtensionsTest.kt @@ -0,0 +1,234 @@ +package io.foldright.cffu.kotlin + +import io.foldright.cffu.NoCfsProvidedException +import io.foldright.cffu.tuple.Tuple2 +import io.foldright.cffu.tuple.Tuple3 +import io.foldright.cffu.tuple.Tuple4 +import io.foldright.cffu.tuple.Tuple5 +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.booleans.shouldBeFalse +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.future.await +import java.util.concurrent.CompletableFuture + +class CompletableFutureExtensionsTest : FunSpec({ + test("allOf*") { + listOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) + listOf>().allOfCompletableFuture().await() shouldBe emptyList() + + setOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) + + arrayOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfCompletableFuture().await() shouldBe listOf(42, 43, 44) + arrayOf>().allOfCompletableFuture().await() shouldBe emptyList() + + //////////////////////////////////////// + + listOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfCompletableFutureVoid().await().shouldBeNull() + listOf>().allOfCompletableFutureVoid().await().shouldBeNull() + + setOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfCompletableFutureVoid().await().shouldBeNull() + + // FIXME: Need Type arguments for array... + arrayOf>( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfCompletableFutureVoid().await().shouldBeNull() + arrayOf>().allOfCompletableFutureVoid().await().shouldBeNull() + + //////////////////////////////////////// + + listOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCompletableFuture().await() shouldBe listOf(42, 43, 44) + listOf>().allOfFastFailCompletableFuture().await() shouldBe emptyList() + + setOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCompletableFuture().await() shouldBe listOf(42, 43, 44) + + arrayOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture(43), + CompletableFuture.completedFuture(44), + ).allOfFastFailCompletableFuture().await() shouldBe listOf(42, 43, 44) + arrayOf>().allOfFastFailCompletableFuture().await() shouldBe emptyList() + + //////////////////////////////////////// + + listOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfFastFailCompletableFutureVoid().await().shouldBeNull() + listOf>().allOfFastFailCompletableFutureVoid().await().shouldBeNull() + + setOf( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfFastFailCompletableFutureVoid().await().shouldBeNull() + + // FIXME: Need Type arguments for array... + arrayOf>( + CompletableFuture.completedFuture(42), + CompletableFuture.completedFuture("42"), + CompletableFuture.completedFuture(42.0), + ).allOfFastFailCompletableFutureVoid().await().shouldBeNull() + arrayOf>().allOfFastFailCompletableFutureVoid().await().shouldBeNull() + + } + + test("anyOf*") { + listOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFuture().await() shouldBe 42 + listOf>().anyOfCompletableFuture().isDone.shouldBeFalse() + + setOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFuture().await() shouldBe 42 + + arrayOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFuture().await() shouldBe 42 + arrayOf>().anyOfCompletableFuture().isDone.shouldBeFalse() + + //////////////////////////////////////// + + listOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFutureAny().await() shouldBe 42 + listOf>().anyOfCompletableFutureAny().isDone.shouldBeFalse() + + setOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFutureAny().await() shouldBe 42 + + // FIXME: Need Type arguments for array... + arrayOf>( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfCompletableFutureAny().await() shouldBe 42 + arrayOf>().anyOfCompletableFutureAny().isDone.shouldBeFalse() + + //////////////////////////////////////// + + listOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCompletableFuture().await() shouldBe 42 + shouldThrow { + listOf>().anyOfSuccessCompletableFuture().await() + } + + setOf( + CompletableFuture(), + CompletableFuture.completedFuture(42), + CompletableFuture(), + ).anyOfSuccessCompletableFuture().await() shouldBe 42 + + arrayOf( + CompletableFuture(), + CompletableFuture.completedFuture(42), + CompletableFuture(), + ).anyOfSuccessCompletableFuture().await() shouldBe 42 + shouldThrow { + arrayOf>().anyOfSuccessCompletableFuture().await() + } + + //////////////////////////////////////// + + listOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCompletableFutureAny().await() shouldBe 42 + shouldThrow { + listOf>().anyOfSuccessCompletableFutureAny().await() + } + + setOf( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCompletableFutureAny().await() shouldBe 42 + + // FIXME: Need Type arguments for array... + arrayOf>( + CompletableFuture(), + CompletableFuture(), + CompletableFuture.completedFuture(42), + ).anyOfSuccessCompletableFutureAny().await() shouldBe 42 + shouldThrow { + arrayOf>().anyOfSuccessCompletableFutureAny().await() + } + + } + + //////////////////////////////////////// + // combine + //////////////////////////////////////// + + test("combine - CompletableFuture") { + CompletableFuture.completedFuture(n).combine( + CompletableFuture.completedFuture(s) + ).get() shouldBe Tuple2.of(n, s) + + CompletableFuture.completedFuture(n).combine( + CompletableFuture.completedFuture(s), + CompletableFuture.completedFuture(d) + ).get() shouldBe Tuple3.of(n, s, d) + + CompletableFuture.completedFuture(n).combine( + CompletableFuture.completedFuture(s), + CompletableFuture.completedFuture(d), + CompletableFuture.completedFuture(anotherN) + ).get() shouldBe Tuple4.of(n, s, d, anotherN) + + CompletableFuture.completedFuture(n).combine( + CompletableFuture.completedFuture(s), + CompletableFuture.completedFuture(d), + CompletableFuture.completedFuture(anotherN), + CompletableFuture.completedFuture(n + n) + ).get() shouldBe Tuple5.of(n, s, d, anotherN, n + n) + } +})