ListenableFuture provides CompletableFuture adaptation via completable()
Issue: SPR-15696
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.util.concurrent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -34,12 +35,8 @@ public class ListenableFutureTaskTests {
|
||||
@Test
|
||||
public void success() throws Exception {
|
||||
final String s = "Hello World";
|
||||
Callable<String> callable = new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return s;
|
||||
}
|
||||
};
|
||||
Callable<String> callable = () -> s;
|
||||
|
||||
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
|
||||
task.addCallback(new ListenableFutureCallback<String>() {
|
||||
@Override
|
||||
@@ -52,17 +49,19 @@ public class ListenableFutureTaskTests {
|
||||
}
|
||||
});
|
||||
task.run();
|
||||
|
||||
assertSame(s, task.get());
|
||||
assertSame(s, task.completable().get());
|
||||
task.completable().thenAccept(v -> assertSame(s, v));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failure() throws Exception {
|
||||
final String s = "Hello World";
|
||||
Callable<String> callable = new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
throw new IOException(s);
|
||||
}
|
||||
Callable<String> callable = () -> {
|
||||
throw new IOException(s);
|
||||
};
|
||||
|
||||
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
|
||||
task.addCallback(new ListenableFutureCallback<String>() {
|
||||
@Override
|
||||
@@ -75,12 +74,28 @@ public class ListenableFutureTaskTests {
|
||||
}
|
||||
});
|
||||
task.run();
|
||||
|
||||
try {
|
||||
task.get();
|
||||
fail("Should have thrown ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
assertSame(s, ex.getCause().getMessage());
|
||||
}
|
||||
try {
|
||||
task.completable().get();
|
||||
fail("Should have thrown ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
assertSame(s, ex.getCause().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void successWithLambdas() throws Exception {
|
||||
final String s = "Hello World";
|
||||
Callable<String> callable = () -> s;
|
||||
|
||||
SuccessCallback<String> successCallback = mock(SuccessCallback.class);
|
||||
FailureCallback failureCallback = mock(FailureCallback.class);
|
||||
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
|
||||
@@ -88,6 +103,10 @@ public class ListenableFutureTaskTests {
|
||||
task.run();
|
||||
verify(successCallback).onSuccess(s);
|
||||
verifyZeroInteractions(failureCallback);
|
||||
|
||||
assertSame(s, task.get());
|
||||
assertSame(s, task.completable().get());
|
||||
task.completable().thenAccept(v -> assertSame(s, v));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -97,6 +116,7 @@ public class ListenableFutureTaskTests {
|
||||
Callable<String> callable = () -> {
|
||||
throw ex;
|
||||
};
|
||||
|
||||
SuccessCallback<String> successCallback = mock(SuccessCallback.class);
|
||||
FailureCallback failureCallback = mock(FailureCallback.class);
|
||||
ListenableFutureTask<String> task = new ListenableFutureTask<>(callable);
|
||||
@@ -104,6 +124,21 @@ public class ListenableFutureTaskTests {
|
||||
task.run();
|
||||
verify(failureCallback).onFailure(ex);
|
||||
verifyZeroInteractions(successCallback);
|
||||
|
||||
try {
|
||||
task.get();
|
||||
fail("Should have thrown ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex2) {
|
||||
assertSame(s, ex2.getCause().getMessage());
|
||||
}
|
||||
try {
|
||||
task.completable().get();
|
||||
fail("Should have thrown ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex2) {
|
||||
assertSame(s, ex2.getCause().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.util.concurrent;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@@ -52,6 +53,16 @@ public class SettableListenableFutureTests {
|
||||
assertTrue(settableListenableFuture.isDone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void returnsSetValueFromCompletable() throws ExecutionException, InterruptedException {
|
||||
String string = "hello";
|
||||
assertTrue(settableListenableFuture.set(string));
|
||||
Future<String> completable = settableListenableFuture.completable();
|
||||
assertThat(completable.get(), equalTo(string));
|
||||
assertFalse(completable.isCancelled());
|
||||
assertTrue(completable.isDone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValueUpdatesDoneStatus() {
|
||||
settableListenableFuture.set("hello");
|
||||
@@ -60,7 +71,7 @@ public class SettableListenableFutureTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsSetExceptionWrappedInExecutionException() throws ExecutionException, InterruptedException {
|
||||
public void throwsSetExceptionWrappedInExecutionException() throws Exception {
|
||||
Throwable exception = new RuntimeException();
|
||||
assertTrue(settableListenableFuture.setException(exception));
|
||||
|
||||
@@ -77,7 +88,25 @@ public class SettableListenableFutureTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsSetErrorWrappedInExecutionException() throws ExecutionException, InterruptedException {
|
||||
public void throwsSetExceptionWrappedInExecutionExceptionFromCompletable() throws Exception {
|
||||
Throwable exception = new RuntimeException();
|
||||
assertTrue(settableListenableFuture.setException(exception));
|
||||
Future<String> completable = settableListenableFuture.completable();
|
||||
|
||||
try {
|
||||
completable.get();
|
||||
fail("Expected ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
assertThat(ex.getCause(), equalTo(exception));
|
||||
}
|
||||
|
||||
assertFalse(completable.isCancelled());
|
||||
assertTrue(completable.isDone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsSetErrorWrappedInExecutionException() throws Exception {
|
||||
Throwable exception = new OutOfMemoryError();
|
||||
assertTrue(settableListenableFuture.setException(exception));
|
||||
|
||||
@@ -93,6 +122,24 @@ public class SettableListenableFutureTests {
|
||||
assertTrue(settableListenableFuture.isDone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void throwsSetErrorWrappedInExecutionExceptionFromCompletable() throws Exception {
|
||||
Throwable exception = new OutOfMemoryError();
|
||||
assertTrue(settableListenableFuture.setException(exception));
|
||||
Future<String> completable = settableListenableFuture.completable();
|
||||
|
||||
try {
|
||||
completable.get();
|
||||
fail("Expected ExecutionException");
|
||||
}
|
||||
catch (ExecutionException ex) {
|
||||
assertThat(ex.getCause(), equalTo(exception));
|
||||
}
|
||||
|
||||
assertFalse(completable.isCancelled());
|
||||
assertTrue(completable.isDone());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setValueTriggersCallback() {
|
||||
String string = "hello";
|
||||
|
||||
Reference in New Issue
Block a user