package org.eclipse.jst.validation.test.internal.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
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.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jem.util.logger.LogEntry;
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.registry.BVTValidationRegistryReader;
import org.eclipse.jst.validation.test.internal.registry.ITestcaseMetaData;
import org.eclipse.jst.validation.test.internal.registry.MessageMetaData;
import org.eclipse.jst.validation.test.internal.registry.MessageUtility;
import org.eclipse.jst.validation.test.internal.registry.OperationTestcase;
import org.eclipse.jst.validation.test.internal.registry.TestSetupImport;
import org.eclipse.jst.validation.test.internal.registry.TestcaseUtility;
import org.eclipse.jst.validation.test.internal.registry.ValidatorTestcase;
import org.eclipse.jst.validation.test.setup.IBuffer;
import org.eclipse.jst.validation.test.setup.ITestStatus;
import org.eclipse.wst.validation.internal.InternalValidatorManager;
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.operations.OneValidatorOperation;
import org.eclipse.wst.validation.internal.operations.ValidationOperation;
import org.eclipse.wst.validation.internal.operations.ValidatorManager;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;

/**
 */
public final class BVTRunner {
	private static BVTRunner _inst = null;
	private List _extra = null; // The extra markers reported (stored in a list to make reading easier).
	private List _missing = null; // The missing MMD that were supposed to be reported (stored in a list to make reading easier).

	public static BVTRunner singleton() {
		if(_inst == null) {
			_inst = new BVTRunner();
		}
		return _inst;
	}
	
	private BVTRunner() {
		super();
		_extra = new ArrayList();
		_missing = new ArrayList();
	}
	
	private boolean isVerbose() {
		Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
		if(logger.isLoggingLevel(Level.FINEST)) {
			return true;
		}
		return false;
	}

	private char getSeverityChar(Integer severity) {
		if(severity == null) {
			return '?';
		}
		
		switch(severity.intValue()) {
			case(IMarker.SEVERITY_ERROR): {
				return 'E';
			}
			
			case(IMarker.SEVERITY_WARNING): {
				return 'W';
			}
			
			case(IMarker.SEVERITY_INFO): {
				return 'I';
			}
			
			default: {
				return '?';
			}
		}
	}
	
	private String[] getNames(IProject[] projects) {
		if(projects == null) {
			return new String[0];
		}
		String[] names = new String[projects.length];
		for(int i=0; i<projects.length; i++) {
			IProject project = projects[i];
			names[i] = project.getName();
		}
		return names;
	}

	private void debug(IBuffer buffer, IMarker[] messages) {
		if(messages == null) {
			buffer.write("Nothing to debug because nothing was reported"); //$NON-NLS-1$
		}
		
		for(int i=0; i<messages.length; i++) {
			IMarker marker = messages[i];
			buffer.write(MessageUtility.toString(marker));
		}
	}

	protected IProgressMonitor getDebugMonitor(IProgressMonitor monitor) {
		if(isVerbose()) {
			return monitor;
		}
		else {
			return new NullProgressMonitor(); // if verbose is true, show progress messages for the creation & validation of the project. Otherwise show only the BVT status.
		}
	}
	
