ThenComposeExceptionTest.java revision 12677:a4299d47bd00
1/* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24import org.testng.Assert; 25import org.testng.annotations.DataProvider; 26import org.testng.annotations.Test; 27 28import java.util.ArrayList; 29import java.util.List; 30import java.util.concurrent.CompletableFuture; 31import java.util.concurrent.CompletionException; 32import java.util.concurrent.atomic.AtomicReference; 33import java.util.function.BiFunction; 34import java.util.function.Consumer; 35 36 37/** 38 * @test 39 * @bug 8068432 8072030 40 * @run testng ThenComposeExceptionTest 41 * @summary Test that CompletableFuture.thenCompose works correctly if the 42 * composing future completes exceptionally 43 */ 44@Test 45public class ThenComposeExceptionTest { 46 47 static final BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>> 48 THEN_COMPOSE = (f, fe) -> f.thenCompose(s -> fe); 49 50 static final BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>> 51 THEN_COMPOSE_ASYNC = (f, fe) -> f.thenComposeAsync(s -> fe); 52 53 static final Consumer<CompletableFuture<String>> 54 COMPLETE_EXCEPTIONALLY = f -> f.completeExceptionally(new RuntimeException()); 55 56 static final Consumer<CompletableFuture<String>> 57 NOP = f -> { }; 58 59 static Object[][] actionsDataProvider; 60 61 @DataProvider(name = "actions") 62 static Object[][] actionsDataProvider() { 63 if (actionsDataProvider != null) { 64 return actionsDataProvider; 65 } 66 67 List<Object[]> data = new ArrayList<>(); 68 data.add(new Object[]{"thenCompose and completeExceptionally", NOP, THEN_COMPOSE, COMPLETE_EXCEPTIONALLY}); 69 data.add(new Object[]{"thenComposeAsync and completeExceptionally", NOP, THEN_COMPOSE_ASYNC, COMPLETE_EXCEPTIONALLY}); 70 data.add(new Object[]{"completeExceptionally and thenCompose", COMPLETE_EXCEPTIONALLY, THEN_COMPOSE, NOP}); 71 data.add(new Object[]{"completeExceptionally and thenComposeAsync", COMPLETE_EXCEPTIONALLY, THEN_COMPOSE_ASYNC, NOP}); 72 73 return actionsDataProvider = data.toArray(new Object[0][]); 74 } 75 76 @Test(dataProvider = "actions") 77 public void testThenCompose( 78 String description, 79 Consumer<CompletableFuture<String>> beforeAction, 80 BiFunction<CompletableFuture<String>, CompletableFuture<String>, CompletableFuture<String>> composeFunction, 81 Consumer<CompletableFuture<String>> afterAction) throws Exception { 82 CompletableFuture<String> f = new CompletableFuture<>(); 83 CompletableFuture<String> fe = new CompletableFuture<>(); 84 85 // Ensure pre-composed stage is completed to trigger 86 // processing the composing future 87 f.complete(""); 88 89 beforeAction.accept(fe); 90 91 CompletableFuture<String> f_thenCompose = composeFunction.apply(f, fe); 92 Assert.assertNotSame(f_thenCompose, fe, "Composed CompletableFuture returned directly"); 93 94 AtomicReference<Throwable> eOnWhenComplete = new AtomicReference<>(); 95 CompletableFuture<String> f_whenComplete = f_thenCompose. 96 whenComplete((r, e) -> eOnWhenComplete.set(e)); 97 98 afterAction.accept(fe); 99 100 Throwable eOnJoined = null; 101 try { 102 f_thenCompose.join(); 103 } 104 catch (Throwable t) { 105 eOnJoined = t; 106 } 107 Assert.assertTrue(eOnJoined instanceof CompletionException, 108 "Incorrect exception reported when joined on thenCompose: " + eOnJoined); 109 110 // Need to wait for f_whenComplete to complete to avoid 111 // race condition when updating eOnWhenComplete 112 eOnJoined = null; 113 try { 114 f_whenComplete.join(); 115 } catch (Throwable t) { 116 eOnJoined = t; 117 } 118 Assert.assertTrue(eOnJoined instanceof CompletionException, 119 "Incorrect exception reported when joined on whenComplete: " + eOnJoined); 120 Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException, 121 "Incorrect exception passed to whenComplete: " + eOnWhenComplete.get()); 122 } 123} 124