org.codehaus.groovy.eclipse.refactoring.test.RefactoringTest.java Source code

Java tutorial

Introduction

Here is the source code for org.codehaus.groovy.eclipse.refactoring.test.RefactoringTest.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.codehaus.groovy.eclipse.refactoring.test;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import junit.framework.TestCase;

import org.codehaus.groovy.eclipse.refactoring.core.rename.ForcePreviewParticipant;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceManipulation;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameRequestor;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.corext.util.Strings;
import org.eclipse.jdt.testplugin.JavaProjectHelper;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.ChangeDescriptor;
import org.eclipse.ltk.core.refactoring.CheckConditionsOperation;
import org.eclipse.ltk.core.refactoring.CreateChangeOperation;
import org.eclipse.ltk.core.refactoring.IUndoManager;
import org.eclipse.ltk.core.refactoring.PerformChangeOperation;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringChangeDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringContribution;
import org.eclipse.ltk.core.refactoring.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;

public abstract class RefactoringTest extends TestCase {

    /**
     * If <code>true</code> a descriptor is created from the change.
     * The new descriptor is then used to create the refactoring again
     * and run the refactoring. As this is very time consuming this should
     * be <code>false</code> by default.
     */
    private static final boolean DESCRIPTOR_TEST = false;

    private IPackageFragmentRoot fRoot;
    private IPackageFragment fPackageP;

    public boolean fIsPreDeltaTest = false;

    public static final String TEST_PATH_PREFIX = "";

    protected static final String TEST_INPUT_INFIX = "/in/";
    protected static final String TEST_OUTPUT_INFIX = "/out/";
    protected static final String CONTAINER = "src";

    protected static final List/*<String>*/ PROJECT_RESOURCE_CHILDREN = Arrays
            .asList(new String[] { ".project", ".classpath", ".settings" });

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

    @Override
    protected void setUp() throws Exception {
        fRoot = RefactoringTestSetup.getDefaultSourceFolder();
        fPackageP = RefactoringTestSetup.getPackageP();
        fIsPreDeltaTest = false;

        System.out.println("\n---------------------------------------------");
        System.out.println("\nTest:" + getClass() + "." + getName());
        RefactoringCore.getUndoManager().flush();
        ForcePreviewParticipant.mute();
    }

    protected void performDummySearch() throws Exception {
        performDummySearch(getPackageP());
    }

    /**
     * Removes contents of {@link #getPackageP()}, of {@link #getRoot()} (except for p) and of the
     * Java project (except for src and the JRE library).
     *
     * @throws Exception in case of errors
     */
    @Override
    protected void tearDown() throws Exception {
        try {
            refreshFromLocal();
            performDummySearch();

            if (getPackageP().exists()) {
                tryDeletingAllJavaChildren(getPackageP());
                tryDeletingAllNonJavaChildResources(getPackageP());
            }

            if (getRoot().exists()) {
                IJavaElement[] packages = getRoot().getChildren();
                for (int i = 0; i < packages.length; i++) {
                    IPackageFragment pack = (IPackageFragment) packages[i];
                    if (!pack.equals(getPackageP()) && pack.exists() && !pack.isReadOnly())
                        if (pack.isDefaultPackage())
                            pack.delete(true, null);
                        else
                            JavaProjectHelper.delete(pack.getResource()); // also delete packages with subpackages
                }
            }

            restoreTestProject();
        } finally {
            TestRenameParticipantShared.reset();
            TestRenameParticipantSingle.reset();
            ForcePreviewParticipant.unmute();

        }
    }

