blob: e6f88be0b4d04e39655cb5f5122e0aec79ac5399 [file] [log] [blame]
/**********************************************************************
* This file is part of "Object Teams Development Tooling"-Software
*
* Copyright 2004, 2010 Fraunhofer Gesellschaft, Munich, Germany,
* for its Fraunhofer Institute and Computer Architecture and Software
* Technology (FIRST), Berlin, Germany and Technical University Berlin,
* Germany.
*
* 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
* $Id$
*
* Please visit http://www.eclipse.org/objectteams for updates and contact.
*
* Contributors:
* Fraunhofer FIRST - Initial API and implementation
* Technical University Berlin - Initial API and implementation
**********************************************************************/
package org.eclipse.objectteams.otdt.ui.tests.refactoring.pullup;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.core.runtime.NullProgressMonitor;
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.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.structure.PullUpRefactoringProcessor;
import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
import org.eclipse.ltk.core.refactoring.participants.ProcessorBasedRefactoring;
import org.eclipse.objectteams.otdt.ui.tests.refactoring.MySetup;
import org.eclipse.objectteams.otdt.ui.tests.refactoring.RefactoringTest;
/**
* Example TestCase to practice testing for the diploma thesis.
*
* @author Johannes Gebauer
*/
@SuppressWarnings("restriction")
public class PullUpTests extends RefactoringTest {
private static final String REFACTORING_PATH = "PullUp/";
public PullUpTests(String name) {
super(name);
}
public static Test suite() {
return new MySetup(new TestSuite(PullUpTests.class));
}
public static Test setUpTest(Test test) {
return new MySetup(test);
}
protected String getRefactoringPath() {
return REFACTORING_PATH;
}
private void setTargetClass(PullUpRefactoringProcessor processor, int targetClassIndex) throws JavaModelException {
IType[] possibleClasses = getPossibleTargetClasses(processor);
processor.setDestinationType(getPossibleTargetClasses(processor)[possibleClasses.length - 1 - targetClassIndex]);
}
private IType[] getPossibleTargetClasses(PullUpRefactoringProcessor processor) throws JavaModelException {
return processor.getCandidateTypes(new RefactoringStatus(), new NullProgressMonitor());
}
private static IMethod[] getMethods(IMember[] members) {
List<IJavaElement> l = Arrays.asList(JavaElementUtil.getElementsOfType(members, IJavaElement.METHOD));
return l.toArray(new IMethod[l.size()]);
}
private static PullUpRefactoringProcessor createRefactoringProcessor(IMember[] methods) throws JavaModelException {
IJavaProject project = null;
if (methods != null && methods.length > 0)
project = methods[0].getJavaProject();
if (RefactoringAvailabilityTester.isPullUpAvailable(methods)) {
PullUpRefactoringProcessor processor = new PullUpRefactoringProcessor(methods, JavaPreferencesSettings.getCodeGenerationSettings(project));
new ProcessorBasedRefactoring(processor);
return processor;
}
return null;
}
/**
* The <code>ICompilationUnit</code> containing the declaring type must be
* at position 0.
*
* @param fieldNames
* TODO
*/
private void performPullUp_pass(String[] cuNames, String[] methodNames, String[][] signatures, String[] fieldNames, boolean deleteAllInSourceType,
boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType) throws Exception {
performPullUp_pass(cuNames, methodNames, signatures, null, fieldNames, deleteAllInSourceType, deleteAllMatchingMethods, targetClassIndex, nameOfDeclaringType);
}
private void performPullUp_pass(String[] cuNames, String[] methodNames, String[][] signatures, boolean[] makeAbstract, String[] fieldNames,
boolean deleteAllInSourceType, boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType) throws Exception {
performPullUp_pass(cuNames, methodNames, signatures, makeAbstract, fieldNames, deleteAllInSourceType, deleteAllMatchingMethods, targetClassIndex, nameOfDeclaringType, false/*replace*/);
}
private void performPullUp_pass(String[] cuNames, String[] methodNames, String[][] signatures, boolean[] makeAbstract, String[] fieldNames,
boolean deleteAllInSourceType, boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType, boolean replace)
throws Exception
{
ICompilationUnit[] cus = createCUs(cuNames);
try {
IType declaringType = getType(cus[0], nameOfDeclaringType);
IMethod[] methods = getMethods(declaringType, methodNames, signatures, makeAbstract, false);
IField[] fields = getFields(declaringType, fieldNames);
IMember[] members = merge(methods, fields);
PullUpRefactoringProcessor processor = createRefactoringProcessor(members);
if (makeAbstract != null)
processor.setAbstractMethods(getMethods(declaringType, methodNames, signatures, makeAbstract, true));
Refactoring ref = processor.getRefactoring();
assertTrue("activation", ref.checkInitialConditions(new NullProgressMonitor()).isOK());
setTargetClass(processor, targetClassIndex);
List<IMethod> methodList = new ArrayList<IMethod>();
if (deleteAllInSourceType)
methodList.addAll(Arrays.asList(methods));
if (deleteAllMatchingMethods)
methodList.addAll(Arrays.asList(getMethods(processor.getMatchingElements(new NullProgressMonitor(), false))));
if (!methodList.isEmpty())
processor.setDeletedMethods(methodList.toArray(new IMethod[methodList.size()]));
if (replace)
processor.setReplace(true);
RefactoringStatus checkInputResult = ref.checkFinalConditions(new NullProgressMonitor());
assertTrue("precondition was supposed to pass", !checkInputResult.hasError());
performChange(ref, false);
for (int i = 0; i < cus.length; i++) {
String expected = getFileContents(getOutputTestFileName(cuNames[i]));
String actual = cus[i].getSource();
assertEqualLines(expected, actual);
}
} finally {
performDummySearch();
for (int i = 0; i < cus.length; i++) {
cus[i].delete(false, null);
}
}
}
/**
* The <code>ICompilationUnit</code> containing the declaring type must be
* at position 0.
*/
private void performPullUp_warning(String[] cuNames, String[] methodNames, String[][] signatures, boolean deleteAllInSourceType,
boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType) throws Exception {
ICompilationUnit[] cus = createCUs(cuNames);
try {
IType declaringType = getType(cus[0], nameOfDeclaringType);
IMethod[] methods = getMethods(declaringType, methodNames, signatures);
PullUpRefactoringProcessor processor = createRefactoringProcessor(methods);
Refactoring ref = processor.getRefactoring();
assertTrue("activation", ref.checkInitialConditions(new NullProgressMonitor()).isOK());
setTargetClass(processor, targetClassIndex);
if (deleteAllInSourceType)
processor.setDeletedMethods(methods);
if (deleteAllMatchingMethods)
processor.setDeletedMethods(getMethods(processor.getMatchingElements(new NullProgressMonitor(), false)));
RefactoringStatus checkInputResult = ref.checkFinalConditions(new NullProgressMonitor());
RefactoringStatusEntry[] initialConditionStatus = checkInputResult.getEntries();
assertEquals("precondition was supposed to give a warning", RefactoringStatus.WARNING, initialConditionStatus[0].getSeverity());
assertEquals("precondition was supposed to give only one warning", initialConditionStatus.length, 1);
performChange(ref, false);
for (int i = 0; i < cus.length; i++) {
String expected = getFileContents(getOutputTestFileName(cuNames[i]));
String actual = cus[i].getSource();
assertEqualLines(expected, actual);
}
} finally {
performDummySearch();
for (int i = 0; i < cus.length; i++) {
cus[i].delete(false, null);
}
}
}
private void performPullUp_failing(String[] cuNames, String[] methodNames, String[][] signatures, String[] fieldNames, boolean deleteAllInSourceType,
boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType) throws Exception {
performPullUp_failing(cuNames, methodNames, signatures, null,
fieldNames, deleteAllInSourceType, deleteAllMatchingMethods, targetClassIndex, nameOfDeclaringType,
null);
}
private void performPullUp_failing(String[] cuNames, String[] methodNames, String[][] signatures, boolean[] makeAbstract, String[] fieldNames, boolean deleteAllInSourceType,
boolean deleteAllMatchingMethods, int targetClassIndex, String nameOfDeclaringType, String[] errorMessages)
throws Exception
{
ICompilationUnit[] cus = createCUs(cuNames);
try {
IType declaringType = getType(cus[0], nameOfDeclaringType);
IMethod[] methods = getMethods(declaringType, methodNames, signatures, makeAbstract, false);
IField[] fields = getFields(declaringType, fieldNames);
IMember[] members = merge(methods, fields);
PullUpRefactoringProcessor processor = createRefactoringProcessor(members);
if (makeAbstract != null)
processor.setAbstractMethods(getMethods(declaringType, methodNames, signatures, makeAbstract, true));
Refactoring ref = processor.getRefactoring();
setTargetClass(processor, targetClassIndex);
if (deleteAllInSourceType)
processor.setDeletedMethods(methods);
if (deleteAllMatchingMethods)
processor.setDeletedMethods(getMethods(processor.getMatchingElements(new NullProgressMonitor(), false)));
RefactoringStatus result = performRefactoring(ref);
assertNotNull("precondition was supposed to fail.", result);
assertTrue("precondition was supposed to fail.", !result.isOK());
assertNotNull("precondition result is expected to contain an error.", result.getEntryMatchingSeverity(RefactoringStatus.ERROR));
if (errorMessages != null) {
int i=0;
for(RefactoringStatusEntry entry : result.getEntries()) {
if (entry.isFatalError()) {
assertEquals("Wrong error message", errorMessages[i++], entry.getMessage());
}
}
assertEquals("Wrong number of error messages", errorMessages.length, i);
}
} finally {
performDummySearch();
for (int i = 0; i < cus.length; i++) {
cus[i].delete(false, null);
}
}
}
/******* tests ******************/
/* Pull up Method Tests */
public void testPullUpBoundMethod() throws Exception {
performPullUp_warning(new String[] { "B", "BSuper", "T" }, new String[] { "bm" }, new String[][] { new String[0] }, true, false, 0, "B");
}
public void testPullUpCallinMethod() throws Exception {
performPullUp_pass(new String[] { "T", "TSuper", "B" }, new String[] { "rm" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "R");
}
public void testPullUpMethodToImplicitSuperclass() throws Exception {
performPullUp_pass(new String[] { "T", "TSuper", "B" }, new String[] { "rm" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "R");
}
public void testDeletionOfMatchingMethods() throws Exception {
performPullUp_pass(new String[] { "T", "T2", "TSuper", "B" }, new String[] { "rm" }, new String[][] { new String[0] }, new String[] {}, true, true, 0,
"R");
}
public void testReferencingRoleInDeclaredLifting() throws Exception {
performPullUp_failing(new String[] { "T", "TSuper", "B" }, new String[] { "m" }, new String[][] { new String[] { "QB;" } }, new String[] {}, true,
false, 0, "T");
}
public void testPulledUpMethodIsOverriddenInImplicitSubRole() throws Exception {
performPullUp_failing(new String[] { "T1", "T2", "TSuper", }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false, 0,
"R");
}
public void testAmbiguityInExplicitRelatedRole1() throws Exception {
performPullUp_failing(new String[] { "T", "B" }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "R1");
}
public void testAmbiguityInExplicitRelatedRole2() throws Exception {
performPullUp_failing(new String[] { "T", "B" }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "R1");
}
public void testAmbiguityInImplicitRelatedRole1() throws Exception {
performPullUp_failing(new String[] { "T1", "T2", "TSuper", "B" }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false,
0, "R");
}
public void testAmbiguityInImplicitRelatedRole2() throws Exception {
performPullUp_failing(new String[] { "T1", "T2", "TSuper", "B" }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false,
0, "R");
}
public void testAmbiguityInBase1() throws Exception {
performPullUp_failing(new String[] { "B2", "B1", "T" }, new String[] { "bm" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "B2");
}
public void testAmbiguityInBase2() throws Exception {
performPullUp_failing(new String[] { "B2", "B1", "T" }, new String[] { "bm" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "B2");
}
public void testPullUpCallinIntoRegularClass() throws Exception {
performPullUp_failing(new String[] { "T", "C" }, new String[] { "m" }, new String[][] { new String[0] }, new String[] {}, true, false, 0, "R");
}
/* Pull up Field Tests */
public void testPullUpAnchoredTypeField() throws Exception {
performPullUp_failing(new String[] { "T2", "T1", "T3" }, new String[] {}, new String[][] { new String[0] }, new String[] { "extern" }, true, false, 0,
"T2");
}
public void testPulledUpFieldWillBeShadowed() throws Exception {
performPullUp_failing(new String[] { "T2", "T1", "T3" }, new String[] {}, new String[][] { new String[0] }, new String[] { "f" }, true, false, 0,
"Role");
}
public void testPullUpCalloutFieldInBase() throws Exception {
performPullUp_pass(new String[] { "B1", "B2", "T" }, new String[] {}, new String[][] { new String[0] }, new String[] { "f" }, true, false, 0, "B1");
}
public void testPullUpFieldToImplicitSuperclass() throws Exception {
performPullUp_pass(new String[] { "T", "TSuper" }, new String[] {}, new String[][] { new String[0] }, new String[] { "f" }, true, false, 0, "R");
}
// Bug 374841 - [refactoring] pull up does not work among (nested) roles
public void testPullUpWithReferenceToCallout1() throws Exception {
// without pull-up of getS1/getS2 we cannot succeed:
performPullUp_failing(new String[] {"T", "B"}, new String[]{"foo"}, new String[][] { new String[0] }, new String[0], true, true, 0, "RSub");
}
// Bug 386587 - [refactoring] pull-up refactoring cannot handle callout bindings
public void testPullUpWithReferenceToCallout2() throws Exception {
performPullUp_pass(new String[] {"T", "B"},
new String[]{"foo", "getS1", "getS2"},
new String[][] { new String[0], new String[0], new String[0] },
new boolean[] {false, true, true},
new String[0], true, true, 0, "RSub",
true /*replace*/);
}
// Bug 386814 - [refactoring] pull-up should distinguish callouts that can be pull-up vs. abstract decl.
public void testPullUpCallout1() throws Exception {
performPullUp_failing(new String[] {"T", "B"},
new String[]{"foo", "getS1", "getS2"},
new String[][] { new String[0], new String[0], new String[0] },
new boolean[] {false, false, true}, // true pull up of callout not possible
new String[0], true, true, 0, "RSub",
new String[]{"The callout binding 'getS1() -> String s' can only be moved to a bound role (OTJLD \u00A73.1.(a))."});
}
// Bug 386814 - [refactoring] pull-up should distinguish callouts that can be pull-up vs. abstract decl.
public void testPullUpCallout2() throws Exception {
performPullUp_pass(new String[] {"T", "B0", "B1", "B2"},
new String[]{"foo", "getS1", "getS2"},
new String[][] { new String[0], new String[0], new String[0] },
new boolean[] {false, false, false}, // true pull up of callout
new String[0], true, true, 0, "RSub");
}
// Bug 386814 - [refactoring] pull-up should distinguish callouts that can be pull-up vs. abstract decl.
public void testPullUpCallout3() throws Exception {
performPullUp_failing(new String[] {"T", "B0", "B1", "B2"},
new String[]{"foo", "getS1", "getS2"},
new String[][] { new String[0], new String[0], new String[0] },
new boolean[] {false, false, false}, // true pull up of callout, which are NOT available in super base (B1)
new String[0], true, true, 0, "RSub",
new String[]{
"The callout binding 'getS1() -> String s' cannot be moved to class 'RSuper', because the the bound base member 's' will not be accessible after refactoring (OTJLD \u00A73.1.(a)).",
"The callout binding 'getS2() -> getS()' cannot be moved to class 'RSuper', because the the bound base member 'getS' will not be accessible after refactoring (OTJLD \u00A73.1.(a))."});
}
}