Futures { public static CompletionException combineErrors( Throwable error1, Throwable error2 ) { if ( error1 != null && error2 != null ) { Throwable cause1 = completionExceptionCause( error1 ); Throwable cause2 = completionExceptionCause( error2 ); addSuppressed( cause1, cause2 ); return asCompletionException( cause1 ); } else if ( error1 != null ) { return asCompletionException( error1 ); } else if ( error2 != null ) { return asCompletionException( error2 ); } else { return null; } } private  Futures(); @SuppressWarnings( "unchecked" ) static CompletableFuture<T> completedWithNull(); static CompletableFuture<T> completeWithNullIfNoError( CompletableFuture<T> future, Throwable error ); static CompletionStage<T> asCompletionStage( io.netty.util.concurrent.Future<T> future ); static CompletionStage<T> asCompletionStage( io.netty.util.concurrent.Future<T> future, CompletableFuture<T> result ); static CompletableFuture<T> failedFuture( Throwable error ); static V blockingGet( CompletionStage<V> stage ); static V blockingGet( CompletionStage<V> stage, Runnable interruptHandler ); static T getNow( CompletionStage<T> stage ); static Throwable completionExceptionCause( Throwable error ); static CompletionException asCompletionException( Throwable error ); static CompletionException combineErrors( Throwable error1, Throwable error2 ); @SuppressWarnings( "ThrowableNotThrown" ) static CompletableFuture<T> onErrorContinue( CompletableFuture<T> future, Throwable errorRecorder,
            Function<Throwable,? extends CompletionStage<T>> onErrorAction );  }
@Test void shouldCombineTwoErrors() { RuntimeException error1 = new RuntimeException( "Error1" ); RuntimeException error2Cause = new RuntimeException( "Error2" ); CompletionException error2 = new CompletionException( error2Cause ); CompletionException combined = Futures.combineErrors( error1, error2 ); assertEquals( error1, combined.getCause() ); assertArrayEquals( new Throwable[]{error2Cause}, combined.getCause().getSuppressed() ); }
@Test void shouldCombineErrorAndNull() { RuntimeException error1 = new RuntimeException( "Error1" ); CompletionException combined = Futures.combineErrors( error1, null ); assertEquals( error1, combined.getCause() ); }
@Test void shouldCombineNullAndError() { RuntimeException error2 = new RuntimeException( "Error2" ); CompletionException combined = Futures.combineErrors( null, error2 ); assertEquals( error2, combined.getCause() ); }
@Test void shouldCombineNullAndNullErrors() { assertNull( Futures.combineErrors( null, null ) ); }