    private void restoreTestProject() throws Exception {
        IJavaProject javaProject = getRoot().getJavaProject();
        if (javaProject.exists()) {
            IClasspathEntry srcEntry = getRoot().getRawClasspathEntry();
            try {
                IClasspathEntry[] jreEntries = RefactoringTestSetup.getJRELibrariesAsRawClasspathEntry();
                IClasspathEntry[] cpes = javaProject.getRawClasspath();
                ArrayList newCPEs = new ArrayList();
                boolean cpChanged = false;
                for (int i = 0; i < cpes.length; i++) {
                    IClasspathEntry cpe = cpes[i];
                    boolean isJREEntry = false;
                    for (int j = 0; j < jreEntries.length; j++) {
                        if (cpe.equals(jreEntries[j])) {
                            isJREEntry = true;
                            break;
                        }
                    }
                    if (cpe.equals(srcEntry) || isJREEntry) {
                        newCPEs.add(cpe);
                    } else {
                        cpChanged = true;
                    }
                }
                if (cpChanged) {
                    IClasspathEntry[] newCPEsArray = (IClasspathEntry[]) newCPEs
                            .toArray(new IClasspathEntry[newCPEs.size()]);
                    javaProject.setRawClasspath(newCPEsArray, null);
                }
            } catch (JavaModelException e) {
                System.err.println(
                        "Exception thrown when trying to restore project to original state.  We can probable ignore this.");
                e.printStackTrace();
            }

            Object[] nonJavaResources = javaProject.getNonJavaResources();
            for (int i = 0; i < nonJavaResources.length; i++) {
                Object kid = nonJavaResources[i];
                if (kid instanceof IResource) {
                    IResource resource = (IResource) kid;
                    if (!PROJECT_RESOURCE_CHILDREN.contains(resource.getName())) {
                        JavaProjectHelper.delete(resource);
                    }
                }
            }
        }
    }

    private void refreshFromLocal() throws CoreException {
        if (getRoot().exists())
            getRoot().getResource().refreshLocal(IResource.DEPTH_INFINITE, null);
        else if (getPackageP().exists())//don't refresh package if root already refreshed
            getPackageP().getResource().refreshLocal(IResource.DEPTH_INFINITE, null);
    }

    private static void tryDeletingAllNonJavaChildResources(IPackageFragment pack) throws CoreException {
        Object[] nonJavaKids = pack.getNonJavaResources();
        for (int i = 0; i < nonJavaKids.length; i++) {
            if (nonJavaKids[i] instanceof IResource) {
                IResource resource = (IResource) nonJavaKids[i];
                JavaProjectHelper.delete(resource);
            }
        }
    }

    private static void tryDeletingAllJavaChildren(IPackageFragment pack) throws CoreException {
        IJavaElement[] kids = pack.getChildren();
        for (int i = 0; i < kids.length; i++) {
            if (kids[i] instanceof ISourceManipulation) {
                if (kids[i].exists() && !kids[i].isReadOnly())
                    JavaProjectHelper.delete(kids[i]);
            }
        }
    }

    protected IPackageFragmentRoot getRoot() {
        return fRoot;
    }

    protected IPackageFragment getPackageP() {
        return fPackageP;
    }

    protected IJavaProject getProject() {
        return fRoot.getJavaProject();
    }

    protected final RefactoringStatus performRefactoring(RefactoringDescriptor descriptor) throws Exception {
        return performRefactoring(descriptor, true);
    }

    protected final RefactoringStatus performRefactoring(RefactoringDescriptor descriptor, boolean providesUndo)
            throws Exception {
        Refactoring refactoring = createRefactoring(descriptor);
        return performRefactoring(refactoring, providesUndo);
    }

    protected final Refactoring createRefactoring(RefactoringDescriptor descriptor) throws CoreException {
        RefactoringStatus status = new RefactoringStatus();
        Refactoring refactoring = descriptor.createRefactoring(status);
        assertNotNull("refactoring should not be null", refactoring);
        assertTrue("status should be ok", status.isOK());
        return refactoring;
    }

    protected final RefactoringStatus performRefactoring(Refactoring ref, boolean performOnFail) throws Exception {
        return performRefactoring(ref, true, performOnFail);
    }

