Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 11 migration: ambassador async-method-invocation balking bridge builder #1076

Merged
merged 5 commits into from
Nov 11, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Moves async-method-invocation pattern to java 11
  • Loading branch information
anuragagarwal561994 committed Nov 10, 2019
commit 2e212b9b254045e76e8aedd41be922aa258334c8
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,24 @@ public class App {
*/
public static void main(String[] args) throws Exception {
// construct a new executor that will run async tasks
AsyncExecutor executor = new ThreadAsyncExecutor();
var executor = new ThreadAsyncExecutor();

// start few async tasks with varying processing times, two last with callback handlers
final AsyncResult<Integer> asyncResult1 = executor.startProcess(lazyval(10, 500));
final AsyncResult<String> asyncResult2 = executor.startProcess(lazyval("test", 300));
final AsyncResult<Long> asyncResult3 = executor.startProcess(lazyval(50L, 700));
final AsyncResult<Integer> asyncResult4 =
executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
final AsyncResult<String> asyncResult5 =
final var asyncResult1 = executor.startProcess(lazyval(10, 500));
final var asyncResult2 = executor.startProcess(lazyval("test", 300));
final var asyncResult3 = executor.startProcess(lazyval(50L, 700));
final var asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
final var asyncResult5 =
executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));

// emulate processing in the current thread while async tasks are running in their own threads
Thread.sleep(350); // Oh boy I'm working hard here
log("Some hard work done");

