package fault;

import fault.circuit.ICircuitBreaker;
import fault.messages.ResultMessage;
import fault.messages.ScheduleMessage;
import fault.metrics.IActionMetrics;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;


/**
 * Created by timbrooks on 12/12/14.
 */
public class ScheduleLoopTest {

    private final int poolSize = 2;
    @Mock
    private ICircuitBreaker circuitBreaker;
    @Mock
    private IActionMetrics actionMetrics;
    @Mock
    private ConcurrentLinkedQueue<ScheduleMessage<Object>> toScheduleQueue;
    @Mock
    private ConcurrentLinkedQueue<ResultMessage<Object>> toReturnQueue;
    @Mock
    private ExecutorService executorService;
    @Mock
    private Map<ResultMessage<Object>, ResilientTask<Object>> taskMap;
    @Mock
    private SortedMap<Long, List<ResultMessage<Object>>> scheduled;
    @Captor
    private ArgumentCaptor<ResilientTask<Object>> taskCaptor;
    @Mock
    private ResilientAction<Object> action;
    @Mock
    private ResilientAction<Object> action2;
    @Mock
    private ResilientPromise<Object> promise2;
    @Mock
    private ResilientPromise<Object> promise;

    private ScheduleContext context;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        context = new ScheduleContext(poolSize, circuitBreaker, actionMetrics, toScheduleQueue, toReturnQueue,
                executorService, scheduled, taskMap);
    }

    @Test
    public void testActionsScheduled() throws Exception {
        ScheduleMessage<Object> scheduleMessage = new ScheduleMessage<>(action, promise, 100L);
        ScheduleMessage<Object> scheduleMessage2 = new ScheduleMessage<>(action2, promise2, 101L);
        when(toScheduleQueue.poll()).thenReturn(scheduleMessage, scheduleMessage2);
        ScheduleLoop.runLoop(context);

        verify(executorService, times(2)).submit(taskCaptor.capture());

        List<ResilientTask<Object>> tasks = taskCaptor.getAllValues();

        ResilientTask<Object> task1 = tasks.get(0);
        assertEquals(promise, task1.resilientPromise);
        task1.run();
        verify(action).run();


        ResilientTask<Object> task2 = tasks.get(1);
        assertEquals(promise2, task2.resilientPromise);
        task2.run();
        verify(action2).run();

    }
}

@@ -550,16 +550,103 @@
 Equals;%0A
+import static org.junit.Assert.assertFalse;%0Aimport static org.junit.Assert.assertTrue;%0A
 import s
@@ -678,16 +678,16 @@
 .times;%0A
-
 import s
@@ -844,44 +844,8 @@
  %7B%0A%0A
-    private final int poolSize = 2;%0A
     
@@ -1757,164 +1757,937 @@
     
-c
+setC
 ontext
- = new ScheduleContext(poolSize, circuitBreaker, actionMetrics, toScheduleQueue, toReturnQueue,%0A        
+(2);%0A    %7D%0A%0A    @Test%0A    public void testRunLoopReturnsFalseIfNothingDone() throws Exception %7B%0A        setContext(1);%0A        when(toScheduleQueue.poll()).thenReturn(null);%0A        when(toReturnQueue.poll()).thenReturn(null);%0A%0A        assertFalse(ScheduleLoop.runLoop(context));%0A    %7D%0A%0A    @Test%0A    public void testRunLoopReturnsTrueIfActionScheduled() throws Exception %7B%0A        setContext(1);%0A        when(toScheduleQueue.poll()).thenReturn(new ScheduleMessage%3C%3E(action, promise, 100L));%0A        when(toReturnQueue.poll()).thenReturn(null);%0A%0A        assertTrue(ScheduleLoop.runLoop(context));%0A
     
+%7D%0A%0A
     
-executorService, scheduled, taskMap);
+@Test%0A    public void testRunLoopReturnsTrueIfResultHandled() throws Exception %7B%0A        setContext(1);%0A        when(toScheduleQueue.poll()).thenReturn(null);%0A        when(toReturnQueue.poll()).thenReturn(new ResultMessage%3CObject%3E(ResultMessage.Type.ASYNC));%0A%0A        assertTrue(ScheduleLoop.runLoop(context));%0A
 %0A   
@@ -3548,11 +3548,233 @@
 ;%0A%0A    %7D
+%0A%0A    private void setContext(int threadCount) %7B%0A        context = new ScheduleContext(threadCount, circuitBreaker, actionMetrics, toScheduleQueue, toReturnQueue,%0A                executorService, scheduled, taskMap);%0A    %7D
 %0A%7D%0A

Add basic tests for schedule loop