    protected final RefactoringStatus performRefactoring(Refactoring ref, boolean providesUndo,
            boolean performOnFail) throws Exception {
        performDummySearch();
        IUndoManager undoManager = getUndoManager();
        if (DESCRIPTOR_TEST) {
            final CreateChangeOperation create = new CreateChangeOperation(
                    new CheckConditionsOperation(ref, CheckConditionsOperation.ALL_CONDITIONS),
                    RefactoringStatus.FATAL);
            create.run(new NullProgressMonitor());
            RefactoringStatus checkingStatus = create.getConditionCheckingStatus();
            if (checkingStatus.hasError())
                return checkingStatus;
            Change change = create.getChange();
            ChangeDescriptor descriptor = change.getDescriptor();
            if (descriptor instanceof RefactoringChangeDescriptor) {
                RefactoringChangeDescriptor rcd = (RefactoringChangeDescriptor) descriptor;
                RefactoringDescriptor refactoringDescriptor = rcd.getRefactoringDescriptor();
                if (refactoringDescriptor instanceof JavaRefactoringDescriptor) {
                    JavaRefactoringDescriptor jrd = (JavaRefactoringDescriptor) refactoringDescriptor;
                    RefactoringStatus validation = jrd.validateDescriptor();
                    if (validation.hasError() && !performOnFail)
                        return validation;
                    RefactoringStatus refactoringStatus = new RefactoringStatus();
                    Class expected = jrd.getClass();
                    RefactoringContribution contribution = RefactoringCore.getRefactoringContribution(jrd.getID());
                    jrd = (JavaRefactoringDescriptor) contribution.createDescriptor(jrd.getID(), jrd.getProject(),
                            jrd.getDescription(), jrd.getComment(), contribution.retrieveArgumentMap(jrd),
                            jrd.getFlags());
                    assertEquals(expected, jrd.getClass());
                    ref = jrd.createRefactoring(refactoringStatus);
                    if (refactoringStatus.hasError() && !performOnFail)
                        return refactoringStatus;
                    TestRenameParticipantSingle.reset();
                }
            }
        }
        final CreateChangeOperation create = new CreateChangeOperation(
                new CheckConditionsOperation(ref, CheckConditionsOperation.ALL_CONDITIONS),
                RefactoringStatus.FATAL);
        final PerformChangeOperation perform = new PerformChangeOperation(create);
        perform.setUndoManager(undoManager, ref.getName());
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        executePerformOperation(perform, workspace);
        RefactoringStatus status = create.getConditionCheckingStatus();
        if (!status.hasError() && !performOnFail)
            return status;
        assertTrue("Change wasn't executed", perform.changeExecuted());
        Change undo = perform.getUndoChange();
        if (providesUndo) {
            assertNotNull("Undo doesn't exist", undo);
            assertTrue("Undo manager is empty", undoManager.anythingToUndo());
        } else {
            assertNull("Undo manager contains undo but shouldn't", undo);
        }
        return null;
    }

    protected void executePerformOperation(final PerformChangeOperation perform, IWorkspace workspace)
            throws CoreException {
        workspace.run(perform, new NullProgressMonitor());
    }

    public RefactoringStatus performRefactoringWithStatus(Refactoring ref, boolean performOnFail)
            throws Exception, CoreException {
        RefactoringStatus status = performRefactoring(ref, performOnFail);
        if (status == null)
            return new RefactoringStatus();
        return status;
    }

    protected final Change performChange(Refactoring refactoring, boolean storeUndo) throws Exception {
        CreateChangeOperation create = new CreateChangeOperation(refactoring);
        PerformChangeOperation perform = new PerformChangeOperation(create);
        if (storeUndo) {
            perform.setUndoManager(getUndoManager(), refactoring.getName());
        }
        ResourcesPlugin.getWorkspace().run(perform, new NullProgressMonitor());
        assertTrue("Change wasn't executed", perform.changeExecuted());
        return perform.getUndoChange();
    }

    protected final Change performChange(final Change change) throws Exception {
        PerformChangeOperation perform = new PerformChangeOperation(change);
        ResourcesPlugin.getWorkspace().run(perform, new NullProgressMonitor());
        assertTrue("Change wasn't executed", perform.changeExecuted());
        return perform.getUndoChange();
    }

    protected IUndoManager getUndoManager() {
        IUndoManager undoManager = RefactoringCore.getUndoManager();
        undoManager.flush();
        return undoManager;
    }

    /* ===================  helpers  ================= */
    protected IType getType(ICompilationUnit cu, String name) throws JavaModelException {
        IType[] types = cu.getAllTypes();
        for (int i = 0; i < types.length; i++)
            if (types[i].getTypeQualifiedName('.').equals(name) || types[i].getElementName().equals(name))
                return types[i];
        return null;
    }

    /*
     * subclasses override to inform about the location of their test cases
     */
    protected String getRefactoringPath() {
        return "";
    }

    /*
     *  example "RenameType/"
     */
    protected String getTestPath() {
        return TEST_PATH_PREFIX + getRefactoringPath();
    }

    protected String createTestFileName(String cuName, String infix) {
        return getTestPath() + getName() + infix + cuName + ".groovy";
    }

    protected String getInputTestFileName(String cuName) {
        return createTestFileName(cuName, TEST_INPUT_INFIX);
    }

