package storm.starter.tools; import static org.fest.assertions.api.Assertions.assertThat; import java.util.List; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import com.google.common.collect.Lists; public class RankingsTest { private static final int ANY_TOPN = 42; private static final Rankable ANY_RANKABLE = new RankableObjectWithFields("someObject", ANY_TOPN); private static final Rankable A = new RankableObjectWithFields("A", 1); private static final Rankable B = new RankableObjectWithFields("B", 2); private static final Rankable C = new RankableObjectWithFields("C", 3); private static final Rankable D = new RankableObjectWithFields("D", 4); private static final Rankable E = new RankableObjectWithFields("E", 5); private static final Rankable F = new RankableObjectWithFields("F", 6); private static final Rankable G = new RankableObjectWithFields("G", 7); private static final Rankable H = new RankableObjectWithFields("H", 8); @DataProvider public Object[][] illegalTopNData() { return new Object[][] { { 0 }, { -1 }, { -2 }, { -10 } }; } @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegalTopNData") public void constructorWithNegativeOrZeroTopNShouldThrowIAE(int topN) { new Rankings(topN); } @DataProvider public Object[][] legalTopNData() { return new Object[][] { { 1 }, { 2 }, { 1000 }, { 1000000 } }; } @Test(dataProvider = "legalTopNData") public void constructorWithPositiveTopNShouldBeOk(int topN) { // given/when Rankings rankings = new Rankings(topN); // then assertThat(rankings.maxSize()).isEqualTo(topN); } @Test public void shouldHaveDefaultConstructor() { new Rankings(); } @Test public void defaultConstructorShouldSetPositiveTopN() { // given/when Rankings rankings = new Rankings(); // then assertThat(rankings.maxSize()).isGreaterThan(0); } @DataProvider public Object[][] rankingsGrowData() { return new Object[][] { { 2, Lists.newArrayList(new RankableObjectWithFields("A", 1), new RankableObjectWithFields("B", 2), new RankableObjectWithFields("C", 3)) }, { 2, Lists.newArrayList(new RankableObjectWithFields("A", 1), new RankableObjectWithFields("B", 2), new RankableObjectWithFields("C", 3), new RankableObjectWithFields("D", 4)) } }; } @Test(dataProvider = "rankingsGrowData") public void sizeOfRankingsShouldNotGrowBeyondTopN(int topN, List<Rankable> rankables) { // sanity check of the provided test data assertThat(rankables.size()).overridingErrorMessage( "The supplied test data is not correct: the number of rankables <%d> should be greater than <%d>", rankables.size(), topN).isGreaterThan(topN); // given Rankings rankings = new Rankings(topN); // when for (Rankable r : rankables) { rankings.updateWith(r); } // then assertThat(rankings.size()).isLessThanOrEqualTo(rankings.maxSize()); } @DataProvider public Object[][] simulatedRankingsData() { return new Object[][] { { Lists.newArrayList(A), Lists.newArrayList(A) }, { Lists.newArrayList(B, D, A, C), Lists.newArrayList(D, C, B, A) }, { Lists.newArrayList(B, F, A, C, D, E), Lists.newArrayList(F, E, D, C, B, A) }, { Lists.newArrayList(G, B, F, A, C, D, E, H), Lists.newArrayList(H, G, F, E, D, C, B, A) } }; } @Test(dataProvider = "simulatedRankingsData") public void shouldCorrectlyRankWhenUpdatedWithRankables(List<Rankable> unsorted, List<Rankable> expSorted) { // given Rankings rankings = new Rankings(unsorted.size()); // when for (Rankable r : unsorted) { rankings.updateWith(r); } // then assertThat(rankings.getRankings()).isEqualTo(expSorted); } @Test(dataProvider = "simulatedRankingsData") public void shouldCorrectlyRankWhenEmptyAndUpdatedWithOtherRankings(List<Rankable> unsorted, List<Rankable> expSorted) { // given Rankings rankings = new Rankings(unsorted.size()); Rankings otherRankings = new Rankings(rankings.maxSize()); for (Rankable r : unsorted) { otherRankings.updateWith(r); } // when rankings.updateWith(otherRankings); // then assertThat(rankings.getRankings()).isEqualTo(expSorted); } @Test(dataProvider = "simulatedRankingsData") public void shouldCorrectlyRankWhenUpdatedWithEmptyOtherRankings(List<Rankable> unsorted, List<Rankable> expSorted) { // given Rankings rankings = new Rankings(unsorted.size()); for (Rankable r : unsorted) { rankings.updateWith(r); } Rankings emptyRankings = new Rankings(ANY_TOPN); // when rankings.updateWith(emptyRankings); // then assertThat(rankings.getRankings()).isEqualTo(expSorted); } @DataProvider public Object[][] simulatedRankingsAndOtherRankingsData() { return new Object[][] { { Lists.newArrayList(A), Lists.newArrayList(A), Lists.newArrayList(A) }, { Lists.newArrayList(A, C), Lists.newArrayList(B, D), Lists.newArrayList(D, C, B, A) }, { Lists.newArrayList(B, F, A), Lists.newArrayList(C, D, E), Lists.newArrayList(F, E, D, C, B, A) }, { Lists.newArrayList(G, B, F, A, C), Lists.newArrayList(D, E, H), Lists.newArrayList(H, G, F, E, D, C, B, A) } }; } @Test(dataProvider = "simulatedRankingsAndOtherRankingsData") public void shouldCorrectlyRankWhenNotEmptyAndUpdatedWithOtherRankings(List<Rankable> unsorted, List<Rankable> unsortedForOtherRankings, List<Rankable> expSorted) { // given Rankings rankings = new Rankings(expSorted.size()); for (Rankable r : unsorted) { rankings.updateWith(r); } Rankings otherRankings = new Rankings(unsortedForOtherRankings.size()); for (Rankable r : unsortedForOtherRankings) { otherRankings.updateWith(r); } // when rankings.updateWith(otherRankings); // then assertThat(rankings.getRankings()).isEqualTo(expSorted); } @DataProvider public Object[][] duplicatesData() { Rankable A1 = new RankableObjectWithFields("A", 1); Rankable A2 = new RankableObjectWithFields("A", 2); Rankable A3 = new RankableObjectWithFields("A", 3); return new Object[][] { { Lists.newArrayList(ANY_RANKABLE, ANY_RANKABLE, ANY_RANKABLE) }, { Lists.newArrayList(A1, A2, A3) }, }; } @Test(dataProvider = "duplicatesData") public void shouldNotRankDuplicateObjectsMoreThanOnce(List<Rankable> duplicates) { // given Rankings rankings = new Rankings(duplicates.size()); // when for (Rankable r : duplicates) { rankings.updateWith(r); } // then assertThat(rankings.size()).isEqualTo(1); } }