318 |
|
|
319 |
|
// Choose non-commutative actions for better coverage |
320 |
|
|
321 |
< |
// A non-commutative function that handles null values as well |
322 |
< |
public static int subtract(Integer x, Integer y) { |
323 |
< |
return ((x == null) ? 42 : x.intValue()) |
321 |
> |
// A non-commutative function that handles null values as well, |
322 |
> |
// and produces null values occasionally. |
323 |
> |
public static Integer subtract(Integer x, Integer y) { |
324 |
> |
return (x == null && y == null) ? null : |
325 |
> |
((x == null) ? 42 : x.intValue()) |
326 |
|
- ((y == null) ? 99 : y.intValue()); |
327 |
|
} |
328 |
|
|
337 |
|
public void accept(Integer x) { value = x.intValue() + 1; } |
338 |
|
} |
339 |
|
static final class SubtractAction implements BiConsumer<Integer, Integer> { |
340 |
< |
volatile int invocationCount = 0; |
341 |
< |
int value; |
340 |
> |
int invocationCount = 0; |
341 |
> |
Integer value; |
342 |
|
// Check this action was invoked exactly once when result is computed. |
343 |
|
public boolean ran() { return invocationCount == 1; } |
344 |
|
public void accept(Integer x, Integer y) { |
347 |
|
} |
348 |
|
} |
349 |
|
static final class SubtractFunction implements BiFunction<Integer, Integer, Integer> { |
350 |
< |
volatile int invocationCount = 0; |
351 |
< |
int value; |
350 |
> |
int invocationCount = 0; |
351 |
> |
Integer value; |
352 |
|
// Check this action was invoked exactly once when result is computed. |
353 |
|
public boolean ran() { return invocationCount == 1; } |
354 |
|
public Integer apply(Integer x, Integer y) { |
355 |
|
invocationCount++; |
356 |
< |
return subtract(x, y); |
356 |
> |
return value = subtract(x, y); |
357 |
|
} |
358 |
|
} |
359 |
|
static final class Noop implements Runnable { |
932 |
|
final CompletableFuture<Integer> f = new CompletableFuture<>(); |
933 |
|
final CompletableFuture<Integer> g = new CompletableFuture<>(); |
934 |
|
final SubtractFunction r = new SubtractFunction(); |
935 |
< |
final CompletableFuture<Integer> h = m.thenCombine(f, g, subtract); |
935 |
> |
final CompletableFuture<Integer> h = m.thenCombine(f, g, r); |
936 |
|
final CFException ex = new CFException(); |
937 |
|
|
938 |
|
g.completeExceptionally(ex); |
977 |
|
|
978 |
|
f.completeExceptionally(ex); |
979 |
|
g.complete(v1); |
980 |
< |
final CompletableFuture<Integer> h = m.thenCombine(f, g, subtract); |
980 |
> |
final CompletableFuture<Integer> h = m.thenCombine(f, g, r); |
981 |
|
|
982 |
|
checkCompletedWithWrappedCFException(h, ex); |
983 |
|
checkCompletedWithWrappedCFException(f, ex); |
1130 |
|
|
1131 |
|
f.complete(v1); |
1132 |
|
checkIncomplete(h); |
1133 |
< |
assertEquals(r.value, 0); |
1133 |
> |
assertFalse(r.ran()); |
1134 |
|
g.complete(v2); |
1135 |
|
|
1136 |
|
checkCompletedNormally(h, null); |
1152 |
|
|
1153 |
|
g.complete(v2); |
1154 |
|
checkIncomplete(h); |
1155 |
< |
assertEquals(r.value, 0); |
1155 |
> |
assertFalse(r.ran()); |
1156 |
|
f.complete(v1); |
1157 |
|
|
1158 |
|
checkCompletedNormally(h, null); |