blob: 3ebf653ae4559283c3065b057bc6cc8722a3597f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ui.tests.refactoring;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringBufferInputStream;
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.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
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.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.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Strings;
import org.eclipse.jdt.ui.tests.refactoring.infra.RefactoringTestPlugin;
import org.eclipse.ltk.core.refactoring.Change;
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.RefactoringCore;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
public abstract class RefactoringTest extends TestCase {
private IPackageFragmentRoot fRoot;
private IPackageFragment fPackageP;
public boolean fIsVerbose= false;
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);
}
protected void setUp() throws Exception {
fRoot= RefactoringTestSetup.getDefaultSourceFolder();
fPackageP= RefactoringTestSetup.getPackageP();
fIsPreDeltaTest= false;
if (fIsVerbose){
System.out.println("\n---------------------------------------------");
System.out.println("\nTest:" + getClass() + "." + getName());
}
RefactoringCore.getUndoManager().flush();
}
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
*/
protected void tearDown() throws Exception {
refreshFromLocal();
performDummySearch();
if (getPackageP().exists()){
tryDeletingAllJavaChildren(getPackageP());
tryDeletingAllNonJavaChildResources(getPackageP());
}
if (getRoot().exists()){
IJavaElement[] packages= getRoot().getChildren();
for (int i= 0; i < packages.length; i++){
try{
IPackageFragment pack= (IPackageFragment)packages[i];
if (! pack.equals(getPackageP()) && pack.exists() && ! pack.isReadOnly())
if (pack.isDefaultPackage())
pack.delete(true, null);
else
pack.getResource().delete(true, null); // also delete packages with subpackages
} catch (JavaModelException e){
//try to delete'em all
e.printStackTrace();
}
}
}
restoreTestProject();
}
private void restoreTestProject() throws Exception {
IJavaProject javaProject= getRoot().getJavaProject();
if (javaProject.exists()) {
IClasspathEntry srcEntry= getRoot().getRawClasspathEntry();
IClasspathEntry jreEntry= RefactoringTestSetup.getJRELibrary().getRawClasspathEntry();
IClasspathEntry[] cpes= javaProject.getRawClasspath();
ArrayList newCPEs= new ArrayList();
boolean cpChanged= false;
for (int i= 0; i < cpes.length; i++) {
IClasspathEntry cpe= cpes[i];
if (cpe.equals(srcEntry) || cpe.equals(jreEntry)) {
newCPEs.add(cpe);
} else {
cpChanged= true;
}
}
if (cpChanged) {
IClasspathEntry[] newCPEsArray= (IClasspathEntry[]) newCPEs.toArray(new IClasspathEntry[newCPEs.size()]);
javaProject.setRawClasspath(newCPEsArray, null);
}
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())) {
try {
resource.delete(true, null);
} catch (CoreException e) {
//try to delete'em all
e.printStackTrace();
}
}
}
}
}
}
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 JavaModelException {
Object[] nonJavaKids= pack.getNonJavaResources();
for (int i= 0; i < nonJavaKids.length; i++) {
if (nonJavaKids[i] instanceof IResource) {
IResource resource= (IResource)nonJavaKids[i];
try {
resource.delete(true, null);
} catch (CoreException e) {
//try to delete'em all
e.printStackTrace();
}
}
}
}
private static void tryDeletingAllJavaChildren(IPackageFragment pack) throws JavaModelException {
IJavaElement[] kids= pack.getChildren();
for (int i= 0; i < kids.length; i++){
if (kids[i] instanceof ISourceManipulation){
try{
if (kids[i].exists() && ! kids[i].isReadOnly())
((ISourceManipulation)kids[i]).delete(true, null);
} catch (JavaModelException e){
//try to delete'em all
e.printStackTrace();
}
}
}
}
protected IPackageFragmentRoot getRoot() {
return fRoot;
}
protected IPackageFragment getPackageP() {
return fPackageP;
}
protected final RefactoringStatus performRefactoring(Refactoring ref) throws Exception {
return performRefactoring(ref, true);
}
protected final RefactoringStatus performRefactoring(Refactoring ref, boolean providesUndo) throws Exception {
performDummySearch();
IUndoManager undoManager= getUndoManager();
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();
if (fIsPreDeltaTest) {
IResourceChangeListener listener= new IResourceChangeListener() {
public void resourceChanged(IResourceChangeEvent event) {
if (create.getConditionCheckingStatus().isOK() && perform.changeExecuted()) {
TestModelProvider.assertTrue(event.getDelta());
}
}
};
try {
TestModelProvider.clearDelta();
workspace.checkpoint(false);
workspace.addResourceChangeListener(listener);
executePerformOperation(perform, workspace);
} finally {
workspace.removeResourceChangeListener(listener);
}
} else {
executePerformOperation(perform, workspace);
}
RefactoringStatus status= create.getConditionCheckingStatus();
if (!status.isOK())
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());
}
protected final RefactoringStatus performRefactoringWithStatus(Refactoring ref) throws Exception {
performDummySearch();
CreateChangeOperation create= new CreateChangeOperation(
new CheckConditionsOperation(ref, CheckConditionsOperation.ALL_CONDITIONS),
RefactoringStatus.FATAL);
PerformChangeOperation perform= new PerformChangeOperation(create);
perform.setUndoManager(RefactoringCore.getUndoManager(), ref.getName());
ResourcesPlugin.getWorkspace().run(perform, new NullProgressMonitor());
RefactoringStatus status= create.getConditionCheckingStatus();
if (status.hasFatalError())
return status;
assertTrue("Change wasn't executed", perform.changeExecuted());
return status;
}
protected final Change performChange(final 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 (JavaModelUtil.getTypeQualifiedName(types[i]).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 + ".java";
}
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 + ".java", 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 + ".java", contents);
}
protected void printTestDisabledMessage(String explanation){
System.out.println("\n" +getClass().getName() + "::"+ getName() + " disabled (" + explanation + ")");
}
//-----------------------
public static InputStream getStream(String content){
return new StringBufferInputStream(content);
}
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 {
if (pack.getCompilationUnit(name).exists())
return pack.getCompilationUnit(name);
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,
"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) throws JavaModelException{
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) throws JavaModelException{
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) throws JavaModelException{
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 {
}
}