blob: 5e30d53c3fd6c92cc095a92679fb1f3e31475b0b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.validation.test.internal.registry;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.validation.test.BVTValidationException;
import org.eclipse.jst.validation.test.BVTValidationPlugin;
import org.eclipse.jst.validation.test.ValidationTypeEnum;
import org.eclipse.jst.validation.test.internal.util.BVTRunner;
import org.eclipse.jst.validation.test.setup.IBuffer;
import org.eclipse.wst.validation.internal.ConfigurationManager;
import org.eclipse.wst.validation.internal.GlobalConfiguration;
import org.eclipse.wst.validation.internal.TaskListUtility;
import org.eclipse.wst.validation.internal.VThreadManager;
import org.eclipse.wst.validation.internal.ValidatorMetaData;
import org.eclipse.wst.validation.internal.core.IFileDelta;
import org.eclipse.wst.validation.internal.operations.ValidatorSubsetOperation;
public class ValidatorTestcase implements ITestcaseMetaData {
private String _pluginId = null; // The plugin id that has contributed this test case.
private ValidatorMetaData _vmd = null;
private MessageMetaData[] _messages = null;
private String _projectName = null; // the name of the project that this test case tests
private String[] _resourceNames = null; // the resources listed in the MessageMetaData of this test case.
private String _inputFileName = null;
private String _name = null; // the name of the test case
private boolean _visible = true; // Is this test case visible on the Test Collector menu
public ValidatorTestcase(String pluginName, String project, ValidatorMetaData vmd, String inputFileName, boolean visible) {
_pluginId = pluginName;
_projectName = project;
_vmd = vmd;
_inputFileName = inputFileName;
_visible = visible;
}
public boolean isVisible() {
return _visible;
}
public String getDeclaringPluginId() {
return _pluginId;
}
public String getProjectName() {
return _projectName;
}
public IProject getProject() {
return TestcaseUtility.findProject(this);
}
public String getInputFileName() {
return _inputFileName;
}
/**
* Return the number of messages
*/
public int getNumMessages() {
return getMessages(ValidationTypeEnum.RUN_VALIDATION).size();
}
/**
* Return the list of messages that should be reported for the given build
* type. (e.g. if the validator does not support incremental validation,
* then instead of returning the list of expected messages, return an empty
* list.)
*/
public List getMessages(int buildType) {
// The messages need to be stored in a list instead of an array because
// the list is sorted before searching & displaying.
switch(buildType) {
case(ValidationTypeEnum.AUTO_VALIDATION):
case(ValidationTypeEnum.INCREMENTAL_VALIDATION): {
if(!getValidatorMetaData().isIncremental()) {
return Collections.EMPTY_LIST;
}
// Otherwise, return the default copy below.
break;
}
case(ValidationTypeEnum.FULL_VALIDATION): {
if(!getValidatorMetaData().isFullBuild()) {
return Collections.EMPTY_LIST;
}
// Otherwise, return the default copy below.
break;
}
case(ValidationTypeEnum.RUN_VALIDATION):
default: {
// Return the default copy below.
}
}
List copy = new ArrayList();
for(int i=0; i<_messages.length; i++) {
copy.add(_messages[i]);
}
return copy;
}
// Return the resources in this project for which there is a message in this test case.
// No resource instance will be in the resource more than once.
public IResource[] getResources(IProject project) {
Set temp = new HashSet(); // use a set in case there is more than one message registered against a resource (don't want duplicates in the list).
String[] resourceNames = getResourceNames();
for(int i=0; i<resourceNames.length; i++) {
String resourceName = resourceNames[i];
IResource resource = project.findMember(resourceName);
if(resource != null) {
// resource exists
temp.add(resource);
}
}
IResource[] result = new IResource[temp.size()];
temp.toArray(result);
return result;
}
public String[] getResourceNames() {
if(_resourceNames == null) {
_resourceNames = new String[_messages.length];
for(int i=0; i<_messages.length; i++) {
_resourceNames[i] = _messages[i].getResource();
}
}
return _resourceNames;
}
/**
* When an empty TMD is used to test an operation, and the operation needs the IResource[]
* affected by the TMD to know whether or not the operation passes (i.e., one of the ValidatorSubsetOperation
* constructors takes an IResource[], and the IResource[] must not be empty or null), then
* this method is used to set the "resources" affected by the test case.
*/
public void setResourceNames(String[] resourceNames) {
_resourceNames = resourceNames;
}
public void setMessages(MessageMetaData[] messages) {
// If messages are null, that means that the test case expects no validation errors.
_messages = ((messages == null) ? new MessageMetaData[0] : messages);
}
public ValidatorMetaData getValidatorMetaData() {
return _vmd;
}
public String getValidatorClass() {
return getValidatorMetaData().getValidatorUniqueName();
}
public String getName() {
if(_name == null) {
_name = _vmd.getValidatorDisplayName() + "::" + getProjectName(); //$NON-NLS-1$
}
return _name;
}
public void run(IBuffer buffer, IProject project) {
String status = ">>>>>RUN VALIDATION TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
buffer.addExecutionStatus(getName(), ValidationTypeEnum.RUN_VALIDATION_NAME, validate(buffer, project, ValidationTypeEnum.RUN_VALIDATION, ValidationTypeEnum.RUN_VALIDATION_NAME));
status = ">>>>>END RUN VALIDATION TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
status = ">>>>>FULL BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
buffer.addExecutionStatus(getName(), ValidationTypeEnum.FULL_VALIDATION_NAME, validate(buffer, project, ValidationTypeEnum.FULL_VALIDATION, ValidationTypeEnum.FULL_VALIDATION_NAME));
status = ">>>>>END FULL BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
status = ">>>>>INCREMENTAL BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
buffer.addExecutionStatus(getName(), ValidationTypeEnum.INCREMENTAL_VALIDATION_NAME, validate(buffer, project, ValidationTypeEnum.INCREMENTAL_VALIDATION, ValidationTypeEnum.INCREMENTAL_VALIDATION_NAME));
status = ">>>>>END INCREMENTAL BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
status = ">>>>>AUTO BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
buffer.addExecutionStatus(getName(), ValidationTypeEnum.AUTO_VALIDATION_NAME, validate(buffer, project, ValidationTypeEnum.AUTO_VALIDATION, ValidationTypeEnum.AUTO_VALIDATION_NAME));
status = ">>>>>END AUTO BUILD TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
if(getValidatorMetaData().isAsync()) {
status = ">>>>>ASYNCHRONOUS VALIDATION TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
buffer.addExecutionStatus(getName(), ValidationTypeEnum.ASYNC_NAME, asyncValidate(buffer, project, ValidationTypeEnum.ASYNC_NAME));
status = ">>>>>END ASYNCHRONOUS VALIDATION TEST PASS [" + project.getName() + "]>>>>>"; //$NON-NLS-1$ //$NON-NLS-2$
buffer.getProgressMonitor().subTask(status);
buffer.write(status);
}
else {
// By default, "pass" the asynchrous tests of any validator that cannot run asynchronous tests.
buffer.addExecutionStatus(getName(), ValidationTypeEnum.ASYNC_NAME, true);
}
}
private boolean validate(IBuffer buffer, IProject project, int validationTypeEnum, String taskName) {
long start = System.currentTimeMillis();
boolean passed = true;
try {
passed = BVTRunner.singleton().test(buffer, project, this, validationTypeEnum);
}
catch(BVTValidationException exc) {
Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
if(logger.isLoggingLevel(Level.SEVERE)) {
logger.write(Level.SEVERE, exc);
if(exc.getTargetException() != null) {
logger.write(Level.SEVERE, exc.getTargetException());
}
}
}
finally {
long end = System.currentTimeMillis();
buffer.addElapsedTime(taskName, (end - start));
buffer.write("Total time for validator " + getValidatorMetaData().getValidatorDisplayName() + " of project " + project.getName() + " in " + taskName + " mode was " + (end - start) + " milliseconds."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
}
return passed;
}
private boolean asyncValidate(IBuffer buffer, IProject project, String subTaskName) {
boolean passed = true;
long start = System.currentTimeMillis();
long end = 0;
try {
GlobalConfiguration gconf = ConfigurationManager.getManager().getGlobalConfiguration();
//boolean disableValidation = gconf.numberOfEnabledValidators()==0;
//boolean autoValidate = gconf.isAutoValidate();
//boolean buildValidate = gconf.isBuildValidate();
try {
//gconf.setAutoValidate(false);
// Turn off auto-validate so that the project isn't validated automatically.
//gconf.setAutoValidate(false);
//gconf.setBuildValidate(false);
gconf.passivate();
// Two tests:
// 1. Run validation on copies of the original project: "projectName.fork" and "projectName.noFork"
// Compare the markers of the copies to the FVT TestcaseMetaData, and the validator passes if the
// results of each copy matches the TestcaseMetaData.
// 2. Run validation on copies, but this time introduce changes during the validation.
// Extract the names of resources from the testcase metadata, find those resources, and
// add/delete/rename/move/close/change them.
boolean pass1 = validateAndCompare(buffer, project, subTaskName);
boolean pass2 = validateChangeAndCompare(buffer, project, IFileDelta.CHANGED, subTaskName);
boolean pass3 = validateChangeAndCompare(buffer, project, IFileDelta.DELETED, subTaskName);
passed = (pass1 && pass2 && pass3);
}
catch(CoreException exc) {
// Couldn't create copy.Just continue with the next test.
Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
if(logger.isLoggingLevel(Level.SEVERE)) {
logger.write(Level.SEVERE, exc);
}
}
catch(BVTValidationException exc) {
Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
if(logger.isLoggingLevel(Level.SEVERE)) {
logger.write(Level.SEVERE, exc);
if(exc.getTargetException() != null) {
logger.write(Level.SEVERE, exc.getTargetException());
}
}
}
catch(Throwable exc) {
Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
if(logger.isLoggingLevel(Level.SEVERE)) {
logger.write(Level.SEVERE, exc);
}
}
finally {
//gconf.setAutoValidate(autoValidate);
//gconf.setBuildValidate(buildValidate);
gconf.passivate();
}
}
catch(InvocationTargetException exc) {
Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
if(logger.isLoggingLevel(Level.SEVERE)) {
logger.write(Level.SEVERE, exc);
if(exc.getTargetException() != null) {
logger.write(Level.SEVERE, exc.getTargetException());
}
}
}
finally {
end = System.currentTimeMillis();
buffer.addElapsedTime(ValidationTypeEnum.ASYNC_NAME, (end - start));
buffer.write("Total time for validator " + getValidatorMetaData().getValidatorDisplayName() + " of project " + project.getName() + " in asynchronous mode was " + (end - start) + " milliseconds."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
return passed;
}
/**
* Run validation, using several operations (both forked and not forked), on the IProject.
* Return true if the result, after the last operation is complete, is the expected result.
*/
private boolean validateAndCompare(IBuffer buffer, IProject project, String subTaskName) throws CoreException, BVTValidationException {
// Now compare the IProject's result to the expected TestcaseMetaData result.
// Validate
ValidatorSubsetOperation noForkOp = new ValidatorSubsetOperation(project, true, false);
noForkOp.setValidators(getValidatorMetaData().getValidatorNames());
noForkOp.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp = new ValidatorSubsetOperation(project, true, true);
forkOp.setValidators(getValidatorMetaData().getValidatorNames());
forkOp.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation noForkOp2 = new ValidatorSubsetOperation(project, true, false);
noForkOp2.setValidators(getValidatorMetaData().getValidatorNames());
noForkOp2.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp2 = new ValidatorSubsetOperation(project, true, true);
forkOp2.setValidators(getValidatorMetaData().getValidatorNames());
forkOp2.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp3 = new ValidatorSubsetOperation(project, true, true);
forkOp3.setValidators(getValidatorMetaData().getValidatorNames());
forkOp3.run(buffer.getProgressMonitor());
// Wait until all of the threads have complete.
buffer.getProgressMonitor().subTask("Waiting for all forked threads to finish..."); //$NON-NLS-1$
while(!VThreadManager.getManager().isDone() && !buffer.getProgressMonitor().isCanceled()) {}
buffer.getProgressMonitor().subTask("All threads are complete. Beginning the comparison."); //$NON-NLS-1$
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
// Compare
IMarker[] markers = TaskListUtility.getValidationTasks(project, getValidatorMetaData().getValidatorNames());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
return BVTRunner.singleton().verify(buffer, getName(), subTaskName, project, getMessages(ValidationTypeEnum.RUN_VALIDATION), markers);
}
private boolean validateChangeAndCompare(IBuffer buffer, IProject project, int ifileDeltaType, String subTaskName) throws BVTValidationException, CoreException {
boolean passed = true;
ValidatorMetaData[] vmds = new ValidatorMetaData[]{getValidatorMetaData()};
ValidatorSubsetOperation noForkOpOrig = new ValidatorSubsetOperation(project, true, false);
noForkOpOrig.setValidators(getValidatorMetaData().getValidatorNames());
noForkOpOrig.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation noForkOpChanged = new ValidatorSubsetOperation(project, vmds, getResources(project), ifileDeltaType, false, false); // false = do not force if there's no deltas to validate
noForkOpChanged.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOpOrig = new ValidatorSubsetOperation(project, true, true);
forkOpOrig.setValidators(getValidatorMetaData().getValidatorNames());
forkOpOrig.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOpChanged = new ValidatorSubsetOperation(project, vmds, getResources(project), ifileDeltaType, false, true); // false = do not force if there's no deltas to validate
forkOpChanged.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation noForkOp2Orig = new ValidatorSubsetOperation(project, true, false);
noForkOp2Orig.setValidators(getValidatorMetaData().getValidatorNames());
noForkOp2Orig.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation noForkOp2Changed = new ValidatorSubsetOperation(project, vmds, getResources(project), ifileDeltaType, false, false); // false = do not force if there's no deltas to validate
noForkOp2Changed.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp2Orig = new ValidatorSubsetOperation(project, true, true);
forkOp2Orig.setValidators(getValidatorMetaData().getValidatorNames());
forkOp2Orig.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp2Changed = new ValidatorSubsetOperation(project, vmds, getResources(project), ifileDeltaType, false, true); // false = do not force if there's no deltas to validate
forkOp2Changed.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp3Orig = new ValidatorSubsetOperation(project, true, true);
forkOp3Orig.setValidators(getValidatorMetaData().getValidatorNames());
forkOp3Orig.run(buffer.getProgressMonitor());
if(buffer.getProgressMonitor().isCanceled()) {
return false;
}
ValidatorSubsetOperation forkOp3Changed = new ValidatorSubsetOperation(project, vmds, getResources(project), ifileDeltaType, false, true); // false = do not force if there's no deltas to validate
forkOp3Changed.run(buffer.getProgressMonitor());
// Wait until all of the threads have complete.
buffer.getProgressMonitor().subTask("Waiting for all forked threads to finish..."); //$NON-NLS-1$
while(!VThreadManager.getManager().isDone() && !buffer.getProgressMonitor().isCanceled()) {}
if(buffer.getProgressMonitor().isCanceled()) {
buffer.getProgressMonitor().subTask("Comparison cancelled. Performing cleanup."); //$NON-NLS-1$
return false;
}
buffer.getProgressMonitor().subTask("All threads are complete. Beginning the comparison."); //$NON-NLS-1$
// Compare
IMarker[] markers = TaskListUtility.getValidationTasks(project, getValidatorMetaData().getValidatorNames());
// Now compare the IProject's result to the expected TestcaseMetaData result.
// Don't write _passed = _passed && get...
// When the _passed == false, then java didn't bother running the test.
passed = BVTRunner.singleton().verify(buffer, getName(), subTaskName, project, getMessages(ValidationTypeEnum.RUN_VALIDATION), markers);
ResourcesPlugin.getWorkspace().deleteMarkers(markers);
return passed;
}
}