/* * Copyright 2016 Kejun Xia * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.shipdream.lib.android.mvc.controller; import com.shipdream.lib.android.mvc.BaseTest; import com.shipdream.lib.android.mvc.MvcGraphException; import com.shipdream.lib.android.mvc.Task; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import java.util.concurrent.Executors; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; public class TestRunAsyncTask extends BaseTest { private MyController controller; private MyController.View view; private static final long WAIT_DURATION = MyController.LONG_TASK_DURATION + 100; @Before public void setUp() throws Exception { super.setUp(); executorService = Executors.newSingleThreadExecutor(); controller = new MyController(); graph.inject(controller); controller.onCreated(); view = mock(MyController.View.class); eventBusV.register(view); controller.view = view; } @Test public void should_be_able_to_run_async_task_without_error_handler_with_default_executorService() throws Exception { Task.Monitor asyncTask = controller.loadHeavyResourceSuccessfullyWithoutErrorHandlerWithDefaultExecutorService(this); Thread.sleep(WAIT_DURATION); verify(view, times(1)).onResourceLoaded(); Assert.assertEquals(asyncTask.getState(), Task.Monitor.State.DONE); } @Test public void should_be_able_to_run_async_task_without_error_handler() throws Exception { Task.Monitor asyncTask = controller.loadHeavyResourceSuccessfullyWithoutErrorHandler(this); Thread.sleep(WAIT_DURATION); verify(view, times(1)).onResourceLoaded(); Assert.assertEquals(asyncTask.getState(), Task.Monitor.State.DONE); } @Test public void shouldBeAbleToRunAsyncTaskSuccessfully() throws Exception { Task.Monitor asyncTask = controller.loadHeavyResourceSuccessfullyWithErrorHandler(this); Thread.sleep(WAIT_DURATION); verify(view, times(1)).onResourceLoaded(); verify(view, times(0)).onResourceFailed(any(MvcGraphException.class)); verify(view, times(0)).onResourceCancelled(); Assert.assertEquals(asyncTask.getState(), Task.Monitor.State.DONE); } @Test public void shouldHandleAsyncTaskExceptionAndDetectFailEvent() throws Exception { Task.Monitor asyncTask = controller.loadHeavyResourceWithException(this); Thread.sleep(WAIT_DURATION); verify(view, times(0)).onResourceLoaded(); verify(view, times(1)).onResourceFailed(any(MvcGraphException.class)); verify(view, times(0)).onResourceCancelled(); Assert.assertEquals(asyncTask.getState(), Task.Monitor.State.ERRED); } @Test public void shouldBeAbleToCancelAsyncActionAndDetectInterruptedEvent() throws Exception { Task.Monitor monitor = controller.loadHeavyResourceAndCancel(this); Thread.sleep(10); monitor.cancel(true); Thread.sleep(WAIT_DURATION); verify(view, times(0)).onResourceLoaded(); verify(view, times(0)).onResourceFailed(any(MvcGraphException.class)); verify(view, times(1)).onResourceCancelled(); Assert.assertEquals(monitor.getState(), Task.Monitor.State.INTERRUPTED); } @Test public void shouldBeAbleToCancelAsyncActionAndDetectCancelEvent() throws Exception { Task.Monitor monitor = controller.loadHeavyResourceAndCancel(this); Thread.sleep(10); monitor.cancel(false); Thread.sleep(WAIT_DURATION); verify(view, times(0)).onResourceLoaded(); verify(view, times(0)).onResourceFailed(any(MvcGraphException.class)); verify(view, times(1)).onResourceCancelled(); Assert.assertEquals(monitor.getState(), Task.Monitor.State.CANCELED); } @Test public void should_catch_exception_during_running_async_task() throws Exception { final Task.Callback callback = mock(Task.Callback.class); Task.Monitor monitor1 = controller.loadHeavyResource(this, new Task() { @Override public Object execute(Monitor monitor) throws Exception { Thread.sleep(50); throw new RuntimeException(); } }, new Task.Callback() { @Override public void onStarted() { super.onStarted(); callback.onStarted(); } @Override public void onStarted(Task.Monitor monitor) { super.onStarted(monitor); callback.onStarted(monitor); } @Override public void onSuccess(Object o) { super.onSuccess(o); callback.onSuccess(o); } @Override public void onCancelled(boolean interrupted) { super.onCancelled(interrupted); callback.onCancelled(interrupted); } @Override public void onException(Exception e) throws Exception { callback.onException(e); } @Override public void onFinally() { super.onFinally(); callback.onFinally(); } }); Thread.sleep(100); verify(callback, times(1)).onStarted(monitor1); verify(callback, times(1)).onException(any(Exception.class)); verify(callback, times(0)).onSuccess(anyObject()); verify(callback, times(0)).onCancelled(anyBoolean()); verify(callback, times(1)).onFinally(); } @Test public void should_be_able_to_cancel_a_task_before_it_starts() throws Exception { Task.Callback callback = mock(Task.Callback.class); Task.Monitor monitor1 = controller.loadHeavyResource(this, new Task() { @Override public Object execute(Monitor monitor) throws Exception { Thread.sleep(WAIT_DURATION); return null; } }, callback); Task.Callback callback2 = mock(Task.Callback.class); Task.Monitor monitor2 = controller.loadHeavyResource(this, new Task() { @Override public Object execute(Monitor monitor) throws Exception { return null; } }, callback2); monitor2.cancel(true); Thread.sleep(WAIT_DURATION + 100); verify(callback, times(1)).onStarted(monitor1); verify(callback, times(0)).onException(any(Exception.class)); verify(callback, times(1)).onSuccess(anyObject()); verify(callback, times(0)).onCancelled(anyBoolean()); verify(callback, times(1)).onFinally(); verify(callback2, times(0)).onStarted(monitor2); verify(callback2, times(0)).onException(any(Exception.class)); verify(callback2, times(0)).onSuccess(anyObject()); verify(callback2, times(1)).onCancelled(anyBoolean()); verify(callback2, times(1)).onFinally(); Assert.assertEquals(monitor1.getState(), Task.Monitor.State.DONE); Assert.assertEquals(monitor2.getState(), Task.Monitor.State.CANCELED); Assert.assertFalse(monitor1.cancel(true)); Assert.assertFalse(monitor1.cancel(false)); Assert.assertFalse(monitor2.cancel(true)); Assert.assertFalse(monitor2.cancel(false)); } }