/******************************************************************************* * Copyright (c) 2009-2014 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.jsf.test.validation; import java.io.InputStream; import java.io.StringBufferInputStream; import java.text.MessageFormat; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResourceDelta; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.wst.validation.ValidationResult; import org.eclipse.wst.validation.ValidationState; import org.eclipse.wst.validation.internal.core.Message; import org.jboss.tools.common.base.test.validation.TestUtil; import org.jboss.tools.jsf.web.validation.JSFValidationMessage; import org.jboss.tools.jsf.web.validation.XHTMLValidator; import org.jboss.tools.test.util.ProjectImportTestSetup; import org.jboss.tools.tests.AbstractResourceMarkerTest; /** * The JUnit test case for JBIDE-9828 and JBIDE-9846 issues * * @author Victor V. Rubezhny * */ public class XHTMLValidatorTest extends AbstractResourceMarkerTest { protected static String PLUGIN_ID = "org.jboss.tools.jsf.test"; protected static String PROJECT_NAME = "jsf2pr"; protected static String PROJECT_PATH = "/projects/jsf2pr"; protected static final String FILE_NAME = "WebContent/XHTMLValidatorTest.xhtml"; protected static Set<String> LOCALIZED_ERROR_MESSAGES = new HashSet<String>(); static { LOCALIZED_ERROR_MESSAGES.add(MessageFormat.format(JSFValidationMessage.XHTML_VALIDATION_NO_END_TAG, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME)); LOCALIZED_ERROR_MESSAGES.add(MessageFormat.format(JSFValidationMessage.XHTML_VALIDATION_NO_START_TAG, XHTMLValidationTestMessages.XHTML_WRONG_TAGNAME)); } protected static Set<String> LOCALIZED_LARGE_ERROR_MESSAGES = new HashSet<String>(); static { LOCALIZED_LARGE_ERROR_MESSAGES.add(MessageFormat.format(JSFValidationMessage.XHTML_VALIDATION_NO_END_TAG, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME)); LOCALIZED_LARGE_ERROR_MESSAGES.add(MessageFormat.format(JSFValidationMessage.XHTML_VALIDATION_NO_START_TAG, XHTMLValidationTestMessages.XHTML_LARGE_WRONG_TAGNAME)); LOCALIZED_LARGE_ERROR_MESSAGES.add(JSFValidationMessage.XHTML_VALIDATION_BAD_ENTITY); } protected static String LOCALIZED_BROKEN_ERROR_MESSAGE = XHTMLValidationTestMessages.XHTML_MARKUP_IS_BROKEN_ERROR; // "Bad" file validation time should be not greater than "Good" file validation time multiplied by 10 protected static final double NOT_BAD_DIFF_PERCENTAGE = 2000.0; // Each validation session should take less that 1 second (1000ms) protected static final long MAX_VALIDATION_TIME = 2000; IProject project; /* (non-Javadoc) * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { project = ProjectImportTestSetup.loadProject(PROJECT_NAME); TestUtil._waitForValidation(project); } public void testWebContentValidation() throws CoreException { XHTMLValidator validator = new XHTMLValidator(); ValidationState state = new ValidationState(); try { // Validate file with good DOCTYPE declaration and no XHTML Syntax errors IFile file = createTestFile(XHTMLValidationTestMessages.XHTML_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME); long start = System.currentTimeMillis(); ValidationResult result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long goodValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with good DOCTYPE declaration and no XHTML Syntax errors validation time: " + goodValidationTime + " ms"); assertTrue("XHTML file with good DOCTYPE declaration and no XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (goodValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); List messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); // Validate file with bad DOCTYPE declaration and no XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_WRONG_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_WRONG_URI, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long badValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with bad DOCTYPE declaration and no XHTML Syntax errors validation time: " + badValidationTime + " ms"); assertTrue("XHTML file with bad DOCTYPE declaration and no XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (badValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); // Check that the difference between good and bad files validation time is not greater that NOT_BAD_DIFF_PERCENTAGE (%) of a good value double diff = 100*(badValidationTime + 1)/(goodValidationTime + 1); System.out.println("(With no errors) Validation time difference: " + diff + "%"); assertTrue("Validation time difference between good and wrong content is greater than " + NOT_BAD_DIFF_PERCENTAGE + "%", (diff < NOT_BAD_DIFF_PERCENTAGE)); // Validate file with good DOCTYPE declaration and XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_WRONG_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); goodValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with good DOCTYPE declaration and XHTML Syntax errors validation time: " + goodValidationTime + " ms"); assertTrue("XHTML file with good DOCTYPE declaration and XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (goodValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 1, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_ERROR_MESSAGES.contains(message.getText())); } // Validate file with bad DOCTYPE declaration and XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_WRONG_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_WRONG_URI, XHTMLValidationTestMessages.XHTML_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_WRONG_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); badValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with bad DOCTYPE declaration and XHTML Syntax errors validation time: " + badValidationTime + " ms"); assertTrue("XHTML file with bad DOCTYPE declaration and XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (badValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_ERROR_MESSAGES.contains(message.getText())); } // Check that the difference between good and bad files validation time is not greater that NOT_BAD_DIFF_PERCENTAGE (%) of a good value diff = 100*(badValidationTime + 1)/(goodValidationTime + 1); System.out.println("(With errors) Validation time difference: " + diff + "%"); assertTrue("Validation time difference between good and wrong content is greater than " + NOT_BAD_DIFF_PERCENTAGE + "%", (diff < NOT_BAD_DIFF_PERCENTAGE)); } finally { removeTestFile(); } } public void testBrokenWebContentValidation() throws CoreException { XHTMLValidator validator = new XHTMLValidator(); ValidationState state = new ValidationState(); try { // Validate file with good DOCTYPE declaration and broken content IFile file = createBrokenTestFile(XHTMLValidationTestMessages.XHTML_BROKEN_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI); long start = System.currentTimeMillis(); ValidationResult result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long goodValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with good DOCTYPE declaration and broken content validation time: " + goodValidationTime + " ms"); assertTrue("XHTML file with good DOCTYPE declaration and broken content validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (goodValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); List messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 1, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; // System.out.println("Error Message: " + message.getText()); assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_BROKEN_ERROR_MESSAGE.contains(message.getText())); } // Validate file with DOCTYPE declaration and broken content file = createBrokenTestFile(XHTMLValidationTestMessages.XHTML_BROKEN_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_WRONG_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_WRONG_URI); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long badValidationTime = System.currentTimeMillis() - start; System.out.println("XHTML file with bad DOCTYPE declaration and broken content validation time: " + badValidationTime + " ms"); assertTrue("XHTML file with bad DOCTYPE declaration and broken content validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (badValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; // System.out.println("Error Message: " + message.getText()); assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_BROKEN_ERROR_MESSAGE.contains(message.getText())); } // Check that the difference between good and bad files validation time is not greater that NOT_BAD_DIFF_PERCENTAGE (%) of a good value double diff = 100*(badValidationTime+1)/(goodValidationTime + 1); System.out.println("(With broken content) Validation time difference: " + diff + "%"); assertTrue("Validation time difference between good and wrong DOCTYPE declaration is greater than " + NOT_BAD_DIFF_PERCENTAGE + "%", (diff < NOT_BAD_DIFF_PERCENTAGE)); } finally { removeTestFile(); } } public void testLargeWebContentValidation() throws CoreException { XHTMLValidator validator = new XHTMLValidator(); ValidationState state = new ValidationState(); try { // Validate file with good DOCTYPE declaration and no XHTML Syntax errors IFile file = createTestFile(XHTMLValidationTestMessages.XHTML_LARGE_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME); long start = System.currentTimeMillis(); ValidationResult result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long goodValidationTime = System.currentTimeMillis() - start; System.out.println("Large XHTML file with good DOCTYPE declaration and no XHTML Syntax errors validation time: " + goodValidationTime + " ms"); assertTrue("Large XHTML file with good DOCTYPE declaration and no XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (goodValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); List messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 1, messages == null ? 0 : messages.size()); // Validate file with bad DOCTYPE declaration and no XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_LARGE_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_WRONG_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_WRONG_URI, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); long badValidationTime = System.currentTimeMillis() - start; System.out.println("Large XHTML file with bad DOCTYPE declaration and no XHTML Syntax errors validation time: " + badValidationTime + " ms"); assertTrue("Large XHTML file with bad DOCTYPE declaration and no XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (badValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); // Check that the difference between good and bad files validation time is not greater that NOT_BAD_DIFF_PERCENTAGE (%) of a good value double diff = 100*(badValidationTime+1)/(goodValidationTime + 1); System.out.println("(Large With no errors) Validation time difference: " + diff + "%"); assertTrue("Validation time difference between good and wrong content is greater than " + NOT_BAD_DIFF_PERCENTAGE + "%", (diff < NOT_BAD_DIFF_PERCENTAGE)); // Validate file with good DOCTYPE declaration and XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_LARGE_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_LARGE_WRONG_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); goodValidationTime = System.currentTimeMillis() - start; System.out.println("Large XHTML file with good DOCTYPE declaration and XHTML Syntax errors validation time: " + goodValidationTime + " ms"); assertTrue("Large XHTML file with good DOCTYPE declaration and XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (goodValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 1, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; // System.out.println("Error Message: " + message.getText()); assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_LARGE_ERROR_MESSAGES.contains(message.getText())); } // Validate file with bad DOCTYPE declaration and XHTML Syntax errors file = createTestFile(XHTMLValidationTestMessages.XHTML_LARGE_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_WRONG_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_WRONG_URI, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_LARGE_WRONG_TAGNAME); start = System.currentTimeMillis(); result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); badValidationTime = System.currentTimeMillis() - start; System.out.println("Large XHTML file with bad DOCTYPE declaration and XHTML Syntax errors validation time: " + badValidationTime + " ms"); assertTrue("Large XHTML file with bad DOCTYPE declaration and XHTML Syntax errors validation takes too much time (more than " + MAX_VALIDATION_TIME + " ms)", (badValidationTime < MAX_VALIDATION_TIME)); assertNotNull("No validation result is returned", result); assertNotNull("No validation result is returned", result.getReporter(null)); messages = result.getReporter(null).getMessages(); assertEquals("Wrong number of error messages reported", 0, messages == null ? 0 : messages.size()); for (Object m : messages) { assertTrue("Wrong type of validation message is returned", (m instanceof Message)); Message message = (Message)m; // System.out.println("Error Message: " + message.getText()); assertTrue("Unexpected error message found: " + message.getText(), LOCALIZED_LARGE_ERROR_MESSAGES.contains(message.getText())); } // Check that the difference between good and bad files validation time is not greater that NOT_BAD_DIFF_PERCENTAGE (%) of a good value diff = 100*(badValidationTime+1)/(goodValidationTime + 1); System.out.println("(Large With errors) Validation time difference: " + diff + "%"); assertTrue("Validation time difference between good and wrong content is greater than " + NOT_BAD_DIFF_PERCENTAGE + "%", (diff < NOT_BAD_DIFF_PERCENTAGE)); } finally { removeTestFile(); } } public void testBrokenEntityWebContentValidation() throws CoreException { XHTMLValidator validator = new XHTMLValidator(); ValidationState state = new ValidationState(); try { // Validate file with good DOCTYPE declaration and no XHTML Syntax errors IFile file = createTestFile(XHTMLValidationTestMessages.XHTML_LARGE_CONTENT_TEMPLATE, XHTMLValidationTestMessages.XHTML_GOOD_PUBLIC_ID, XHTMLValidationTestMessages.XHTML_GOOD_URI, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME, XHTMLValidationTestMessages.XHTML_LARGE_GOOD_TAGNAME); ValidationResult result = validator.validate(file, IResourceDelta.CHANGED, state, new NullProgressMonitor()); } catch (NullPointerException e) { fail("Validation on XHTML file with a 'broken' entity has failed with NullPointerException: " + e.getLocalizedMessage()); } catch (ArrayIndexOutOfBoundsException e) { fail("Validation on XHTML file with a 'broken' entity has failed with ArrayIndexOutOfBoundsException: " + e.getLocalizedMessage()); } finally { removeTestFile(); } } private IFile createTestFile(String template, String publicId, String uri, String openingTagName, String closingTagName) { IFile testFile = project.getFile(FILE_NAME); String content = MessageFormat.format(template, publicId, uri, openingTagName, closingTagName); InputStream source = new StringBufferInputStream(content); try { if (testFile.exists()) { testFile.setContents(source, true, false, new NullProgressMonitor()); } else { testFile.create(source, true, new NullProgressMonitor()); } } catch (CoreException e) { fail(e.getLocalizedMessage()); } return testFile; } private IFile createBrokenTestFile(String template, String publicId, String uri) { IFile testFile = project.getFile(FILE_NAME); String content = MessageFormat.format(template, publicId, uri); InputStream source = new StringBufferInputStream(content); try { if (testFile.exists()) { testFile.setContents(source, true, false, new NullProgressMonitor()); } else { testFile.create(source, true, new NullProgressMonitor()); } } catch (CoreException e) { fail(e.getLocalizedMessage()); } return testFile; } private void removeTestFile() { IFile testFile = project.getFile(FILE_NAME); if (testFile.exists()) { try { testFile.delete(true, new NullProgressMonitor()); } catch (CoreException e) { // Do not throw the exception e.printStackTrace(); } } } }