package storm.starter.tools; import backtype.storm.tuple.Tuple; import com.google.common.collect.Lists; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.util.ArrayList; import java.util.List; import static org.fest.assertions.api.Assertions.assertThat; import static org.mockito.Mockito.*; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class RankableObjectWithFieldsTest { private static final Object ANY_OBJECT = new Object(); private static final long ANY_COUNT = 271; private static final String ANY_FIELD = "someAdditionalField"; private static final int GREATER_THAN = 1; private static final int EQUAL_TO = 0; private static final int SMALLER_THAN = -1; @Test(expectedExceptions = IllegalArgumentException.class) public void constructorWithNullObjectAndNoFieldsShouldThrowIAE() { new RankableObjectWithFields(null, ANY_COUNT); } @Test(expectedExceptions = IllegalArgumentException.class) public void constructorWithNullObjectAndFieldsShouldThrowIAE() { Object someAdditionalField = new Object(); new RankableObjectWithFields(null, ANY_COUNT, someAdditionalField); } @Test(expectedExceptions = IllegalArgumentException.class) public void constructorWithNegativeCountAndNoFieldsShouldThrowIAE() { new RankableObjectWithFields(ANY_OBJECT, -1); } @Test(expectedExceptions = IllegalArgumentException.class) public void constructorWithNegativeCountAndFieldsShouldThrowIAE() { Object someAdditionalField = new Object(); new RankableObjectWithFields(ANY_OBJECT, -1, someAdditionalField); } @Test public void shouldBeEqualToItself() { RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT); assertThat(r).isEqualTo(r); } @DataProvider public Object[][] otherClassesData() { return new Object[][]{ { new String("foo") }, { new Object() }, { Integer.valueOf(4) }, { Lists.newArrayList(7, 8, 9) } }; } @Test(dataProvider = "otherClassesData") public void shouldNotBeEqualToInstancesOfOtherClasses(Object notARankable) { RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT); assertFalse(r.equals(notARankable), r + " is equal to " + notARankable + " but it should not be"); } @DataProvider public Object[][] falseDuplicatesData() { return new Object[][]{ { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1) }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("Foo", 1) }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("FOO", 1) }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("bar", 1) }, { new RankableObjectWithFields("", 0), new RankableObjectWithFields("", 1) }, { new RankableObjectWithFields("", 1), new RankableObjectWithFields("bar", 1) } }; } @Test(dataProvider = "falseDuplicatesData") public void shouldNotBeEqualToFalseDuplicates(RankableObjectWithFields r, RankableObjectWithFields falseDuplicate) { assertFalse(r.equals(falseDuplicate), r + " is equal to " + falseDuplicate + " but it should not be"); } @Test(dataProvider = "falseDuplicatesData") public void shouldHaveDifferentHashCodeThanFalseDuplicates(RankableObjectWithFields r, RankableObjectWithFields falseDuplicate) { assertThat(r.hashCode()).isNotEqualTo(falseDuplicate.hashCode()); } @DataProvider public Object[][] trueDuplicatesData() { return new Object[][]{ { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0) }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0, "someOtherField") }, { new RankableObjectWithFields("foo", 0, "someField"), new RankableObjectWithFields("foo", 0, "someOtherField") } }; } @Test(dataProvider = "trueDuplicatesData") public void shouldBeEqualToTrueDuplicates(RankableObjectWithFields r, RankableObjectWithFields trueDuplicate) { assertTrue(r.equals(trueDuplicate), r + " is not equal to " + trueDuplicate + " but it should be"); } @Test(dataProvider = "trueDuplicatesData") public void shouldHaveSameHashCodeAsTrueDuplicates(RankableObjectWithFields r, RankableObjectWithFields trueDuplicate) { assertThat(r.hashCode()).isEqualTo(trueDuplicate.hashCode()); } @DataProvider public Object[][] compareToData() { return new Object[][]{ { new RankableObjectWithFields("foo", 1000), new RankableObjectWithFields("foo", 0), GREATER_THAN }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("foo", 0), GREATER_THAN }, { new RankableObjectWithFields("foo", 1000), new RankableObjectWithFields("bar", 0), GREATER_THAN }, { new RankableObjectWithFields("foo", 1), new RankableObjectWithFields("bar", 0), GREATER_THAN }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 0), EQUAL_TO }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 0), EQUAL_TO }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1000), SMALLER_THAN }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("foo", 1), SMALLER_THAN }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 1), SMALLER_THAN }, { new RankableObjectWithFields("foo", 0), new RankableObjectWithFields("bar", 1000), SMALLER_THAN }, }; } @Test(dataProvider = "compareToData") public void verifyCompareTo(RankableObjectWithFields first, RankableObjectWithFields second, int expCompareToValue) { assertThat(first.compareTo(second)).isEqualTo(expCompareToValue); } @DataProvider public Object[][] toStringData() { return new Object[][]{ { new String("foo"), 0L }, { new String("BAR"), 8L } }; } @Test(dataProvider = "toStringData") public void toStringShouldContainStringRepresentationsOfObjectAndCount(Object obj, long count) { // given RankableObjectWithFields r = new RankableObjectWithFields(obj, count); // when String strRepresentation = r.toString(); // then assertThat(strRepresentation).contains(obj.toString()).contains("" + count); } @Test public void shouldReturnTheObject() { // given RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD); // when Object obj = r.getObject(); // then assertThat(obj).isEqualTo(ANY_OBJECT); } @Test public void shouldReturnTheCount() { // given RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD); // when long count = r.getCount(); // then assertThat(count).isEqualTo(ANY_COUNT); } @DataProvider public Object[][] fieldsData() { return new Object[][]{ { ANY_OBJECT, ANY_COUNT, new Object[]{ ANY_FIELD } }, { "quux", 42L, new Object[]{ "one", "two", "three" } } }; } @Test(dataProvider = "fieldsData") public void shouldReturnTheFields(Object obj, long count, Object[] fields) { // given RankableObjectWithFields r = new RankableObjectWithFields(obj, count, fields); // when List<Object> actualFields = r.getFields(); // then assertThat(actualFields).isEqualTo(Lists.newArrayList(fields)); } @Test(expectedExceptions = UnsupportedOperationException.class) public void fieldsShouldBeImmutable() { // given RankableObjectWithFields r = new RankableObjectWithFields(ANY_OBJECT, ANY_COUNT, ANY_FIELD); // when List<Object> fields = r.getFields(); // try to modify the list, which should fail fields.remove(0); // then (exception) } @Test public void shouldCreateRankableObjectFromTuple() { // given Tuple tuple = mock(Tuple.class); List<Object> tupleValues = Lists.newArrayList(ANY_OBJECT, ANY_COUNT, ANY_FIELD); when(tuple.getValues()).thenReturn(tupleValues); // when RankableObjectWithFields r = RankableObjectWithFields.from(tuple); // then assertThat(r.getObject()).isEqualTo(ANY_OBJECT); assertThat(r.getCount()).isEqualTo(ANY_COUNT); List<Object> fields = new ArrayList<Object>(); fields.add(ANY_FIELD); assertThat(r.getFields()).isEqualTo(fields); } @DataProvider public Object[][] copyData() { return new Object[][]{ { new RankableObjectWithFields("foo", 0) }, { new RankableObjectWithFields("foo", 3, "someOtherField") }, { new RankableObjectWithFields("foo", 0, "someField") } }; } // TODO: What would be a good test to ensure that RankableObjectWithFields is at least somewhat defensively copied? // The contract of Rankable#copy() returns a Rankable value, not a RankableObjectWithFields. @Test(dataProvider = "copyData") public void copyShouldReturnCopy(RankableObjectWithFields original) { // given // when Rankable copy = original.copy(); // then assertThat(copy.getObject()).isEqualTo(original.getObject()); assertThat(copy.getCount()).isEqualTo(original.getCount()); } }