// wait for completion of the tasks
final Integer result1 = executor.endProcess(asyncResult1);
final String result2 = executor.endProcess(asyncResult2);
final Long result3 = executor.endProcess(asyncResult3);
final var result1 = executor.endProcess(asyncResult1);
final var result2 = executor.endProcess(asyncResult2);
final var result3 = executor.endProcess(asyncResult3);
asyncResult4.await();
asyncResult5.await();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public <T> AsyncResult<T> startProcess(Callable<T> task) {

@Override
public <T> AsyncResult<T> startProcess(Callable<T> task, AsyncCallback<T> callback) {
CompletableResult<T> result = new CompletableResult<>(callback);
var result = new CompletableResult<>(callback);
new Thread(() -> {
try {
result.setValue(task.call());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@
/**
* Application test
*/
public class AppTest {

class AppTest {
@Test
public void test() throws Exception {
String[] args = {};
App.main(args);
void test() throws Exception {
App.main(new String[]{});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,66 @@
package com.iluwatar.async.method.invocation;

import static java.time.Duration.ofMillis;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTimeout;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.internal.verification.VerificationModeFactory.times;

import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
* Date: 12/6/15 - 10:49 AM
*
* @author Jeroen Meulemeester
*/
public class ThreadAsyncExecutorTest {
class ThreadAsyncExecutorTest {

@Captor
private ArgumentCaptor<Optional<Exception>> optionalCaptor;

@Mock
private Callable<Object> task;

@Mock
private AsyncCallback<Object> callback;

@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}

/**
* Test used to verify the happy path of {@link ThreadAsyncExecutor#startProcess(Callable)}
*/
@Test
public void testSuccessfulTaskWithoutCallback() throws Exception {
void testSuccessfulTaskWithoutCallback() throws Exception {
assertTimeout(ofMillis(3000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final var executor = new ThreadAsyncExecutor();

final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
final var result = new Object();
when(task.call()).thenReturn(result);

final AsyncResult<Object> asyncResult = executor.startProcess(task);
final var asyncResult = executor.startProcess(task);
assertNotNull(asyncResult);
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());
Expand All @@ -74,17 +101,15 @@ public void testSuccessfulTaskWithoutCallback() throws Exception {
* AsyncCallback)}
*/
@Test
public void testSuccessfulTaskWithCallback() throws Exception {
void testSuccessfulTaskWithCallback() throws Exception {
assertTimeout(ofMillis(3000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final var executor = new ThreadAsyncExecutor();

final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
final var result = new Object();
when(task.call()).thenReturn(result);

final AsyncCallback callback = mock(AsyncCallback.class);
final AsyncResult<Object> asyncResult = executor.startProcess(task, callback);
final var asyncResult = executor.startProcess(task, callback);
assertNotNull(asyncResult);
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());
Expand All @@ -93,11 +118,9 @@ public void testSuccessfulTaskWithCallback() throws Exception {
verify(task, times(1)).call();

// ... same for the callback, we expect our object
final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(eq(result), optionalCaptor.capture());

final Optional<Exception> optionalException = optionalCaptor.getValue();
final var optionalException = optionalCaptor.getValue();
assertNotNull(optionalException);
assertFalse(optionalException.isPresent());

Expand All @@ -111,19 +134,18 @@ public void testSuccessfulTaskWithCallback() throws Exception {
* task takes a while to execute
*/
@Test
public void testLongRunningTaskWithoutCallback() throws Exception {
void testLongRunningTaskWithoutCallback() throws Exception {
assertTimeout(ofMillis(5000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final var executor = new ThreadAsyncExecutor();

final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
final var result = new Object();
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});

final AsyncResult<Object> asyncResult = executor.startProcess(task);
final var asyncResult = executor.startProcess(task);
assertNotNull(asyncResult);
assertFalse(asyncResult.isCompleted());

Expand Down Expand Up @@ -152,20 +174,18 @@ public void testLongRunningTaskWithoutCallback() throws Exception {
* AsyncCallback)} when a task takes a while to execute
*/
@Test
public void testLongRunningTaskWithCallback() throws Exception {
void testLongRunningTaskWithCallback() throws Exception {
assertTimeout(ofMillis(5000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final var executor = new ThreadAsyncExecutor();

final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
final var result = new Object();
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});

final AsyncCallback<Object> callback = mock(AsyncCallback.class);
final AsyncResult<Object> asyncResult = executor.startProcess(task, callback);
final var asyncResult = executor.startProcess(task, callback);
assertNotNull(asyncResult);
assertFalse(asyncResult.isCompleted());

Expand All @@ -180,12 +200,9 @@ public void testLongRunningTaskWithCallback() throws Exception {

// Our task should only execute once, but it can take a while ...
verify(task, timeout(3000).times(1)).call();

final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, timeout(3000).times(1)).onComplete(eq(result), optionalCaptor.capture());

final Optional<Exception> optionalException = optionalCaptor.getValue();
final var optionalException = optionalCaptor.getValue();
assertNotNull(optionalException);
assertFalse(optionalException.isPresent());

Expand All @@ -205,19 +222,18 @@ public void testLongRunningTaskWithCallback() throws Exception {
* ThreadAsyncExecutor#endProcess(AsyncResult)}
*/
@Test
public void testEndProcess() throws Exception {
void testEndProcess() throws Exception {
assertTimeout(ofMillis(5000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final var executor = new ThreadAsyncExecutor();

final Object result = new Object();
final Callable<Object> task = mock(Callable.class);
final var result = new Object();
when(task.call()).thenAnswer(i -> {
Thread.sleep(1500);
return result;
});

final AsyncResult<Object> asyncResult = executor.startProcess(task);
final var asyncResult = executor.startProcess(task);
assertNotNull(asyncResult);
assertFalse(asyncResult.isCompleted());

Expand All @@ -243,11 +259,11 @@ public void testEndProcess() throws Exception {
* the callable is 'null'
*/
@Test
public void testNullTask() throws Exception {
void testNullTask() throws Exception {
assertTimeout(ofMillis(3000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final AsyncResult<Object> asyncResult = executor.startProcess(null);
final var executor = new ThreadAsyncExecutor();
final var asyncResult = executor.startProcess(null);

assertNotNull(asyncResult, "The AsyncResult should not be 'null', even though the task was 'null'.");
asyncResult.await(); // Prevent timing issues, and wait until the result is available
Expand All @@ -270,26 +286,22 @@ public void testNullTask() throws Exception {
* AsyncCallback)} when the callable is 'null', but the asynchronous callback is provided
*/
@Test
public void testNullTaskWithCallback() throws Exception {
void testNullTaskWithCallback() throws Exception {
assertTimeout(ofMillis(3000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final AsyncCallback<Object> callback = mock(AsyncCallback.class);
final AsyncResult<Object> asyncResult = executor.startProcess(null, callback);
final var executor = new ThreadAsyncExecutor();
final var asyncResult = executor.startProcess(null, callback);

assertNotNull(asyncResult, "The AsyncResult should not be 'null', even though the task was 'null'.");
asyncResult.await(); // Prevent timing issues, and wait until the result is available
assertTrue(asyncResult.isCompleted());

final ArgumentCaptor<Optional<Exception>> optionalCaptor =
ArgumentCaptor.forClass((Class) Optional.class);
verify(callback, times(1)).onComplete(Matchers.isNull(), optionalCaptor.capture());

final Optional<Exception> optionalException = optionalCaptor.getValue();
final var optionalException = optionalCaptor.getValue();
assertNotNull(optionalException);
assertTrue(optionalException.isPresent());

final Exception exception = optionalException.get();
final var exception = optionalException.get();
assertNotNull(exception);
assertEquals(NullPointerException.class, exception.getClass());

Expand All @@ -310,11 +322,11 @@ public void testNullTaskWithCallback() throws Exception {
* AsyncCallback)} when both the callable and the asynchronous callback are 'null'
*/
@Test
public void testNullTaskWithNullCallback() throws Exception {
void testNullTaskWithNullCallback() throws Exception {
assertTimeout(ofMillis(3000), () -> {
// Instantiate a new executor and start a new 'null' task ...
final ThreadAsyncExecutor executor = new ThreadAsyncExecutor();
final AsyncResult<Object> asyncResult = executor.startProcess(null, null);
final var executor = new ThreadAsyncExecutor();
final var asyncResult = executor.startProcess(null, null);

assertNotNull(
asyncResult,
Expand Down