From f4eacc4acfc6742bb410e3e04d626dbc6d8aa134 Mon Sep 17 00:00:00 2001 From: JParams <26733487+jparams@users.noreply.github.com> Date: Fri, 14 Dec 2018 16:44:58 +0000 Subject: [PATCH] Bugfix/hashcode fix (#19) * Fix issue with hash code in the apache preset * Add tests --- .gitignore | 3 ++- build.gradle | 2 +- .../verifier/tostring/HashCodeProvider.java | 16 +++++++++++ .../tostring/ObjectHashCodeProvider.java | 13 +++++++++ .../SystemIdentityHashCodeProvider.java | 13 +++++++++ .../verifier/tostring/ToStringVerifier.java | 16 ++++++++++- .../preset/ApacheToStringBuilderPreset.java | 3 ++- .../tostring/ObjectHashCodeProviderTest.java | 18 +++++++++++++ .../SystemIdentityHashCodeProviderTest.java | 18 +++++++++++++ .../tostring/ToStringVerifierTest.java | 4 ++- .../verifier/tostring/pojo/Person.java | 8 ++++++ .../tostring/preset/AbstractDataTest.java | 27 +++++++++++++++++++ 12 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/jparams/verifier/tostring/HashCodeProvider.java create mode 100644 src/main/java/com/jparams/verifier/tostring/ObjectHashCodeProvider.java create mode 100644 src/main/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProvider.java create mode 100644 src/test/java/com/jparams/verifier/tostring/ObjectHashCodeProviderTest.java create mode 100644 src/test/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProviderTest.java diff --git a/.gitignore b/.gitignore index cd112d6..491c4b4 100755 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ build/ target/ *.iml *rebel.xml -src/generated/ \ No newline at end of file +src/generated/ +key.gpg \ No newline at end of file diff --git a/build.gradle b/build.gradle index 03223fe..104e628 100755 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ apply plugin: 'maven' apply from: 'publish.gradle' group = 'com.jparams' -version = '1.4.4' +version = '1.4.5' sourceCompatibility = 1.8 diff --git a/src/main/java/com/jparams/verifier/tostring/HashCodeProvider.java b/src/main/java/com/jparams/verifier/tostring/HashCodeProvider.java new file mode 100644 index 0000000..538e7ad --- /dev/null +++ b/src/main/java/com/jparams/verifier/tostring/HashCodeProvider.java @@ -0,0 +1,16 @@ +package com.jparams.verifier.tostring; + +/** + * Hash code provider + */ +@FunctionalInterface +public interface HashCodeProvider +{ + /** + * Provide object hash code + * + * @param obj object + * @return hash code + */ + int provide(Object obj); +} diff --git a/src/main/java/com/jparams/verifier/tostring/ObjectHashCodeProvider.java b/src/main/java/com/jparams/verifier/tostring/ObjectHashCodeProvider.java new file mode 100644 index 0000000..be423be --- /dev/null +++ b/src/main/java/com/jparams/verifier/tostring/ObjectHashCodeProvider.java @@ -0,0 +1,13 @@ +package com.jparams.verifier.tostring; + +/** + * Provides the hash code by calling {@link Object#hashCode()} + */ +public class ObjectHashCodeProvider implements HashCodeProvider +{ + @Override + public int provide(final Object obj) + { + return obj.hashCode(); + } +} diff --git a/src/main/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProvider.java b/src/main/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProvider.java new file mode 100644 index 0000000..a913971 --- /dev/null +++ b/src/main/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProvider.java @@ -0,0 +1,13 @@ +package com.jparams.verifier.tostring; + +/** + * Provides the System identity hash code by calling {@link System#identityHashCode(Object)} + */ +public class SystemIdentityHashCodeProvider implements HashCodeProvider +{ + @Override + public int provide(final Object obj) + { + return System.identityHashCode(obj); + } +} diff --git a/src/main/java/com/jparams/verifier/tostring/ToStringVerifier.java b/src/main/java/com/jparams/verifier/tostring/ToStringVerifier.java index ec67967..44b1a58 100644 --- a/src/main/java/com/jparams/verifier/tostring/ToStringVerifier.java +++ b/src/main/java/com/jparams/verifier/tostring/ToStringVerifier.java @@ -56,6 +56,7 @@ public final class ToStringVerifier private boolean hashCode = false; private String nullValue = "null"; private boolean failOnExcludedFields = false; + private HashCodeProvider hashCodeProvider = new SystemIdentityHashCodeProvider(); private ToStringVerifier(final Collection> classes) { @@ -326,6 +327,19 @@ public ToStringVerifier withNullValue(final String nullValue) return this; } + /** + * With hash code provider + * + * @param hashCodeProvider hash code provider + * @return verifier + */ + public ToStringVerifier withHashCodeProvider(final HashCodeProvider hashCodeProvider) + { + assertNotNull(hashCodeProvider); + this.hashCodeProvider = hashCodeProvider; + return this; + } + /** * Perform verification * @@ -376,7 +390,7 @@ private Optional verify(final Class clazz) if (hashCode) { - verifyHashCode(stringValue, subject.hashCode()).ifPresent(verificationErrors::add); + verifyHashCode(stringValue, hashCodeProvider.provide(subject)).ifPresent(verificationErrors::add); } final List fieldValues = FieldsProvider.provide(clazz, inheritedFields) diff --git a/src/main/java/com/jparams/verifier/tostring/preset/ApacheToStringBuilderPreset.java b/src/main/java/com/jparams/verifier/tostring/preset/ApacheToStringBuilderPreset.java index 36a2c3a..00de603 100644 --- a/src/main/java/com/jparams/verifier/tostring/preset/ApacheToStringBuilderPreset.java +++ b/src/main/java/com/jparams/verifier/tostring/preset/ApacheToStringBuilderPreset.java @@ -1,6 +1,7 @@ package com.jparams.verifier.tostring.preset; import com.jparams.verifier.tostring.NameStyle; +import com.jparams.verifier.tostring.SystemIdentityHashCodeProvider; import com.jparams.verifier.tostring.ToStringVerifier; /** @@ -26,7 +27,7 @@ public void apply(final ToStringVerifier verifier) break; case DEFAULT_STYLE: case MULTI_LINE_STYLE: - verifier.withClassName(NameStyle.NAME).withHashCode(true); + verifier.withClassName(NameStyle.NAME).withHashCode(true).withHashCodeProvider(new SystemIdentityHashCodeProvider()); break; case SHORT_PREFIX_STYLE: verifier.withClassName(NameStyle.SIMPLE_NAME).withHashCode(false); diff --git a/src/test/java/com/jparams/verifier/tostring/ObjectHashCodeProviderTest.java b/src/test/java/com/jparams/verifier/tostring/ObjectHashCodeProviderTest.java new file mode 100644 index 0000000..518dd04 --- /dev/null +++ b/src/test/java/com/jparams/verifier/tostring/ObjectHashCodeProviderTest.java @@ -0,0 +1,18 @@ +package com.jparams.verifier.tostring; + +import com.jparams.verifier.tostring.pojo.Person; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ObjectHashCodeProviderTest +{ + @Test + public void testProvider() + { + final Person person = new Person(1, "1", "1"); + final int hashCode = new ObjectHashCodeProvider().provide(person); + assertThat(hashCode).isEqualTo(person.hashCode()); + } +} \ No newline at end of file diff --git a/src/test/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProviderTest.java b/src/test/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProviderTest.java new file mode 100644 index 0000000..48a3f73 --- /dev/null +++ b/src/test/java/com/jparams/verifier/tostring/SystemIdentityHashCodeProviderTest.java @@ -0,0 +1,18 @@ +package com.jparams.verifier.tostring; + +import com.jparams.verifier.tostring.pojo.Person; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SystemIdentityHashCodeProviderTest +{ + @Test + public void testProvider() + { + final Person person = new Person(1, "1", "1"); + final int hashCode = new SystemIdentityHashCodeProvider().provide(person); + assertThat(hashCode).isEqualTo(System.identityHashCode(person)); + } +} \ No newline at end of file diff --git a/src/test/java/com/jparams/verifier/tostring/ToStringVerifierTest.java b/src/test/java/com/jparams/verifier/tostring/ToStringVerifierTest.java index 0204cb2..cfd2e19 100644 --- a/src/test/java/com/jparams/verifier/tostring/ToStringVerifierTest.java +++ b/src/test/java/com/jparams/verifier/tostring/ToStringVerifierTest.java @@ -37,7 +37,7 @@ public void setUp() lock.lock(); // to force only one test to run at a time Person.setStringValue(null); - subject = ToStringVerifier.forClass(Person.class); + subject = ToStringVerifier.forClass(Person.class).withHashCodeProvider(new ObjectHashCodeProvider()); } @After @@ -369,6 +369,7 @@ public void testToStringWithMultipleClasses() ToStringVerifier.forClasses(Person.class, Identified.class) .withMatchingFields((subject, field) -> false) .withHashCode(true) + .withHashCodeProvider(new ObjectHashCodeProvider()) .verify(); TestCase.fail("Exception expected"); @@ -391,6 +392,7 @@ public void testToStringWithPackageScan() ToStringVerifier.forPackage("com.jparams.verifier.tostring.pojo", false) .withMatchingFields((subject, field) -> false) .withHashCode(true) + .withHashCodeProvider(new ObjectHashCodeProvider()) .verify(); TestCase.fail("Exception expected"); diff --git a/src/test/java/com/jparams/verifier/tostring/pojo/Person.java b/src/test/java/com/jparams/verifier/tostring/pojo/Person.java index dad1ef6..5909c34 100644 --- a/src/test/java/com/jparams/verifier/tostring/pojo/Person.java +++ b/src/test/java/com/jparams/verifier/tostring/pojo/Person.java @@ -3,6 +3,7 @@ public class Person extends Identified { private static String stringValue = null; + private static Person testInstance = null; private final String firstName; private final String lastName; @@ -27,6 +28,8 @@ public String getLastName() @Override public String toString() { + testInstance = this; + if (stringValue != null) { return stringValue; @@ -54,4 +57,9 @@ public static String getStringValue() { return stringValue; } + + public static Person getTestInstance() + { + return testInstance; + } } diff --git a/src/test/java/com/jparams/verifier/tostring/preset/AbstractDataTest.java b/src/test/java/com/jparams/verifier/tostring/preset/AbstractDataTest.java index 681da15..3c5f09b 100644 --- a/src/test/java/com/jparams/verifier/tostring/preset/AbstractDataTest.java +++ b/src/test/java/com/jparams/verifier/tostring/preset/AbstractDataTest.java @@ -1,8 +1,10 @@ package com.jparams.verifier.tostring.preset; import java.math.BigDecimal; +import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Objects; abstract class AbstractDataTest { @@ -10,4 +12,29 @@ abstract class AbstractDataTest List list; Map map; String[] ary; + + @Override + public boolean equals(final Object other) + { + if (this == other) + { + return true; + } + + if (other == null || getClass() != other.getClass()) + { + return false; + } + + final AbstractDataTest that = (AbstractDataTest) other; + return Objects.equals(str, that.str) && Objects.equals(list, that.list) && Objects.equals(map, that.map) && Arrays.equals(ary, that.ary); + } + + @Override + public int hashCode() + { + int result = Objects.hash(str, list, map); + result = 31 * result + Arrays.hashCode(ary); + return result; + } }