package org.jboss.resteasy.test.validation; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.container.test.api.OperateOnDeployment; import org.jboss.arquillian.junit.Arquillian; import org.jboss.logging.Logger; import org.jboss.resteasy.api.validation.ResteasyConstraintViolation; import org.jboss.resteasy.api.validation.Validation; import org.jboss.resteasy.api.validation.ViolationReport; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.test.validation.resource.ValidationComplexA; import org.jboss.resteasy.test.validation.resource.ValidationComplexArrayOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexB; import org.jboss.resteasy.test.validation.resource.ValidationComplexCrossParameterConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexCrossParameterValidator; import org.jboss.resteasy.test.validation.resource.ValidationComplexFoo; import org.jboss.resteasy.test.validation.resource.ValidationComplexFooConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexFooReaderWriter; import org.jboss.resteasy.test.validation.resource.ValidationComplexFooValidator; import org.jboss.resteasy.test.validation.resource.ValidationComplexInterface; import org.jboss.resteasy.test.validation.resource.ValidationComplexInterfaceSub; import org.jboss.resteasy.test.validation.resource.ValidationComplexInterfaceSuper; import org.jboss.resteasy.test.validation.resource.ValidationComplexListOfArrayOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexListOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexMapOfListOfArrayOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexMapOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexOneString; import org.jboss.resteasy.test.validation.resource.ValidationComplexOtherGroup; import org.jboss.resteasy.test.validation.resource.ValidationComplexOtherGroupConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassConstraint2; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassInheritanceSubConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassInheritanceSuperConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassValidator; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassValidator2; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassValidatorSubInheritance; import org.jboss.resteasy.test.validation.resource.ValidationComplexClassValidatorSuperInheritance; import org.jboss.resteasy.test.validation.resource.ValidationComplexProxyInterface; import org.jboss.resteasy.test.validation.resource.ValidationComplexProxyResource; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithAllFivePotentialViolations; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithArray; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithClassConstraint; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithFieldAndProperty; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithGraph; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithInvalidField; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithList; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithMap; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithMapOfListOfArrayOfStrings; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithOtherGroups; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithParameters; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithProperty; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithReturnValues; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithSubLocators; import org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithValidField; import org.jboss.resteasy.test.validation.resource.ValidationComplexSubResourceWithCrossParameterConstraint; import org.jboss.resteasy.util.HttpResponseCodes; import org.jboss.resteasy.utils.PermissionUtil; import org.jboss.resteasy.utils.PortProviderUtil; import org.jboss.resteasy.utils.TestUtil; import org.jboss.resteasy.utils.TimeoutUtil; import org.jboss.shrinkwrap.api.Archive; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import javax.servlet.http.HttpServletResponse; import javax.ws.rs.InternalServerErrorException; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Cookie; import javax.ws.rs.core.Form; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.lang.reflect.ReflectPermission; import java.util.*; /** * @tpSubChapter Response * @tpChapter Integration tests * @tpTestCaseDetails Complex basic test for Resteasy Validator Provider * @tpSince RESTEasy 3.0.16 */ @RunWith(Arquillian.class) public class ValidationComplexTest { static final String RESPONSE_ERROR_MSG = "Response has wrong content"; static final String WRONG_ERROR_MSG = "Expected validation error is not in response"; private static Logger logger = Logger.getLogger(ValidationComplexTest.class); private static final String BASIC_DEPLOYMENT = "basicDeployment"; private static final String CUSTOM_OBJECT_DEPLOYMENT = "customObjectDeployment"; private static final String ASYNC_CUSTOM_OBJECT_DEPLOYMENT = "asyncCustomObjectDeployment"; ResteasyClient client; @Before public void init() { client = new ResteasyClientBuilder().build().register(ValidationComplexFooReaderWriter.class); } @After public void after() throws Exception { client.close(); } private static String generateURL(String type, String path, String testName) { return PortProviderUtil.generateURL(path, String.format("%s%s", type, testName)); } public static WebArchive addBasicClasses(WebArchive war) { war.addClasses(ValidationComplexA.class, ValidationComplexArrayOfStrings.class, ValidationComplexB.class, ValidationComplexMapOfStrings.class, ValidationComplexListOfStrings.class, ValidationComplexMapOfListOfArrayOfStrings.class, ValidationComplexOneString.class, ValidationComplexListOfArrayOfStrings.class, ValidationComplexProxyInterface.class, ValidationComplexOtherGroupConstraint.class, ValidationComplexOtherGroup.class, ValidationComplexClassValidator.class, ValidationComplexClassInheritanceSubConstraint.class, ValidationComplexClassValidatorSubInheritance.class, ValidationComplexInterfaceSuper.class, ValidationComplexInterface.class, ValidationComplexCrossParameterConstraint.class, ValidationComplexCrossParameterValidator.class, ValidationComplexFooReaderWriter.class, ValidationComplexFoo.class, ValidationComplexClassConstraint.class, ValidationComplexInterfaceSub.class, ValidationComplexClassInheritanceSuperConstraint.class, ValidationComplexClassValidatorSuperInheritance.class, ValidationComplexClassConstraint2.class, ValidationComplexClassValidator2.class); // Arquillian in the deployment war.addAsManifestResource(PermissionUtil.createPermissionsXmlAsset(new ReflectPermission("suppressAccessChecks"), new RuntimePermission("accessDeclaredMembers"), new PropertyPermission("arquillian.*", "read")), "permissions.xml"); war.addClasses(TestUtil.class, PortProviderUtil.class); return war; } public static WebArchive addCustomObjectClasses(WebArchive war) { war.addClasses(ValidationComplexFoo.class, ValidationComplexResourceWithAllFivePotentialViolations.class, ValidationComplexResourceWithValidField.class, ValidationComplexResourceWithInvalidField.class, ValidationComplexResourceWithProperty.class, ValidationComplexFooConstraint.class, ValidationComplexFooValidator.class); return war; } public static Archive<?> basicDeployment(Class<?> clazz) { WebArchive war = TestUtil.prepareArchive(BASIC_DEPLOYMENT + clazz.getSimpleName()); war = addBasicClasses(war); return TestUtil.finishContainerPrepare(war, null, clazz); } public static Archive<?> customObjectDeployment(Class<?> clazz) { WebArchive war = TestUtil.prepareArchive(CUSTOM_OBJECT_DEPLOYMENT + clazz.getSimpleName()); war = addBasicClasses(war); war = addCustomObjectClasses(war); return TestUtil.finishContainerPrepare(war, null, clazz, ValidationComplexFooReaderWriter.class); } public static Archive<?> asyncCustomObjectDeployment(Class<?> clazz) { WebArchive war = TestUtil.prepareArchive(ASYNC_CUSTOM_OBJECT_DEPLOYMENT + clazz.getSimpleName()); war = addBasicClasses(war); war = addCustomObjectClasses(war); Map<String, String> contextParams = new HashMap<>(); contextParams.put("resteasy.async.job.service.enabled", "true"); return TestUtil.finishContainerPrepare(war, contextParams, clazz, ValidationComplexFooReaderWriter.class); } @Deployment(name = "basicDeploymentTestResourceWithValidField") public static Archive<?> basicDeploymentTestResourceWithValidField() { return basicDeployment(ValidationComplexResourceWithValidField.class); } @Deployment(name = "basicDeploymentTestResourceWithInvalidField") public static Archive<?> basicDeploymentTestResourceWithInvalidField() { return basicDeployment(ValidationComplexResourceWithInvalidField.class); } @Deployment(name = "basicDeploymentTestResourceWithProperty") public static Archive<?> basicDeploymentTestResourceWithProperty() { return basicDeployment(ValidationComplexResourceWithProperty.class); } @Deployment(name = "basicDeploymentTestResourceWithFieldAndProperty") public static Archive<?> basicDeploymentTestResourceWithFieldAndProperty() { return basicDeployment(ValidationComplexResourceWithFieldAndProperty.class); } @Deployment(name = "basicDeploymentTestResourceWithClassConstraint") public static Archive<?> basicDeploymentTestResourceWithClassConstraint() { return basicDeployment(ValidationComplexResourceWithClassConstraint.class); } @Deployment(name = "basicDeploymentTestResourceWithGraph") public static Archive<?> basicDeploymentTestResourceWithGraph() { return basicDeployment(ValidationComplexResourceWithGraph.class); } @Deployment(name = "basicDeploymentTestResourceWithArray") public static Archive<?> basicDeploymentTestResourceWithArray() { return basicDeployment(ValidationComplexResourceWithArray.class); } @Deployment(name = "basicDeploymentTestResourceWithMap") public static Archive<?> basicDeploymentTestResourceWithMap() { return basicDeployment(ValidationComplexResourceWithMap.class); } @Deployment(name = "basicDeploymentTestResourceWithList") public static Archive<?> basicDeploymentTestResourceWithList() { return basicDeployment(ValidationComplexResourceWithList.class); } @Deployment(name = "basicDeploymentTestResourceWithMapOfListOfArrayOfStrings") public static Archive<?> basicDeploymentTestResourceWithMapOfListOfArrayOfStrings() { return basicDeployment(ValidationComplexResourceWithMapOfListOfArrayOfStrings.class); } @Deployment(name = "customObjectDeploymentTestResourceWithParameters") public static Archive<?> customObjectDeploymentTestResourceWithParameters() { return customObjectDeployment(ValidationComplexResourceWithParameters.class); } @Deployment(name = "customObjectDeploymentTestResourceWithReturnValues") public static Archive<?> customObjectDeploymentTestResourceWithReturnValues() { return customObjectDeployment(ValidationComplexResourceWithReturnValues.class); } @Deployment(name = "customObjectDeploymentTestResourceWithAllFivePotentialViolations") public static Archive<?> customObjectDeploymentTestResourceWithAllFivePotentialViolations() { return customObjectDeployment(ValidationComplexResourceWithAllFivePotentialViolations.class); } @Deployment(name = "basicDeploymentInterfaceTestSub") public static Archive<?> basicDeploymentInterfaceTestSub() { return basicDeployment(ValidationComplexInterfaceSub.class); } @Deployment(name = "customObjectDeploymentTestResourceWithSubLocators") public static Archive<?> customObjectDeploymentTestResourceWithSubLocators() { return customObjectDeployment(ValidationComplexResourceWithSubLocators.class); } @Deployment(name = "asyncCustomObjectDeploymentTestResourceWithAllFivePotentialViolations") public static Archive<?> asyncCustomObjectDeploymentTestResourceWithAllFivePotentialViolations() { return asyncCustomObjectDeployment(ValidationComplexResourceWithAllFivePotentialViolations.class); } @Deployment(name = "basicDeploymentTestSubResourceWithCrossParameterConstraint") public static Archive<?> basicDeploymentTestSubResourceWithCrossParameterConstraint() { return basicDeployment(ValidationComplexSubResourceWithCrossParameterConstraint.class); } @Deployment(name = "basicDeploymentTestProxyResource") public static Archive<?> basicDeploymentTestProxyResource() { return basicDeployment(ValidationComplexProxyResource.class); } @Deployment(name = "basicDeploymentTestResourceWithOtherGroups") public static Archive<?> basicDeploymentTestResourceWithOtherGroups() { return basicDeployment(ValidationComplexResourceWithOtherGroups.class); } /** * @tpTestDetails Valid field test * @tpSince RESTEasy 3.0.16 */ @Test public void testFieldValid() throws Exception { Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/", ValidationComplexResourceWithValidField.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); } /** * @tpTestDetails Invalid field test * @tpSince RESTEasy 3.0.16 */ @Test public void testFieldInvalid() throws Exception { Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/", ValidationComplexResourceWithInvalidField.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); logger.info("cv: " + cv); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(WRONG_ERROR_MSG, "abcde", cv.getValue()); response.close(); } /** * @tpTestDetails Valid property test * @tpSince RESTEasy 3.0.16 */ @Test public void testPropertyValid() throws Exception { Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc/unused", ValidationComplexResourceWithProperty.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); } /** * @tpTestDetails Invalid property test * @tpSince RESTEasy 3.0.16 */ @Test public void testPropertyInvalid() throws Exception { Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcdef/unused", ValidationComplexResourceWithProperty.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(entity); TestUtil.countViolations(r, 0, 1, 0, 0, 0); ResteasyConstraintViolation cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(WRONG_ERROR_MSG, "abcdef", cv.getValue()); response.close(); } /** * @tpTestDetails Field and property validation test * @tpSince RESTEasy 3.0.16 */ @Test public void testFieldAndProperty() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc/wxyz", ValidationComplexResourceWithFieldAndProperty.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/a/uvwxyz", ValidationComplexResourceWithFieldAndProperty.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(entity); TestUtil.countViolations(r, 1, 1, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(WRONG_ERROR_MSG, "a", cv.getValue()); cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 3 and 5", cv.getMessage()); Assert.assertEquals(WRONG_ERROR_MSG, "uvwxyz", cv.getValue()); response.close(); } /** * @tpTestDetails Check class constraints * @tpSince RESTEasy 3.0.16 */ @Test public void testClassConstraint() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc/xyz", ValidationComplexResourceWithClassConstraint.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/a/b", ValidationComplexResourceWithClassConstraint.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(entity); TestUtil.countViolations(r, 0, 0, 1, 0, 0); ResteasyConstraintViolation cv = r.getClassViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "Concatenation of s and t must have length > 5", cv.getMessage()); Assert.assertEquals(WRONG_ERROR_MSG, "ValidationComplexResourceWithClassConstraint(\"a\", \"b\")", cv.getValue()); logger.info(cv.getValue()); response.close(); } /** * @tpTestDetails Graph test * @tpSince RESTEasy 3.0.16 */ @Test public void testGraph() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcd/vwxyz", ValidationComplexResourceWithGraph.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc/xyz", ValidationComplexResourceWithGraph.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 2, 0, 0, 0, 0); Iterator<ResteasyConstraintViolation> it = r.getFieldViolations().iterator(); ResteasyConstraintViolation cv1 = it.next(); ResteasyConstraintViolation cv2 = it.next(); if (cv1.getValue().equals("xyz")) { ResteasyConstraintViolation tmp = cv1; cv1 = cv2; cv2 = tmp; } Assert.assertTrue(WRONG_ERROR_MSG, cv1.getMessage().startsWith("size must be between 4 and")); Assert.assertEquals(WRONG_ERROR_MSG, "abc", cv1.getValue()); Assert.assertTrue(WRONG_ERROR_MSG, cv2.getMessage().startsWith("size must be between 5 and")); Assert.assertEquals(WRONG_ERROR_MSG, "xyz", cv2.getValue()); response.close(); } /** * @tpTestDetails Validation of array * @tpSince RESTEasy 3.0.16 */ @Test public void testArray() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcde", ValidationComplexResourceWithArray.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc", ValidationComplexResourceWithArray.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().startsWith("size must be between 5 and")); Assert.assertEquals(WRONG_ERROR_MSG, "abc", cv.getValue()); response.close(); } /** * @tpTestDetails Validation of list * @tpSince RESTEasy 3.0.16 */ @Test public void testList() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcde", ValidationComplexResourceWithList.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc", ValidationComplexResourceWithList.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().startsWith("size must be between 5 and")); Assert.assertEquals(WRONG_ERROR_MSG, "abc", cv.getValue()); response.close(); } /** * @tpTestDetails Validation of map * @tpSince RESTEasy 3.0.16 */ @Test public void testMap() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcde", ValidationComplexResourceWithMap.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc", ValidationComplexResourceWithMap.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().startsWith("size must be between 5 and")); Assert.assertEquals(WRONG_ERROR_MSG, "abc", cv.getValue()); response.close(); } /** * @tpTestDetails Validation of map of list of array of string * @tpSince RESTEasy 3.0.16 */ @Test public void testMapOfListOfArrayOfStrings() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/abcde", ValidationComplexResourceWithMapOfListOfArrayOfStrings.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/abc", ValidationComplexResourceWithMapOfListOfArrayOfStrings.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); logger.info("exception: " + r); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().startsWith("size must be between 5 and")); Assert.assertEquals(WRONG_ERROR_MSG, "abc", cv.getValue()); response.close(); } /** * @tpTestDetails Test parameters validation * @tpSince RESTEasy 3.0.16 */ @Test public void testParameters() throws Exception { // Valid native constraint Response response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/native", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("a"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Valid imposed constraint response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/imposed", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcde"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Valid native and imposed constraints. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/nativeAndImposed", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abc"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid native constraint // Valid native and imposed constraints. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/native", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(entity); TestUtil.countViolations(r, 0, 0, 0, 1, 0); ResteasyConstraintViolation cv = r.getParameterViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().equals("s must have length: 1 <= length <= 3")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv.getValue()); response.close(); // Invalid imposed constraint response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/imposed", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 1, 0); cv = r.getParameterViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().equals("s must have length: 3 <= length <= 5")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv.getValue()); response.close(); // Invalid native and imposed constraints response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/nativeAndImposed", ValidationComplexResourceWithParameters.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(entity); TestUtil.countViolations(r, 0, 0, 0, 2, 0); Iterator<ResteasyConstraintViolation> it = r.getParameterViolations().iterator(); ResteasyConstraintViolation cv1 = it.next(); ResteasyConstraintViolation cv2 = it.next(); if (cv1.toString().indexOf('1') < 0) { ResteasyConstraintViolation temp = cv1; cv1 = cv2; cv2 = temp; } Assert.assertTrue(WRONG_ERROR_MSG, cv1.getMessage().equals("s must have length: 1 <= length <= 3")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv1.getValue()); Assert.assertTrue(WRONG_ERROR_MSG, cv2.getMessage().equals("s must have length: 3 <= length <= 5")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv2.getValue()); response.close(); // Valid other parameters String url = generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/other/ppp", ValidationComplexResourceWithParameters.class.getSimpleName()); // path param url += ";m=mmm"; // matrix param url += "?q=qqq"; // query param Form form = new Form().param("f", "fff"); response = client.target(url).request().header("h", "hhh").cookie(new Cookie("c", "ccc")).post(Entity.form(form)); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid other parameters url = generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/other/pppp", ValidationComplexResourceWithParameters.class.getSimpleName()); // path param url += ";m=mmmm"; // matrix param url += "?q=qqqq"; // query param form = new Form().param("f", "ffff"); response = client.target(url).request().header("h", "hhhh").cookie(new Cookie("c", "cccc")).post(Entity.form(form)); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 6, 0); List<String> list = getMessages(r); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; pppp")); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; mmmm")); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; qqqq")); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; ffff")); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; hhhh")); Assert.assertTrue(WRONG_ERROR_MSG, list.contains("size must be between 2 and 3; cccc")); response.close(); } /** * @tpTestDetails Test return value validation * @tpSince RESTEasy 3.0.16 */ @Test public void testReturnValues() throws Exception { // Valid native constraint ValidationComplexFoo foo = new ValidationComplexFoo("a"); Response response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/native", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, foo, response.readEntity(ValidationComplexFoo.class)); response.close(); // Valid imposed constraint foo = new ValidationComplexFoo("abcde"); response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/imposed", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, foo, response.readEntity(ValidationComplexFoo.class)); response.close(); // Valid native and imposed constraints. foo = new ValidationComplexFoo("abc"); response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/nativeAndImposed", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, foo, response.readEntity(ValidationComplexFoo.class)); response.close(); // Invalid native constraint response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/native", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 1); ResteasyConstraintViolation cv = r.getReturnValueViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().equals("s must have length: 1 <= length <= 3")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv.getValue()); response.close(); // Invalid imposed constraint response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/imposed", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 1); cv = r.getReturnValueViolations().iterator().next(); Assert.assertTrue(WRONG_ERROR_MSG, cv.getMessage().equals("s must have length: 3 <= length <= 5")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv.getValue()); response.close(); // Invalid native and imposed constraints response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/nativeAndImposed", ValidationComplexResourceWithReturnValues.class.getSimpleName())) .request().post(Entity.entity(new ValidationComplexFoo("abcdef"), "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 2); Iterator<ResteasyConstraintViolation> it = r.getReturnValueViolations().iterator(); ResteasyConstraintViolation cv1 = it.next(); ResteasyConstraintViolation cv2 = it.next(); if (cv1.toString().indexOf('1') < 0) { ResteasyConstraintViolation temp = cv1; cv1 = cv2; cv2 = temp; } Assert.assertTrue(WRONG_ERROR_MSG, cv1.getMessage().equals("s must have length: 1 <= length <= 3")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv1.getValue()); Assert.assertTrue(WRONG_ERROR_MSG, cv2.getMessage().equals("s must have length: 3 <= length <= 5")); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[abcdef]", cv2.getValue()); response.close(); } /** * @tpTestDetails Check validations before checking return value * @tpSince RESTEasy 3.0.16 */ @Test public void testViolationsBeforeReturnValue() throws Exception { // Valid ValidationComplexFoo foo = new ValidationComplexFoo("pqrs"); Response response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/abc/wxyz/unused/unused", ValidationComplexResourceWithAllFivePotentialViolations.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(foo, response.readEntity(ValidationComplexFoo.class)); response.close(); // Invalid: Should have 1 each of field, property, class, and parameter violations, // and no return value violations. foo = new ValidationComplexFoo("p"); response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/a/z/unused/unused", ValidationComplexResourceWithAllFivePotentialViolations.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 1, 1, 1, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "a", cv.getValue()); cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 3 and 5", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "z", cv.getValue()); cv = r.getClassViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "Concatenation of s and t must have length > 5", cv.getMessage()); Assert.assertTrue(WRONG_ERROR_MSG, cv.getValue().startsWith("org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithAllFivePotentialViolations@")); cv = r.getParameterViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "s must have length: 3 <= length <= 5", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[p]", cv.getValue()); response.close(); } /** * @tpTestDetails Validation in inheritence classes * @tpSince RESTEasy 3.0.16 */ @Test @OperateOnDeployment("basicDeploymentInterfaceTestSub") public void testInheritence() throws Exception { { // Valid - inherited annotations ValidationComplexInterfaceSuper.t = "aaa"; ValidationComplexInterfaceSub.u = "bbb"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/inherit", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("ccc", MediaType.TEXT_PLAIN_TYPE)); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, "ccc", response.readEntity(String.class)); response.close(); } { // Valid - overridden annotations ValidationComplexInterfaceSuper.t = "aaa"; ValidationComplexInterfaceSub.u = "bbb"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/override", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("ccc", MediaType.TEXT_PLAIN_TYPE)); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, "ccc", response.readEntity(String.class)); response.close(); } { // Invalid - inherited class, parameter annotations ValidationComplexInterfaceSuper.t = "a"; ValidationComplexInterfaceSub.u = "d"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/inherit", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("e", MediaType.TEXT_PLAIN_TYPE)); logger.info("status: " + response.getStatus()); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 2, 1, 0); response.close(); } { // Invalid - overridden class, parameter annotations ValidationComplexInterfaceSuper.t = "a"; ValidationComplexInterfaceSub.u = "d"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/override", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("e", MediaType.TEXT_PLAIN_TYPE)); logger.info("status: " + response.getStatus()); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 2, 1, 0); response.close(); } { // Invalid - inherited return value annotations ValidationComplexInterfaceSuper.t = "aaa"; ValidationComplexInterfaceSub.u = "bbb"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/inherit", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("eeee", MediaType.TEXT_PLAIN_TYPE)); logger.info("status: " + response.getStatus()); Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 1); response.close(); } { // Invalid - overridden return value annotations ValidationComplexInterfaceSuper.t = "aaa"; ValidationComplexInterfaceSub.u = "bbb"; Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/override", ValidationComplexInterfaceSub.class.getSimpleName())) .request().post(Entity.entity("eeee", MediaType.TEXT_PLAIN_TYPE)); logger.info("status: " + response.getStatus()); Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 2); response.close(); } } /** * @tpTestDetails Locators validation * @tpSince RESTEasy 3.0.16 */ @Test public void testLocators() throws Exception { // Sub-resource locator returns resource with valid field. Response response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/validField", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Sub-resource locator returns resource with invalid field. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/invalidField", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(entity); TestUtil.countViolations(r, 1, 0, 0, 0, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "abcde", cv.getValue()); response.close(); // Sub-resource locator returns resource with valid property. // Note: The resource ValidationComplexResourceWithProperty has a @PathParam annotation used by a setter, // but it is not used when ValidationComplexResourceWithProperty is used a sub-resource. Hence "unused". response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/property/abc/unused", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Sub-resource locator returns resource with invalid property. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/property/abcdef/unused", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(entity); TestUtil.countViolations(r, 0, 1, 0, 0, 0); cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "abcdef", cv.getValue()); response.close(); // Valid ValidationComplexFoo foo = new ValidationComplexFoo("pqrs"); response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/everything/abc/wxyz/unused/unused", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_OK, response.getStatus()); Assert.assertEquals(RESPONSE_ERROR_MSG, foo, response.readEntity(ValidationComplexFoo.class)); response.close(); // Invalid: Should have 1 each of field, property, class, and parameter violations,and no return value violations. // Note: expect warning because ValidationComplexResourceWithAllFivePotentialViolations is being used a sub-resource and it has an injectible field: // WARN org.jboss.resteasy.core.ResourceLocator - Field s of subresource org.jboss.resteasy.test.validation.ValidationComplexTest$ValidationComplexResourceWithAllFivePotentialViolations will not be injected according to spec foo = new ValidationComplexFoo("p"); response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/everything/a/z/unused/unused", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 1, 1, 1, 0); cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "a", cv.getValue()); cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 3 and 5", cv.getMessage()); cv = r.getClassViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "Concatenation of s and t must have length > 5", cv.getMessage()); Assert.assertTrue(RESPONSE_ERROR_MSG, cv.getValue().startsWith("org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithAllFivePotentialViolations@")); response.close(); // Sub-sub-resource locator returns resource with valid property. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/locator/sublocator/abc", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Sub-resource locator returns resource with invalid property. response = client.target(generateURL(CUSTOM_OBJECT_DEPLOYMENT, "/locator/sublocator/abcdef", ValidationComplexResourceWithSubLocators.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 0, 0, 0, 0); cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 3", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "abcdef", cv.getValue()); response.close(); } /** * @tpTestDetails Validation with asynchronous requests * @tpSince RESTEasy 3.0.16 */ @Test public void testAsynch() throws Exception { // Submit asynchronous job with violations prior to execution of resource method. ValidationComplexFoo foo = new ValidationComplexFoo("p"); Response response = client.target(generateURL(ASYNC_CUSTOM_OBJECT_DEPLOYMENT, "/a/z/unused/unused?asynch=true", ValidationComplexResourceWithAllFivePotentialViolations.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpServletResponse.SC_ACCEPTED, response.getStatus()); String jobUrl = response.getHeaderString(HttpHeaders.LOCATION); logger.info("JOB: " + jobUrl); response.close(); // Get result: Should have 1 each of field, property, class, and parameter violations, // and no return value violations. response = client.target(jobUrl).request().get(); for (int i = 0; i < 60; i++) { Thread.sleep(TimeoutUtil.adjust(1000)); response.close(); response = client.target(jobUrl).request().get(); if (HttpServletResponse.SC_ACCEPTED != response.getStatus()) { break; } } Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); Object entity = response.readEntity(String.class); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 1, 1, 1, 1, 0); ResteasyConstraintViolation cv = r.getFieldViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "a", cv.getValue()); cv = r.getPropertyViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 3 and 5", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "z", cv.getValue()); cv = r.getClassViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "Concatenation of s and t must have length > 5", cv.getMessage()); Assert.assertTrue(RESPONSE_ERROR_MSG, cv.getValue().startsWith("org.jboss.resteasy.test.validation.resource.ValidationComplexResourceWithAllFivePotentialViolations@")); cv = r.getParameterViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "s must have length: 3 <= length <= 5", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[p]", cv.getValue()); response.close(); // Delete job. response = client.target(jobUrl).request().delete(); Assert.assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus()); response.close(); // Submit asynchronous job with violations in result of resource method. foo = new ValidationComplexFoo("pqr"); response = client.target(generateURL(ASYNC_CUSTOM_OBJECT_DEPLOYMENT, "/abc/xyz/unused/unused?asynch=true", ValidationComplexResourceWithAllFivePotentialViolations.class.getSimpleName())) .request().post(Entity.entity(foo, "application/foo")); Assert.assertEquals(HttpServletResponse.SC_ACCEPTED, response.getStatus()); jobUrl = response.getHeaderString(HttpHeaders.LOCATION); logger.info("JOB: " + jobUrl); response.close(); // Get result: Should have no field, property, class, or parameter violations, // and one return value violation. response = client.target(jobUrl).request().get(); for (int i = 0; i < 60; i++) { Thread.sleep(TimeoutUtil.adjust(1000)); response.close(); response = client.target(jobUrl).request().get(); if (HttpServletResponse.SC_ACCEPTED != response.getStatus()) { break; } } Assert.assertEquals(HttpResponseCodes.SC_INTERNAL_SERVER_ERROR, response.getStatus()); entity = response.readEntity(String.class); r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 1); cv = r.getReturnValueViolations().iterator().next(); Assert.assertEquals(WRONG_ERROR_MSG, "s must have length: 4 <= length <= 5", cv.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "ValidationComplexFoo[pqr]", cv.getValue()); response.close(); // Delete job. response = client.target(jobUrl).request().delete(); Assert.assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus()); response.close(); } /** * @tpTestDetails Validation by cross-parameter constraints * @tpSince RESTEasy 3.0.16 */ @Test public void testCrossParameterConstraint() throws Exception { // Valid Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/2/3", ValidationComplexSubResourceWithCrossParameterConstraint.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_NO_CONTENT, response.getStatus()); response.close(); // Invalid response = client.target(generateURL(BASIC_DEPLOYMENT, "/5/7", ValidationComplexSubResourceWithCrossParameterConstraint.class.getSimpleName())) .request().post(Entity.text(new String())); Assert.assertEquals(HttpResponseCodes.SC_BAD_REQUEST, response.getStatus()); String header = response.getHeaderString(Validation.VALIDATION_HEADER); Assert.assertNotNull("Missing validation header", header); Assert.assertTrue("Wrong validation header", Boolean.valueOf(header)); Object entity = response.readEntity(String.class); logger.info("entity: " + entity); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 1, 0); ResteasyConstraintViolation violation = r.getParameterViolations().iterator().next(); logger.info("violation: " + violation); Assert.assertEquals(WRONG_ERROR_MSG, "Parameters must total <= 7", violation.getMessage()); logger.info("violation value: " + violation.getValue()); Assert.assertEquals(RESPONSE_ERROR_MSG, "[5, 7]", violation.getValue()); response.close(); } /** * @tpTestDetails Validation with client proxies * @tpSince RESTEasy 3.0.16 */ @Test public void testProxy() throws Exception { // Valid ValidationComplexProxyInterface client = this.client.target(generateURL(BASIC_DEPLOYMENT, "/", ValidationComplexProxyResource.class.getSimpleName())) .proxy(ValidationComplexProxyInterface.class); client.s("abcd"); String result = client.g(); Assert.assertEquals("abcd", result); // Invalid client.s("abcde"); try { client.g(); } catch (InternalServerErrorException e) { Response response = e.getResponse(); logger.info("status: " + response.getStatus()); String header = response.getHeaderString(Validation.VALIDATION_HEADER); Assert.assertNotNull("Missing validation header", header); Assert.assertTrue("Wrong validation header", Boolean.valueOf(header)); Object entity = response.readEntity(String.class); logger.info("entity: " + entity); ViolationReport r = new ViolationReport(String.class.cast(entity)); TestUtil.countViolations(r, 0, 0, 0, 0, 1); ResteasyConstraintViolation violation = r.getReturnValueViolations().iterator().next(); logger.info("violation: " + violation); Assert.assertEquals(WRONG_ERROR_MSG, "size must be between 2 and 4", violation.getMessage()); Assert.assertEquals(RESPONSE_ERROR_MSG, "abcde", violation.getValue()); response.close(); } catch (Exception e) { throw new RuntimeException("expected InternalServerErrorException", e); } } /** * @tpTestDetails Check other groups validation * @tpSince RESTEasy 3.0.16 */ @Test public void testOtherGroups() throws Exception { // Test invalid field, property, parameter, and class. Response response = client.target(generateURL(BASIC_DEPLOYMENT, "/test/a/z", ValidationComplexResourceWithOtherGroups.class.getSimpleName())) .request().post(Entity.text(new String())); String entity = response.readEntity(String.class); logger.info("entity: " + entity); Assert.assertEquals(RESPONSE_ERROR_MSG, "z", entity); response.close(); } private List<String> getMessages(ViolationReport r) { List<String> list = new ArrayList<>(); list.addAll(getMessagesFromList(r.getFieldViolations())); list.addAll(getMessagesFromList(r.getPropertyViolations())); list.addAll(getMessagesFromList(r.getClassViolations())); list.addAll(getMessagesFromList(r.getParameterViolations())); list.addAll(getMessagesFromList(r.getReturnValueViolations())); return list; } private List<String> getMessagesFromList(List<ResteasyConstraintViolation> rcvs) { List<String> list = new ArrayList<>(); for (Iterator<ResteasyConstraintViolation> it = rcvs.iterator(); it.hasNext(); ) { ResteasyConstraintViolation rcv = it.next(); list.add(rcv.getMessage() + "; " + rcv.getValue()); } return list; } }