	/**
	 * When invoking the test from the UI, the input has already been imported, so just test it.
	 * The name of the test is derived from the name of the project.
	 * Return the number of tests that passed.
	 */	
	public int test(IBuffer buffer, IProject[] projects) throws BVTValidationException {	
		String[] testNames = getNames(projects);
		BVTValidationRegistryReader reader = BVTValidationRegistryReader.getReader();
		
		buffer.getProgressMonitor().beginTask("Running BVT tests", projects.length); //$NON-NLS-1$
		int totalTests = 0;
		int totalPassed = 0;
		for(int i=0; i<projects.length; i++) {
			buffer.getProgressMonitor().subTask("Testing project " + (i+1) + " of " + projects.length); //$NON-NLS-1$ //$NON-NLS-2$
			IProject project = projects[i];
			ValidatorTestcase[] tests = reader.getValidatorTests(buffer.getProgressMonitor(), testNames[i]);
			if((tests == null) || (tests.length == 0)) {
				buffer.getProgressMonitor().subTask("There are no tests to run."); //$NON-NLS-1$
				continue;
			}
			
			int numTestsPassed = 0;
			for(int j=0; j<tests.length; j++) {
				ValidatorTestcase tmd = tests[j];
				if(test(buffer, project, tmd, ValidationTypeEnum.RUN_VALIDATION)) {
					numTestsPassed++;
					buffer.getProgressMonitor().subTask("Test " + (j+1) + " of " + tests.length + " passed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
				else {
					buffer.getProgressMonitor().subTask("Test " + (j+1) + " of " + tests.length + " failed."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
				buffer.getProgressMonitor().worked(1);
			}
			
			totalTests += tests.length;
			totalPassed += numTestsPassed;
			
			buffer.write(numTestsPassed + " of " + tests.length + " tests passed."); //$NON-NLS-1$ //$NON-NLS-2$
		}
		buffer.write("\n>>>>>>>>>>TEST RESULTS>>>>>>>>>>"); //$NON-NLS-1$
		buffer.write(totalPassed + " of " + totalTests + " tests passed."); //$NON-NLS-1$ //$NON-NLS-2$
		buffer.getProgressMonitor().done();
		
		return totalPassed;
	}
	
	/**
	 * Construct a ValidationOperation on the IProject, invoke the operation, and verify that the
	 * resulting IMarkers match the expected messages in the tmd.
	 */	
	public boolean test(IBuffer buffer, IProject project, ValidatorTestcase tmd, int validationEnumType) throws BVTValidationException {
		switch(validationEnumType) {
			case(ValidationTypeEnum.RUN_VALIDATION): {
				return test(buffer, tmd.getName(), ValidationTypeEnum.RUN_VALIDATION_NAME, tmd.getMessages(validationEnumType), new OneValidatorOperation(project, tmd.getValidatorClass(), true, false), InternalValidatorManager.getManager().getValidatorNames(new ValidatorMetaData[]{tmd.getValidatorMetaData()})); // true=force, false=no for
			}
			
			case(ValidationTypeEnum.FULL_VALIDATION): {
				return build(buffer, project, tmd, validationEnumType, ValidationTypeEnum.FULL_VALIDATION_NAME);
			}
			
			case(ValidationTypeEnum.INCREMENTAL_VALIDATION): {
				return build(buffer, project, tmd, validationEnumType, ValidationTypeEnum.INCREMENTAL_VALIDATION_NAME);
			}
			
			case(ValidationTypeEnum.AUTO_VALIDATION): {
				return build(buffer, project, tmd, validationEnumType, ValidationTypeEnum.AUTO_VALIDATION_NAME);
			}
			
			default: {
				buffer.addExecutionStatus(tmd.getName(), null, ITestStatus.FAIL, buffer, "Unrecognized validation option:" + validationEnumType); //$NON-NLS-1$
				return false;
			}
		}
	}
	
	private boolean build(IBuffer buffer, final IProject project, final ValidatorTestcase tmd, final int validationEnumType, String subTaskName) throws BVTValidationException {
		try {
			IProgressMonitor nullMonitor = new NullProgressMonitor();
			ResourcesPlugin.getWorkspace().run(
			new IWorkspaceRunnable(){
				public void run(IProgressMonitor monitor) {
					try {
						IResource[] resources = tmd.getResources(project);
						for(int i=0; i<resources.length; i++) {
							IResource res = resources[i];
							res.touch(monitor);
						}
					}
					catch(CoreException exc) {
						Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
						if(logger.isLoggingLevel(Level.SEVERE)) {
							logger.write(exc);
						}
					}
				}
			}, nullMonitor);
		}
		catch(CoreException exc) {
			Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
			if(logger.isLoggingLevel(Level.SEVERE)) {
				logger.write(exc);
			}
			buffer.addExecutionStatus(tmd.getName(), subTaskName, ITestStatus.FAIL, buffer, "CoreException caught; stack trace in LoggingUtil.log"); //$NON-NLS-1$
			return false;
		}

		try {
			// Do not build using only the validation builder because some validators
			// (i.e., the EJB Validator) depend on the output of other builders 
			// (i.e., the Java Builder).
			project.build(validationEnumType, new NullProgressMonitor());
		}
		catch(CoreException exc) {
			Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
			if(logger.isLoggingLevel(Level.SEVERE)) {
				logger.write(exc);
			}
			buffer.write("CoreException caught; stack trace in LoggingUtil.log"); //$NON-NLS-1$
			return false;
		}

		IMarker[] messages = TaskListUtility.getValidationTasks(project, InternalValidatorManager.getManager().getValidatorNames(new ValidatorMetaData[]{tmd.getValidatorMetaData()}));
		return verify(buffer, tmd.getName(), subTaskName, project, tmd.getMessages(validationEnumType), messages);
	}
	
	/**
	 * Run the given ValidationOperation and ensure that the results match the results of the given test case.
	 * Return true if the results match and false if they don't.
	 * 
	 * This method is public because it's needed for the TestOpConstr operation.
	 */
	public boolean test(IBuffer buffer, String testName, String subTaskName, List expectedMessages, ValidationOperation op, String[] validatorNames) throws BVTValidationException {
		IProgressMonitor debugMonitor = getDebugMonitor(buffer.getProgressMonitor());
		boolean passed = true;
		try {
			
			if(op == null) {
				Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
				if(logger.isLoggingLevel(Level.WARNING)) {
					logger.write(Level.WARNING, "Cannot run tests because the Operation is null."); //$NON-NLS-1$
				}
				passed = false;
			}
			else {
				try {
						ValidatorManager.getManager().setNoMessageLimit(op.getProject());
					
						ResourcesPlugin.getWorkspace().run(op, debugMonitor); 
						
						if(op.isFork()) {
							// Wait until all forked threads are complete
							while(!VThreadManager.getManager().isDone()){};
						}
			
						// Load the enabled validators from the test, not the operation,
						// because the test has the messages for a single validator, and
						// if the messages from all enabled validators are retrieved,
						// then "extra" messages, reported by validators whose messages
						// aren't expected by the test, fail the test case. 
						IMarker[] messages = TaskListUtility.getValidationTasks(op.getProject(), validatorNames);
						passed = verify(buffer, testName, subTaskName, op.getProject(), expectedMessages, messages);
				}
				catch(Throwable exc) {
					Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
					if(logger.isLoggingLevel(Level.SEVERE)) {
						logger.write(Level.SEVERE, exc);
					}
					passed = false;
				}
			}
		}
		catch(Throwable exc) {
			Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
			if(logger.isLoggingLevel(Level.SEVERE)) {
				logger.write(Level.SEVERE, exc);
			}
			passed = false;
		}
		return passed;
	}

	public boolean setupTests(IBuffer buffer, boolean verbose) {
		ValidatorTestcase[] vts = BVTValidationRegistryReader.getReader().getValidatorTests(buffer.getProgressMonitor(), (String)null);
		OperationTestcase[] ots = BVTValidationRegistryReader.getReader().getOperationTests(buffer.getProgressMonitor(), (String)null);
		boolean successful = true;
		for(int i=0; i<vts.length; i++) {
			ValidatorTestcase vtest = vts[i];
			successful = setupTests(buffer, vtest, false) && successful;
		}
		
		for(int j=0; j<ots.length; j++) {
			OperationTestcase otest = ots[j];
			successful = setupTests(buffer, otest, false) && successful;
		}
		
		return successful;
	}
	
	/**
	 * Return true if all of the test cases' input were found and imported.
	 */
	public boolean setupTests(IBuffer buffer, ITestcaseMetaData tmd, boolean verbose) {
		int executionMap = 0x0;
		boolean imported = true;
		Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
		try {
			BVTValidationRegistryReader reader = BVTValidationRegistryReader.getReader();
	
			// Each import operation deletes any project before it re-imports it.
			String dir = TestcaseUtility.getInputDir(tmd);
			TestSetupImport[] setup = reader.getTestSetup(buffer, dir, tmd, verbose);
			if((setup == null) || (setup.length == 0)) {
				String message = "Cannot import input that does not exist. Check that directory " + dir + " exists."; //$NON-NLS-1$ //$NON-NLS-2$ 
				buffer.write(message);
				executionMap |= 0x1;
				imported = false;
				if(logger.isLoggingLevel(Level.SEVERE)) {
					LogEntry entry = ValidationPlugin.getLogEntry();
					entry.setExecutionMap(executionMap);
					entry.setText(message);
					logger.write(Level.SEVERE, entry);
				}
			}
			else {
				buffer.getProgressMonitor().beginTask("Importing files; please wait...", setup.length); //$NON-NLS-1$
				for(int i=0; i<setup.length; i++) {
					buffer.getProgressMonitor().subTask("Importing file " + (i+1) + " of " + setup.length); //$NON-NLS-1$ //$NON-NLS-2$
					if(!setup[i].importFile(buffer.getProgressMonitor(), dir)) {
						// One of the input files couldn't be imported.
						executionMap |= 0x2;
						imported = false;
						if(logger.isLoggingLevel(Level.SEVERE)) {
							LogEntry entry = ValidationPlugin.getLogEntry();
							entry.setExecutionMap(executionMap);
							entry.setText("Import failed for dir " + dir); //$NON-NLS-1$
							logger.write(Level.SEVERE, entry);
						}
						continue;
					}
					buffer.getProgressMonitor().worked(1);
				}
				buffer.getProgressMonitor().done();
			}
		}
		finally {
			if(!imported) {
				String tmdName = (tmd == null) ? "?" : tmd.getName(); //$NON-NLS-1$
				LogEntry entry = ValidationPlugin.getLogEntry();
				entry.setExecutionMap(executionMap);
				entry.setText("Test setup for " + tmdName + " was unsuccessful."); //$NON-NLS-1$ //$NON-NLS-2$
				logger.write(Level.SEVERE, entry);
			}
		}
		return imported;
	}

	/**
	 * Return true if the expected messages (tmdMmdList) matches the reported messages (ml2).
	 */
	public boolean compare(IBuffer buffer, String testName, String subTaskName, List tmdMmdList, IMarker[] ml2) {
		// Convert one of the arrays into a list so that it can be sorted.
		int numMatched = 0;
		List mmdList = new ArrayList(tmdMmdList); // create a copy of the tmd's expected output so that the tmd's output remains intact
		int numExpected = mmdList.size();
		int numReported = ml2.length;
		boolean passed = true;
	

		try {		
			Collections.sort(mmdList, MessageUtility.getMessageComparator(buffer, isVerbose()));
	
			try {
				for(int i=0; i<ml2.length; i++) {
					IMarker marker = ml2[i];
					MessageMetaData matching = getMatchingMetaData(buffer, mmdList, marker);
					if(matching == null) {
						_extra.add(marker);
						continue;
					}
					else {
						// Every time a mmd is matched to a marker, remove the mmd
						// from the list so that mmds without a marker can be flagged.
						mmdList.remove(matching);
						numMatched++;
					}
				}
	
				if(mmdList.size() != 0) {
					_missing.addAll(mmdList);
				}
			}
			catch(Throwable exc) {
				Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
				if(logger.isLoggingLevel(Level.SEVERE)) {
					logger.write(Level.SEVERE, exc);
				}
				passed = false;
			}
			finally {
				passed = passed && ((_missing.size() == 0) && (_extra.size() == 0));
				
				// Report the missing markers after the MMD list is sorted
				Collections.sort(_missing, MessageUtility.getMessageComparator(buffer, isVerbose()));
				Iterator iterator = _missing.iterator();
				while(iterator.hasNext()) {
					MessageMetaData mmd = (MessageMetaData)iterator.next();
					buffer.addExecutionStatus(testName, subTaskName, ITestStatus.FAIL, buffer, "ERROR[missing message]: " + MessageUtility.toString(mmd)); //$NON-NLS-1$
				}
				
				// Report the extra markers after they're sorted.
				Collections.sort(_extra, MessageUtility.getMessageComparator(buffer, isVerbose()));
				iterator = _extra.iterator();
				while(iterator.hasNext()) {
					IMarker marker = (IMarker)iterator.next();
					buffer.addExecutionStatus(testName, subTaskName, ITestStatus.FAIL, buffer, "ERROR[extra message]: " + MessageUtility.toString(marker) + ", Text is: \"" + MessageUtility.getMessage(marker) + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				}
		
				if(numExpected != numReported) {
					buffer.write("Wrong number of messages reported. Expected " + numExpected + " and got " + numReported); //$NON-NLS-1$ //$NON-NLS-2$
				}
	
				buffer.write("Number of extra messages: " + _extra.size()); //$NON-NLS-1$
				buffer.write("Number of missing messages: " + _missing.size()); //$NON-NLS-1$
				buffer.write("Number of matched messages: " + numMatched); //$NON-NLS-1$
			}
		}
		finally {
			mmdList.clear();
			_extra.clear(); // Clear the list of extra markers (stored in a list to make reading easier).
			_missing.clear(); // Clear the list of missing markers (stored in a list to make reading easier).
		}
		return passed;
	}
	
	public boolean verify(IBuffer buffer, String testName, String subTaskName, IProject project, List mmdListOrig, IMarker[] messages) {
		buffer.write("Test case: " + testName); //$NON-NLS-1$

		int numMatched = 0;
		int numExpected = 0;
		int numReported = 0;
		boolean passed = true;
		List mmdList = new ArrayList(mmdListOrig); // Need to modify the list, but do not want to modify the original, so create a copy.
		try {
			// First, check that the number of messages match.
			if(messages == null) {
				passed = false;
				Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
				if(logger.isLoggingLevel(Level.INFO)) {
					logger.write(Level.INFO, "No messages were reported."); //$NON-NLS-1$
				}
				return passed;
			}
			
			numExpected = mmdList.size();
			numReported = messages.length;
			
			Collections.sort(mmdList, MessageUtility.getMessageComparator(buffer, isVerbose()));

			for(int i=0; i<messages.length; i++) {
				IMarker marker = messages[i];
				MessageMetaData mmd = getMatchingMetaData(buffer, mmdList, marker);
	
				if(mmd == null) {
					_extra.add(marker);
					continue;
				}
				else {
					// Every time a mmd is matched to a marker, remove the mmd
					// from the list so that mmds without a marker can be flagged.
					mmdList.remove(mmd);
					if(isVerbose()) {
						buffer.write("matched " + MessageUtility.toString(marker) + " to " + MessageUtility.toString(mmd)); //$NON-NLS-1$ //$NON-NLS-2$
					}
					numMatched++;
				}
				
				// Check severity
				try {
					// Fail a test case based on severity mismatch because EJB deploy
					// relies on the severity to determine whether or not deployment
					// can continue?
					verifySeverity(buffer, testName, subTaskName, mmd, marker);
				}
				catch(CoreException e) {
					passed = false;
					Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
					if(logger.isLoggingLevel(Level.SEVERE)) {
						logger.write(Level.SEVERE, e);
					}
					buffer.write("ERROR[Testcase::" + testName + "]. CoreException caught while verifying severity"); //$NON-NLS-1$ //$NON-NLS-2$
					continue;
				}
				
				// Check resource
				try {
					// Don't fail a test case based on resource, because the "location" column will
					// uniquely identify the location of the message, anyway. Should still let the 
					// user know, though.
					verifyResource(buffer, testName, subTaskName, mmd, marker);
				}
				catch(CoreException e) {
					passed = false;
					buffer.write("ERROR[Testcase::" + testName + "]. CoreException caught while verifying resource"); //$NON-NLS-1$ //$NON-NLS-2$
					Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
					if(logger.isLoggingLevel(Level.SEVERE)) {
						logger.write(Level.SEVERE, e);
					}
					continue;
				}
				
				// Check location
				try {
					// Don't fail a test case based on location, because the line number calculation
					// is different in UI & batch, and the test cases are based on UI test results.
					// Should still alert the user, though.
					verifyLocation(buffer, testName, subTaskName,  mmd, marker);
				}
				catch(CoreException e) {
					passed = false;
					Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
					if(logger.isLoggingLevel(Level.SEVERE)) {
						logger.write(Level.SEVERE, e);
					}
					buffer.write("ERROR[Testcase::" + testName + "]. CoreException caught while verifying line number"); //$NON-NLS-1$ //$NON-NLS-2$
					continue;
				}
			}
			
			if(mmdList.size() != 0) {
				_missing.addAll(mmdList);
			}
		}
		catch(Throwable exc) {
			Logger logger = BVTValidationPlugin.getPlugin().getMsgLogger();
			if(logger.isLoggingLevel(Level.SEVERE)) {
				logger.write(Level.SEVERE, exc);
			}
			passed = false;
		}
		finally {
			if(!((_missing.size() == 0) && (_extra.size() == 0))) {
				passed = false;
			}
			
			if(passed) {
				buffer.write("PASS[Testcase::" + testName + "]"); //$NON-NLS-1$ //$NON-NLS-2$
				buffer.addExecutionStatus(testName, subTaskName, true); // If fail, will be reported in the extra & missing below.
			}
			else {
				buffer.write("FAIL[Testcase::" + testName + "]"); //$NON-NLS-1$ //$NON-NLS-2$

				// No point in listing the mmdList because it's empty by the time the finally block is reached
				if(isVerbose()) {
					buffer.write("List of markers reported:"); //$NON-NLS-1$
					debug(buffer, messages);
				}
			}
			
			// Report the missing markers after the MMD list is sorted
			Collections.sort(_missing, MessageUtility.getMessageComparator(buffer, isVerbose()));
			Iterator iterator = _missing.iterator();
			while(iterator.hasNext()) {
				MessageMetaData mmd = (MessageMetaData)iterator.next();
				buffer.addExecutionStatus(testName, subTaskName, ITestStatus.FAIL, buffer, "ERROR[missing message]: " + MessageUtility.toString(mmd)); //$NON-NLS-1$
			}
			
			// Report the extra markers after they're sorted.
			Collections.sort(_extra, MessageUtility.getMessageComparator(buffer, isVerbose()));
			iterator = _extra.iterator();
			while(iterator.hasNext()) {
				IMarker marker = (IMarker)iterator.next();
				buffer.addExecutionStatus(testName, subTaskName, ITestStatus.FAIL, buffer, "ERROR[extra message]: " + MessageUtility.toString(marker) + ", Text is: \"" + MessageUtility.getMessage(marker) + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
	
			if(numExpected != numReported) {
				buffer.write("Wrong number of messages reported. Expected " + numExpected + " and got " + numReported); //$NON-NLS-1$ //$NON-NLS-2$
			}

			buffer.write("Number of extra messages: " + _extra.size()); //$NON-NLS-1$
			buffer.write("Number of missing messages: " + _missing.size()); //$NON-NLS-1$
			buffer.write("Number of matched messages: " + numMatched); //$NON-NLS-1$
			buffer.write("End of test case: " + testName); //$NON-NLS-1$
			_extra.clear(); // Clear the list of extra markers (stored in a list to make reading easier).
			_missing.clear(); // Clear the list of missing markers (stored in a list to make reading easier).
		}
		return passed;
	}
	
	private int verifySeverity(IBuffer buffer, String testName, String subTaskName, MessageMetaData mmd, IMarker marker) throws CoreException {
		// If prefixSeverity is null, marker has no prefix, therefore it has no severity
		Integer prefixSeverity = MessageUtility.getSeverity(marker);
		if(prefixSeverity != null) {
			Integer severity = (Integer)marker.getAttribute(IMarker.SEVERITY); // IMarker.SEVERITY_ERROR, IMarker.SEVERITY_WARNING, IMarker.SEVERITY_INFO
			boolean severityEqual = true;
			if((severity == null) && (prefixSeverity == null)) {
				severityEqual = true;
			}
			else if(severity == null) {
				severityEqual = false;
			}
			else if(prefixSeverity == null) {
				severityEqual = false;
			}
			else {
				severityEqual = severity.equals(prefixSeverity);
			}
			
			if(!severityEqual) {
				buffer.addExecutionStatus(testName, subTaskName, ITestStatus.WARN, buffer, "WARNING[mismatching severity]: expected " + getSeverityChar(prefixSeverity) + ", got " + getSeverityChar(severity) + " on marker " + MessageUtility.toString(marker)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				return ITestStatus.WARN;
			}
		}
			
		return ITestStatus.PASS;
	}
	
	private int verifyResource(IBuffer buffer, String testName, String subTaskName, MessageMetaData mmd, IMarker marker) throws CoreException {
		String resource = MessageUtility.getResource(marker);
		if(!resource.equals(mmd.getResource())) {
			buffer.addExecutionStatus(testName, subTaskName, ITestStatus.WARN, buffer, "INFO[wrong resource]: expected " + mmd.getResource() + ", got " + resource + " on marker " + MessageUtility.toString(marker)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			return ITestStatus.WARN;
		}
		return ITestStatus.PASS;
	}
	
	private int verifyLocation(IBuffer buffer, String testName, String subTaskName, MessageMetaData mmd, IMarker marker) throws CoreException {
		// Either compare two line numbers or two text locations, but not a line number to a text location.
		if(mmd.isSetLineNumber()) {
			Integer lineNumber = MessageUtility.getLineNumber(marker);
			if(lineNumber == null) {
				// Marker has a text location, not a line number.
				return ITestStatus.PASS;
			}
			
			if(lineNumber.intValue() != mmd.getLineNumber()) {
				buffer.addExecutionStatus(testName, subTaskName, ITestStatus.WARN, buffer, "INFO[wrong location]: expected " + mmd.getLineNumber() + ", got " + lineNumber + " on marker " + MessageUtility.toString(marker)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				return ITestStatus.WARN;
			}
		}
		else if(mmd.isSetLocation()) {
			String location = MessageUtility.getLocation(marker);
			if(location == null) {
				// marker has a line number, not a text location
				return ITestStatus.PASS;
			}
			
			if(!(mmd.getLocation().equals(location))) {
				buffer.addExecutionStatus(testName, subTaskName, ITestStatus.WARN, buffer, "INFO[wrong location]: expected " + mmd.getLocation() + ", got " + location + " on marker " + MessageUtility.toString(marker)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				return ITestStatus.WARN;
			}
		}
		
		return ITestStatus.PASS;
	}
	
	
	private MessageMetaData getMatchingMetaData(IBuffer buffer, List mmdList, IMarker marker) {
		int result = Collections.binarySearch(mmdList, marker, MessageUtility.getMessageComparator(buffer, isVerbose()));
		if(result < 0) {
			return null;
		}
		return (MessageMetaData)mmdList.get(result);
	}
}