Skip to content

Commit

Permalink
HV-1373 Replacing calls to hashCode with System#identityHashCode()
Browse files Browse the repository at this point in the history
hashCode() methods of validated beans as well as validated values of those
beans shouldn't be called as they might throw exceptions that we do not expect,
especially NPEs.
  • Loading branch information
marko-bekhta authored and gsmet committed Oct 20, 2017
1 parent 0b6e5f3 commit 87e082f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 3 deletions.
Expand Up @@ -327,9 +327,9 @@ public String toString() {
private int createHashCode() {
int result = interpolatedMessage != null ? interpolatedMessage.hashCode() : 0;
result = 31 * result + ( propertyPath != null ? propertyPath.hashCode() : 0 );
result = 31 * result + ( rootBean != null ? rootBean.hashCode() : 0 );
result = 31 * result + ( leafBeanInstance != null ? leafBeanInstance.hashCode() : 0 );
result = 31 * result + ( value != null ? value.hashCode() : 0 );
result = 31 * result + System.identityHashCode( rootBean );
result = 31 * result + System.identityHashCode( leafBeanInstance );
result = 31 * result + System.identityHashCode( value );
result = 31 * result + ( constraintDescriptor != null ? constraintDescriptor.hashCode() : 0 );
result = 31 * result + ( messageTemplate != null ? messageTemplate.hashCode() : 0 );
result = 31 * result + ( rootBeanClass != null ? rootBeanClass.hashCode() : 0 );
Expand Down
Expand Up @@ -9,21 +9,27 @@
import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat;
import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf;

import java.util.ArrayList;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.hibernate.validator.testutil.TestForIssue;

import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

/**
* Test related to the identity of {@link org.hibernate.validator.internal.engine.ConstraintViolationImpl}s.
*
* @author Gunnar Morling
* @author Marko Bekhta
*/
public class ConstraintViolationImplIdentityTest {

Expand All @@ -45,9 +51,70 @@ public void testTwoViolationsForDifferentConstraintsAreNotEqual() {
);
}

@Test
@TestForIssue(jiraKey = "HV-1373")
public void testHashCodeOfBeanInstanceIsNotCalled() throws Exception {
Set<ConstraintViolation<Bar>> violations = validator.validate( new Bar( null ) );
assertThat( violations ).containsOnlyViolations(
violationOf( NotNull.class )
);
}

@Test
@TestForIssue(jiraKey = "HV-1373")
public void testHashCodeOfBeanInstanceValuesIsNotCalled() throws Exception {
Set<ConstraintViolation<FooBar>> violations = validator.validate( new FooBar( new FooList() ) );
assertThat( violations ).containsOnlyViolations(
violationOf( NotEmpty.class )
);
}

private static class Foo {
@Size(min = 2, message = "must be 2 at least")
@DecimalMin(value = "2", message = "must be 2 at least")
String name = "1";
}

private static class Bar {
@NotNull
private final String property;

private Bar(String property) {
this.property = property;
}

@Override
public boolean equals(Object o) {
return super.equals( o );
}

@Override
public int hashCode() {
throw new IllegalStateException( "Bean's hashCode() may not be called" );
}
}

private class FooBar {

@NotEmpty
private final FooList list;

private FooBar(FooList list) {
this.list = list;
}
}

private static class FooList extends ArrayList<String> {

@Override
public boolean equals(Object o) {
return super.equals( o );
}

@Override
public int hashCode() {
throw new IllegalStateException( "Bean's value hashCode() may not be called" );
}
}

}

0 comments on commit 87e082f

Please sign in to comment.