blob: 3ad042beb86cdc5cd2d2269b63762a7857e8bd5e [file] [log] [blame]
/**
* 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);
}
}