/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     Samrat Dhillon <samrat.dhillon@gmail.com> - [introduce factory] Introduce Factory on an abstract class adds a statement to create an instance of that class - https://bugs.eclipse.org/bugs/show_bug.cgi?id=395016
 *******************************************************************************/
package org.eclipse.jdt.ui.tests.refactoring;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.eclipse.jdt.testplugin.JavaProjectHelper;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;

import org.eclipse.ltk.core.refactoring.RefactoringStatus;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.SourceRange;

import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceFactoryRefactoring;

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

/**
 * @author rfuhrer@watson.ibm.com
 */
public class IntroduceFactoryTests extends RefactoringTest {

	private static final Class<IntroduceFactoryTests> clazz= IntroduceFactoryTests.class;
	private static final String REFACTORING_PATH= "IntroduceFactory/";

	public IntroduceFactoryTests(String name) {
		super(name);
	}

	@Override
	protected String getRefactoringPath() {
		return REFACTORING_PATH;
	}

	public static Test suite() {
		return new Java16Setup(new TestSuite(clazz));
	}

	public static Test setUpTest(Test someTest) {
	    return new Java16Setup(someTest);
	}

	/**
	 * Produces a test file name based on the name of this JUnit testcase.
	 * For input files, trims off the trailing part of the test name that
	 * begins with a '_', to get rid of the options part, so that we can
	 * have a single (suite of) input file(s) but several outputs dependent
	 * on the option settings.
	 * @param input true iff the requested file is an input file.
	 * @return the name of the test file, with a trailing "_in.java" if an input
	 * file and a trailing "_XXX.java" if an output file and the test name/options
	 * are "_XXX".
	 */
	private String getSimpleTestFileName(boolean input) {
		String	testName = getName();
		int		usIdx=  testName.indexOf('_');
		int		endIdx= (usIdx >= 0) ? usIdx : testName.length();
		String	fileName = (input ? (testName.substring(4, endIdx) + "_in") : testName.substring(4));

		return fileName + ".java";
	}

	/**
	 * Produces a test file name based on the name of this JUnit testcase,
	 * like getSimpleTestFileName(), but also prepends the appropriate version
	 * of the resource path (depending on the value of <code>positive</code>).
	 * Test files are assumed to be located in the resources directory.
	 * @param positive true iff the requested file is for a positive unit test
	 * @param input true iff the requested file is an input file
	 * @return the test file name
	 */
	private String getTestFileName(boolean positive, boolean input) {
		String path= TEST_PATH_PREFIX + getRefactoringPath();

		path += (positive ? "positive/": "negative/");
		return path + getSimpleTestFileName(input);
	}

	/**
	 * Produces a compilation unit from an input source file whose name
	 * is based on the testcase name.
	 * Test files are assumed to be located in the resources directory.
	 * @param pack
	 * @param positive
	 * @param input
	 * @return the ICompilationUnit created from the specified test file
	 * @throws Exception
	 */
	private ICompilationUnit createCUForSimpleTest(IPackageFragment pack,
												  boolean positive, boolean input)
		throws Exception
	{
		String	fileName= getTestFileName(positive, input);
		String	cuName= getSimpleTestFileName(input);

		return createCU(pack, cuName, getFileContents(fileName));
	}

