1 /*
2  * Copyright (c) 2018, 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 
24 package jdk.internal.net.http.common;
25 
26 import org.testng.annotations.DataProvider;
27 import org.testng.annotations.Test;
28 
29 import java.util.concurrent.CompletableFuture;
30 import java.util.concurrent.CompletionException;
31 import java.util.concurrent.ExecutorService;
32 import java.util.concurrent.Executors;
33 
34 import static org.testng.Assert.assertThrows;
35 
36 public class MinimalFutureTest {
37 
38     @Test(dataProvider = "futures")
test(CompletableFuture<Object> mf)39     public void test(CompletableFuture<Object> mf) {
40         ExecutorService executor = Executors.newSingleThreadExecutor();
41         try {
42             assertNoObtrusion(mf.thenApply(MinimalFutureTest::apply));
43             assertNoObtrusion(mf.thenApplyAsync(MinimalFutureTest::apply));
44             assertNoObtrusion(mf.thenApplyAsync(MinimalFutureTest::apply, executor));
45 
46             assertNoObtrusion(mf.thenAccept(MinimalFutureTest::accept));
47             assertNoObtrusion(mf.thenAcceptAsync(MinimalFutureTest::accept));
48             assertNoObtrusion(mf.thenAcceptAsync(MinimalFutureTest::accept, executor));
49 
50             assertNoObtrusion(mf.thenRun(MinimalFutureTest::run));
51             assertNoObtrusion(mf.thenRunAsync(MinimalFutureTest::run));
52             assertNoObtrusion(mf.thenRunAsync(MinimalFutureTest::run, executor));
53 
54             assertNoObtrusion(mf.thenCombine(otherFuture(), MinimalFutureTest::apply));
55             assertNoObtrusion(mf.thenCombineAsync(otherFuture(), MinimalFutureTest::apply));
56             assertNoObtrusion(mf.thenCombineAsync(otherFuture(), MinimalFutureTest::apply, executor));
57 
58             assertNoObtrusion(mf.thenAcceptBoth(otherFuture(), MinimalFutureTest::accept));
59             assertNoObtrusion(mf.thenAcceptBothAsync(otherFuture(), MinimalFutureTest::accept));
60             assertNoObtrusion(mf.thenAcceptBothAsync(otherFuture(), MinimalFutureTest::accept, executor));
61 
62             assertNoObtrusion(mf.runAfterBoth(otherFuture(), MinimalFutureTest::run));
63             assertNoObtrusion(mf.runAfterBothAsync(otherFuture(), MinimalFutureTest::run));
64             assertNoObtrusion(mf.runAfterBothAsync(otherFuture(), MinimalFutureTest::run, executor));
65 
66             // "either" methods may return something else if otherFuture() is
67             // not MinimalFuture
68 
69             assertNoObtrusion(mf.applyToEither(otherFuture(), MinimalFutureTest::apply));
70             assertNoObtrusion(mf.applyToEitherAsync(otherFuture(), MinimalFutureTest::apply));
71             assertNoObtrusion(mf.applyToEitherAsync(otherFuture(), MinimalFutureTest::apply, executor));
72 
73             assertNoObtrusion(mf.acceptEither(otherFuture(), MinimalFutureTest::accept));
74             assertNoObtrusion(mf.acceptEitherAsync(otherFuture(), MinimalFutureTest::accept));
75             assertNoObtrusion(mf.acceptEitherAsync(otherFuture(), MinimalFutureTest::accept, executor));
76 
77             assertNoObtrusion(mf.runAfterEither(otherFuture(), MinimalFutureTest::run));
78             assertNoObtrusion(mf.runAfterEitherAsync(otherFuture(), MinimalFutureTest::run));
79             assertNoObtrusion(mf.runAfterEitherAsync(otherFuture(), MinimalFutureTest::run, executor));
80 
81             assertNoObtrusion(mf.thenCompose(MinimalFutureTest::completionStageOf));
82             assertNoObtrusion(mf.thenComposeAsync(MinimalFutureTest::completionStageOf));
83             assertNoObtrusion(mf.thenComposeAsync(MinimalFutureTest::completionStageOf, executor));
84 
85             assertNoObtrusion(mf.handle(MinimalFutureTest::relay));
86             assertNoObtrusion(mf.handleAsync(MinimalFutureTest::relay));
87             assertNoObtrusion(mf.handleAsync(MinimalFutureTest::relay, executor));
88 
89             assertNoObtrusion(mf.whenComplete(MinimalFutureTest::accept));
90             assertNoObtrusion(mf.whenCompleteAsync(MinimalFutureTest::accept));
91             assertNoObtrusion(mf.whenCompleteAsync(MinimalFutureTest::accept, executor));
92 
93             assertNoObtrusion(mf.toCompletableFuture());
94             assertNoObtrusion(mf.exceptionally(t -> null));
95 
96             assertNoObtrusion(mf);
97             assertNoObtrusion(mf.copy());
98             assertNoObtrusion(mf.newIncompleteFuture());
99         } finally {
100             executor.shutdownNow();
101         }
102     }
103 
otherFuture()104     private static CompletableFuture<Object> otherFuture() {
105         return MinimalFuture.completedFuture(new Object());
106     }
107 
relay(Object r, Throwable e)108     private static Object relay(Object r, Throwable e) {
109         if (e != null)
110             throw new CompletionException(e);
111         else
112             return r;
113     }
114 
completionStageOf(Object r)115     private static CompletableFuture<?> completionStageOf(Object r) {
116         return new CompletableFuture<>();
117     }
118 
accept(Object arg)119     private static void accept(Object arg) {
120     }
121 
accept(Object arg1, Object arg2)122     private static void accept(Object arg1, Object arg2) {
123     }
124 
run()125     private static void run() {
126     }
127 
apply(Object arg)128     private static Object apply(Object arg) {
129         return new Object();
130     }
131 
apply(Object arg1, Object arg2)132     private static Object apply(Object arg1, Object arg2) {
133         return new Object();
134     }
135 
136 
137     @DataProvider(name = "futures")
futures()138     public Object[][] futures() {
139 
140         MinimalFuture<Object> mf = new MinimalFuture<>();
141         mf.completeExceptionally(new Throwable());
142 
143         MinimalFuture<Object> mf1 = new MinimalFuture<>();
144         mf1.complete(new Object());
145 
146         return new Object[][]{
147                 new Object[]{new MinimalFuture<>()},
148                 new Object[]{MinimalFuture.failedFuture(new Throwable())},
149                 new Object[]{MinimalFuture.completedFuture(new Object())},
150                 new Object[]{mf},
151                 new Object[]{mf1},
152         };
153     }
154 
assertNoObtrusion(CompletableFuture<?> cf)155     private void assertNoObtrusion(CompletableFuture<?> cf) {
156         assertThrows(UnsupportedOperationException.class,
157                      () -> cf.obtrudeValue(null));
158         assertThrows(UnsupportedOperationException.class,
159                      () -> cf.obtrudeException(new RuntimeException()));
160     }
161 }
162