package com.twitter.common.util.concurrent; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import com.google.common.testing.TearDown; import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.junit.Before; import org.junit.Test; import com.twitter.common.quantity.Amount; import com.twitter.common.quantity.Time; import com.twitter.common.testing.easymock.EasyMockTest; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class ExceptionHandlingExecutorServiceTest extends EasyMockTest { private static final RuntimeException EXCEPTION = new RuntimeException(); private ExecutorService executorService; private Thread.UncaughtExceptionHandler signallingHandler; @Before public void setUp() throws Exception { signallingHandler = createMock(Thread.UncaughtExceptionHandler.class); executorService = MoreExecutors.exceptionHandlingExecutor( Executors.newCachedThreadPool(new ThreadFactoryBuilder() .setNameFormat("ExceptionHandlingExecutorServiceTest-%d") .build()), signallingHandler); final ExecutorServiceShutdown executorServiceShutdown = new ExecutorServiceShutdown( executorService, Amount.of(3L, Time.SECONDS)); addTearDown(new TearDown() { @Override public void tearDown() throws Exception { executorServiceShutdown.execute(); } }); } @Test public void testSubmitRunnable() throws Exception { Runnable runnable = createMock(Runnable.class); runnable.run(); control.replay(); executorService.submit(runnable).get(); } @Test public void testSubmitFailingRunnable() throws Exception { signallingHandler.uncaughtException(anyObject(Thread.class), eq(EXCEPTION)); Runnable runnable = createMock(Runnable.class); runnable.run(); expectLastCall().andThrow(EXCEPTION); control.replay(); try { executorService.submit(runnable).get(); fail(EXCEPTION.getClass().getSimpleName() + " should be thrown."); } catch (ExecutionException e) { assertEquals(EXCEPTION, e.getCause()); } } @Test public void testSubmitCallable() throws Exception { Integer returnValue = 123; Callable<Integer> callable = createMock(new Clazz<Callable<Integer>>() {}); callable.call(); expectLastCall().andReturn(returnValue); control.replay(); assertEquals(returnValue, executorService.submit(callable).get()); } @Test public void testSubmitFailingCallable() throws Exception { signallingHandler.uncaughtException(anyObject(Thread.class), eq(EXCEPTION)); Callable<Void> callable = createMock(new Clazz<Callable<Void>>() {}); expect(callable.call()).andThrow(EXCEPTION); control.replay(); try { executorService.submit(callable).get(); fail(EXCEPTION.getClass().getSimpleName() + " should be thrown."); } catch (ExecutionException e) { assertEquals(EXCEPTION, e.getCause()); } } @Test(expected = NullPointerException.class) public void testNullHandler() throws Exception { control.replay(); MoreExecutors.exceptionHandlingExecutor(executorService, null); } }