/* * Hibernate Validator, declare and validate application constraints * * License: Apache License, Version 2.0 * See the license.txt file in the root directory or <http://www.apache.org/licenses/LICENSE-2.0>. */ package org.hibernate.validator.test.internal.engine; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertCorrectConstraintTypes; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertCorrectPropertyPaths; import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertNumberOfViolations; import static org.hibernate.validator.testutils.ValidatorUtil.getValidator; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.GroupSequence; import javax.validation.Valid; import javax.validation.ValidationException; import javax.validation.Validator; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import javax.validation.executable.ExecutableValidator; import javax.validation.metadata.BeanDescriptor; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.internal.engine.ValidatorImpl; import org.hibernate.validator.testutil.CountValidationCalls; import org.hibernate.validator.testutil.CountValidationCallsValidator; import org.hibernate.validator.testutil.TestForIssue; import org.testng.annotations.Test; /** * @author Hardy Ferentschik * @author Kevin Pollet <kevin.pollet@serli.com> (C) 2011 SERLI * @author Guillaume Smet */ public class ValidatorTest { @Test @TestForIssue(jiraKey = "HV-429") public void testValidatePropertyWithRedefinedDefaultGroupOnMainEntity() { Validator validator = getValidator(); A testInstance = new A(); testInstance.c = new C( "aaa" ); Set<ConstraintViolation<A>> constraintViolations = validator.validateProperty( testInstance, "c.id" ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "c.id" ); } @Test @TestForIssue(jiraKey = "HV-429") public void testValidatePropertyWithRedefinedDefaultGroupOnSuperClass() { Validator validator = getValidator(); A testInstance = new A(); testInstance.d = new D( "aa" ); Set<ConstraintViolation<A>> constraintViolations = validator.validateProperty( testInstance, "d.e" ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "d.e" ); } @Test @TestForIssue(jiraKey = "HV-429") public void testValidateValueWithRedefinedDefaultGroupOnMainEntity() { Validator validator = getValidator(); Set<ConstraintViolation<A>> constraintViolations = validator.validateValue( A.class, "c.id", "aaa" ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "c.id" ); } @Test @TestForIssue(jiraKey = "HV-429") public void testValidateValueWithRedefinedDefaultGroupOnSuperClass() { Validator validator = getValidator(); Set<ConstraintViolation<A>> constraintViolations = validator.validateValue( A.class, "d.e", "aa" ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "d.e" ); } @Test @TestForIssue(jiraKey = "HV-376") public void testValidatePropertyWithCurrencySymbol() { Validator validator = getValidator(); Ticket testInstance = new Ticket(); Set<ConstraintViolation<Ticket>> constraintViolations = validator.validateProperty( testInstance, "€price" ); assertNumberOfViolations( constraintViolations, 1 ); } @Test @TestForIssue(jiraKey = "HV-376") public void testValidateValueWithCurrencySymbol() { Validator validator = getValidator(); Ticket testInstance = new Ticket(); Set<ConstraintViolation<Ticket>> constraintViolations = validator.validateValue( Ticket.class, "€price", testInstance.€price ); assertNumberOfViolations( constraintViolations, 1 ); } @Test @TestForIssue(jiraKey = "HV-208") public void testPropertyPathDoesNotStartWithLeadingDot() { Validator validator = getValidator(); A testInstance = new A(); Set<ConstraintViolation<A>> constraintViolations = validator.validate( testInstance ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "b" ); } @Test public void testIsBeanConstrained() { Validator validator = getValidator(); BeanDescriptor beanDescriptor = validator.getConstraintsForClass( B.class ); assertTrue( beanDescriptor.isBeanConstrained() ); } @Test @TestForIssue(jiraKey = "HV-466") public void testValidateInterfaceConstraintsAreValidatedOneTime() { CountValidationCallsValidator.init(); Set<ConstraintViolation<H>> constraintViolations = getValidator().validate( new H() ); assertNumberOfViolations( constraintViolations, 0 ); assertEquals( CountValidationCallsValidator.getNumberOfValidationCall(), 2 ); } @Test @TestForIssue(jiraKey = "HV-466") public void testValidatePropertyInterfaceConstraintsAreValidatedOneTime() { CountValidationCallsValidator.init(); Set<ConstraintViolation<H>> constraintViolations = getValidator().validateProperty( new H(), "foo" ); assertNumberOfViolations( constraintViolations, 0 ); assertEquals( CountValidationCallsValidator.getNumberOfValidationCall(), 1 ); } @Test @TestForIssue(jiraKey = "HV-466") public void testValidateValueInterfaceConstraintsAreValidatedOneTime() { CountValidationCallsValidator.init(); Set<ConstraintViolation<H>> constraintViolations = getValidator().validateValue( H.class, "foo", null ); assertNumberOfViolations( constraintViolations, 0 ); assertEquals( CountValidationCallsValidator.getNumberOfValidationCall(), 1 ); } @Test @TestForIssue(jiraKey = "HV-468") public void testPropertyPath() { Validator validator = getValidator(); Foo foo = new Foo(); Set<ConstraintViolation<Foo>> constraintViolations = validator.validate( foo ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "bar[0].alwaysNull" ); } @Test public void testConstraintDefinedOnEntityNotFollowingBeanNotation() { CountValidationCallsValidator.init(); Set<ConstraintViolation<NotFollowingJavaBeanNotation>> constraintViolations = getValidator().validate( new NotFollowingJavaBeanNotation() ); // validating the whole entity assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, NotNull.class ); // using validateProperty (which is used by JSF) to validate explicitly constraintViolations = getValidator().validateProperty( new NotFollowingJavaBeanNotation(), "m_foo" ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, NotNull.class ); // using validateProperty (which is used by JSF) to validate explicitly (no violation, because there is no // property foo Validator knows about constraintViolations = getValidator().validateProperty( new NotFollowingJavaBeanNotation(), "foo" ); assertNumberOfViolations( constraintViolations, 0 ); } @Test(expectedExceptions = ValidationException.class) public void testUnwrapToImplementationCausesValidationException() { Validator validator = getValidator(); validator.unwrap( ValidatorImpl.class ); } @Test(expectedExceptions = ValidationException.class) public void testUnwrapToExecutableValidatorCausesValidationException() { Validator validator = getValidator(); validator.unwrap( ExecutableValidator.class ); } @Test public void testUnwrapToPublicTypesSucceeds() { Validator validator = getValidator(); Validator asValidator = validator.unwrap( Validator.class ); assertSame( asValidator, validator ); Object asObject = validator.unwrap( Object.class ); assertSame( asObject, validator ); } @Test @TestForIssue(jiraKey = "HV-596") public void testValidateValueWithNestedPath() { Validator validator = getValidator(); Set<ConstraintViolation<X>> constraintViolations = validator.validateValue( X.class, "list[0].foo", null ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "list[0].foo" ); Set<ConstraintViolation<K>> constraintViolationsK = validator.validateValue( K.class, "foo.bar", null ); assertNumberOfViolations( constraintViolationsK, 1 ); assertCorrectPropertyPaths( constraintViolationsK, "foo.bar" ); } @Test @TestForIssue(jiraKey = "HV-1002") public void testValidatePropertyWithNestedPath() { Validator validator = getValidator(); X someX = new X(); someX.addZ( new Z() ); Set<ConstraintViolation<X>> constraintViolationsX = validator.validateProperty( someX, "list[0].foo" ); assertNumberOfViolations( constraintViolationsX, 1 ); assertCorrectPropertyPaths( constraintViolationsX, "list[0].foo" ); I someI = new I(); someI.putJ( "bar", new J() ); Set<ConstraintViolation<I>> constraintViolationsI = validator.validateProperty( someI, "map[bar].foo" ); assertNumberOfViolations( constraintViolationsI, 1 ); assertCorrectPropertyPaths( constraintViolationsI, "map[bar].foo" ); K someK = new K(); someK.foo = new L<String>(); Set<ConstraintViolation<K>> constraintViolationsK = validator.validateProperty( someK, "foo.bar" ); assertNumberOfViolations( constraintViolationsK, 1 ); assertCorrectPropertyPaths( constraintViolationsK, "foo.bar" ); constraintViolationsK = validator.validateProperty( someK, "foo.genericProperty" ); assertNumberOfViolations( constraintViolationsK, 1 ); assertCorrectPropertyPaths( constraintViolationsK, "foo.genericProperty" ); } @Test(expectedExceptions = { ValidationException.class }, expectedExceptionsMessageRegExp = "^HV000195:.*") @TestForIssue(jiraKey = "HV-1002") public void testValidatePropertyWithNestedPathAndNullPropertyInTheWay() { Validator validator = getValidator(); X someX = new X(); validator.validateProperty( someX, "list[0].foo" ); } @Test(expectedExceptions = { IllegalArgumentException.class }, expectedExceptionsMessageRegExp = "^HV000039:.*") @TestForIssue(jiraKey = "HV-1002") public void testValidatePropertyWithNestedPathAndMissingValid() { Validator validator = getValidator(); M someM = new M(); validator.validateProperty( someM, "foo.baz" ); } class A { @NotNull String b; @Valid C c; @Valid D d; } class B { private boolean b; @AssertTrue public boolean hasB() { return b; } } @GroupSequence({ TestGroup.class, C.class }) class C { @Pattern(regexp = "[0-9]+", groups = TestGroup.class) @Length(min = 2) String id; C(String id) { this.id = id; } } @GroupSequence({ TestGroup.class, E.class }) class E { String e; E(String e) { this.e = e; } @Pattern(regexp = "[0-9]+", groups = TestGroup.class) public String getE() { return e; } } class D extends E { D(String e) { super( e ); } @Override @Length(min = 2) public String getE() { return super.getE(); } } class Ticket { @NotNull Float €price; } interface TestGroup { } interface F { @CountValidationCalls String getFoo(); @CountValidationCalls String getBar(); } class G implements F { @Override public String getFoo() { return null; } @Override public String getBar() { return null; } } class H extends G implements F { } class Foo { @Valid private final Collection<Bar> bar; public Foo() { bar = new ArrayList<Bar>(); bar.add( new Bar() ); } } class Bar { @NotNull String alwaysNull; } class NotFollowingJavaBeanNotation { @NotNull String m_foo; public String getFoo() { return m_foo; } } class I { @Valid Map<String, J> map = new HashMap<String, J>(); public void putJ(String key, J j) { map.put( key, j ); } } class J { @NotNull String foo; } class K { @Valid L<String> foo; } class L<T> { @NotNull String bar; @NotNull T genericProperty; } class M { N foo; @NotNull String bar; } class N { @NotNull String baz; } class X { @Valid List<Z> list = new ArrayList<Z>(); public void addZ(Z z) { list.add( z ); } } class Z { @NotNull String foo; } }