diff --git a/.gitignore b/.gitignore index d1316227..b63f50cc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.swo # Eclipse +bin/ .idea *.iml target/ diff --git a/checkstyle.xml b/checkstyle.xml index d22aed45..e527b198 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -9,7 +9,7 @@ - + diff --git a/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target b/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target index e76914ce..d512e166 100644 --- a/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target +++ b/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target @@ -8,7 +8,7 @@ - + diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/META-INF/MANIFEST.MF b/tests/org.codechecker.eclipse.rcp.it.tests/META-INF/MANIFEST.MF index 3751c704..51bbd2ff 100644 --- a/tests/org.codechecker.eclipse.rcp.it.tests/META-INF/MANIFEST.MF +++ b/tests/org.codechecker.eclipse.rcp.it.tests/META-INF/MANIFEST.MF @@ -17,4 +17,5 @@ Require-Bundle: org.junit;bundle-version="4.12.0", org.eclipse.cdt.make.ui;bundle-version="7.3.0", org.eclipse.cdt.build.gcc.core;bundle-version="1.0.0", org.eclipse.cdt.gdb.ui;bundle-version="7.0.0", - org.eclipse.swtbot.eclipse.finder;bundle-version="2.7.0" + org.eclipse.swtbot.eclipse.finder;bundle-version="2.7.0", + org.codechecker.eclipse.rcp.shared;bundle-version="1.0.0" diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/build.properties b/tests/org.codechecker.eclipse.rcp.it.tests/build.properties index e3023e14..5ebbdd9b 100644 --- a/tests/org.codechecker.eclipse.rcp.it.tests/build.properties +++ b/tests/org.codechecker.eclipse.rcp.it.tests/build.properties @@ -2,4 +2,5 @@ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ - fragment.xml + fragment.xml,\ + resources/ diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/pom.xml b/tests/org.codechecker.eclipse.rcp.it.tests/pom.xml index 9f730d77..cf8c8cda 100644 --- a/tests/org.codechecker.eclipse.rcp.it.tests/pom.xml +++ b/tests/org.codechecker.eclipse.rcp.it.tests/pom.xml @@ -24,21 +24,9 @@ false org.codechecker.eclipse.feature org.eclipse.ui.ide.workbench + org.codechecker.eclipse.plugin.AllTests - - org.apache.maven.plugins - maven-checkstyle-plugin - 3.0.0 - - - validate - - true - - - - diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/AllTests.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/AllTests.java new file mode 100644 index 00000000..eb0c7497 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/AllTests.java @@ -0,0 +1,33 @@ +package org.codechecker.eclipse.plugin; + +import org.codechecker.eclipse.plugin.utils.GuiUtils; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +/** + * Test Suite for running the gui tests. Add your class to the Suite class list. + */ +@RunWith(Suite.class) +@SuiteClasses({ PluginTest.class, IndicatorTest.class }) +public class AllTests { + + /** + * Never called. + */ + private AllTests() {} + + /** + * Import cpp project into workspace, and setup SWTBot. + * + */ + @BeforeClass + public static void setup() { + //clearWs(); + SWTWorkbenchBot bot = new SWTWorkbenchBot(); + GuiUtils.closeWelcomeIfPresent(bot); + GuiUtils.changePerspectiveTo(GuiUtils.C_CPP_PESPECTIVE, bot); + } +} diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/IndicatorTest.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/IndicatorTest.java new file mode 100644 index 00000000..d2918f5b --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/IndicatorTest.java @@ -0,0 +1,95 @@ +package org.codechecker.eclipse.plugin; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.utils.GuiUtils; +import org.codechecker.eclipse.rcp.shared.utils.Utils; +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotCLabel; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; +import org.hamcrest.core.IsNull; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * CodeChecker plugin preferences indicator tests. + */ +public class IndicatorTest { + + private static final int SHORT_WAIT_TIME = 500; // in milliseconds + + private static final String CODECHECKER = "CodeChecker"; + + private static SWTWorkbenchBot bot; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private SWTBotShell preferencesShell; + + /** + * Import cpp project into workspace, and setup SWTBot. + * + */ + @BeforeClass + public static void setup() { + bot = new SWTWorkbenchBot(); + } + + /** + * Open preferences, CodeChecker page before every test. + */ + @Before + public void openPreferences() { + preferencesShell = GuiUtils.getPreferencesTab(CODECHECKER, bot); + } + + /** + * Test that with unconfigured CodeChecker, a warning message is displayed. + */ + @Test + public void testNoCodeCheckerFound() { + SWTBotCLabel label = null; + try { + label = bot.clabel("CodeChecker package directory is invalid"); + } catch (WidgetNotFoundException e) { + System.out.println(e.getMessage()); + } + assertThat("There was no invalid CodeChecker message displayed", label, is(IsNull.notNullValue())); + + preferencesShell.close(); + } + + /** + * Test that with CodeChecker configured, a confirmation message is displayed. + */ + @Test + public void testCodeCheckerFound() { + Path ccDir = Utils.prepareCodeChecker(); + + SWTBotText text = bot.textWithLabel("CodeChecker package root directory"); + text.setText(ccDir.toString()); + text.setFocus(); + bot.textWithLabel("Python virtualenv root directory (optional)").setFocus(); + + bot.sleep(SHORT_WAIT_TIME); + + SWTBotCLabel label = null; + try { + label = bot.clabel("CodeChecker package directory is valid"); + } catch (WidgetNotFoundException e) { + System.out.println(e.getMessage()); + } + assertThat("There was no valid CodeChecker message displayed", label, is(IsNull.notNullValue())); + + preferencesShell.close(); + } +} diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/PluginTest.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/PluginTest.java index f59f23ed..045b2b42 100644 --- a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/PluginTest.java +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/PluginTest.java @@ -3,30 +3,21 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; -import java.net.URL; +import java.nio.file.Path; import java.nio.file.Paths; -import org.codechecker.eclipse.plugin.utils.Utils; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IProjectDescription; +import org.codechecker.eclipse.plugin.utils.ProjectImporter; +import org.codechecker.eclipse.rcp.shared.utils.Utils; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.FileLocator; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Platform; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; -import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; -import org.eclipse.swtbot.swt.finder.results.VoidResult; import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; -import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; -import org.eclipse.ui.PlatformUI; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.osgi.framework.Bundle; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; @@ -38,10 +29,6 @@ public class PluginTest { private static final String CPP_PROJ = "cppTest"; - private static final String WINDOW_MENU = "Window"; - private static final String PERSP_MENU = "Perspective"; - private static final String OPEN_PERSP = "Open Perspective"; - private static final String OTHER_MENU = "Other..."; private static final String ADD_NATURE_MENU = "Add CodeChecker Nature"; private static SWTWorkbenchBot bot; @@ -51,56 +38,30 @@ public class PluginTest { /** * Import cpp project into workspace, and setup SWTBot. - * */ @BeforeClass public static void setup() { - // http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/ - Bundle bundle = Platform.getBundle("org.codechecker.eclipse.rcp.it.tests"); - URL fileURL = bundle.getEntry("resources/cppTest"); - File file = null; + bot = new SWTWorkbenchBot(); + + Path file = null; try { - file = new File(FileLocator.resolve(fileURL).toURI()); - } catch (URISyntaxException e1) { - e1.printStackTrace(); - } catch (IOException e1) { - e1.printStackTrace(); + file = Utils.loadFileFromBundle("org.codechecker.eclipse.rcp.it.tests", + Utils.RES + CPP_PROJ); + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); } - assertThat("File not exists.", file.exists()); - Utils.copyFolder(file.toPath(), + + Utils.copyFolder(file, Paths.get(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString() + File.separator)); File project = new File(ResourcesPlugin.getWorkspace().getRoot().getLocation().toOSString() + File.separator + CPP_PROJ + File.separator + ".project"); try { - importProject(project, CPP_PROJ); + ProjectImporter.importProject(project.toPath(), CPP_PROJ); } catch (CoreException e1) { e1.printStackTrace(); } - - bot = new SWTWorkbenchBot(); - UIThreadRunnable.syncExec(new VoidResult() { - public void run() { - PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().forceActive(); - } - }); - - try { - bot.viewByTitle("Welcome").close(); - } catch (WidgetNotFoundException e) { - System.out.println("Welcome Screen wasn't present."); - } - - // Change the perspective via the Open Perspective dialog - bot.menu(WINDOW_MENU).menu(PERSP_MENU).menu(OPEN_PERSP).menu(OTHER_MENU).click(); - SWTBotShell openPerspectiveShell = bot.shell(OPEN_PERSP); - openPerspectiveShell.activate(); - - // select the dialog - bot.table().select("C/C++"); - bot.button("Open").click(); - } /** @@ -121,37 +82,4 @@ public void testAddNatureDisappears() { thrown.expectMessage(containsString("Could not find")); project.contextMenu(ADD_NATURE_MENU); } - - - /** - * Imports a project into workspace. - * https://www.eclipse.org/forums/index.php/t/560903/ - * - * @param projectFile - * The project file to be imported. - * @param projectName - * The project name that will be used to create the project - * @throws CoreException - * Project cannot be created: if this method fails. Reasons include: - * - This project already exists in the workspace. - The name of - * this resource is not valid (according to - * IWorkspace.validateName). - The project location is not valid - * (according to IWorkspace.validateProjectLocation). - The project - * description file could not be created in the project content - * area. - Resource changes are disallowed during certain types of - * resource change event notification. See IResourceChangeEvent for - * more details. .project file has troubles. Reasons include: - The - * project description file does not exist. - The file cannot be - * opened or read. - The file cannot be parsed as a legal project - * description. or during opening - Resource changes are disallowed - * during certain types of resource change event notification. See - * IResourceChangeEvent for more details. - */ - private static void importProject(final File projectFile, final String projectName) throws CoreException { - IProjectDescription description = ResourcesPlugin.getWorkspace() - .loadProjectDescription(new Path(projectFile.getAbsolutePath())); - IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(description.getName()); - project.create(description, null); - project.open(null); - } -} +} \ No newline at end of file diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/GuiUtils.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/GuiUtils.java new file mode 100644 index 00000000..20c9ddf3 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/GuiUtils.java @@ -0,0 +1,205 @@ +package org.codechecker.eclipse.plugin.utils; + +import java.nio.file.Path; + +import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; +import org.eclipse.swtbot.eclipse.finder.waits.Conditions; +import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException; +import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; +import org.eclipse.swtbot.swt.finder.results.VoidResult; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; +import org.eclipse.ui.PlatformUI; + +/** + * Helper functions for navigating the gui. + * + */ +public final class GuiUtils { + + public static final String DOT_PROJECT = ".project"; + public static final String APPLY = "Apply"; + public static final String APPLY_AND_CLOSE = "Apply and Close"; + public static final String CANCEL = "Cancel"; + public static final String C_CPP_BUILD = "C/C++ Build"; + public static final String C_CPP_PESPECTIVE = "C/C++"; + public static final String CPP_PROJECT = "C++ Project"; + public static final String ENVIRONMENT = "Environment"; + public static final String FINISH = "Finish"; + public static final String OPEN_PERSP = "Open Perspective"; + public static final String OTHER_MENU = "Other..."; + public static final String PERSP_MENU = "Perspective"; + public static final String PREFERENCES = "Preferences"; + public static final String PROPERTIES = "Properties"; + public static final String PROPERTIES_FOR = "Properties for "; + public static final String WINDOW_MENU = "Window"; + // CodeChecker related strings. + public static final String DOT_CODECHECKER = ".codechecker"; + public static final String ADD_NATURE_MENU = "Add CodeChecker Nature"; + public static final String COMP_COMMANDS = "compilation_commands.json.javarunner"; + public static final String BIN = "bin"; + public static final String CC_DIR_WIDGET = "CodeChecker package root directory"; + public static final String CODECHECKER = "CodeChecker"; + public static final String ENVIR_LOGGER_BIN = "CC_LOGGER_BIN"; + public static final String ENVIR_LOGGER_FILE = "CC_LOGGER_FILE"; + public static final String LDOGGER = "ldlogger"; + public static final String PY_DIR_WIDGET = "Python virtualenv root directory (optional)"; + public static final String GLOBAL_RADIO = "Use global configuration"; + public static final String PROJECT_RADIO = "Use project configuration"; + + public static final int SHORT_WAIT_TIME = 500; // in milliseconds + /** + * Not called. + */ + private GuiUtils() {} + + /** + * Closes a preferences/properties type shell. Use {@link applyClosePreferences} + * or {@link applyCloseProperties} for better readability. + * + * @param shell + * The shell to be closed. + * @param apply + * If true Apply and Close will be clicked, else Cancel. + * @param bot + * The bot to be used. + */ + public static void closeShell(SWTBotShell shell, boolean apply, SWTWorkbenchBot bot) { + if (apply) + bot.button(GuiUtils.APPLY_AND_CLOSE).click(); + else + bot.button(GuiUtils.CANCEL).click(); + bot.waitUntil(Conditions.shellCloses(shell)); + } + + /** + * Applies and closes and waits for closure of Preferences. + * + * @param preferencesShell + * The Preferences shell to be closed. + * @param bot + * The bot to be used. + */ + public static void applyClosePreferences(SWTBotShell preferencesShell, SWTWorkbenchBot bot) { + closeShell(preferencesShell, true, bot); + } + + /** + * Applies and closes and waits for closure of Properties. + * + * @param propertiesShell + * The Properties shell to be closed. + * @param bot + * The bot to be used. + */ + public static void applyCloseProperties(SWTBotShell propertiesShell, SWTWorkbenchBot bot) { + closeShell(propertiesShell, true, bot); + } + + /** + * You MUST navigate to the correct preferences page, or the method fails and + * possibly throws widget not found exception. Sets The CodeChecker Directory on + * the preferences pages. + * + * @param ccDir + * Path to the CodeChecker Root directory. + * @param bot + * The bot to be guided. + */ + public static void setCCBinDir(Path ccDir, SWTWorkbenchBot bot) { + SWTBotText text = bot.textWithLabel(GuiUtils.CC_DIR_WIDGET); + text.setText(ccDir.toString()); + text.setFocus(); + bot.textWithLabel(GuiUtils.PY_DIR_WIDGET).setFocus(); + + bot.sleep(SHORT_WAIT_TIME); + } + + /** + * Deletes a project from workspace. + * + * @param projectName + * The project to be deleted. + * @param deleteFromDisk + * Delete from the disk. + * @param bot + * The workbench bot to be used. + */ + public static void deleteProject(String projectName, boolean deleteFromDisk, SWTWorkbenchBot bot) { + bot.tree().getTreeItem(projectName).contextMenu("Delete").click(); + SWTBotShell shell = bot.shell("Delete Resources"); + shell.activate(); + if (deleteFromDisk) + bot.checkBox("Delete project contents on disk (cannot be undone)").select(); + bot.button("OK").click(); + bot.waitUntil(Conditions.shellCloses(shell)); + } + + /** + * Convenience method for deleting a project. Exactly the same as + * deleteProject(projectName, false, bot) + * + * @param projectName + * The project to be deleted. + * @param bot + * The workbench bot to be used. + */ + public static void deleteProject(String projectName, SWTWorkbenchBot bot) { + deleteProject(projectName, false, bot); + } + + /** + * Closes welcome window. + * @param bot the workbench bot to be used. + */ + public static void closeWelcomeIfPresent(SWTWorkbenchBot bot) { + try { + bot.viewByTitle("Welcome").close(); + } catch (WidgetNotFoundException e) { + System.out.println("Welcome Screen wasn't present."); + } + } + + /** + * Changes to CDT project. + * + * @param perspective + * The perspective to be changed to. + * @param bot + * the workbench bot to be used. + */ + public static void changePerspectiveTo(String perspective, SWTWorkbenchBot bot) { + UIThreadRunnable.syncExec(new VoidResult() { + public void run() { + PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell().forceActive(); + } + }); + + // Change the perspective via the Open Perspective dialog + bot.menu(WINDOW_MENU).menu(PERSP_MENU).menu(OPEN_PERSP).menu(OTHER_MENU).click(); + SWTBotShell openPerspectiveShell = bot.shell(OPEN_PERSP); + openPerspectiveShell.activate(); + + // select the dialog + bot.table().select(perspective); + bot.button("Open").click(); + + } + + /** + * Open desired dialog specified by it's title in preferences dialog. + * + * @param tab + * The desired preferences tab. + * @param bot + * the workbench bot to be used. + * @return The newly opened shell. + */ + public static SWTBotShell getPreferencesTab(String tab, SWTWorkbenchBot bot) { + bot.menu(WINDOW_MENU).menu(PREFERENCES).click(); + SWTBotShell shell = bot.shell(PREFERENCES); + shell.activate(); + bot.tree().getTreeItem(tab).select(); + return shell; + } +} diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/ProjectImporter.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/ProjectImporter.java new file mode 100644 index 00000000..4cfe8f3a --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/ProjectImporter.java @@ -0,0 +1,93 @@ +package org.codechecker.eclipse.plugin.utils; + +import java.nio.file.Path; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IProjectDescription; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; + +/** + * Import projects into eclipse with this class. + */ +public class ProjectImporter { + + /** + * Hidden utility ctor. + */ + private ProjectImporter() {} + + /** + * Imports a project into workspace. + * https://www.eclipse.org/forums/index.php/t/560903/ + * + * @param projectFile + * The project file to be imported. + * @param projectName + * The project name that will be used to create the project + * @throws CoreException + * Project cannot be created: if this method fails. Reasons include: + * - This project already exists in the workspace. - The name of + * this resource is not valid (according to + * IWorkspace.validateName). - The project location is not valid + * (according to IWorkspace.validateProjectLocation). - The project + * description file could not be created in the project content + * area. - Resource changes are disallowed during certain types of + * resource change event notification. See IResourceChangeEvent for + * more details. .project file has troubles. Reasons include: - The + * project description file does not exist. - The file cannot be + * opened or read. - The file cannot be parsed as a legal project + * description. or during opening - Resource changes are disallowed + * during certain types of resource change event notification. See + * IResourceChangeEvent for more details. + */ + public static void importProject(final Path projectFile, final String projectName) throws CoreException { + IProjectDescription description = ResourcesPlugin.getWorkspace() + .loadProjectDescription(new org.eclipse.core.runtime.Path(projectFile.toFile().getAbsolutePath())); + description.setName(projectName); + create(description, projectName); + } + + /** + * Convenience method for importing projects with names specified + * from the targeted project file. + * Imports a project into workspace. + * https://www.eclipse.org/forums/index.php/t/560903/ + * + * @param projectFile + * The project file to be imported. + * @throws CoreException + * Project cannot be created: if this method fails. Reasons include: + * - This project already exists in the workspace. - The name of + * this resource is not valid (according to + * IWorkspace.validateName). - The project location is not valid + * (according to IWorkspace.validateProjectLocation). - The project + * description file could not be created in the project content + * area. - Resource changes are disallowed during certain types of + * resource change event notification. See IResourceChangeEvent for + * more details. .project file has troubles. Reasons include: - The + * project description file does not exist. - The file cannot be + * opened or read. - The file cannot be parsed as a legal project + * description. or during opening - Resource changes are disallowed + * during certain types of resource change event notification. See + * IResourceChangeEvent for more details. + */ + public static void importProject(final Path projectFile) throws CoreException { + IProjectDescription description = ResourcesPlugin.getWorkspace() + .loadProjectDescription(new org.eclipse.core.runtime.Path(projectFile.toFile().getAbsolutePath())); + create(description, description.getName()); + } + + /** + * The import happens here. + * @param description Description passed in. + * @param projectName The actual project name. + * @throws CoreException Same as above. + */ + public static void create(final IProjectDescription description, final String projectName) throws CoreException { + IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); + if (!project.exists()) + project.create(description, null); + project.open(null); + } +} diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/Utils.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/Utils.java deleted file mode 100644 index 7d2f4746..00000000 --- a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/Utils.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.codechecker.eclipse.plugin.utils; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; - -/** - * Some useful utility methods. - */ -public class Utils { - - /** - * Hidden constructor in Utility class. - */ - private Utils() {}; - - /** - * Recursively copies folders. - * - * @param src The source folder, will be copied. - * @param dest The destination folder to be copied in. - * @throws IOException Could be thrown on access denied, - * or if the copy fails. - */ - public static void copyFolder(Path src, Path dest) { - try { - Files.walk(src).forEach(source -> { - try { - Files.copy(source, dest.resolve(src.getParent().relativize(source)), - StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e) { - e.printStackTrace(); - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/package-info.java b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/package-info.java index 07d20e76..e3daec65 100644 --- a/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/package-info.java +++ b/tests/org.codechecker.eclipse.rcp.it.tests/src/org/codechecker/eclipse/plugin/utils/package-info.java @@ -1,4 +1,4 @@ /** - * Helper classes for unit testing. + * Helper classes for integration testing. */ package org.codechecker.eclipse.plugin.utils; \ No newline at end of file diff --git a/tests/org.codechecker.eclipse.rcp.shared/.classpath b/tests/org.codechecker.eclipse.rcp.shared/.classpath new file mode 100644 index 00000000..110168ff --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tests/org.codechecker.eclipse.rcp.shared/.project b/tests/org.codechecker.eclipse.rcp.shared/.project new file mode 100644 index 00000000..52e3f192 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/.project @@ -0,0 +1,28 @@ + + + org.codechecker.eclipse.rcp.shared + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/tests/org.codechecker.eclipse.rcp.shared/.settings/org.eclipse.jdt.core.prefs b/tests/org.codechecker.eclipse.rcp.shared/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..0c68a61d --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/tests/org.codechecker.eclipse.rcp.shared/META-INF/MANIFEST.MF b/tests/org.codechecker.eclipse.rcp.shared/META-INF/MANIFEST.MF new file mode 100644 index 00000000..ae43257e --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Shared +Bundle-SymbolicName: org.codechecker.eclipse.rcp.shared +Bundle-Version: 1.0.0.qualifier +Bundle-Vendor: Ericsson +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.core.runtime +Export-Package: org.codechecker.eclipse.rcp.shared.utils diff --git a/tests/org.codechecker.eclipse.rcp.shared/build.properties b/tests/org.codechecker.eclipse.rcp.shared/build.properties new file mode 100644 index 00000000..6c89b521 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + resources/ +src.includes = resources/,\ + src/ diff --git a/tests/org.codechecker.eclipse.rcp.shared/resources/CodeChecker/bin/CodeChecker b/tests/org.codechecker.eclipse.rcp.shared/resources/CodeChecker/bin/CodeChecker new file mode 100755 index 00000000..1527abc7 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/resources/CodeChecker/bin/CodeChecker @@ -0,0 +1,55 @@ +#!/usr/bin/python +""" +CodeChecker Stub used to emulate some CodeChecker commands for the tests. +""" + +import sys +import argparse + +""" +Handler function for version information. +""" +def version(args): + print("""CodeChecker analyzer version: +--------------------------------------------------------------- +Kind | Version +--------------------------------------------------------------- +Base package version | 1.2.3 +Package build date | 1970-01-01T00:00 +Git commit ID (hash) | 0000000000000000000000000000000000000000 +Git tag information | 1.2.3 +--------------------------------------------------------------- + +CodeChecker web version: +------------------------------------------------------------------------ +Kind | Version +------------------------------------------------------------------------ +Base package version | 1.2.3 +Package build date | 1970-01-01T00:00 +Git commit ID (hash) | 0000000000000000000000000000000000000000 +Git tag information | 1.2.3 +Configuration schema | v1.0 +Database schema | v1.0 +Server supported API (Thrift) | 1.2 +Client API (Thrift) | 1.2 +------------------------------------------------------------------------""") + +def main(args): + parser = argparse.ArgumentParser( + prog='CodeChecker Stub', + formatter_class=argparse.RawDescriptionHelpFormatter, + description='Used for testing the CodeChecker Eclipse plugin') + + subparsers = parser.add_subparsers(help='commands') + + """ For function extension add a new subparser and a + default handler function to it, for the simplest operation """ + version_parser = subparsers.add_parser('version', + help="Print the version of CodeChecker package that is being used.") + version_parser.set_defaults(func=version) + + args = parser.parse_args() + args.func(args) + +if __name__ == "__main__": + main(sys.argv) diff --git a/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/Utils.java b/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/Utils.java new file mode 100644 index 00000000..90b67cfa --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/Utils.java @@ -0,0 +1,118 @@ +package org.codechecker.eclipse.rcp.shared.utils; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.PosixFilePermissions; + +import org.eclipse.core.runtime.FileLocator; +import org.eclipse.core.runtime.Platform; +import org.osgi.framework.Bundle; + +/** + * Helper functions for: + * * File loading from bundles. + * * Recursive copying of folders. + * * CodeChecker preparation. + */ +public class Utils { + public static final String RES = "resources" + File.separator; + + private static final String CODECHECKER = "CodeChecker"; + private static final String BIN = "bin"; + + /** + * Not called. + */ + private Utils() {} + + /** + * Loads a file from a bundle. + * @param bundlename The bundle to be loaded from. + * @param pathFrom The path to the desired file (use with "resources/"). + * @return returns a Path to the specified resource. + * @throws URISyntaxException If this URL is not formatted strictly according to to RFC2396 and cannot be + * converted to a URI. + * @throws IOException If an error occurs during the conversion. + */ + public static Path loadFileFromBundle(String bundlename, String pathFrom) throws URISyntaxException, IOException { + // http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/ + Bundle bundle = Platform.getBundle(bundlename); + return Paths.get(FileLocator.toFileURL( + FileLocator.find(bundle, new org.eclipse.core.runtime.Path(pathFrom), null)).toURI()); + } + + /** + * Recursively copies folders. + * + * @param src The source folder, will be copied. + * @param dest The destination folder to be copied in. + * @return The path to the copied folder. + * @throws IOException Could be thrown on access denied, + * or if the copy fails. + */ + public static Path copyFolder(Path src, Path dest) { + try { + Files.walk(src).forEach(source -> { + try { + Files.copy(source, dest.resolve(src.getParent().relativize(source)), + StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + return dest.resolve(src.getFileName()); + } + + /** + * Convenience method for quickly get a runnable CodeChecker. + * Has the same effect to loadCodeChecker("CodeChecker"). + * Copies into the default directory layout, and sets runnable permission to Codechecker. + * The path to the runnable CodeChecker will be tmp//CodeChecker/bin/CodeChecker + * @return The path to To the CodeChecker root directory. + * Will point to tmp//CodeChecker . + */ + public static Path prepareCodeChecker() { + return prepareCodeChecker(CODECHECKER); + } + + /** + * Copies into the specified directory, and sets runnable permission to Codechecker. + * The path to the runnable CodeChecker will be tmp///bin/CodeChecker + * @param into This will be the name of the CodeChecker root folder. + * @return The path to To the CodeChecker root directory. + * Will point to tmp// . + */ + public static Path prepareCodeChecker(String into) { + if (into.isEmpty() || into == null) throw new IllegalArgumentException(); + + Path testDir = null; + Path ccRoot = null; + try { + testDir = Files.createTempDirectory("CCTest"); + testDir.toFile().deleteOnExit(); + testDir = Files.createDirectory(Paths.get(testDir.toString(), into)); + ccRoot = Utils.loadFileFromBundle("org.codechecker.eclipse.rcp.shared", + Utils.RES + CODECHECKER); + } catch (IOException | URISyntaxException e1) { + e1.printStackTrace(System.out); + } + // Get the CodeChecker stub from the test resources, and copy it to a temporary folder. + Path ccDir = Utils.copyFolder(ccRoot, testDir); + Path ccBinDir = Paths.get( testDir.toAbsolutePath().toString(), CODECHECKER, BIN, CODECHECKER); + try { + // CodeChecker must be runnable. + Files.setPosixFilePermissions(ccBinDir, PosixFilePermissions.fromString("rwxrwxrwx")); + } catch (IOException e) { + e.printStackTrace(); + } + return ccDir; + } +} diff --git a/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/package-info.java b/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/package-info.java new file mode 100644 index 00000000..d5bc5e46 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.shared/src/org/codechecker/eclipse/rcp/shared/utils/package-info.java @@ -0,0 +1,4 @@ +/** + * Helper utilities for both unit and integration testing. + */ +package org.codechecker.eclipse.rcp.shared.utils; \ No newline at end of file diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/META-INF/MANIFEST.MF b/tests/org.codechecker.eclipse.rcp.unit.tests/META-INF/MANIFEST.MF index 1f6eb754..66cae430 100644 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/META-INF/MANIFEST.MF +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/META-INF/MANIFEST.MF @@ -10,6 +10,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.junit, org.hamcrest;bundle-version="1.1.0", org.mockito;bundle-version="1.9.5", - org.objenesis;bundle-version="1.0.0" + org.objenesis;bundle-version="1.0.0", + org.codechecker.eclipse.rcp.shared;bundle-version="1.0.0" Bundle-ClassPath: ., resources/ diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/pom.xml b/tests/org.codechecker.eclipse.rcp.unit.tests/pom.xml new file mode 100644 index 00000000..07e59264 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + org.codechecker.eclipse + org.codechecker.eclipse.tests + 1.0.0-SNAPSHOT + + + org.codechecker.eclipse.rcp.unit.tests + 1.0.0-SNAPSHOT + eclipse-test-plugin + + + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho.version} + + false + false + org.codechecker.eclipse.feature + org.eclipse.ui.ide.workbench + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + validate + + false + + + + + + + + diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/report/PlistParserTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/report/PlistParserTest.java index 416d4688..552adfd3 100644 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/report/PlistParserTest.java +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/report/PlistParserTest.java @@ -1,18 +1,19 @@ package org.codechecker.eclipse.plugin.report; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasItem; -import static org.hamcrest.Matchers.is; -import static org.mockito.Mockito.mock; - -import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import org.codechecker.eclipse.rcp.shared.utils.Utils; import org.eclipse.core.resources.IProject; import org.junit.Before; import org.junit.Test; -import utils.UrlFileLoader; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.is; +import static org.mockito.Mockito.mock; public class PlistParserTest { private PlistParser parser; @@ -26,11 +27,17 @@ public void initParser(){ @Test public void ParserTest1() { - File file = UrlFileLoader.getFileFromUrl("plists", "test_plist_1", "plist"); - assertThat(file.exists(), is(equalTo(true))); + Path file = null; + try { + file = Utils.loadFileFromBundle("org.codechecker.eclipse.rcp.unit.tests", + Utils.RES + "plists/test_plist_1.plist"); + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + } + assertThat(file.toFile().exists(), is(equalTo(true))); SearchList sl = new SearchList(); - parser.parsePlist(file, sl); + parser.parsePlist(file.toFile(), sl); assertThat(sl.getCheckers(), hasItem("alpha.core.SizeofPtr")); } diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/utils/UrlFileLoader.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/utils/UrlFileLoader.java deleted file mode 100644 index 36b156ca..00000000 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/utils/UrlFileLoader.java +++ /dev/null @@ -1,49 +0,0 @@ -package utils; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStreamReader; - -/** - * Unit test file loader helper class. - */ -public class UrlFileLoader { - - /** - * Utility method for creating test files, because tycho runs unit test in an OSGi container, - * but the eclipse IDE junit laucher won't. The resource that's returned by the class loader - * is a file in the IDE context, but bundlesource in the CLI context, and this is the best way - * I have found to convert it reliably on both environments. - * @param url The url in String form. - * @return The file if can be - * @throws IOException - */ - public static File getFileFromUrl(String path, String fileName, String extension) { - File file = null; - - ClassLoader cl = UrlFileLoader.class.getClassLoader(); - - try { - file = File.createTempFile(fileName, extension); - file.deleteOnExit(); - BufferedWriter out = new BufferedWriter(new FileWriter(file)); - String url = path + File.separator + fileName + "." + extension; - BufferedReader in = new BufferedReader( - new InputStreamReader(cl.getResource(url).openStream())); - String inputLine; - while ((inputLine = in.readLine()) != null){ - out.write(inputLine + System.lineSeparator()); - //System.out.println(inputLine); - } - in.close(); - out.close(); - } catch (IOException e1) { - //throw e1; - } - return file; - } - -} diff --git a/tests/pom.xml b/tests/pom.xml index 62ef0994..031dc517 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -14,5 +14,24 @@ org.codechecker.eclipse.rcp.unit.tests org.codechecker.eclipse.rcp.it.tests + org.codechecker.eclipse.rcp.shared + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + validate + + true + + + + + +