    /*
     * @param subDirName example "p/" or "org/eclipse/jdt/"
     */
    protected String getInputTestFileName(String cuName, String subDirName) {
        return createTestFileName(cuName, TEST_INPUT_INFIX + subDirName);
    }

    protected String getOutputTestFileName(String cuName) {
        return createTestFileName(cuName, TEST_OUTPUT_INFIX);
    }

    /*
     * @param subDirName example "p/" or "org/eclipse/jdt/"
     */
    protected String getOutputTestFileName(String cuName, String subDirName) {
        return createTestFileName(cuName, TEST_OUTPUT_INFIX + subDirName);
    }

    protected ICompilationUnit createCUfromTestFile(IPackageFragment pack, String cuName) throws Exception {
        return createCUfromTestFile(pack, cuName, true);
    }

    protected ICompilationUnit createCUfromTestFile(IPackageFragment pack, String cuName, String subDirName)
            throws Exception {
        return createCUfromTestFile(pack, cuName, subDirName, true);
    }

    protected ICompilationUnit createCUfromTestFile(IPackageFragment pack, String cuName, boolean input)
            throws Exception {
        String contents = input ? getFileContents(getInputTestFileName(cuName))
                : getFileContents(getOutputTestFileName(cuName));
        return createCU(pack, cuName + ".groovy", contents);
    }

    protected ICompilationUnit createCUfromTestFile(IPackageFragment pack, String cuName, String subDirName,
            boolean input) throws Exception {
        String contents = input ? getFileContents(getInputTestFileName(cuName, subDirName))
                : getFileContents(getOutputTestFileName(cuName, subDirName));

        return createCU(pack, cuName + ".groovy", contents);
    }

    protected void printTestDisabledMessage(String explanation) {
        System.out.println("\n" + getClass().getName() + "::" + getName() + " disabled (" + explanation + ")");
    }

    //-----------------------
    public static InputStream getStream(String content) {
        return new ByteArrayInputStream(content.getBytes());
    }

    public static IPackageFragmentRoot getSourceFolder(IJavaProject javaProject, String name)
            throws JavaModelException {
        IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
        for (int i = 0; i < roots.length; i++) {
            if (!roots[i].isArchive() && roots[i].getElementName().equals(name))
                return roots[i];
        }
        return null;
    }

    public String getFileContents(String fileName) throws IOException {
        return getContents(getFileInputStream(fileName));
    }

    public static String getContents(IFile file) throws IOException, CoreException {
        return getContents(file.getContents());
    }

    public static ICompilationUnit createCU(IPackageFragment pack, String name, String contents) throws Exception {
        assertTrue(!pack.getCompilationUnit(name).exists());
        ICompilationUnit cu = pack.createCompilationUnit(name, contents, true, null);
        cu.save(null, true);
        return cu;
    }

