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.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.junit.Assert.*;



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

    public final int poolSize = 2;
    @Mock
    public ICircuitBreaker circuitBreaker;
    @Mock
    public IActionMetrics actionMetrics;
    @Mock
    public ConcurrentLinkedQueue<ScheduleMessage<Object>> toScheduleQueue;
    @Mock
    public ConcurrentLinkedQueue<ResultMessage<Object>> toReturnQueue;
    @Mock
    public ExecutorService executorService;
    @Mock
    public Map<ResultMessage<Object>, ResilientTask<Object>> taskMap;
    @Mock
    public SortedMap<Long, List<ResultMessage<Object>>> scheduled;
    @Captor
    public ArgumentCaptor<ResilientTask<Object>> taskCaptor;
    @Mock
    ResilientAction<Object> action;
    @Mock
    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 testLoop() {
        ScheduleMessage<Object> scheduleMessage = new ScheduleMessage<>(action, promise, 100L);
        when(toScheduleQueue.poll()).thenReturn(scheduleMessage, null);
        ScheduleLoop.runLoop(context);

        verify(executorService).submit(taskCaptor.capture());

        assertEquals(promise, taskCaptor.getValue().resilientPromise);

    }
}

@@ -505,16 +505,102 @@
 rvice;%0A%0A
+import static org.junit.Assert.assertEquals;%0Aimport static org.mockito.Mockito.times;%0A
 import s
@@ -677,43 +677,8 @@
 en;%0A
-import static org.junit.Assert.*;%0A%0A
 %0A%0A/*
@@ -758,21 +758,22 @@
 %7B%0A%0A    p
-ublic
+rivate
  final i
@@ -804,21 +804,22 @@
 ck%0A    p
-ublic
+rivate
  ICircui
@@ -858,21 +858,22 @@
 ck%0A    p
-ublic
+rivate
  IAction
@@ -902,37 +902,38 @@
 %0A    @Mock%0A    p
-ublic
+rivate
  ConcurrentLinke
@@ -996,21 +996,22 @@
 ck%0A    p
-ublic
+rivate
  Concurr
@@ -1078,21 +1078,22 @@
 ck%0A    p
-ublic
+rivate
  Executo
@@ -1133,21 +1133,22 @@
 ck%0A    p
-ublic
+rivate
  Map%3CRes
@@ -1214,21 +1214,22 @@
 ck%0A    p
-ublic
+rivate
  SortedM
@@ -1294,21 +1294,22 @@
 or%0A    p
-ublic
+rivate
  Argumen
@@ -1357,32 +1357,40 @@
 ;%0A    @Mock%0A    
+private 
 ResilientAction%3C
@@ -1419,16 +1419,136 @@
 ock%0A    
+private ResilientAction%3CObject%3E action2;%0A    @Mock%0A    private ResilientPromise%3CObject%3E promise2;%0A    @Mock%0A    private 
 Resilien
@@ -1573,16 +1573,17 @@
 romise;%0A
+%0A
     priv
@@ -1900,14 +1900,43 @@
 test
-Loop()
+ActionsScheduled() throws Exception
  %7B%0A 
@@ -2030,16 +2030,115 @@
  100L);%0A
+        ScheduleMessage%3CObject%3E scheduleMessage2 = new ScheduleMessage%3C%3E(action2, promise2, 101L);%0A
         
@@ -2198,12 +2198,24 @@
 ge, 
-null
+scheduleMessage2
 );%0A 
@@ -2283,16 +2283,26 @@
 rService
+, times(2)
 ).submit
@@ -2338,68 +2338,389 @@
     
-assertEquals(promise, taskCaptor.getValue().resilientPromise
+List%3CResilientTask%3CObject%3E%3E tasks = taskCaptor.getAllValues();%0A%0A        ResilientTask%3CObject%3E task1 = tasks.get(0);%0A        assertEquals(promise, task1.resilientPromise);%0A        task1.run();%0A        verify(action).run();%0A%0A%0A        ResilientTask%3CObject%3E task2 = tasks.get(1);%0A        assertEquals(promise2, task2.resilientPromise);%0A        task2.run();%0A        verify(action2).run(
 );%0A%0A

Modify test to check multiple aspects of scheduling