package storm.starter.tools; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.Map; import static org.fest.assertions.api.Assertions.assertThat; public class SlotBasedCounterTest { private static final int ANY_NUM_SLOTS = 1; private static final int ANY_SLOT = 0; private static final Object ANY_OBJECT = "ANY_OBJECT"; @DataProvider public Object[][] illegalNumSlotsData() { return new Object[][]{ { -10 }, { -3 }, { -2 }, { -1 }, { 0 } }; } @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegalNumSlotsData") public void negativeOrZeroNumSlotsShouldThrowIAE(int numSlots) { new SlotBasedCounter<Object>(numSlots); } @DataProvider public Object[][] legalNumSlotsData() { return new Object[][]{ { 1 }, { 2 }, { 3 }, { 20 } }; } @Test(dataProvider = "legalNumSlotsData") public void positiveNumSlotsShouldBeOk(int numSlots) { new SlotBasedCounter<Object>(numSlots); } @Test public void newInstanceShouldHaveEmptyCounts() { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(ANY_NUM_SLOTS); // when Map<Object, Long> counts = counter.getCounts(); // then assertThat(counts).isEmpty(); } @Test public void shouldReturnNonEmptyCountsWhenAtLeastOneObjectWasCounted() { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(ANY_NUM_SLOTS); counter.incrementCount(ANY_OBJECT, ANY_SLOT); // when Map<Object, Long> counts = counter.getCounts(); // then assertThat(counts).isNotEmpty(); // additional tests that go beyond what this test is primarily about assertThat(counts.size()).isEqualTo(1); assertThat(counts.get(ANY_OBJECT)).isEqualTo(1); } @DataProvider public Object[][] incrementCountData() { return new Object[][]{ { new String[]{ "foo", "bar" }, new int[]{ 3, 2 } } }; } @Test(dataProvider = "incrementCountData") public void shouldIncrementCount(Object[] objects, int[] expCounts) { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(ANY_NUM_SLOTS); // when for (int i = 0; i < objects.length; i++) { Object obj = objects[i]; int numIncrements = expCounts[i]; for (int j = 0; j < numIncrements; j++) { counter.incrementCount(obj, ANY_SLOT); } } // then for (int i = 0; i < objects.length; i++) { assertThat(counter.getCount(objects[i], ANY_SLOT)).isEqualTo(expCounts[i]); } assertThat(counter.getCount("nonexistentObject", ANY_SLOT)).isEqualTo(0); } @Test public void shouldReturnZeroForNonexistentObject() { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(ANY_NUM_SLOTS); // when counter.incrementCount("somethingElse", ANY_SLOT); // then assertThat(counter.getCount("nonexistentObject", ANY_SLOT)).isEqualTo(0); } @Test public void shouldIncrementCountOnlyOneSlotAtATime() { // given int numSlots = 3; Object obj = Long.valueOf(10); SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(numSlots); // when (empty) // then assertThat(counter.getCount(obj, 0)).isEqualTo(0); assertThat(counter.getCount(obj, 1)).isEqualTo(0); assertThat(counter.getCount(obj, 2)).isEqualTo(0); // when counter.incrementCount(obj, 1); // then assertThat(counter.getCount(obj, 0)).isEqualTo(0); assertThat(counter.getCount(obj, 1)).isEqualTo(1); assertThat(counter.getCount(obj, 2)).isEqualTo(0); } @Test public void wipeSlotShouldSetAllCountsInSlotToZero() { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(ANY_NUM_SLOTS); Object countWasOne = "countWasOne"; Object countWasThree = "countWasThree"; counter.incrementCount(countWasOne, ANY_SLOT); counter.incrementCount(countWasThree, ANY_SLOT); counter.incrementCount(countWasThree, ANY_SLOT); counter.incrementCount(countWasThree, ANY_SLOT); // when counter.wipeSlot(ANY_SLOT); // then assertThat(counter.getCount(countWasOne, ANY_SLOT)).isEqualTo(0); assertThat(counter.getCount(countWasThree, ANY_SLOT)).isEqualTo(0); } @Test public void wipeZerosShouldRemoveAnyObjectsWithZeroTotalCount() { // given SlotBasedCounter<Object> counter = new SlotBasedCounter<Object>(2); int wipeSlot = 0; int otherSlot = 1; Object willBeRemoved = "willBeRemoved"; Object willContinueToBeTracked = "willContinueToBeTracked"; counter.incrementCount(willBeRemoved, wipeSlot); counter.incrementCount(willContinueToBeTracked, wipeSlot); counter.incrementCount(willContinueToBeTracked, otherSlot); // when counter.wipeSlot(wipeSlot); counter.wipeZeros(); // then assertThat(counter.getCounts()).doesNotContainKey(willBeRemoved); assertThat(counter.getCounts()).containsKey(willContinueToBeTracked); } }