	/**
	 * Produces a test file name based on the name of this JUnit testcase,
	 * like getSimpleTestFileName(), but also prepends the appropriate version
	 * of the resource path (depending on the value of <code>positive</code>).
	 * Test files are assumed to be located in the resources directory.
	 * @param project the project
	 * @param pack the package fragment
	 * @param fileName the file name
	 * @param input true iff the requested file is an input file
	 * @return the test file name
	 */
	private String getBugTestFileName(IJavaProject project, IPackageFragment pack, String fileName, boolean input) {
		String testName= getName();
		String testNumber= testName.substring("test".length());//$NON-NLS-1$
		String path= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/" +
									(project == null ? "" : project.getElementName() + "/") +
									(pack == getPackageP() ? "" : pack.getElementName() + "/");

		return path + fileName + (input ? "" : "_out") + ".java";//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	/**
	 * Produces a compilation unit from an input source file whose path
	 * is based on the testcase name, but whose basename is supplied by
	 * the caller.
	 * Test files are assumed to be located in the resources directory.
	 * @param project can be null if only 1 project exists in the test workspace
	 * @param pack
	 * @param baseName
	 * @param input
	 * @return the ICompilationUnit created from the specified test file
	 * @throws Exception
	 */
	private ICompilationUnit createCUForBugTestCase(IJavaProject project,
													IPackageFragment pack, String baseName, boolean input)
		throws Exception
	{
		String	fileName= getBugTestFileName(project, pack, baseName, input);
		String	cuName= baseName + (input ? "" : "_out") + ".java";

		return createCU(pack, cuName, getFileContents(fileName));
	}

	static final String SELECTION_START_HERALD= "/*[*/";
	static final String SELECTION_END_HERALD= "/*]*/";

	/**
	 * Finds and returns the selection markers in the given source string,
	 * i.e. the first occurrences of <code>SELECTION_START_HERALD</code> and
	 * <code>SELECTION_END_HERALD</code>. Fails an assertion if either of these
	 * markers is not present in the source string.
	 * @param source
	 * @return an ISourceRange representing the marked selection
	 * @throws Exception
	 */
	private ISourceRange findSelectionInSource(String source) throws Exception {
		int		begin= source.indexOf(SELECTION_START_HERALD) + SELECTION_START_HERALD.length();
		int		end= source.indexOf(SELECTION_END_HERALD);

		if (begin < SELECTION_START_HERALD.length())
			assertTrue("No selection start comment in input source file!", false);
		if (end < 0)
			assertTrue("No selection end comment in input source file!", false);

		return new SourceRange(begin, end-begin);
	}

	private void doSingleUnitTest(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
		ISourceRange		selection= findSelectionInSource(cu.getSource());
		IntroduceFactoryRefactoring	ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());

		ref.setProtectConstructor(protectConstructor);

		RefactoringStatus	activationResult= ref.checkInitialConditions(new NullProgressMonitor());

		assertTrue("activation was supposed to be successful", activationResult.isOK());

		RefactoringStatus	checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());