    public static String getContents(InputStream in) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        StringBuffer sb = new StringBuffer(300);
        try {
            int read = 0;
            while ((read = br.read()) != -1)
                sb.append((char) read);
        } finally {
            br.close();
        }
        return sb.toString();
    }

    public static InputStream getFileInputStream(String fileName) throws IOException {
        return RefactoringTestPlugin.getDefault().getTestResourceStream(fileName);
    }

    public static String removeExtension(String fileName) {
        return fileName.substring(0, fileName.lastIndexOf('.'));
    }

    public static void performDummySearch(IJavaElement element) throws Exception {
        new SearchEngine().searchAllTypeNames(null, SearchPattern.R_EXACT_MATCH, "XXXXXXXXX".toCharArray(), // make sure we search a concrete name. This is faster according to Kent
                SearchPattern.R_EXACT_MATCH, IJavaSearchConstants.CLASS,
                SearchEngine.createJavaSearchScope(new IJavaElement[] { element }), new Requestor(),
                IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
    }

    public static IMember[] merge(IMember[] a1, IMember[] a2, IMember[] a3) {
        return JavaElementUtil.merge(JavaElementUtil.merge(a1, a2), a3);
    }

    public static IMember[] merge(IMember[] a1, IMember[] a2) {
        return JavaElementUtil.merge(a1, a2);
    }

    public static IField[] getFields(IType type, String[] names) {
        if (names == null)
            return new IField[0];
        Set fields = new HashSet();
        for (int i = 0; i < names.length; i++) {
            IField field = type.getField(names[i]);
            assertTrue("field " + field.getElementName() + " does not exist", field.exists());
            fields.add(field);
        }
        return (IField[]) fields.toArray(new IField[fields.size()]);
    }

    public static IType[] getMemberTypes(IType type, String[] names) {
        if (names == null)
            return new IType[0];
        Set memberTypes = new HashSet();
        for (int i = 0; i < names.length; i++) {
            IType memberType;
            if (names[i].indexOf('.') != -1) {
                String[] path = names[i].split("\\.");
                memberType = type.getType(path[0]);
                for (int j = 1; j < path.length; j++) {
                    memberType = memberType.getType(path[j]);
                }
            } else
                memberType = type.getType(names[i]);
            assertTrue("member type " + memberType.getElementName() + " does not exist", memberType.exists());
            memberTypes.add(memberType);
        }
        return (IType[]) memberTypes.toArray(new IType[memberTypes.size()]);
    }

    public static IMethod[] getMethods(IType type, String[] names, String[][] signatures) {
        if (names == null || signatures == null)
            return new IMethod[0];
        List methods = new ArrayList(names.length);
        for (int i = 0; i < names.length; i++) {
            IMethod method = type.getMethod(names[i], signatures[i]);
            assertTrue("method " + method.getElementName() + " does not exist", method.exists());
            if (!methods.contains(method))
                methods.add(method);
        }
        return (IMethod[]) methods.toArray(new IMethod[methods.size()]);
    }

    public static IType[] findTypes(IType[] types, String[] namesOfTypesToPullUp) {
        List found = new ArrayList(types.length);
        for (int i = 0; i < types.length; i++) {
            IType type = types[i];
            for (int j = 0; j < namesOfTypesToPullUp.length; j++) {
                String name = namesOfTypesToPullUp[j];
                if (type.getElementName().equals(name))
                    found.add(type);
            }
        }
        return (IType[]) found.toArray(new IType[found.size()]);
    }

    public static IField[] findFields(IField[] fields, String[] namesOfFieldsToPullUp) {
        List found = new ArrayList(fields.length);
        for (int i = 0; i < fields.length; i++) {
            IField field = fields[i];
            for (int j = 0; j < namesOfFieldsToPullUp.length; j++) {
                String name = namesOfFieldsToPullUp[j];
                if (field.getElementName().equals(name))
                    found.add(field);
            }
        }
        return (IField[]) found.toArray(new IField[found.size()]);
    }

    public static IMethod[] findMethods(IMethod[] selectedMethods, String[] namesOfMethods,
            String[][] signaturesOfMethods) {
        List found = new ArrayList(selectedMethods.length);
        for (int i = 0; i < selectedMethods.length; i++) {
            IMethod method = selectedMethods[i];
            String[] paramTypes = method.getParameterTypes();
            for (int j = 0; j < namesOfMethods.length; j++) {
                String methodName = namesOfMethods[j];
                if (!methodName.equals(method.getElementName()))
                    continue;
                String[] methodSig = signaturesOfMethods[j];
                if (!areSameSignatures(paramTypes, methodSig))
                    continue;
                found.add(method);
            }
        }
        return (IMethod[]) found.toArray(new IMethod[found.size()]);
    }

    private static boolean areSameSignatures(String[] s1, String[] s2) {
        if (s1.length != s2.length)
            return false;
        for (int i = 0; i < s1.length; i++) {
            if (!s1[i].equals(s2[i]))
                return false;
        }
        return true;
    }

    /**
     * Line-based version of junit.framework.Assert.assertEquals(String, String)
     * without considering line delimiters.
     * @param expected the expected value
     * @param actual the actual value
     */
    public static void assertEqualLines(String expected, String actual) {
        assertEqualLines("", expected, actual);
    }

    /**
     * Line-based version of junit.framework.Assert.assertEquals(String, String, String)
     * without considering line delimiters.
     * @param message the message
     * @param expected the expected value
     * @param actual the actual value
     */
    public static void assertEqualLines(String message, String expected, String actual) {
        String[] expectedLines = Strings.convertIntoLines(expected);
        String[] actualLines = Strings.convertIntoLines(actual);

        String expected2 = (expectedLines == null ? null : Strings.concatenate(expectedLines, "\n"));
        String actual2 = (actualLines == null ? null : Strings.concatenate(actualLines, "\n"));
        assertEquals(message, expected2, actual2);
    }

    private static class Requestor extends TypeNameRequestor {
    }
}