/*******************************************************************************
 * Copyright (c) 2008, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Martin Karpisek <martin.karpisek@gmail.com> - Bug 525701
 *******************************************************************************/
package org.eclipse.pde.api.tools.builder.tests;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.tests.builder.BuilderTests;
import org.eclipse.jdt.core.tests.junit.extension.TestCase;
import org.eclipse.pde.api.tools.builder.tests.annotations.AnnotationTest;
import org.eclipse.pde.api.tools.builder.tests.compatibility.CompatibilityTest;
import org.eclipse.pde.api.tools.builder.tests.leak.LeakTest;
import org.eclipse.pde.api.tools.builder.tests.tags.TagTest;
import org.eclipse.pde.api.tools.builder.tests.usage.Java7UsageTest;
import org.eclipse.pde.api.tools.builder.tests.usage.Java8UsageTest;
import org.eclipse.pde.api.tools.builder.tests.usage.UsageTest;
import org.eclipse.pde.api.tools.internal.ApiDescriptionXmlCreator;
import org.eclipse.pde.api.tools.internal.problems.ApiProblemFactory;
import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants;
import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes;
import org.eclipse.pde.api.tools.model.tests.TestSuiteHelper;
import org.eclipse.pde.api.tools.tests.util.FileUtils;
import org.eclipse.pde.api.tools.tests.util.ProjectUtils;
import org.eclipse.pde.internal.core.ICoreConstants;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.ui.tests.util.FreezeMonitor;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.junit.BeforeClass;
import org.osgi.service.prefs.BackingStoreException;

import junit.framework.Test;
import junit.framework.TestSuite;

/**
 * Base class for API builder tests
 *
 * @since 1.0
 */
public abstract class ApiBuilderTest extends BuilderTests {
	/**
	 * Debug flag
	 */
	protected static boolean DEBUG = false;

	public static final String TEST_SOURCE_ROOT = "test-builder"; //$NON-NLS-1$
	public static final String BASELINE = "baseline"; //$NON-NLS-1$
	public static final String JAVA_EXTENSION = ".java"; //$NON-NLS-1$
	public static final String SRC_ROOT = "src"; //$NON-NLS-1$
	public static final String BIN_ROOT = "bin"; //$NON-NLS-1$
	protected final int[] NO_PROBLEM_IDS = new int[0];

	@BeforeClass
	public static void beforeClass() {
		PDECore.getDefault().getPreferencesManager().setValue(ICoreConstants.RUN_API_ANALYSIS_AS_JOB, false);
	}

	/**
	 * Describes a line number mapped to the problem id with the given args we
	 * expect to see there
	 */
	protected class LineMapping {
		private int linenumber = 0;
		private int problemid = 0;
		private String message = null;

		public LineMapping(int linenumber, int problemid, String[] messageargs) {
			this.linenumber = linenumber;
			this.problemid = problemid;
			this.message = ApiProblemFactory.getLocalizedMessage(ApiProblemFactory.getProblemMessageId(this.problemid), messageargs);
		}

		public LineMapping(ApiProblem problem) {
			this.linenumber = problem.getLineNumber();
			this.problemid = problem.getProblemId();
			this.message = problem.getMessage();
		}

		@Override
		public boolean equals(Object obj) {
			if (obj instanceof LineMapping) {
				LineMapping lm = (LineMapping) obj;
				return lm.linenumber == this.linenumber && lm.problemid == this.problemid && (this.message == null ? lm.message == null : this.message.equals(lm.message));
			}
			return super.equals(obj);
		}

		@Override
		public int hashCode() {
			return this.linenumber | this.problemid | (this.message == null ? 0 : this.message.hashCode());
		}

		@Override
		public String toString() {
			StringBuilder buffer = new StringBuilder();
			buffer.append("Line mapping: "); //$NON-NLS-1$
			buffer.append("[line ").append(this.linenumber).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
			buffer.append("[problemid: ").append(problemid).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
			if (this.message != null) {
				buffer.append("[message: ").append(this.message).append("]"); //$NON-NLS-1$ //$NON-NLS-2$
			} else {
				buffer.append("[no message]"); //$NON-NLS-1$
			}
			return super.toString();
		}
	}

	private int[] fProblems = null;
	private String[][] fMessageArgs = null;
	private LineMapping[] fLineMappings = null;

	/**
	 * Constructor
	 *
	 * @param name
	 */
	public ApiBuilderTest(String name) {
		super(name);
	}

