package storm.starter.tools;

import static org.fest.assertions.api.Assertions.assertThat;

import java.util.Map;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class SlidingWindowCounterTest {

    private static final int ANY_WINDOW_LENGTH_IN_SLOTS = 2;
    private static final Object ANY_OBJECT = "ANY_OBJECT";

    @DataProvider
    public Object[][] illegalWindowLengths() {
        return new Object[][] { { -10 }, { -3 }, { -2 }, { -1 }, { 0 }, { 1 } };
    }

    @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegalWindowLengths")
    public void lessThanTwoSlotsShouldThrowIAE(int windowLengthInSlots) {
        new SlidingWindowCounter<Object>(windowLengthInSlots);
    }

    @DataProvider
    public Object[][] legalWindowLengths() {
        return new Object[][] { { 2 }, { 3 }, { 20 } };
    }

    @Test(dataProvider = "legalWindowLengths")
    public void twoOrMoreSlotsShouldBeValid(int windowLengthInSlots) {
        new SlidingWindowCounter<Object>(windowLengthInSlots);
    }

    public void newInstanceShouldHaveEmptyCounts() {
        // given
        SlidingWindowCounter<Object> counter = new SlidingWindowCounter<Object>(ANY_WINDOW_LENGTH_IN_SLOTS);

        // when
        Map<Object, Long> counts = counter.getCountsThenAdvanceWindow();

        // then
        assertThat(counts).isEmpty();
    }

    @DataProvider
    public Object[][] simulatedCounterIterations() {
        return new Object[][] {
                { 2, new int[] { 3, 2, 0, 0, 1, 0, 0, 0 }, new long[] { 3, 5, 2, 0, 1, 1, 0, 0 } },
                { 3, new int[] { 3, 2, 0, 0, 1, 0, 0, 0 }, new long[] { 3, 5, 5, 2, 1, 1, 1, 0 } },
                { 4, new int[] { 3, 2, 0, 0, 1, 0, 0, 0 }, new long[] { 3, 5, 5, 5, 3, 1, 1, 1 } },
                { 5, new int[] { 3, 2, 0, 0, 1, 0, 0, 0 }, new long[] { 3, 5, 5, 5, 6, 3, 1, 1 } },
                {
                        5,
                        new int[] { 3, 11, 5, 13, 7, 17, 0, 3, 50, 600, 7000 },
                        new long[] { 3, 14, 19, 32, 39, 53, 42, 40, 77, 670, 7653 } }, };
    }

    @Test(dataProvider = "simulatedCounterIterations")
    public void testCounterWithSimulatedRuns(int windowLengthInSlots, int[] incrementsPerIteration,
        long[] expCountsPerIteration) {
        // given
        SlidingWindowCounter<Object> counter = new SlidingWindowCounter<Object>(windowLengthInSlots);
        int numIterations = incrementsPerIteration.length;

        for (int i = 0; i < numIterations; i++) {
            int numIncrements = incrementsPerIteration[i];
            long expCounts = expCountsPerIteration[i];

            // given (for this iteration)
            for (int j = 0; j < numIncrements; j++) {
                counter.incrementCount(ANY_OBJECT);
            }

            // when (for this iteration)
            Map<Object, Long> counts = counter.getCountsThenAdvanceWindow();

            // then (for this iteration)
            if (expCounts == 0) {
                assertThat(counts).doesNotContainKey(ANY_OBJECT);
            }
            else {
                assertThat(counts.get(ANY_OBJECT)).isEqualTo(expCounts);
            }
        }
    }

}

@@ -1060,24 +1060,34 @@
 ts);%0A    %7D%0A%0A
+    @Test%0A
     public v

add missing @Test annotation to unit test