8 |
|
import static java.util.concurrent.TimeUnit.MILLISECONDS; |
9 |
|
import static java.util.concurrent.TimeUnit.SECONDS; |
10 |
|
|
11 |
+ |
import java.lang.reflect.Method; |
12 |
+ |
import java.lang.reflect.Modifier; |
13 |
+ |
|
14 |
+ |
import java.util.stream.Collectors; |
15 |
+ |
import java.util.stream.Stream; |
16 |
+ |
|
17 |
|
import java.util.ArrayList; |
18 |
+ |
import java.util.Arrays; |
19 |
|
import java.util.List; |
20 |
|
import java.util.Objects; |
21 |
+ |
import java.util.Set; |
22 |
|
import java.util.concurrent.Callable; |
23 |
|
import java.util.concurrent.CancellationException; |
24 |
|
import java.util.concurrent.CompletableFuture; |
36 |
|
import java.util.function.BiFunction; |
37 |
|
import java.util.function.Consumer; |
38 |
|
import java.util.function.Function; |
39 |
+ |
import java.util.function.Predicate; |
40 |
|
import java.util.function.Supplier; |
41 |
|
|
42 |
|
import junit.framework.Test; |
898 |
|
* whenComplete action executes on normal completion, propagating |
899 |
|
* source result. |
900 |
|
*/ |
901 |
< |
public void testWhenComplete_normalCompletion1() { |
901 |
> |
public void testWhenComplete_normalCompletion() { |
902 |
|
for (ExecutionMode m : ExecutionMode.values()) |
903 |
|
for (boolean createIncomplete : new boolean[] { true, false }) |
904 |
|
for (Integer v1 : new Integer[] { 1, null }) |
3697 |
|
} |
3698 |
|
}} |
3699 |
|
|
3700 |
+ |
/** |
3701 |
+ |
* Minimal completion stages throw UOE for all non-CompletionStage methods |
3702 |
+ |
*/ |
3703 |
+ |
public void testMinimalCompletionStage_minimality() { |
3704 |
+ |
if (!testImplementationDetails) return; |
3705 |
+ |
Function<Method, String> toSignature = |
3706 |
+ |
(method) -> method.getName() + Arrays.toString(method.getParameterTypes()); |
3707 |
+ |
Predicate<Method> isNotStatic = |
3708 |
+ |
(method) -> (method.getModifiers() & Modifier.STATIC) == 0; |
3709 |
+ |
List<Method> minimalMethods = |
3710 |
+ |
Stream.of(Object.class, CompletionStage.class) |
3711 |
+ |
.flatMap((klazz) -> Stream.of(klazz.getMethods())) |
3712 |
+ |
.filter(isNotStatic) |
3713 |
+ |
.collect(Collectors.toList()); |
3714 |
+ |
// Methods from CompletableFuture permitted NOT to throw UOE |
3715 |
+ |
String[] signatureWhitelist = { |
3716 |
+ |
"newIncompleteFuture[]", |
3717 |
+ |
"defaultExecutor[]", |
3718 |
+ |
"minimalCompletionStage[]", |
3719 |
+ |
"copy[]", |
3720 |
+ |
}; |
3721 |
+ |
Set<String> permittedMethodSignatures = |
3722 |
+ |
Stream.concat(minimalMethods.stream().map(toSignature), |
3723 |
+ |
Stream.of(signatureWhitelist)) |
3724 |
+ |
.collect(Collectors.toSet()); |
3725 |
+ |
List<Method> allMethods = Stream.of(CompletableFuture.class.getMethods()) |
3726 |
+ |
.filter(isNotStatic) |
3727 |
+ |
.filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method))) |
3728 |
+ |
.collect(Collectors.toList()); |
3729 |
+ |
|
3730 |
+ |
CompletionStage<Integer> minimalStage = |
3731 |
+ |
new CompletableFuture<Integer>().minimalCompletionStage(); |
3732 |
+ |
|
3733 |
+ |
List<Method> bugs = new ArrayList<>(); |
3734 |
+ |
for (Method method : allMethods) { |
3735 |
+ |
Class<?>[] parameterTypes = method.getParameterTypes(); |
3736 |
+ |
Object[] args = new Object[parameterTypes.length]; |
3737 |
+ |
// Manufacture boxed primitives for primitive params |
3738 |
+ |
for (int i = 0; i < args.length; i++) { |
3739 |
+ |
Class<?> type = parameterTypes[i]; |
3740 |
+ |
if (parameterTypes[i] == boolean.class) |
3741 |
+ |
args[i] = false; |
3742 |
+ |
else if (parameterTypes[i] == int.class) |
3743 |
+ |
args[i] = 0; |
3744 |
+ |
else if (parameterTypes[i] == long.class) |
3745 |
+ |
args[i] = 0L; |
3746 |
+ |
} |
3747 |
+ |
try { |
3748 |
+ |
method.invoke(minimalStage, args); |
3749 |
+ |
bugs.add(method); |
3750 |
+ |
} |
3751 |
+ |
catch (java.lang.reflect.InvocationTargetException expected) { |
3752 |
+ |
if (! (expected.getCause() instanceof UnsupportedOperationException)) { |
3753 |
+ |
bugs.add(method); |
3754 |
+ |
// expected.getCause().printStackTrace(); |
3755 |
+ |
} |
3756 |
+ |
} |
3757 |
+ |
catch (ReflectiveOperationException bad) { throw new Error(bad); } |
3758 |
+ |
} |
3759 |
+ |
if (!bugs.isEmpty()) |
3760 |
+ |
throw new Error("Methods did not throw UOE: " + bugs.toString()); |
3761 |
+ |
} |
3762 |
+ |
|
3763 |
+ |
// static <U> U join(CompletionStage<U> stage) { |
3764 |
+ |
// CompletableFuture<U> f = new CompletableFuture<>(); |
3765 |
+ |
// stage.whenComplete((v, ex) -> { |
3766 |
+ |
// if (ex != null) f.completeExceptionally(ex); else f.complete(v); |
3767 |
+ |
// }); |
3768 |
+ |
// return f.join(); |
3769 |
+ |
// } |
3770 |
+ |
|
3771 |
+ |
// static <U> boolean isDone(CompletionStage<U> stage) { |
3772 |
+ |
// CompletableFuture<U> f = new CompletableFuture<>(); |
3773 |
+ |
// stage.whenComplete((v, ex) -> { |
3774 |
+ |
// if (ex != null) f.completeExceptionally(ex); else f.complete(v); |
3775 |
+ |
// }); |
3776 |
+ |
// return f.isDone(); |
3777 |
+ |
// } |
3778 |
+ |
|
3779 |
+ |
// static <U> U join2(CompletionStage<U> stage) { |
3780 |
+ |
// return stage.toCompletableFuture().copy().join(); |
3781 |
+ |
// } |
3782 |
+ |
|
3783 |
+ |
// static <U> boolean isDone2(CompletionStage<U> stage) { |
3784 |
+ |
// return stage.toCompletableFuture().copy().isDone(); |
3785 |
+ |
// } |
3786 |
+ |
|
3787 |
|
} |