/** * This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details. */ package edu.illinois.codingspectator.ui.tests; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.ltk.internal.core.refactoring.RefactoringCorePlugin; import org.eclipse.swtbot.swt.finder.waits.DefaultCondition; import org.junit.BeforeClass; import org.junit.Test; import edu.illinois.codingspectator.data.CodingSpectatorDataPlugin; import edu.illinois.codingspectator.efs.EFSFile; import edu.illinois.codingspectator.monitor.ui.RunningModes; import edu.illinois.codingspectator.monitor.ui.submission.Submitter; import edu.illinois.codingspectator.refactoringproblems.logger.ProblemChanges; import edu.illinois.codingspectator.refactorings.parser.RefactoringLog; /** * The methods marked with @Test annotation are final because if you override them, the order in * which SWTBot executes the test methods changes. To change the behavior of a SWTBot test method, * override the template method called in that SWTBot test method. The names of these template * methods begin with "do". * * @author Mohsen Vakilian * @author nchen * @author Balaji Ambresh Rajkumar * */ @SuppressWarnings("restriction") public abstract class RefactoringTest { protected static CodingSpectatorBot bot; private Collection<LogChecker> logCheckers; protected String getProjectName() { return "Prj"; } protected abstract String getTestFileName(); protected String getTestFileFullName() { return getTestFileName() + ".java"; } protected String getRefactoringKind() { String packageFullyQualifiedName= getClass().getPackage().getName(); String[] subpackages= packageFullyQualifiedName.split("\\."); return subpackages[subpackages.length - 1]; } protected String getTestName() { return getClass().getSimpleName(); } protected Collection<LogChecker> getLogCheckers() throws CoreException { if (logCheckers == null) { logCheckers= new ArrayList<LogChecker>(); EFSFile file= new EFSFile(getPathToExpectedResultsOfTest()); if (file.exists()) { HashSet<String> expectedLogs= new HashSet<String>(); expectedLogs.addAll(file.childNames()); if (expectedLogs.contains(ProblemChanges.REFACTORING_PROBLEMS_LOG)) { logCheckers.add(new RefactoringProblemsChecker(getExpectedRefactoringProblemsLogPath())); } addRefactoringLogCheckers(expectedLogs); } else { printMessage(String.format("Expected logs for %s are missing.", getTestName())); } } return logCheckers; } private IPath getExpectedRefactoringProblemsLogPath() { return getPathToExpectedResultsOfTest().append(ProblemChanges.REFACTORING_PROBLEMS_LOG); } private void addRefactoringLogCheckers(Set<String> expectedHistoryFolderNames) { for (String expectedHistoryFolderName : expectedHistoryFolderNames) { if (RefactoringLog.isLogType(expectedHistoryFolderName)) { logCheckers.add(new RefactoringLogChecker(RefactoringLog.toLogType(expectedHistoryFolderName), getRefactoringKind(), getTestName(), getProjectName())); } } } protected Collection<LogChecker> getAllLogCheckers() { Collection<LogChecker> allLogCheckers= new ArrayList<LogChecker>(); for (RefactoringLog.LogType logType : RefactoringLog.getLogTypes()) { allLogCheckers.add(new RefactoringLogChecker(logType, getRefactoringKind(), getTestName(), getProjectName())); } allLogCheckers.add(new RefactoringProblemsChecker(getExpectedRefactoringProblemsLogPath())); return allLogCheckers; } private IPath getPathToExpectedResultsOfTest() { return new Path(RefactoringLogUtils.EXPECTED_DESCRIPTORS).append(getRefactoringKind()).append(getTestName()); } protected void doAddJavaClass() throws Exception { bot.createANewJavaClass(getProjectName(), getTestFileName()); bot.prepareJavaTextInEditor(getRefactoringKind(), getTestFileFullName()); } private void gatherAllDataInWatchedFolder() { new Submitter().notifyListeners(); } protected void waitUntilActualLogsExist() throws CoreException { bot.waitUntil(new DefaultCondition() { @Override public boolean test() throws Exception { gatherAllDataInWatchedFolder(); boolean allActualLogsAreEmpty= true; for (LogChecker logChecker : getLogCheckers()) { allActualLogsAreEmpty&= logChecker.actualLogExists(); } return allActualLogsAreEmpty; } @Override public String getFailureMessage() { return "Some of the actual logs are missing."; } }); } protected void waitUntilActualLogsAreEmpty() throws CoreException { bot.waitUntil(new DefaultCondition() { @Override public boolean test() throws Exception { boolean allActualLogsAreEmpty= true; for (LogChecker logChecker : getLogCheckers()) { allActualLogsAreEmpty&= !logChecker.actualLogExists(); } return allActualLogsAreEmpty; } @Override public String getFailureMessage() { return "Some of the actual logs still exist."; } }); } protected void doLogsShouldBeEmpty() throws CoreException { waitUntilActualLogsAreEmpty(); for (LogChecker logChecker : getLogCheckers()) { logChecker.assertActualLogIsEmpty(); } } abstract protected void doExecuteRefactoring() throws Exception; protected void printMessage(String message) { System.err.println(getClass() + ": " + message); } protected void doGenerateExpectedFiles() throws Exception { if (RunningModes.shouldGenerateExpectedFiles() || RunningModes.shouldOverwriteExpectedFiles()) { for (LogChecker logChecker : getAllLogCheckers()) { logChecker.generateExpectedLog(RunningModes.shouldOverwriteExpectedFiles()); } } } protected void doLogsShouldBeCorrect() throws Exception { for (LogChecker logChecker : getLogCheckers()) { logChecker.assertMatch(); } } protected void doCleanLogs() throws CoreException { new EFSFile(CodingSpectatorDataPlugin.getStorageLocation()).delete(); new EFSFile(RefactoringCorePlugin.getDefault().getStateLocation()).delete(); } // SWTBot tests run in the order in which they are declared. @BeforeClass public static void beforeClass() throws Exception { bot= new CodingSpectatorBot(); bot.dismissWelcomeScreenIfPresent(); } @Test public final void setupProject() throws Exception { bot.createANewJavaProject(getProjectName()); doAddJavaClass(); } @Test public final void logsShouldBeEmpty() throws CoreException { doLogsShouldBeEmpty(); } @Test public final void shouldExecuteRefactoring() throws Exception { doExecuteRefactoring(); } @Test public final void logsShouldBeCorrect() throws Exception { waitUntilActualLogsExist(); doGenerateExpectedFiles(); doLogsShouldBeCorrect(); } @Test public final void shouldCleanUpWorkspace() throws CoreException, OperationCanceledException, InterruptedException { bot.deleteProject(getProjectName()); doCleanLogs(); doLogsShouldBeEmpty(); } }