package com.rackspacecloud.blueflood.service;

import com.rackspacecloud.blueflood.rollup.Granularity;
import com.rackspacecloud.blueflood.rollup.SlotKey;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class ScheduleContextAreKeysRunningTest {

    @Test
    public void noneScheduledOrRunningReturnsFalse() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);

        int slot = Granularity.MIN_5.slot(currentTime);
        SlotKey slotkey = SlotKey.of(Granularity.MIN_5, slot, shard);

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertFalse(areKeysRunning);
    }

    @Test
    public void slotScheduledReturnsTrue() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);
        ctx.update(currentTime - 2, shard);
        ctx.scheduleEligibleSlots(1, 7200000);

        int slot = Granularity.MIN_5.slot(currentTime);
        SlotKey slotkey = SlotKey.of(Granularity.MIN_5, slot, shard);

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertTrue(areKeysRunning);
    }

    @Test
    public void childSlotScheduledReturnsTrue() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);
        ctx.update(currentTime - 2, shard);
        ctx.scheduleEligibleSlots(1, 7200000);

        int slot = Granularity.MIN_20.slot(currentTime);
        SlotKey slotkey = SlotKey.of(Granularity.MIN_20, slot, shard);

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertTrue(areKeysRunning);
    }

    @Test
    public void unrelatedSlotScheduledReturnsFalse() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);
        ctx.update(currentTime - 2, shard);
        ctx.scheduleEligibleSlots(1, 7200000);

        int slot = Granularity.MIN_5.slot(currentTime - 5*60*1000); // check the previous slot from 5 minutes ago
        SlotKey slotkey = SlotKey.of(Granularity.MIN_5, slot, shard);

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertFalse(areKeysRunning);
    }

    @Test
    public void slotRunningReturnsTrue() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);
        ctx.update(currentTime - 2, shard);
        ctx.scheduleEligibleSlots(1, 7200000);

        int slot = Granularity.MIN_5.slot(currentTime);
        SlotKey slotkey = SlotKey.of(Granularity.MIN_5, slot, shard);

        SlotKey runningSlot = ctx.getNextScheduled();

        // precondition
        assertEquals(slotkey, runningSlot);

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertTrue(areKeysRunning);
    }

    @Test
    public void childSlotRunningReturnsTrue() {

        // given
        long currentTime = 1234000L;

        final int shard = 0;
        List<Integer> managedShards = new ArrayList<Integer>() {{ add(shard); }};

        ScheduleContext ctx = new ScheduleContext(currentTime, managedShards);
        ctx.update(currentTime - 2, shard);
        ctx.scheduleEligibleSlots(1, 7200000);

        int slot = Granularity.MIN_20.slot(currentTime);
        SlotKey slotkey = SlotKey.of(Granularity.MIN_20, slot, shard);

        SlotKey runningSlot = ctx.getNextScheduled();

        // when
        boolean areKeysRunning = ctx.areChildKeysOrSelfKeyScheduledOrRunning(slotkey);

        // then
        assertTrue(areKeysRunning);
    }
}

@@ -839,32 +839,155 @@
  slot, shard);%0A%0A
+        // precondition%0A        assertEquals(0, ctx.getScheduledCount());%0A        assertEquals(0, ctx.getRunningCount());%0A%0A
         // when%0A
@@ -978,32 +978,32 @@
         // when%0A
-
         boolean 
@@ -1647,32 +1647,155 @@
  slot, shard);%0A%0A
+        // precondition%0A        assertEquals(1, ctx.getScheduledCount());%0A        assertEquals(0, ctx.getRunningCount());%0A%0A
         // when%0A
@@ -2461,32 +2461,155 @@
  slot, shard);%0A%0A
+        // precondition%0A        assertEquals(1, ctx.getScheduledCount());%0A        assertEquals(0, ctx.getRunningCount());%0A%0A
         // when%0A
@@ -3336,32 +3336,155 @@
  slot, shard);%0A%0A
+        // precondition%0A        assertEquals(1, ctx.getScheduledCount());%0A        assertEquals(0, ctx.getRunningCount());%0A%0A
         // when%0A
@@ -4221,32 +4221,130 @@
 // precondition%0A
+        assertEquals(0, ctx.getScheduledCount());%0A        assertEquals(1, ctx.getRunningCount());%0A
         assertEq
@@ -5053,32 +5053,32 @@
  slot, shard);%0A%0A
-
         SlotKey 
@@ -5108,32 +5108,155 @@
 xtScheduled();%0A%0A
+        // precondition%0A        assertEquals(0, ctx.getScheduledCount());%0A        assertEquals(1, ctx.getRunningCount());%0A%0A
         // when%0A

Add some preconditions.