package ch.hsr.ifs.cdttesting.cdttest; import java.io.File; import java.lang.reflect.Field; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.Properties; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.internal.ui.refactoring.CRefactoring; import org.eclipse.cdt.internal.ui.refactoring.CRefactoringContext; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.ltk.core.refactoring.Change; import org.eclipse.ltk.core.refactoring.Refactoring; import org.eclipse.ltk.core.refactoring.RefactoringContext; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; import ch.hsr.ifs.cdttesting.testsourcefile.TestSourceFile; /** * Most of the code for this class originates from CDT's RefactoringTestBase * class. In our case, it executes on the more correctly set-up project/index of * our cdttesting framework */ @SuppressWarnings("restriction") public abstract class CDTTestingRefactoringTestWithPreferences extends CDTTestingTest { /** Expected counts of errors, warnings and info messages */ protected int expectedInitialErrors; protected int expectedInitialWarnings; protected int expectedFinalErrors; protected int expectedFinalWarnings; protected int expectedFinalInfos; /** * Subclasses must to provide refactoring to execute */ protected abstract Refactoring createRefactoring(); private final Map<String, String> prefBackup = new HashMap<>(); private final Map<String, String> prefEvalBackup = new HashMap<>(); protected IPreferenceStore preferenceStore; /** * @author tstauber * * @return The {@code IPreferenceStore} containing the preferences that * shall be altered while testing. * */ public abstract IPreferenceStore initPrefs(); /** * @author tstauber * * @return The {@code Class} containing the static fields that contain the * {@code String}s representing the preference id's. * */ @SuppressWarnings("rawtypes") public abstract Class getPreferenceConstants(); @Override protected void configureTest(final Properties properties) { final String preference = properties.getProperty("setPreferences"); final String preferenceEval = properties.getProperty("setPreferencesEval"); if (preference != null && !preference.isEmpty()) { if (preferenceStore == null) { preferenceStore = initPrefs(); } final String[] splitPreferences = preference.split(","); final Map<String, String> preferencesMap = new HashMap<>(); splitAndAdd(preferencesMap, splitPreferences); backupPreferences(prefBackup, preferencesMap); setPreferences(preferencesMap); } if (preferenceEval != null && !preferenceEval.isEmpty()) { if (preferenceStore == null) { preferenceStore = initPrefs(); } final String[] splitPreferences = preferenceEval.split(","); final Map<String, String> preferencesMap = new HashMap<>(); splitAndAdd(preferencesMap, splitPreferences); final Map<String, String> evaluatedMap = evaluatePreferences(preferencesMap); backupPreferences(prefEvalBackup, evaluatedMap); setPreferences(evaluatedMap); } super.configureTest(properties); } @Override public void tearDown() throws Exception { setPreferences(prefBackup); setPreferences(prefEvalBackup); super.tearDown(); cleanupProject(); } private void backupPreferences(final Map<String, String> backupMap, final Map<String, String> preferencesMap) { for (final String key : preferencesMap.keySet()) { final String value = preferenceStore.getString(key); backupMap.put(key, value); } } private void setPreferences(final Map<String, String> preferencesMap) { for (final String key : preferencesMap.keySet()) { preferenceStore.setValue(key, preferencesMap.get(key)); } } private void splitAndAdd(final Map<String, String> map, final String[] splitPreferences) { for (final String s : splitPreferences) { final String[] pair = s.substring(1, s.length() - 1).split("\\|"); map.put(pair[0], pair[1]); } } private Map<String, String> evaluatePreferences(final Map<String, String> preferencesMap) { final Map<String, String> evaluatedMap = new HashMap<>(); try { for (final String key : preferencesMap.keySet()) { final Field evaluatedKey = getPreferenceConstants().getDeclaredField(key); final Field evaluatedValue = getPreferenceConstants().getDeclaredField(preferencesMap.get(key)); evaluatedMap.put((String) evaluatedKey.get(null), (String) evaluatedValue.get(null)); } } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) { e.printStackTrace(); } return evaluatedMap; } /** * Subclasses can override to simulate user input. * * @param context */ protected void simulateUserInput(final RefactoringContext context) { simulateUserInput(); // call deprecated method if not overwritten by // user } /** * Subclasses can override to simulate user input. * * @deprecated use {@link #simulateUserInput(RefactoringContext)} instead. */ @Deprecated protected void simulateUserInput() { } /** * Changed to AST comparison * * @throws Exception */ protected void runRefactoringAndAssertSuccess() throws Exception { executeRefactoring(true); assertEqualsAST(getExpectedAST(), getCurrentAST()); // compareFiles(); } protected void runRefactoringAndAssertFailure() throws Exception { executeRefactoring(false); } /** * Deprecated due to bad method name. * * @deprecated use {@link #runRefactoringAndAssertSuccess() * runRefactoringAndAssertSuccess} instead. */ @Deprecated protected void assertRefactoringSuccess() throws Exception { runRefactoringAndAssertSuccess(); } /** * Deprecated due to bad method name. * * @deprecated use {@link #runRefactoringAndAssertFailure() * runRefactoringAndAssertFailure} instead. */ @Deprecated protected void assertRefactoringFailure() throws Exception { runRefactoringAndAssertFailure(); } protected void executeRefactoring(final boolean expectedSuccess) throws Exception { final Refactoring refactoring = createRefactoring(); RefactoringContext context; if (refactoring instanceof CRefactoring) { context = new CRefactoringContext((CRefactoring) refactoring); } else { context = new RefactoringContext(refactoring); } executeRefactoring(refactoring, context, true, expectedSuccess); } protected void executeRefactoring(final Refactoring refactoring, final RefactoringContext context, final boolean withUserInput, final boolean expectedSuccess) throws CoreException, Exception { try { final RefactoringStatus initialStatus = refactoring.checkInitialConditions(new NullProgressMonitor()); if (!expectedSuccess) { assertStatusFatalError(initialStatus); return; } if (expectedInitialErrors != 0) { assertStatusError(initialStatus, expectedInitialErrors); } else if (expectedInitialWarnings != 0) { assertStatusWarning(initialStatus, expectedInitialWarnings); } else { assertStatusOk(initialStatus); } if (withUserInput) { simulateUserInput(context); } final RefactoringStatus finalStatus = refactoring.checkFinalConditions(new NullProgressMonitor()); if (expectedFinalErrors != 0) { assertStatusError(finalStatus, expectedFinalErrors); } else if (expectedFinalWarnings != 0) { assertStatusWarning(finalStatus, expectedFinalWarnings); } else if (expectedFinalInfos != 0) { assertStatusInfo(finalStatus, expectedFinalInfos); } else { assertStatusOk(finalStatus); } final Change change = refactoring.createChange(new NullProgressMonitor()); change.perform(new NullProgressMonitor()); } finally { if (context != null) { context.dispose(); } } } protected void compareFiles() throws Exception { for (final TestSourceFile testFile : fileMap.values()) { final String expectedSource = testFile.getExpectedSource(); final String actualSource = getCurrentSource(testFile.getName()); assertEquals(expectedSource, actualSource); } } protected void assertStatusOk(final RefactoringStatus status) { if (!status.isOK()) { fail("Error or warning status: " + status.getEntries()[0].getMessage()); } } protected void assertStatusWarning(final RefactoringStatus status, final int number) { if (number > 0) { assertTrue("Warning status expected", status.hasWarning()); } final RefactoringStatusEntry[] entries = status.getEntries(); int count = 0; for (final RefactoringStatusEntry entry : entries) { if (entry.isWarning()) { ++count; } } assertEquals("Found " + count + " warnings instead of expected " + number, number, count); } protected void assertStatusInfo(final RefactoringStatus status, final int number) { if (number > 0) { assertTrue("Info status expected", status.hasInfo()); } final RefactoringStatusEntry[] entries = status.getEntries(); int count = 0; for (final RefactoringStatusEntry entry : entries) { if (entry.isInfo()) { ++count; } } assertEquals("Found " + count + " informational messages instead of expected " + number, number, count); } protected void assertStatusError(final RefactoringStatus status, final int number) { if (number > 0) { assertTrue("Error status expected", status.hasError()); } final RefactoringStatusEntry[] entries = status.getEntries(); int count = 0; for (final RefactoringStatusEntry entry : entries) { if (entry.isError()) { ++count; } } assertEquals("Found " + count + " errors instead of expected " + number, number, count); } protected void assertStatusFatalError(final RefactoringStatus status, final int number) { if (number > 0) { assertTrue("Fatal error status expected", status.hasFatalError()); } final RefactoringStatusEntry[] entries = status.getEntries(); int count = 0; for (final RefactoringStatusEntry entry : entries) { if (entry.isFatalError()) { ++count; } } assertEquals("Found " + count + " fatal errors instead of expected " + number, number, count); } protected void assertStatusFatalError(final RefactoringStatus status) { assertTrue("Fatal error status expected", status.hasFatalError()); } protected URI getActiveFileUri() { final String absoluteFilePath = makeProjectAbsolutePath(activeFileName); return new File(absoluteFilePath).toURI(); } public ICElement getActiveCElement() { return CoreModel.getDefault().create(getIFile(activeFileName)); } }