	/**
	 * @return the testing environment cast the the one we want
	 */
	protected ApiTestingEnvironment getEnv() {
		return (ApiTestingEnvironment) env;
	}

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		ApiTestingEnvironment.setTargetPlatform();
	}

	/**
	 * Verifies that the workspace has no problems.
	 */
	@Override
	protected void expectingNoProblems() {
		expectingNoProblemsFor(getEnv().getWorkspaceRootPath());
	}

	/**
	 * Verifies that the given element has no problems.
	 */
	@Override
	protected void expectingNoProblemsFor(IPath root) {
		expectingNoProblemsFor(new IPath[] { root });
	}

	/**
	 * Asserts that there are no compilation problems in the environment
	 *
	 * @throws CoreException
	 */
	protected void expectingNoJDTProblems() throws CoreException {
		expectingNoJDTProblemsFor(getEnv().getWorkspaceRootPath());
	}

	/**
	 * Asserts that there are no compilation problems on the given resource path
	 *
	 * @param resource
	 * @throws CoreException
	 */
	protected void expectingNoJDTProblemsFor(IPath resource) throws CoreException {
		IMarker[] jdtMarkers = getEnv().getAllJDTMarkers(resource);
		int length = jdtMarkers.length;
		if (length != 0) {
			boolean condition = false;
			String cause = "No marker message"; //$NON-NLS-1$
			for (int i = 0; i < length; i++) {
				condition = condition || jdtMarkers[i].getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING) == IMarker.SEVERITY_ERROR;
				if (condition) {
					cause = (String) jdtMarkers[i].getAttribute(IMarker.MESSAGE);
					System.err.println("Unexpected JDT Marker in " + jdtMarkers[i].getResource().getFullPath()); //$NON-NLS-1$
					System.err.println(cause);
				}
			}
			if (condition) {
				/*
				 * We are about to fail, log some extra information for easier
				 * debugging of the fail.
				 */
				logProjectInfos(getName() + " is about to fail, logging extra infos for resource " + resource); //$NON-NLS-1$
			}
			assertFalse("Should not be a JDT error: " + cause, condition); //$NON-NLS-1$
		}
	}

	/**
	 * Verifies that the given elements have no problems.
	 */
	@Override
	protected void expectingNoProblemsFor(IPath[] roots) {
		StringBuilder buffer = new StringBuilder();
		ApiProblem[] problems = allSortedApiProblems(roots);
		if (problems != null) {
			for (ApiProblem problem : problems) {
				buffer.append(problem + "\n"); //$NON-NLS-1$
			}
		}
		String actual = buffer.toString();
		assumeEquals("Unexpected problem(s)!!!", "", actual); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Verifies that the given element has problems and only the given element.
	 */
	@Override
	protected void expectingOnlyProblemsFor(IPath expected) {
		expectingOnlyProblemsFor(new IPath[] { expected });
	}

	/**
	 * Creates a set of the default problem ids of the given count
	 *
	 * @param numproblems
	 * @return the set of default problem ids, or an empty set.
	 */
	protected int[] getDefaultProblemIdSet(int numproblems) {
		if (numproblems < 0) {
			return NO_PROBLEM_IDS;
		}
		int[] set = new int[numproblems];
		for (int i = 0; i < numproblems; i++) {
			set[i] = getDefaultProblemId();
		}
		return set;
	}

	/**
	 * Verifies that the given elements have problems and only the given
	 * elements.
	 */
	@Override
	protected void expectingOnlyProblemsFor(IPath[] expected) {
		if (DEBUG) {
			printProblems();
		}
		IMarker[] rootProblems = getEnv().getMarkers();
		Hashtable<IPath, IPath> actual = new Hashtable<>(rootProblems.length * 2 + 1);
		for (IMarker rootProblem : rootProblems) {
			IPath culprit = rootProblem.getResource().getFullPath();
			actual.put(culprit, culprit);
		}

		for (IPath element : expected) {
			if (!actual.containsKey(element)) {
				assertTrue("missing expected problem with " + element.toString(), false); //$NON-NLS-1$
			}
		}

		if (actual.size() > expected.length) {
			for (Enumeration<IPath> e = actual.elements(); e.hasMoreElements();) {
				IPath path = e.nextElement();
				boolean found = false;
				for (IPath element : expected) {
					if (path.equals(element)) {
						found = true;
						break;
					}
				}
				if (!found) {
					assertTrue("unexpected problem(s) with " + path.toString(), false); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Creates the workspace by importing projects from the 'projectsdir'
	 * directory. All projects in the given directory will try to be imported
	 * into the workspace. The given 'projectsdir' is assumed to be a child path
	 * of the test source path (the test-builder folder in the test workspace).
	 *
	 * This is the initial state of the workspace.
	 *
	 * @param projectsdir the directory to load projects from
	 * @param buildimmediately if a build should be run immediately following
	 *            the import
	 * @param importfiles
	 * @param usetestcompliance
	 * @throws Exception
	 */
	protected void createExistingProjects(String projectsdir, boolean buildimmediately, boolean importfiles, boolean usetestcompliance) throws Exception {
		IPath path = TestSuiteHelper.getPluginDirectoryPath().append(TEST_SOURCE_ROOT).append(projectsdir);
		File dir = path.toFile();
		assertTrue("Test data directory does not exist: " + path.toOSString(), dir.exists()); //$NON-NLS-1$
		File[] files = dir.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				createExistingProject(file, importfiles, usetestcompliance);
			}
		}
		if (buildimmediately) {
			fullBuild();
		}
	}

	/**
	 * Exports the project as an API component to be used in an API baseline.
	 *
	 * @param project project to export
	 * @param apiComponent associated API component from the workspace profile
	 * @param baselineLocation local file system directory to host exported
	 *            component
	 */
	protected void exportApiComponent(IProject project, IApiComponent apiComponent, IPath baselineLocation) throws Exception {
		File root = baselineLocation.toFile();
		File componentDir = new File(root, project.getName());
		componentDir.mkdirs();
		IResource[] members = project.members();
		// copy root files and manifest
		for (IResource res : members) {
			if (res.getType() == IResource.FILE) {
				FileUtils.copyFile(componentDir, (IFile) res);
			} else if (res.getType() == IResource.FOLDER) {
				if (res.getName().equals("META-INF")) { //$NON-NLS-1$
					File manDir = new File(componentDir, "META-INF"); //$NON-NLS-1$
					manDir.mkdirs();
					FileUtils.copyFile(manDir, ((IFolder) res).getFile("MANIFEST.MF")); //$NON-NLS-1$
				}
			}
		}
		// copy over .class files
		IFolder output = project.getFolder("bin"); //$NON-NLS-1$
		FileUtils.copyFolder(output, componentDir);
		// API Description
		ApiDescriptionXmlCreator visitor = new ApiDescriptionXmlCreator(apiComponent);
		apiComponent.getApiDescription().accept(visitor, null);
		String xml = visitor.getXML();
		File desc = new File(componentDir, ".api_description"); //$NON-NLS-1$
		desc.createNewFile();
		try (FileOutputStream stream = new FileOutputStream(desc)) {
			stream.write(xml.getBytes(StandardCharsets.UTF_8));
		}
	}

	/**
	 * Create the project described in record. If it is successful return true.
	 *
	 * @param projectDir directory containing existing project
	 * @param importfiles
	 * @param usetestcompliance
	 */
	@SuppressWarnings("deprecation")
	protected void createExistingProject(File projectDir, boolean importfiles, boolean usetestcompliance) throws Exception {
		String projectName = projectDir.getName();
		final IWorkspace workspace = getEnv().getWorkspace();
		IPath ppath = getEnv().addProject(projectName, usetestcompliance ? getTestCompliance() : null);
		IProject project = getEnv().getProject(ppath);
		IProjectDescription description = workspace.newProjectDescription(projectName);
		IPath locationPath = new Path(projectDir.getAbsolutePath());
		description.setLocation(locationPath);

		URI locationURI = description.getLocationURI();
		// if location is null, project already exists in this location or
		// some error condition occurred.
		assertNotNull("project description location is null", locationURI); //$NON-NLS-1$

		IProjectDescription desc = workspace.newProjectDescription(projectName);
		desc.setBuildSpec(description.getBuildSpec());
		desc.setComment(description.getComment());
		desc.setDynamicReferences(description.getDynamicReferences());
		desc.setNatureIds(description.getNatureIds());
		desc.setReferencedProjects(description.getReferencedProjects());
		description = desc;

		project.setDescription(description, new NullProgressMonitor());
		project.open(null);

		// only import the files if we want them
		if (importfiles) {
			// import operation to import project files
			File importSource = new File(locationURI);
			List<?> filesToImport = FileSystemStructureProvider.INSTANCE.getChildren(importSource);

			ImportOperation operation = new ImportOperation(project.getFullPath(), importSource, FileSystemStructureProvider.INSTANCE, pathString -> IOverwriteQuery.ALL, filesToImport);
			operation.setOverwriteResources(true);
			operation.setCreateContainerStructure(false);
			operation.run(new NullProgressMonitor());
		}

		// force the use of the test compliance
		if (usetestcompliance) {
			getEnv().setProjectCompliance(getEnv().getJavaProject(ppath), getTestCompliance());
		}
	}

	/**
	 * @return the default compiler compliance to use for the test
	 */
	protected String getTestCompliance() {
		return JavaCore.VERSION_1_4;
	}

	/**
	 * Method that can be overridden for custom assertion of the problems after
	 * the build
	 *
	 * @param problems the complete listing of problems from the testing
	 *            environment
	 */
	protected void assertProblems(ApiProblem[] problems) {
		int[] expectedProblemIds = getExpectedProblemIds();
		int length = problems.length;
		if (expectedProblemIds.length != length) {
			for (int i = 0; i < length; i++) {
				System.err.println(problems[i]);
			}
		}
		assertEquals("Wrong number of problems", expectedProblemIds.length, length); //$NON-NLS-1$
		String[][] args = getExpectedMessageArgs();
		if (args != null) {
			// compare messages
			ArrayList<String> messages = new ArrayList<>();
			for (int i = 0; i < length; i++) {
				messages.add(problems[i].getMessage());
			}
			for (int i = 0; i < expectedProblemIds.length; i++) {
				String[] messageArgs = args[i];
				int messageId = ApiProblemFactory.getProblemMessageId(expectedProblemIds[i]);
				String message = ApiProblemFactory.getLocalizedMessage(messageId, messageArgs);
				assertTrue("Missing expected problem: " + message, messages.remove(message)); //$NON-NLS-1$
			}
			if (messages.size() > 0) {
				StringBuilder buffer = new StringBuilder();
				buffer.append('[');
				for (String problem : messages) {
					buffer.append(problem).append(',');
				}
				buffer.append(']');
				fail("There was no problems that matched the arguments: " + buffer.toString()); //$NON-NLS-1$
			}
		} else {
			// compare id's
			ArrayList<Integer> messages = new ArrayList<>();
			for (int i = 0; i < length; i++) {
				messages.add(Integer.valueOf(problems[i].getProblemId()));
			}
			for (int expectedProblemId : expectedProblemIds) {
				assertTrue("Missing expected problem: " + expectedProblemId, messages.remove(Integer.valueOf(expectedProblemId))); //$NON-NLS-1$
			}
		}
		if (fLineMappings != null) {
			ArrayList<LineMapping> mappings = new ArrayList<>(Arrays.asList(fLineMappings));
			for (ApiProblem problem : problems) {
				assertTrue("Missing expected problem line mapping: " + problem, mappings.remove(new LineMapping(problem))); //$NON-NLS-1$
			}
			if (mappings.size() > 0) {
				StringBuilder buffer = new StringBuilder();
				buffer.append('[');
				for (LineMapping mapping : mappings) {
					buffer.append(mapping).append(',');
				}
				buffer.append(']');
				fail("There was no problems that matched the line mappings: " + buffer.toString()); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Sets the ids of the problems you expect to see from deploying a builder
	 * test
	 *
	 * @param problemids
	 */
	protected void setExpectedProblemIds(int[] problemids) {
		fProblems = problemids;
	}

	/**
	 * Sets the line mappings that problems are expected on
	 *
	 * @param linenumbers
	 */
	protected void setExpectedLineMappings(LineMapping[] linemappings) {
		fLineMappings = linemappings;
	}

	/**
	 * Sets the message arguments for corresponding problem ids.
	 *
	 * @param messageArgs message arguments - an array of String for each
	 *            expected problem.
	 */
	protected void setExpectedMessageArgs(String[][] messageArgs) {
		fMessageArgs = messageArgs;
	}

	/**
	 * @return the name of the testing project for the implementing test suite
	 */
	protected abstract String getTestingProjectName();

	/**
	 * @return the default problem id for the given test
	 */
	protected abstract int getDefaultProblemId();

	/**
	 * @return the ids of the
	 *         {@link org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem}
	 *         we are expecting to find after a build.
	 *
	 *         This method is consulted for every call to a deploy* method where
	 *         a builder test is run.
	 *
	 *         The returned array from this method is used to make sure that
	 *         expected problems (kind and count) appear after a build
	 */
	protected int[] getExpectedProblemIds() {
		if (fProblems == null) {
			return NO_PROBLEM_IDS;
		}
		return fProblems;
	}

	/**
	 * Returns the expected message arguments corresponding to expected problem
	 * ids, or <code>null</code> if unspecified.
	 *
	 * @return message arguments for each expected problem or <code>null</code>
	 *         if unspecified
	 */
	protected String[][] getExpectedMessageArgs() {
		return fMessageArgs;
	}

	/**
	 * Verifies that the given element has a specific problem and only the given
	 * problem.
	 */
	protected void expectingOnlySpecificProblemFor(IPath root, int problemid) {
		expectingOnlySpecificProblemsFor(root, new int[] { problemid });
	}

	/**
	 * Returns the problem id from the marker
	 *
	 * @param marker
	 * @return the problem id from the marker or -1 if there isn't one set on
	 *         the marker
	 */
	protected int getProblemId(IMarker marker) {
		if (marker == null) {
			return -1;
		}
		return marker.getAttribute(IApiMarkerConstants.MARKER_ATTR_PROBLEM_ID, -1);
	}

	/**
	 * Verifies that the given element has specifics problems and only the given
	 * problems.
	 */
	protected void expectingOnlySpecificProblemsFor(final IPath root, final int[] problemids) {
		if (DEBUG) {
			printProblemsFor(root);
		}
		IMarker[] markers = getEnv().getMarkersFor(root);
		for (int problemid : problemids) {
			boolean found = false;
			for (int j = 0; j < markers.length; j++) {
				if (getProblemId(markers[j]) == problemid) {
					found = true;
					markers[j] = null;
					break;
				}
			}
			if (!found) {
				printProblemsFor(root);
			}
			assertTrue("problem not found: " + problemid, found); //$NON-NLS-1$
		}
		for (IMarker marker : markers) {
			if (marker != null) {
				printProblemsFor(root);
				assertTrue("unexpected problem: " + marker.toString(), false); //$NON-NLS-1$
			}
		}
	}

	/**
	 * Verifies that the given element has problems.
	 */
	@Override
	protected void expectingProblemsFor(IPath root, String expected) {
		expectingProblemsFor(new IPath[] { root }, expected);
	}

	/**
	 * Verifies that the given elements have problems.
	 */
	@Override
	protected void expectingProblemsFor(IPath[] roots, String expected) {
		ApiProblem[] problems = allSortedApiProblems(roots);
		assumeEquals("Invalid problem(s)!!!", expected, arrayToString(problems)); //$NON-NLS-1$
	}

	/**
	 * Verifies that the given elements have the expected problems.
	 */
	@Override
	protected void expectingProblemsFor(IPath[] roots, @SuppressWarnings("rawtypes") List expected) {
		ApiProblem[] problems = allSortedApiProblems(roots);
		assumeEquals("Invalid problem(s)!!!", arrayToString(expected.toArray()), arrayToString(problems)); //$NON-NLS-1$
	}

	/**
	 * Concatenate and sort all problems for given root paths.
	 *
	 * @param roots The path to get the problems
	 * @return All sorted problems of all given path
	 */
	protected ApiProblem[] allSortedApiProblems(IPath[] roots) {
		ApiProblem[] allProblems = null;
		ApiProblem[] problems = null;
		for (IPath root : roots) {
			problems = (ApiProblem[]) getEnv().getProblemsFor(root);
			int length = problems.length;
			if (problems.length != 0) {
				if (allProblems == null) {
					allProblems = problems;
				} else {
					int all = allProblems.length;
					System.arraycopy(allProblems, 0, allProblems = new ApiProblem[all + length], 0, all);
					System.arraycopy(problems, 0, allProblems, all, length);
				}
			}
		}
		if (allProblems != null) {
			Arrays.sort(allProblems);
		}
		return allProblems;
	}

	/**
	 * Verifies that the given element has a specific problem.
	 */
	protected void expectingSpecificProblemFor(IPath root, int problemid) {
		expectingSpecificProblemsFor(root, new int[] { problemid });
	}

	/**
	 * Verifies that the given element has specific problems.
	 */
	protected void expectingSpecificProblemsFor(IPath root, int[] problemids) {
		if (DEBUG) {
			printProblemsFor(root);
		}
		IMarker[] markers = getEnv().getMarkersFor(root);
		IMarker marker = null;
		next: for (int problemid : problemids) {
			for (int j = 0; j < markers.length; j++) {
				marker = markers[j];
				if (marker != null) {
					if (problemid == getProblemId(marker)) {
						markers[j] = null;
						continue next;
					}
				}
			}
			System.out.println("--------------------------------------------------------------------------------"); //$NON-NLS-1$
			System.out.println("Missing problem while running test " + getName() + ":"); //$NON-NLS-1$ //$NON-NLS-2$
			System.out.println("	- expected : " + problemid); //$NON-NLS-1$
			System.out.println("	- current: " + arrayToString(markers)); //$NON-NLS-1$
			assumeTrue("missing expected problem: " + problemid, false); //$NON-NLS-1$
		}
	}

	/**
	 * Prints all of the problems in the current test workspace
	 */
	@Override
	protected void printProblems() {
		printProblemsFor(getEnv().getWorkspaceRootPath());
	}

	/**
	 * Prints all of the problems from the current root to infinite children
	 *
	 * @param root
	 */
	@Override
	protected void printProblemsFor(IPath root) {
		printProblemsFor(new IPath[] { root });
	}

	/**
	 * Prints all of the problems from each of the roots to infinite children
	 *
	 * @param roots
	 */
	@Override
	protected void printProblemsFor(IPath[] roots) {
		for (IPath root : roots) {
			/* get the leaf problems for this type */
			System.out.println(arrayToString(getEnv().getProblemsFor(root)));
			System.out.println();
		}
	}

	/**
	 * Takes each element of the array and calls toString on it to put an array
	 * together as a string
	 *
	 * @param array
	 * @return
	 */
	@Override
	protected String arrayToString(Object[] array) {
		StringBuilder buffer = new StringBuilder();
		int length = array == null ? 0 : array.length;
		if (length == 0) {
			buffer.append("No problem found"); //$NON-NLS-1$
		} else {
			for (int i = 0; i < length; i++) {
				if (array[i] != null) {
					if (i > 0) {
						buffer.append('\n');
					}
					buffer.append(array[i].toString());
				}
			}
		}
		return buffer.toString();
	}

	/**
	 * @return the source path from the test-builder test source root to find
	 *         the test source in
	 */
	protected abstract IPath getTestSourcePath();

	/**
	 * Sets the current builder options to use for the current test. Default is
	 * all set to their default values
	 */
	protected void setBuilderOptions() {
		resetBuilderOptions();
	}

	/**
	 * Resets all of the builder options to their defaults after each test run
	 */
	protected void resetBuilderOptions() {
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		// usage
		inode.put(IApiProblemTypes.ILLEGAL_EXTEND, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.ILLEGAL_IMPLEMENT, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.ILLEGAL_INSTANTIATE, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.ILLEGAL_REFERENCE, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.ILLEGAL_OVERRIDE, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.LEAK_EXTEND, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.LEAK_FIELD_DECL, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.LEAK_IMPLEMENT, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.LEAK_METHOD_PARAM, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.LEAK_METHOD_RETURN_TYPE, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.INVALID_JAVADOC_TAG, ApiPlugin.VALUE_IGNORE);
		inode.put(IApiProblemTypes.INVALID_ANNOTATION, ApiPlugin.VALUE_IGNORE);
		inode.put(IApiProblemTypes.UNUSED_PROBLEM_FILTERS, ApiPlugin.VALUE_WARNING);

		// compatibilities
		for (String allCompatibilityKey : ApiPlugin.AllCompatibilityKeys) {
			inode.put(allCompatibilityKey, ApiPlugin.VALUE_ERROR);
		}

		// version management
		inode.put(IApiProblemTypes.MISSING_SINCE_TAG, ApiPlugin.VALUE_ERROR);
		inode.put(IApiProblemTypes.MALFORMED_SINCE_TAG, ApiPlugin.VALUE_ERROR);
		inode.put(IApiProblemTypes.INVALID_SINCE_TAG_VERSION, ApiPlugin.VALUE_ERROR);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION, ApiPlugin.VALUE_ERROR);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION_REPORT_MINOR_WITHOUT_API_CHANGE,
				ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION_REPORT_MAJOR_WITHOUT_BREAKING_CHANGE,
				ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.CHANGED_EXECUTION_ENV, ApiPlugin.VALUE_ERROR);

		inode.put(IApiProblemTypes.MISSING_DEFAULT_API_BASELINE, ApiPlugin.VALUE_WARNING);
		inode.put(IApiProblemTypes.MISSING_PLUGIN_IN_API_BASELINE, ApiPlugin.VALUE_IGNORE);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables all of the usage problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableUsageOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		// usage
		inode.put(IApiProblemTypes.ILLEGAL_EXTEND, value);
		inode.put(IApiProblemTypes.ILLEGAL_IMPLEMENT, value);
		inode.put(IApiProblemTypes.ILLEGAL_INSTANTIATE, value);
		inode.put(IApiProblemTypes.ILLEGAL_REFERENCE, value);
		inode.put(IApiProblemTypes.ILLEGAL_OVERRIDE, value);
		inode.put(IApiProblemTypes.UNUSED_PROBLEM_FILTERS, value);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables all of the leak problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableLeakOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.LEAK_EXTEND, value);
		inode.put(IApiProblemTypes.LEAK_FIELD_DECL, value);
		inode.put(IApiProblemTypes.LEAK_IMPLEMENT, value);
		inode.put(IApiProblemTypes.LEAK_METHOD_PARAM, value);
		inode.put(IApiProblemTypes.LEAK_METHOD_RETURN_TYPE, value);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Deletes the workspace file at the specified location (full path).
	 *
	 * @param workspaceLocation
	 */
	protected void deleteWorkspaceFile(IPath workspaceLocation, boolean recorddeletion) throws Exception {
		IFile file = getEnv().getWorkspace().getRoot().getFile(workspaceLocation);
		assertTrue("Workspace file does not exist: " + workspaceLocation.toString(), file.exists()); //$NON-NLS-1$
		file.delete(true, null);
		if (recorddeletion) {
			getEnv().removed(workspaceLocation);
		}
	}

	/**
	 * Returns a path in the local file system to an updated file based on this
	 * tests source path and filename.
	 *
	 * @param filename name of file to update
	 * @return path to the file in the local file system
	 */
	protected IPath getUpdateFilePath(String filename) {
		return TestSuiteHelper.getPluginDirectoryPath().append(TEST_SOURCE_ROOT).append(getTestSourcePath()).append(filename);
	}

	/**
	 * Updates the contents of a workspace file at the specified location (full
	 * path), with the contents of a local file at the given replacement
	 * location (absolute path).
	 *
	 * @param workspaceLocation
	 * @param replacementLocation
	 */
	protected void createWorkspaceFile(IPath workspaceLocation, IPath replacementLocation) throws Exception {
		IFile file = getEnv().getWorkspace().getRoot().getFile(workspaceLocation);
		assertFalse("Workspace file should not exist: " + workspaceLocation.toString(), file.exists()); //$NON-NLS-1$
		File replacement = replacementLocation.toFile();
		assertTrue("Replacement file does not exist: " + replacementLocation.toOSString(), replacement.exists()); //$NON-NLS-1$
		try (FileInputStream stream = new FileInputStream(replacement)) {
			file.create(stream, true, null);
		}
		getEnv().added(workspaceLocation);
	}

	/**
	 * Updates the contents of a workspace file at the specified location (full
	 * path), with the contents of a local file at the given replacement
	 * location (absolute path).
	 *
	 * @param workspaceLocation
	 * @param replacementLocation
	 */
	protected void updateWorkspaceFile(IPath workspaceLocation, IPath replacementLocation) throws Exception {
		IFile file = getEnv().getWorkspace().getRoot().getFile(workspaceLocation);
		assertTrue("Workspace file does not exist: " + workspaceLocation.toString(), file.exists()); //$NON-NLS-1$
		File replacement = replacementLocation.toFile();
		assertTrue("Replacement file does not exist: " + replacementLocation.toOSString(), replacement.exists()); //$NON-NLS-1$
		try (FileInputStream stream = new FileInputStream(replacement)) {
			file.setContents(stream, true, false, null);
		}
		getEnv().changed(workspaceLocation);
	}

	/**
	 * Enables or disables the unsupported Javadoc tag problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableUnsupportedTagOptions(boolean enabled) {
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.INVALID_JAVADOC_TAG, enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables the unsupported annotation problems for the builder
	 *
	 * @param enabled
	 * @since 1.0.400
	 */
	protected void enableUnsupportedAnnotationOptions(boolean enabled) {
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.INVALID_ANNOTATION, enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables all of the compatibility problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableCompatibilityOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		for (String allCompatibilityKey : ApiPlugin.AllCompatibilityKeys) {
			inode.put(allCompatibilityKey, value);
		}
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables all of the since tag problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableSinceTagOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.MISSING_SINCE_TAG, value);
		inode.put(IApiProblemTypes.MALFORMED_SINCE_TAG, value);
		inode.put(IApiProblemTypes.INVALID_SINCE_TAG_VERSION, value);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables all of the version number problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error' or
	 *            'Enabled', false sets the options to 'Ignore' or 'Disabled'
	 */
	protected void enableVersionNumberOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		String value2 = enabled ? ApiPlugin.VALUE_ENABLED : ApiPlugin.VALUE_DISABLED;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION, value);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION_REPORT_MINOR_WITHOUT_API_CHANGE, value2);
		inode.put(IApiProblemTypes.INCOMPATIBLE_API_COMPONENT_VERSION_REPORT_MAJOR_WITHOUT_BREAKING_CHANGE, value2);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables the API baseline problems for the builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableBaselineOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.MISSING_DEFAULT_API_BASELINE, value);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Enables or disables the External Depencency breakage problems for the
	 * builder
	 *
	 * @param enabled if true the builder options are set to 'Error', false sets
	 *            the options to 'Ignore'
	 */
	protected void enableExternalDependencyCheckOptions(boolean enabled) {
		String value = enabled ? ApiPlugin.VALUE_ERROR : ApiPlugin.VALUE_IGNORE;
		IEclipsePreferences inode = InstanceScope.INSTANCE.getNode(ApiPlugin.PLUGIN_ID);
		inode.put(IApiProblemTypes.API_USE_SCAN_TYPE_SEVERITY, value);
		inode.put(IApiProblemTypes.API_USE_SCAN_METHOD_SEVERITY, value);
		inode.put(IApiProblemTypes.API_USE_SCAN_FIELD_SEVERITY, value);
		try {
			inode.flush();
		} catch (BackingStoreException e) {
			ApiPlugin.log(e);
		}
	}

	/**
	 * Sets up this test.
	 */
	@Override
	protected void setUp() throws Exception {
		FreezeMonitor.expectCompletionInAMinute();
		if (env == null) {
			env = new ApiTestingEnvironment();
			env.openEmptyWorkspace();
			env.setAutoBuilding(false);
		}
		setBuilderOptions();
		super.setUp();
	}

	@Override
	protected void tearDown() throws Exception {
		resetBuilderOptions();
		fProblems = null;
		fMessageArgs = null;
		this.debugRequestor.clearResult();
		super.tearDown();
		FreezeMonitor.done();
	}

	/**
	 * @return all of the child test classes of this class
	 */
	private static Class<?>[] getAllTestClasses() {
		ArrayList<Class<?>> classes = new ArrayList<>();
		classes.add(CompatibilityTest.class);
		classes.add(UsageTest.class);
		classes.add(LeakTest.class);
		classes.add(TagTest.class);
		classes.add(AnnotationTest.class);
		if (ProjectUtils.isJava7Compatible()) {
			classes.add(Java7UsageTest.class);
		}
		if (ProjectUtils.isJava8Compatible()) {
			classes.add(Java8UsageTest.class);
		}
		return classes.toArray(new Class[classes.size()]);
	}

	/**
	 * Collects tests from the getAllTestClasses() method into the given suite
	 *
	 * @param suite
	 */
	private static void collectTests(TestSuite suite) {
		// Hack to load all classes before computing their suite of test cases
		// this allow to reset test cases subsets while running all Builder
		// tests...
		Class<?>[] classes = getAllTestClasses();

		// Reset forgotten subsets of tests
		TestCase.TESTS_PREFIX = null;
		TestCase.TESTS_NAMES = null;
		TestCase.TESTS_NUMBERS = null;
		TestCase.TESTS_RANGE = null;
		TestCase.RUN_ONLY_ID = null;

		/* tests */
		for (Class<?> clazz : classes) {
			Method suiteMethod;
			try {
				suiteMethod = clazz.getDeclaredMethod("suite"); //$NON-NLS-1$
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
				continue;
			}
			Object test;
			try {
				test = suiteMethod.invoke(clazz);
			} catch (IllegalAccessException e) {
				e.printStackTrace();
				continue;
			} catch (InvocationTargetException e) {
				e.printStackTrace();
				continue;
			}
			suite.addTest((Test) test);
		}
	}

	/**
	 * loads builder tests
	 *
	 * @return
	 */
	public static Test suite() {
		TestSuite suite = new TestSuite(ApiBuilderTest.class.getName());
		collectTests(suite);
		return suite;
	}

	private static void logProjectInfos(String message) {
		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
		logProjectInfos(message, IStatus.ERROR, Arrays.asList(projects));
	}

	/**
	 * Logs the classpath of each accessible project of the specified projects,
	 * as well as all markers in the workspace.
	 *
	 * @param message
	 *            a prefix for the logged message
	 * @param severity
	 *            the severity of the logged entry
	 * @param projectNames
	 *            the names of the projects for which to log classpaths
	 */
	protected static void logProjectInfos(String message, String[] projectNames) {
		List<IProject> projects = new ArrayList<>();
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		for (String projectName : projectNames) {
			IProject project = root.getProject(projectName);
			projects.add(project);
		}
		logProjectInfos(message, IStatus.INFO, projects);
	}

	/**
	 * Logs the classpath of each accessible project of the specified projects,
	 * as well as all markers in the workspace.
	 *
	 * @param message
	 *            a prefix for the logged message
	 * @param severity
	 *            the severity of the logged entry
	 * @param projects
	 *            the projects for which to log classpaths
	 */
	protected static void logProjectInfos(String message, int severity, List<IProject> projects) {
		IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
		ILog log = PDECore.getDefault().getLog();
		try {
			IMarker[] markers = workspaceRoot.findMarkers(null, true, IResource.DEPTH_INFINITE);

			String infosContent = String.join(System.lineSeparator(), message, toString(projects), toString(markers));

			IStatus infos = new Status(severity, PDECore.PLUGIN_ID, infosContent, new Exception());
			log.log(infos);
		} catch (Exception e) {
			IStatus error = Status.error("error occurred while logging extra info", e); //$NON-NLS-1$
			log.log(error);
		}
	}

	private static String toString(List<IProject> projects) throws Exception {
		StringBuilder contents = new StringBuilder();
		contents.append("Listing " + projects.size() + " projects:"); //$NON-NLS-1$ //$NON-NLS-2$
		for (IProject project : projects) {
			contents.append(System.lineSeparator());
			contents.append("    name: " + project.getName()); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    location: " + project.getLocation()); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    is accessible: " + project.isAccessible()); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    is open: " + project.isOpen()); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			if (project.hasNature(JavaCore.NATURE_ID) && project.isAccessible()) {
				IJavaProject javaProject = JavaCore.create(project);
				boolean ignoreUnresolvedEntry = true;
				IClasspathEntry[] projectClassPath = javaProject.getResolvedClasspath(ignoreUnresolvedEntry);
				contents.append(toString(projectClassPath));

			}
		}
		return contents.toString();
	}

	private static String toString(IClasspathEntry[] classpathEntries) {
		StringBuilder contents = new StringBuilder();
		contents.append("Listing " + classpathEntries.length + " classpath entries:"); //$NON-NLS-1$ //$NON-NLS-2$
		contents.append(System.lineSeparator());
		for (IClasspathEntry classpathEntry : classpathEntries) {
			contents.append(classpathEntry);
			contents.append(System.lineSeparator());
		}
		return contents.toString();
	}

	private static String toString(IMarker[] markers) throws CoreException {
		StringBuilder contents = new StringBuilder();
		contents.append("Listing " + markers.length + " markers:"); //$NON-NLS-1$ //$NON-NLS-2$
		for (IMarker marker : markers) {
			contents.append(System.lineSeparator());
			contents.append("    message: " + marker.getAttribute(IMarker.MESSAGE)); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    severity: " + marker.getAttribute(IMarker.SEVERITY)); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    line number: " + marker.getAttribute(IMarker.LINE_NUMBER)); //$NON-NLS-1$
			contents.append(System.lineSeparator());
			contents.append("    resource: " + marker.getResource().getFullPath()); //$NON-NLS-1$
		}
		return contents.toString();
	}
}
