package fitnesse.slim; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; import java.util.concurrent.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.MockitoAnnotations.initMocks; public class StatementTimeoutExecutorTest { private static final String INSTANCE_NAME = "instanceName"; private static final String CLASS_NAME = "className"; private static final String ARG = "arg"; private static final String SYMBOL_NAME = "symbol"; private static final String METHOD_NAME = "method name"; private static final int TIMEOUT = 4000; @Mock private StatementExecutorInterface inner; @Mock private ExecutorService executorService; private StatementExecutorInterface executor; @Before public void setup() { initMocks(this); executor = StatementTimeoutExecutor.decorate(inner, TIMEOUT); } @Test public void testCreateDelegatesToInner() throws SlimException { executor.create(INSTANCE_NAME, CLASS_NAME, ARG); verify(inner).create(INSTANCE_NAME, CLASS_NAME, ARG); } @Test public void testCallAndAssignDelegatesToInner() throws SlimException { when(inner.callAndAssign(SYMBOL_NAME, INSTANCE_NAME, METHOD_NAME, ARG)).thenReturn("answer"); Object answer = executor.callAndAssign(SYMBOL_NAME, INSTANCE_NAME, METHOD_NAME, ARG); assertEquals("answer", answer); } @Test public void testCallDelegatesToInner() throws SlimException { when(inner.call(INSTANCE_NAME, METHOD_NAME, ARG)).thenReturn("answer"); Object answer = executor.call(INSTANCE_NAME, METHOD_NAME, ARG); assertEquals("answer", answer); } @Test public void testCreateRethrowsSlimException() throws Exception { Exception error = givenSlimExceptionThrownOnFutureGet(); Exception actual = createExpectingException(); assertEquals(actual, error); } @Test public void testCallAndAssignRethrowsSlimException() throws Exception { Exception error = givenSlimExceptionThrownOnFutureGet(); Exception actual = callAndAssignExpectingException(); assertEquals(actual, error); } @Test public void testCallRethrowsSlimException() throws Exception { Exception error = givenSlimExceptionThrownOnFutureGet(); Exception actual = callExpectingException(); assertEquals(actual, error); } @Test public void testCreateWrapsOtherErrorsThrownInFuture() throws Exception { Exception error = givenRuntimeExceptionThrownOnFutureGet(); Exception actual = createExpectingException(); assertNotNull(actual); assertEquals(error, actual.getCause()); } @Test public void testCallAndAssignWrapsOtherErrorsThrownInFuture() throws Exception { Exception error = givenRuntimeExceptionThrownOnFutureGet(); Exception actual = callAndAssignExpectingException(); assertNotNull(actual); assertEquals(error, actual.getCause()); } @Test public void testCallWrapsOtherErrorsThrownInFuture() throws Exception { Exception error = givenRuntimeExceptionThrownOnFutureGet(); Exception actual = callExpectingException(); assertNotNull(actual); assertEquals(error, actual.getCause()); } @Test public void testCreateThrowsWhenTimeoutExceptionThrown() throws Exception { givenTimeoutExceptionThrownOnFutureGet(); Exception actual = createExpectingException(); assertNotNull(actual); assertEquals("4000", actual.getMessage()); } @Test public void testCallAndAssignThrowsWhenTimeoutExceptionThrown() throws Exception { givenTimeoutExceptionThrownOnFutureGet(); Exception actual = callAndAssignExpectingException(); assertNotNull(actual); assertEquals("4000", actual.getMessage()); } @Test public void testCallThrowsWhenTimeoutExceptionThrown() throws Exception { givenTimeoutExceptionThrownOnFutureGet(); Exception actual = callExpectingException(); assertNotNull(actual); assertEquals("4000", actual.getMessage()); } private Exception createExpectingException() { Exception actual = null; try { executor.create(INSTANCE_NAME, CLASS_NAME, ARG); } catch (SlimException e) { actual = e; } return actual; } private Exception callAndAssignExpectingException() { Exception actual = null; try { executor.callAndAssign(SYMBOL_NAME, INSTANCE_NAME, METHOD_NAME, ARG); } catch (SlimException e) { actual = e; } return actual; } private Exception callExpectingException() { Exception actual = null; try { executor.call(INSTANCE_NAME, METHOD_NAME, ARG); } catch (SlimException e) { actual = e; } return actual; } private Exception givenRuntimeExceptionThrownOnFutureGet() throws InterruptedException, ExecutionException, TimeoutException { RuntimeException error = new RuntimeException("error"); ExecutionException executionException = new ExecutionException(error); givenExceptionThrownOnFutureGet(executionException); return error; } private Exception givenTimeoutExceptionThrownOnFutureGet() throws InterruptedException, ExecutionException, TimeoutException { TimeoutException error = new TimeoutException(); givenExceptionThrownOnFutureGet(error); return error; } private Exception givenSlimExceptionThrownOnFutureGet() throws InterruptedException, ExecutionException, TimeoutException { SlimException error = new SlimException("error"); ExecutionException executionException = new ExecutionException(error); givenExceptionThrownOnFutureGet(executionException); return error; } private void givenExceptionThrownOnFutureGet(Exception executionException) throws InterruptedException, ExecutionException, TimeoutException { executor = StatementTimeoutExecutor.decorate(inner, TIMEOUT, executorService); Future future = Mockito.mock(Future.class); when(future.get(TIMEOUT, TimeUnit.SECONDS)).thenThrow(executionException); when(executorService.submit(any(Callable.class))).thenReturn(future); } }