| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| 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); |
| } |
| } |