package net.nightwhistler.pageturner.scheduling;
import android.annotation.TargetApi;
import android.os.AsyncTask;
import org.junit.Ignore;
import org.robolectric.RobolectricTestRunner;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.Config;
import java.util.concurrent.Executor;
import static org.mockito.Mockito.*;
/**
* Created with IntelliJ IDEA.
* User: alex
* Date: 5/11/13
* Time: 4:12 PM
* To change this template use File | Settings | File Templates.
*/
@TargetApi(16)
@Config(emulateSdk = 16)
@RunWith(RobolectricTestRunner.class)
public class TaskQueueTest {
private TaskQueue taskQueue;
private TaskQueue.TaskQueueListener listener;
@Before
public void init() {
this.taskQueue = new TaskQueue();
this.listener = mock(TaskQueue.TaskQueueListener.class);
this.taskQueue.setTaskQueueListener(listener);
}
@Test
public void testSingleTask() {
String[] params = { "param1" };
QueueableAsyncTask<String, String, String>
mockTaskA = mock(QueueableAsyncTask.class);
taskQueue.executeTask(mockTaskA, params);
verify(mockTaskA).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
//Mock completion of task A
taskQueue.taskCompleted(mockTaskA, false);
verify( listener ).queueEmpty();
}
@Test(expected = RuntimeException.class )
public void testTasksOutOfSync() {
String[] params = { "param1" };
QueueableAsyncTask<String, String, String>
mockTaskA = mock(QueueableAsyncTask.class);
taskQueue.executeTask(mockTaskA, params);
verify(mockTaskA).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
//Mock completion of a different task
taskQueue.taskCompleted(mock(QueueableAsyncTask.class), false);
}
/**
* Very basic test-case: we queue 3 tasks and
* check that all 3 are executed in order.
*/
@Test
public void testHappyFlow() {
QueueableAsyncTask<String, String, String>
mockTaskA = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskB = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskC = mock(QueueableAsyncTask.class);
taskQueue.executeTask(mockTaskA);
taskQueue.executeTask(mockTaskB);
taskQueue.executeTask(mockTaskC);
verify(mockTaskA).executeOnExecutor(any(Executor.class));
verify(mockTaskB, never() ).executeOnExecutor(any(Executor.class));
verify(mockTaskC, never() ).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskA, false);
verifyZeroInteractions(listener);
verify( mockTaskB ).executeOnExecutor(any(Executor.class));
verify(mockTaskC, never() ).executeOnExecutor(any(Executor.class));
//Should not be executed again
verify(mockTaskA, times(1)).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskB, false);
verify(mockTaskC).executeOnExecutor(any(Executor.class));
verify(mockTaskA, times(1)).executeOnExecutor(any(Executor.class));
verify(mockTaskB, times(1)).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskC, false);
verify(listener).queueEmpty();
}
@Test
public void testQueueClear() {
QueueableAsyncTask<String, String, String>
mockTaskA = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskB = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskC = mock(QueueableAsyncTask.class);
taskQueue.executeTask(mockTaskA);
taskQueue.executeTask(mockTaskB);
taskQueue.executeTask(mockTaskC);
verify(mockTaskA).executeOnExecutor( any(Executor.class) );
verify(mockTaskB, never() ).executeOnExecutor(any(Executor.class));
verify(mockTaskC, never()).executeOnExecutor(any(Executor.class));
taskQueue.clear();
verify( mockTaskA ).requestCancellation();
taskQueue.taskCompleted(mockTaskA, true);
verify(mockTaskB, never()).executeOnExecutor(any(Executor.class));
verify(mockTaskC, never()).executeOnExecutor(any(Executor.class));
//verifyZeroInteractions(listener); ???
}
/**
* Tests queue-jumping: the currently executing task
* is cancelled and the new task is put ahead of the queue.
*
* The rest of the tasks execute as usual.
*/
@Test
public void testQueueJumping() {
QueueableAsyncTask<String, String, String>
mockTaskA = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskB = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskC = mock(QueueableAsyncTask.class);
QueueableAsyncTask<String, String, String>
mockTaskD = mock(QueueableAsyncTask.class);
taskQueue.executeTask(mockTaskA);
taskQueue.executeTask(mockTaskB);
taskQueue.executeTask(mockTaskC);
verify(mockTaskA).executeOnExecutor(any(Executor.class));
verify(mockTaskB, never() ).executeOnExecutor(any(Executor.class));
verify(mockTaskC, never() ).executeOnExecutor(any(Executor.class));
taskQueue.jumpQueueExecuteTask(mockTaskD);
verify(mockTaskA).requestCancellation();
verify(mockTaskD).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskA, true);
taskQueue.taskCompleted(mockTaskD, false);
verify( mockTaskB ).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskB, false);
verify(mockTaskC).executeOnExecutor(any(Executor.class));
taskQueue.taskCompleted(mockTaskC, false);
verify(listener).queueEmpty();
}
}