		if (!checkInputResult.isOK()) {
			performChange(ref, false);

			String newSource = cu.getSource();

			System.err.println("!!!Precondition failed for " + getName() + "!!!");
			System.err.println("Compile-time error: " + checkInputResult.toString());
			System.err.println("Offending source:");
			System.err.print(newSource);
			assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), false);
		}

		performChange(ref, false);

		String newSource = cu.getSource();

		assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
	}

	private void doSingleUnitTestWithWarning(boolean protectConstructor, ICompilationUnit cu, String outputFileName) throws Exception, JavaModelException, IOException {
		ISourceRange selection= findSelectionInSource(cu.getSource());
		IntroduceFactoryRefactoring ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());

		ref.setProtectConstructor(protectConstructor);

		RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());

		assertTrue("activation was supposed to be successful", activationResult.isOK());

		RefactoringStatus checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());

		assertEquals(RefactoringStatus.WARNING, checkInputResult.getSeverity());
		performChange(ref, false);

		String newSource= cu.getSource();

		assertEqualLines(getName() + ": ", getFileContents(outputFileName), newSource);
	}

	/**
	 * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
	 * whose name is the test name (minus the "test" prefix and any trailing
	 * options indicator such as "_FFF"), and compares the transformed code
	 * to a source file whose name is the test name (minus the "test" prefix).
	 * Test files are assumed to be located in the resources directory.
	 * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
	 * @throws Exception
	 */
	void singleUnitHelper(boolean protectConstructor)
		throws Exception
	{
		ICompilationUnit	cu= createCUForSimpleTest(getPackageP(), true, true);

		doSingleUnitTest(protectConstructor, cu, getTestFileName(true, false));
	}

	/**
	 * Tests the IntroduceFactoryRefactoring refactoring on a single input source file
	 * whose name is the test name (minus the "test" prefix and any trailing
	 * options indicator such as "_FFF"), and compares the transformed code
	 * to a source file whose name is the test name (minus the "test" prefix).
	 * Test files are assumed to be located in the resources directory.
	 * @param baseFileName the base file name
	 * @param protectConstructor true iff IntroduceFactoryRefactoring should make the constructor private
	 * @throws Exception
	 */
	protected void singleUnitBugHelper(String baseFileName, boolean protectConstructor)
		throws Exception
	{
		ICompilationUnit	cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);

		doSingleUnitTest(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
	}

	protected void singleUnitBugHelperWithWarning(String baseFileName, boolean protectConstructor)
			throws Exception
	{
		ICompilationUnit cu= createCUForBugTestCase(null, getPackageP(), baseFileName, true);

		doSingleUnitTestWithWarning(protectConstructor, cu, getBugTestFileName(null, getPackageP(), baseFileName, false));
	}

	/**
	 * Like singleUnitHelper(), but allows for the specification of the names of
	 * the generated factory method, class, and interface, as appropriate.
	 * @param factoryMethodName the name to use for the generated factory method
	 * @param factoryClassName the name of the factory class
	 * @throws Exception
	 */
	void namesHelper(String factoryMethodName, String factoryClassName)
		throws Exception
	{
		ICompilationUnit	cu= createCUForSimpleTest(getPackageP(), true, true);
		ISourceRange		selection= findSelectionInSource(cu.getSource());
		IntroduceFactoryRefactoring	ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());

		RefactoringStatus	activationResult= ref.checkInitialConditions(new NullProgressMonitor());

		assertTrue("activation was supposed to be successful", activationResult.isOK());

		if (factoryMethodName != null)
			ref.setNewMethodName(factoryMethodName);
		if (factoryClassName != null)
			ref.setFactoryClass(factoryClassName);

		RefactoringStatus	checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());

		assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());

		performChange(ref, false);

		String newSource = cu.getSource();

		assertEqualLines(getName() + ": ", getFileContents(getTestFileName(true, false)), newSource);
	}

	/**
	 * Creates a compilation unit for a source file with a given base name (plus
	 * "_in" suffix) in the given package. The source file is assumed to be
	 * located in the test resources directory.<br>
	 * Currently only handles positive tests.
	 * @param fileName the base name of the source file (minus the "_in" suffix)
	 * @param pack an IPackageFragment for the containing package
	 * @return the ICompilationUnit for the newly-created unit
	 * @throws Exception
	 */
	private ICompilationUnit createCUFromFileName(String fileName, IPackageFragment pack) throws Exception {
		String fullName = TEST_PATH_PREFIX + getRefactoringPath() + "positive/" + fileName + "_in.java";

		return createCU(pack, fileName + "_in.java", getFileContents(fullName));
	}

	private void doMultiUnitTest(ICompilationUnit[] CUs, String testPath, String[] outputFileBaseNames, String factoryClassName) throws Exception, JavaModelException, IOException {
		ISourceRange selection= findSelectionInSource(CUs[0].getSource());
		IntroduceFactoryRefactoring	ref= new IntroduceFactoryRefactoring(CUs[0], selection.getOffset(), selection.getLength());

		RefactoringStatus activationResult= ref.checkInitialConditions(new NullProgressMonitor());

		assertTrue("activation was supposed to be successful", activationResult.isOK());

		if (factoryClassName != null)
			ref.setFactoryClass(factoryClassName);

		RefactoringStatus	checkInputResult= ref.checkFinalConditions(new NullProgressMonitor());

		assertTrue("precondition was supposed to pass but was " + checkInputResult.toString(), checkInputResult.isOK());

		performChange(ref, false);

		String	testName= getName();

		for (int i = 0; i < CUs.length; i++) {
			int optIdx= testName.indexOf("_");
			String testOptions= (optIdx >= 0) ? testName.substring(optIdx) : "";
			String outFileName= testPath + outputFileBaseNames[i] + testOptions + "_out.java";
			String xformedSrc= CUs[i].getSource();
			String expectedSrc= getFileContents(outFileName);

			assertEqualLines(getName() + ": ", expectedSrc, xformedSrc);
		}
	}

	/**
	 * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
	 * whose names are supplied in the <code>fileBaseNames</code> argument,
	 * and compares the transformed code to source files whose names are
	 * the input base names plus the options suffix (e.g. "_FFF").
	 * Test files are assumed to be located in the resources directory.
	 * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
	 * @param inputFileBaseNames an array of input source file base names
	 * @throws Exception
	 */
	void multiUnitHelper(boolean staticFactoryMethod, String[] inputFileBaseNames)
		throws Exception
	{
		IPackageFragment	pkg= getPackageP();
		ICompilationUnit	CUs[]= new ICompilationUnit[inputFileBaseNames.length];

		for (int i = 0; i < inputFileBaseNames.length; i++)
			CUs[i] = createCUFromFileName(inputFileBaseNames[i], pkg);

		String	testPath= TEST_PATH_PREFIX + getRefactoringPath() + "positive/";

		doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);
	}

	/**
	 * Tests the IntroduceFactoryRefactoring refactoring on a set of input source files
	 * whose names are supplied in the <code>fileBaseNames</code> argument,
	 * and compares the transformed code to source files whose names are
	 * the input base names plus the options suffix (e.g. "_FFF").
	 * Test files are assumed to be located in the resources directory.
	 * @param staticFactoryMethod true iff IntroduceFactoryRefactoring should make the factory method static
	 * @param inputFileBaseNames an array of input source file base names
	 * @param factoryClassName the fully-qualified name of the class to receive the factory method, or null
	 * if the factory method is to be placed on the class defining the given constructor
	 * @throws Exception
	 */
	void multiUnitBugHelper(boolean staticFactoryMethod, String[] inputFileBaseNames, String factoryClassName)
		throws Exception
	{
		ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];

		for(int i= 0; i < inputFileBaseNames.length; i++) {
			int pkgEnd= inputFileBaseNames[i].lastIndexOf('/')+1;
			boolean explicitPkg= (pkgEnd > 0);
			IPackageFragment pkg= explicitPkg ? getRoot().createPackageFragment(inputFileBaseNames[i].substring(0, pkgEnd-1), true, new NullProgressMonitor()) : getPackageP();

			CUs[i]= createCUForBugTestCase(null, pkg, inputFileBaseNames[i].substring(pkgEnd), true);
		}

		String	testName= getName();
		String	testNumber= testName.substring("test".length());
		String	testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";

		doMultiUnitTest(CUs, testPath, inputFileBaseNames, factoryClassName);
	}

	void multiProjectBugHelper(String[] inputFileBaseNames, String[] dependencies) throws Exception {
		Map<String, Set<String>> projName2PkgNames= collectProjectPackages(inputFileBaseNames);
		Map<String, IJavaProject> projName2Project= new HashMap<>();
		Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot= new HashMap<>();

		try {
			createProjectPackageStructure(projName2PkgNames, projName2Project, proj2PkgRoot);

			ICompilationUnit[] CUs= createCUs(inputFileBaseNames, projName2Project, proj2PkgRoot);

			addProjectDependencies(dependencies, projName2Project);

			String testName= getName();
			String testNumber= testName.substring("test".length());
			String testPath= TEST_PATH_PREFIX + getRefactoringPath() + "Bugzilla/" + testNumber + "/";

			doMultiUnitTest(CUs, testPath, inputFileBaseNames, null);

		} finally {
			for (Iterator<IJavaProject> iter= proj2PkgRoot.keySet().iterator(); iter.hasNext();) {
				IJavaProject project= iter.next();
				if (project.exists()) {
					try {
						project.getProject().delete(true, null);
					} catch (CoreException e) {
						// swallow exception to avoid destroying the original one
						e.printStackTrace();
					}
				}
			}
		}
	}

	private ICompilationUnit[] createCUs(String[] inputFileBaseNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws Exception {
		ICompilationUnit CUs[]= new ICompilationUnit[inputFileBaseNames.length];

		for(int i= 0; i < inputFileBaseNames.length; i++) {
			String filePath= inputFileBaseNames[i];

			int projEnd= filePath.indexOf('/');
			int pkgEnd= filePath.lastIndexOf('/');
			int fileBegin= pkgEnd+1;

			String projName= filePath.substring(0, projEnd);
			String pkgName= filePath.substring(projEnd+1, pkgEnd).replace('/', '.');

			IJavaProject project= projName2Project.get(projName);
			IPackageFragmentRoot root= proj2PkgRoot.get(project);
			IPackageFragment pkg= root.getPackageFragment(pkgName);

			CUs[i]= createCUForBugTestCase(project, pkg, filePath.substring(fileBegin), true);
		}
		return CUs;
	}

	private void addProjectDependencies(String[] dependencies, Map<String, IJavaProject> projName2Project) throws JavaModelException {
		for (String dependency : dependencies) {
			// dependent:provider
			int colonIdx= dependency.indexOf(':');
			String depName= dependency.substring(0, colonIdx);
			String provName= dependency.substring(colonIdx+1);
			IJavaProject depProj= projName2Project.get(depName);
			IJavaProject provProj= projName2Project.get(provName);
			JavaProjectHelper.addRequiredProject(depProj, provProj);
		}
	}

	private void createProjectPackageStructure(Map<String, Set<String>> projName2PkgNames, Map<String, IJavaProject> projName2Project, Map<IJavaProject, IPackageFragmentRoot> proj2PkgRoot) throws CoreException, JavaModelException {
		for (Map.Entry<String, Set<String>> entry : projName2PkgNames.entrySet()) {
			String projName = entry.getKey();
			IJavaProject project= JavaProjectHelper.createJavaProject(projName, "bin");
			IPackageFragmentRoot root= JavaProjectHelper.addSourceContainer(project, CONTAINER);
			JavaProjectHelper.addRTJar(project);
			Set<IPackageFragment> pkgs= new HashSet<>();
			projName2Project.put(projName, project);
			proj2PkgRoot.put(project, root);
			for (String pkgName : entry.getValue()) {
				pkgs.add(root.createPackageFragment(pkgName, true, null));
			}
		}
	}

	private Map<String, Set<String>> collectProjectPackages(String[] inputFileBaseNames) {
		Map<String, Set<String>> proj2Pkgs= new HashMap<>();

		for (String filePath : inputFileBaseNames) {
			int projEnd= filePath.indexOf('/');
			String projName= filePath.substring(0, projEnd);
			String pkgName= filePath.substring(projEnd+1, filePath.lastIndexOf('/'));

			Set<String> projPkgs= proj2Pkgs.get(projName);

			if (projPkgs == null)
				proj2Pkgs.put(projName, projPkgs= new HashSet<>());
			projPkgs.add(pkgName);
		}
		return proj2Pkgs;
	}

	private void failHelper(int expectedStatus) throws Exception {
		ICompilationUnit	cu= createCUForSimpleTest(getPackageP(), false, true);
		ISourceRange		selection= findSelectionInSource(cu.getSource());
		IntroduceFactoryRefactoring	ref= new IntroduceFactoryRefactoring(cu, selection.getOffset(), selection.getLength());
		RefactoringStatus	result= performRefactoring(ref);

		assertNotNull("precondition was supposed to fail", result);
		assertEquals("status", expectedStatus, result.getSeverity());
	}

	//--- TESTS
	public void testStaticContext_FFF() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testInstanceContext_FFF() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	static final String[]	k_Names = { "createThing", "ThingFactory", "IThingFactory" };

	public void testNames_FFF() throws Exception {
		namesHelper(k_Names[0], null);
	}
	//
	// ================================================================================
	//
	public void testMultipleCallers_FFF() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testSelectConstructor() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testDifferentSigs() throws Exception {
		singleUnitHelper(false);
	}

	public void testDifferentArgs1() throws Exception {
		singleUnitHelper(false);
	}

	public void testDifferentArgs2() throws Exception {
		singleUnitHelper(false);
	}

	public void testDifferentArgs3() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testUnmovableArg1() throws Exception {
		singleUnitHelper(false);
	}

	public void testUnmovableArg2() throws Exception {
		singleUnitHelper(false);
	}

	public void testDontMoveArgs1() throws Exception {
		singleUnitHelper(false);
	}

	public void testDontMoveArgs2() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testProtectConstructor1() throws Exception {
		singleUnitHelper(true);
	}

	public void testProtectConstructor2() throws Exception {
		singleUnitHelper(true);
	}
	//
	// ================================================================================
	//
	public void testStaticInstance() throws Exception {
		singleUnitHelper(false);
	}
	//
	// ================================================================================
	//
	public void testCtorThrows() throws Exception {
		singleUnitHelper(true);
	}
	//
	// ================================================================================
	//
	public void testJavadocRef() throws Exception {
		singleUnitHelper(true);
	}
	//
	// ================================================================================
	//
	public void testNestedClass() throws Exception {
		failHelper(RefactoringStatus.FATAL);
	}



    //
    // ================================================================================
    // Generics-related tests
    public void testTypeParam() throws Exception {
        singleUnitHelper(true);
    }

    public void testTwoTypeParams() throws Exception {
        singleUnitHelper(true);
    }

    public void testBoundedTypeParam() throws Exception {
        singleUnitHelper(true);
    }

    public void testTwoBoundedTypeParams() throws Exception {
        singleUnitHelper(true);
    }

	public void testWildcardParam() throws Exception {
		singleUnitHelper(true);
	}

    public void testTypeParam2() throws Exception {
        namesHelper(null, "p.Factory");
    }
    //
	// ================================================================================
	// Other J2SE 5.0 tests
    public void testEnum() throws Exception {
    	failHelper(RefactoringStatus.FATAL);
    }

    public void testAnnotation1() throws Exception {
   		singleUnitHelper(true);
    }

    public void testAnnotation2() throws Exception {
   		singleUnitHelper(true);
    }

    public void testAnnotation3() throws Exception {
   		singleUnitHelper(true);
    }

	public void testVarArgsCtor() throws Exception {
	    // RMF - As of I20050202, search engine doesn't reliably find call sites to varargs methods
		singleUnitHelper(true);
	}
    //
	// ================================================================================
	//
	public void testMultipleUnits_FFF() throws Exception {
		multiUnitHelper(false, new String[] { "MultiUnit1A", "MultiUnit1B", "MultiUnit1C" });
	}
	//
	// ================================================================================
	// Bugzilla bug regression tests
	// ================================================================================
	//
	public void test45942() throws Exception {
		multiUnitBugHelper(true, new String[] { "TestClass", "UseTestClass" }, null);
	}

	public void test46189() throws Exception {
		singleUnitBugHelper("TestClass", true);
	}

	public void test46189B() throws Exception {
		singleUnitBugHelper("TestClass", true);
	}

	public void test46373() throws Exception {
		singleUnitBugHelper("ImplicitCtor", false);
	}

	public void test46374() throws Exception {
		singleUnitBugHelper("QualifiedName", false);
	}

	public void test46608() throws Exception {
		multiUnitBugHelper(true, new String[] { "p1/TT", "p2/TT" }, null);
	}

	public void test59284() throws Exception {
		singleUnitBugHelper("ArgTypeImport", true);
	}

	public void test59280() throws Exception {
		singleUnitBugHelper("ExplicitSuperCtorCall", true);
	}

	public void test48504() throws Exception {
		multiUnitBugHelper(true, new String[] { "p1/A", "p1/B" }, "p1.B");
	}

	public void test58293() throws Exception {
		singleUnitBugHelper("ImplicitSuperCtorCall", true);
	}

	public void test59283() throws Exception {
		multiProjectBugHelper(new String[] { "proj1/pA/A", "proj2/pB/B" },
				new String[] { "proj2:proj1" });
	}

	public void test84807() throws Exception {
		singleUnitBugHelper("CtorOfParamType", true);
	}

	public void test85465() throws Exception {
		singleUnitBugHelper("Varargs1", true);
	}

	public void test97507() throws Exception {
		singleUnitBugHelper("CtorTypeArgBounds", true);
	}

	public void test250660() throws Exception {
		singleUnitBugHelper("HasAnonymous", true);
	}

	public void test74759() throws Exception {
		singleUnitBugHelper("Test", true);
	}

	public void test298281() throws Exception {
		singleUnitBugHelper("Thing", true);
	}

	public void test395016_1() throws Exception {
		singleUnitBugHelperWithWarning("AbstractClass", true);
	}

	public void test395016_2() throws Exception {
		singleUnitBugHelperWithWarning("AbstractMethod", true);
	}

	public void testFactoryClash() throws Exception {
		failHelper(RefactoringStatus.ERROR);
	}
}
