From 2949e9b6dcf972c5626c2a62e51b01b8702f9df0 Mon Sep 17 00:00:00 2001 From: Vodorok Date: Tue, 23 Jul 2019 16:20:33 +0200 Subject: [PATCH 1/3] Add new CodeChecker resolution logic Refactored the logic, how CodeChecker is found and configured. There is now an internal representation of a CodeChecker. There are a locator service introduced to handle CodeChecker resolution. There are a new gui radio button group to select how CodeChecker should be found. There is a proper dynamic widget enablement function depending on the selected options, and more verbose messages for the preferences panel. --- .../plugin/codechecker/CodeChecker.java | 83 +++++ .../codechecker/CodeCheckerFactory.java | 17 + .../plugin/codechecker/ICodeChecker.java | 55 +++ .../codechecker/ICodeCheckerFactory.java | 25 ++ .../locator/CodeCheckerLocatorFactory.java | 27 ++ .../locator/CodeCheckerLocatorService.java | 30 ++ .../CustomBuiltCodeCheckerLocatorService.java | 58 +++ .../locator/EnvCodeCheckerLocatorService.java | 30 ++ .../locator/InvalidCodeCheckerException.java | 17 + .../PreBuiltCodeCheckerLocatorService.java | 29 ++ .../locator/ResolutionMethodTypes.java | 41 +++ .../codechecker/locator/package-info.java | 4 + .../plugin/codechecker/package-info.java | 4 + .../plugin/config/CcConfigurationBase.java | 19 + .../eclipse/plugin/config/CommonGui.java | 345 +++++++++++++----- .../eclipse/plugin/config/Config.java | 2 + .../config/project/CodeCheckerProject.java | 11 +- .../eclipse/plugin/report/job/AnalyzeJob.java | 98 ++--- .../runtime/CodeCheckEnvironmentChecker.java | 176 --------- .../plugin/runtime/CodeCheckerLocator.java | 40 -- .../plugin/runtime/EnvironmentParser.java | 22 -- .../runtime/IShellExecutorHelperFactory.java | 17 + .../runtime/ShellExecutorHelperFactory.java | 15 + .../eclipse/plugin/runtime/package-info.java | 4 + .../CodeCheckEnvironmentCheckerTest.java | 97 ----- .../runtime/CodeCheckerLocatorTest.java | 105 ------ .../plugin/runtime/EnvironmentParserTest.java | 32 -- 27 files changed, 805 insertions(+), 598 deletions(-) create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerFactory.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeCheckerFactory.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/InvalidCodeCheckerException.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/package-info.java delete mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentChecker.java delete mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocator.java delete mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParser.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/IShellExecutorHelperFactory.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/ShellExecutorHelperFactory.java create mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/package-info.java delete mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentCheckerTest.java delete mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocatorTest.java delete mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParserTest.java diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java new file mode 100644 index 00000000..d7fd6678 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java @@ -0,0 +1,83 @@ +package org.codechecker.eclipse.plugin.codechecker; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.config.CcConfigurationBase; +import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; +import org.codechecker.eclipse.plugin.runtime.LogI; +import org.codechecker.eclipse.plugin.runtime.SLogger; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; +import org.eclipse.core.runtime.IProgressMonitor; + +import com.google.common.base.Optional; + +/** + * Internal representation of a CodeChecker package. + */ +public class CodeChecker implements ICodeChecker { + + private Path location; + private ShellExecutorHelper she; + private Map subMap; + + /** + * + * @param path + * Path to the binary itself. + * @param she + * The ShellExecutor to be used. + * + * @throws InvalidCodeCheckerException + * Thrown when no CodeChecker found. + */ + public CodeChecker(Path path, ShellExecutorHelper she) throws InvalidCodeCheckerException { + location = path; + this.she = she; + subMap = new HashMap(); + subMap.put("location", path.toAbsolutePath().toFile()); + getVersion(); + } + + @Override + public String getCheckers() { + String cmd = "${location} checkers"; + Optional ccOutput = she.waitReturnOutput(cmd, subMap, false); + return ccOutput.or("No Checkers found"); + } + + @Override + public String getVersion() throws InvalidCodeCheckerException { + String cmd = "${location} version"; + Optional ccOutput = she.waitReturnOutput(cmd, subMap, false); + if (!ccOutput.isPresent() || ccOutput.get().isEmpty()) + throw new InvalidCodeCheckerException("Couldn't run CodeChecker version!"); + return ccOutput.get(); + } + + @Override + public Path getLocation() { + return location; + } + + @Override + public String analyze(Path logFile, boolean logToConsole, IProgressMonitor monitor, int taskCount, + CcConfigurationBase config) { + + subMap.put("results", logFile.getParent().toAbsolutePath().resolve(Paths.get("results")).toFile()); + subMap.put("logFile", logFile.toAbsolutePath().toFile()); + String cmd = "${location} analyze " + config.get(ConfigTypes.CHECKER_LIST) + " -j " + + config.get(ConfigTypes.ANAL_THREADS) + " -n javarunner" + " -o " + + "${results} ${logFile}"; + + SLogger.log(LogI.INFO, "Running analyze Command: " + cmd); + Optional ccOutput = she.progressableWaitReturnOutput(cmd, subMap, logToConsole, monitor, taskCount); + + return ccOutput.or(""); + } + +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerFactory.java new file mode 100644 index 00000000..613f095c --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerFactory.java @@ -0,0 +1,17 @@ +package org.codechecker.eclipse.plugin.codechecker; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; + +/** + * Implementation of the {@link ICodeCheckerFactory} interface. + */ +public class CodeCheckerFactory implements ICodeCheckerFactory { + @Override + public ICodeChecker createCodeChecker(Path pathToBin, ShellExecutorHelper she) + throws InvalidCodeCheckerException { + return new CodeChecker(pathToBin, she); + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java new file mode 100644 index 00000000..f8075d4b --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java @@ -0,0 +1,55 @@ +package org.codechecker.eclipse.plugin.codechecker; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.config.CcConfigurationBase; +import org.eclipse.core.runtime.IProgressMonitor; + +/** + * Interface representing a CodeChecker package. + */ +public interface ICodeChecker { + /** + * Returns the unformatted output of the CodeChecker checkers command. + * + * @return The checker list. + */ + public String getCheckers(); + + /** + * Returns the full and complete version string of the CodeChecker package. + * + * @return The version String. + * @throws InvalidCodeCheckerException + * Thrown when no version string can be returned. + */ + public String getVersion() throws InvalidCodeCheckerException; + + /** + * To get the location of the CodeChecker binary. + * + * @return The path. + */ + public Path getLocation(); + + /** + * Executes CodeChecker check command on the build log received in the fileName + * parameter. + * + * @param logFile + * A Path to the build log in the followin format: + * http://clang.llvm.org/docs/JSONCompilationDatabase.html . + * @param logToConsole + * Flag for indicating console logging. + * @param monitor + * ProgressMonitor for to be able to increment progress bar. + * @param taskCount + * How many analyze step to be taken. + * @param config + * The configuration being used. + * @return CodeChecker The full analyze command output. + */ + public String analyze(Path logFile, boolean logToConsole, IProgressMonitor monitor, int taskCount, + CcConfigurationBase config); +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeCheckerFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeCheckerFactory.java new file mode 100644 index 00000000..af7a9718 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeCheckerFactory.java @@ -0,0 +1,25 @@ +package org.codechecker.eclipse.plugin.codechecker; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; + +/** + * Interface for CodeChecker factory. + */ +public interface ICodeCheckerFactory { + /** + * Method for creating CodeChecker instances. + * + * @param pathToBin + * Path to the CodeChecker binary. (Not to root!) + * @param she + * The shell executor helper that will be used. + * @return A newly created {@link ICodeChecker} ICodeChecker instance. + * @throws InvalidCodeCheckerException + * Thrown when a new instance couldn't be created. + */ + public ICodeChecker createCodeChecker(Path pathToBin, ShellExecutorHelper she) + throws InvalidCodeCheckerException; +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java new file mode 100644 index 00000000..f2e7a75f --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java @@ -0,0 +1,27 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +/** + * Class responsible to create {@link CodeCheckerLocatorService} instances. + */ +public class CodeCheckerLocatorFactory { + /** + * Returns a {@link CodeCheckerLocatorService} depending on a the input + * parameter. + * + * @param t + * Any of the {@link ResolutionMethodTypes} enum values. + * @return A {@link CodeCheckerLocatorService} instance. + */ + public CodeCheckerLocatorService create(ResolutionMethodTypes t) { + switch (t) { + case PATH: + return new EnvCodeCheckerLocatorService(); + case PRE: + return new PreBuiltCodeCheckerLocatorService(); + case PY: + return new CustomBuiltCodeCheckerLocatorService(); + default: + return null; + } + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java new file mode 100644 index 00000000..f81b75d7 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java @@ -0,0 +1,30 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; +import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; +import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; + +/** + * Implementations of this interface should return the location of the + * CodeChecker package. + */ +public abstract class CodeCheckerLocatorService { + /** + * @param pathToBin + * Path to CodeChecker package root. + * @param pathToVenv + * Path to the root of the virtual environment. + * @param ccfactory + * An {@link ICodeCheckerFactory} that will create the CodeChecker. + * @param sheFactory + * A {@link IShellExecutorHelperFactory} to be used. + * @return A CodeChecker Instance. + * @throws InvalidCodeCheckerException + * Thrown when the {@link ICodeChecker} instantiation fails. + */ + public abstract ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, ICodeCheckerFactory ccfactory, + IShellExecutorHelperFactory sheFactory) + throws InvalidCodeCheckerException; +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java new file mode 100644 index 00000000..9d722a6a --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java @@ -0,0 +1,58 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; +import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; +import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; + +import com.google.common.base.Optional; + +/** + * Provides a CodeChecker instance which is tied to a Custom built CodeChecker + * package. + */ +public class CustomBuiltCodeCheckerLocatorService extends CodeCheckerLocatorService { + public static final String ERROR = "Couldn't find CodeChecker at the given destination!"; + public static final String ENV_ERROR = "There was an error when reading the given python environment!"; + + @Override + public ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, + ICodeCheckerFactory ccfactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { + + ShellExecutorHelper she = sheFactory.createShellExecutorHelper(System.getenv()); + Map subMap = new HashMap(); + subMap.put("venv", pathToVenv.resolve(Paths.get("bin", "activate")).toFile()); + Optional output = she + .quickReturnOutput("source ${venv} ; env", subMap); + if (!output.isPresent()) + throw new IllegalArgumentException(); + try { + Map env = parseEnvironment(output.get()); + ShellExecutorHelper pyShe = sheFactory.createShellExecutorHelper(env); + return ccfactory.createCodeChecker(pathToBin, pyShe); + } catch (ArrayIndexOutOfBoundsException e) { + throw new ArrayIndexOutOfBoundsException(ENV_ERROR); + } catch (InvalidCodeCheckerException e) { + throw new InvalidCodeCheckerException(ERROR); + } + } + + /** + * Returns a String - String map from a raw "Key=Value\n..." String. + * @param envOutput The String input. + * @return A Map containing all the environment variables. + */ + private Map parseEnvironment(String envOutput){ + Map map = Stream.of(envOutput.split("\n")).map(String::trim).map(line -> line.split("=")) + .collect(Collectors.toMap(k -> k[0], v -> v.length < 2 ? "" : v[1])); + return map; + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java new file mode 100644 index 00000000..26e2bf2e --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java @@ -0,0 +1,30 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; +import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; +import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; + +/** + * Provides a CodeChecker instance tied to a CodeChecker package resulting of + * "which CodeChecker". + */ +public class EnvCodeCheckerLocatorService extends CodeCheckerLocatorService { + public static final String ERROR = "CodeChecker wasn't found in PATH environment variable!"; + + @Override + public ICodeChecker findCodeChecker(Path path, Path pathToVenv, + ICodeCheckerFactory ccFactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { + + ShellExecutorHelper she = sheFactory.createShellExecutorHelper(System.getenv()); + String location = she.quickReturnFirstLine("which CodeChecker", null).or(""); + try { + return ccFactory.createCodeChecker(Paths.get(location), she); + } catch (InvalidCodeCheckerException e) { + throw new InvalidCodeCheckerException(ERROR); + } + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/InvalidCodeCheckerException.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/InvalidCodeCheckerException.java new file mode 100644 index 00000000..93134481 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/InvalidCodeCheckerException.java @@ -0,0 +1,17 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +/** + * Custom exception indicating a failed CodeChecker instance creation. + */ +@SuppressWarnings("serial") +public class InvalidCodeCheckerException extends Exception { + /** + * Ctor. + * + * @param errorMessage + * Error message. + */ + public InvalidCodeCheckerException(String errorMessage) { + super(errorMessage); + } +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java new file mode 100644 index 00000000..4ff90c00 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java @@ -0,0 +1,29 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +import java.nio.file.Path; + +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; +import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; +import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; + +/** + * Provides a CodeChecker instance which is tied to a pre-built CodeChecker + * package. + */ +public class PreBuiltCodeCheckerLocatorService extends CodeCheckerLocatorService { + public static final String INVALID = "The path to the CodeChecker binary is not valid"; + public static final String ERROR = "Couldn't find CodeChecker at the given destination!"; + + @Override + public ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, + ICodeCheckerFactory ccfactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { + if (pathToBin == null) + throw new IllegalArgumentException(INVALID); + try { + return ccfactory.createCodeChecker(pathToBin, sheFactory.createShellExecutorHelper(System.getenv())); + } catch (InvalidCodeCheckerException e) { + throw new InvalidCodeCheckerException(ERROR); + } + } + +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java new file mode 100644 index 00000000..f989c2b3 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java @@ -0,0 +1,41 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +/** + * This enum represents the available types of CodeChecker resolution methods. + */ +public enum ResolutionMethodTypes { + PATH("PATH"), PRE("PRE"), PY("PY"); + + private String value; + + /** + * + * @param def utility method for setting the default value. + */ + private ResolutionMethodTypes(String def) { + this.value = def; + } + + /** + * + * @return Returns the value associated with the enum. + */ + public String getDefaultValue() { + return value; + } + + /** + * + * @param s + * The query string. + * @return The matching ResolutionMethodTypes if exists null otherwise. + */ + public static ResolutionMethodTypes getFromString(String s) { + for (ResolutionMethodTypes r : ResolutionMethodTypes.values()) { + if (s.equals(r.toString())) + return r; + } + return null; + } + +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java new file mode 100644 index 00000000..3c866f38 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java @@ -0,0 +1,4 @@ +/** + * CodeChecker locator related classes. + */ +package org.codechecker.eclipse.plugin.codechecker.locator; \ No newline at end of file diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/package-info.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/package-info.java new file mode 100644 index 00000000..39fe37d6 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/package-info.java @@ -0,0 +1,4 @@ +/** + * CodeChecker related classes. + */ +package org.codechecker.eclipse.plugin.codechecker; \ No newline at end of file diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CcConfigurationBase.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CcConfigurationBase.java index e2fc158e..2aa94270 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CcConfigurationBase.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CcConfigurationBase.java @@ -5,6 +5,7 @@ import java.util.Set; import java.util.stream.Collectors; +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; import org.eclipse.core.runtime.preferences.IEclipsePreferences; @@ -17,6 +18,7 @@ public abstract class CcConfigurationBase { protected Map config; protected IEclipsePreferences preferences; + protected ICodeChecker codeChecker; private final Set listeners = new HashSet<>(); @@ -49,6 +51,23 @@ public CcConfigurationBase(CcConfigurationBase other) { */ protected abstract void validate(); + /** + * @return The CodeChecker being used. + */ + public ICodeChecker getCodeChecker() { + return codeChecker; + } + + /** + * Sets the currently used CodeChecker. + * + * @param codeChecker + * The CodeChecker that will be stored. + */ + public void setCodeChecker(ICodeChecker codeChecker) { + this.codeChecker = codeChecker; + } + /** * @return the internal configuration. */ diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java index f8fd06c2..8e67e90f 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java @@ -1,22 +1,33 @@ package org.codechecker.eclipse.plugin.config; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codechecker.eclipse.plugin.Logger; +import org.codechecker.eclipse.plugin.codechecker.CodeCheckerFactory; +import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; +import org.codechecker.eclipse.plugin.codechecker.locator.CodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.CustomBuiltCodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.EnvCodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.codechecker.locator.PreBuiltCodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.ResolutionMethodTypes; import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; import org.codechecker.eclipse.plugin.config.global.CcGlobalConfiguration; import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; import org.codechecker.eclipse.plugin.itemselector.CheckerView; -import org.codechecker.eclipse.plugin.runtime.CodeCheckEnvironmentChecker; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelperFactory; import org.codechecker.eclipse.plugin.utils.CheckerItem; import org.codechecker.eclipse.plugin.utils.CheckerItem.LAST_ACTION; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.IMessageProvider; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; @@ -28,6 +39,8 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; @@ -45,9 +58,10 @@ */ public class CommonGui { - private static final String CC_BINARY = "/bin/CodeChecker"; - private static final String VALID_PACKAGE = "CodeChecker package directory is valid"; - private static final String INVALID_PACKAGE = "CodeChecker package directory is invalid"; + public static final String CC_BIN_LABEL = "CodeChecker binary:"; + public static final String VENV_LABEL = "Virtual env:"; + + private static final String VALID_PACKAGE = "CodeChecker being used: "; private static final String BROSWE = "Browse"; private static final String CHECKER_ENABLED = " -e "; private static final String CHECKER_DISABLED = " -d "; @@ -55,6 +69,7 @@ public class CommonGui { private static final int TEXTWIDTH = 200; private static final int FORM_COLUMNS = 3; + private static final int FORM_ONE_ROW = 1; private boolean globalGui;// whether this class is for global or project // specific preferences @@ -62,8 +77,20 @@ public class CommonGui { // whether to use global preferences private CcConfigurationBase config; private CodeCheckerProject cCProject; + private ICodeChecker codeChecker; + + private Button pathCc; + private Button preBuiltCc; + private Button customBuiltCc; + private Composite ccDirClient; private Text codeCheckerDirectoryField;// codechecker dir + private Button codeCheckerDirectoryFieldBrowse; + private Composite ccVenvClient; + private Text pythonEnvField;// CodeChecker python env + private Button pythonEnvFieldBrowse; + private ResolutionMethodTypes currentResMethod; + private Section checkerConfigSection; private Text numThreads;// #of analysis threads private Text cLoggers;// #C compiler commands to catch @@ -136,73 +163,31 @@ public Control createContents(final Composite parent) { layout.maxNumColumns = 1; form.getBody().setLayout(layout); + loadConfig(false); + Section globalConfigSection = null; if (!globalGui) { globalConfigSection = toolkit.createSection(form.getBody(), ExpandableComposite.EXPANDED); } - final Section checkerConfigSection = toolkit.createSection(form.getBody(), - ExpandableComposite.TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED); - checkerConfigSection.setEnabled(true); - - final Composite client = toolkit.createComposite(checkerConfigSection); - client.setLayout(new GridLayout(FORM_COLUMNS, false)); - checkerConfigSection.setClient(client); - checkerConfigSection.setText("Configuration"); + Section packageSection = createConfigSection(toolkit); - codeCheckerDirectoryField = addTextField(toolkit, client, "CodeChecker package root directory", ""); - codeCheckerDirectoryField.addModifyListener(new ModifyListener() { - - @Override - public void modifyText(ModifyEvent e) { - try { - Map changedConfig = getConfigFromFields(); - CodeCheckEnvironmentChecker.getCheckerEnvironment(changedConfig, - changedConfig.get(ConfigTypes.CHECKER_PATH) + CC_BINARY); - form.setMessage(VALID_PACKAGE, IMessageProvider.INFORMATION); - } catch (IllegalArgumentException e1) { - form.setMessage(INVALID_PACKAGE, IMessageProvider.ERROR); - } - } - }); + checkerConfigSection = toolkit.createSection(form.getBody(), + ExpandableComposite.SHORT_TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED); + checkerConfigSection.setEnabled(true); - final Button codeCheckerDirectoryFieldBrowse = new Button(client, SWT.PUSH); - codeCheckerDirectoryFieldBrowse.setText(BROSWE); - codeCheckerDirectoryFieldBrowse.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - DirectoryDialog dlg = new DirectoryDialog(client.getShell()); - dlg.setFilterPath(codeCheckerDirectoryField.getText()); - dlg.setText("Browse codechecker root"); - String dir = dlg.open(); - if (dir != null) { - codeCheckerDirectoryField.setText(dir); - try { - Map changedConfig = getConfigFromFields(); - CodeCheckEnvironmentChecker.getCheckerEnvironment(changedConfig, - changedConfig.get(ConfigTypes.CHECKER_PATH) + CC_BINARY); - form.setMessage(VALID_PACKAGE, IMessageProvider.INFORMATION); - } catch (IllegalArgumentException e1) { - form.setMessage(INVALID_PACKAGE, IMessageProvider.ERROR); - } - } - } - }); + final Composite comp = toolkit.createComposite(checkerConfigSection); + comp.setLayout(new GridLayout(FORM_COLUMNS, false)); - numThreads = addTextField(toolkit, client, "Number of analysis threads", "4"); - toolkit.createLabel(client, ""); - cLoggers = addTextField(toolkit, client, "Compiler commands to log", "gcc:g++:clang:clang++"); - toolkit.createLabel(client, ""); + checkerConfigSection.setClient(comp); + checkerConfigSection.setText("Analysis options"); - Map configMap = loadConfig(false); - try { - CodeCheckEnvironmentChecker.getCheckerEnvironment(configMap, - configMap.get(ConfigTypes.CHECKER_PATH) + CC_BINARY); - form.setMessage(VALID_PACKAGE, IMessageProvider.INFORMATION); - } catch (IllegalArgumentException e1) { - form.setMessage(INVALID_PACKAGE, IMessageProvider.ERROR); - } + numThreads = addTextField(toolkit, comp, "Number of analysis threads", "4"); + toolkit.createLabel(comp, ""); + cLoggers = addTextField(toolkit, comp, "Compiler commands to log", "gcc:g++:clang:clang++"); + toolkit.createLabel(comp, ""); - final Button checkers = toolkit.createButton(client, "Toggle enabled checkers", SWT.PUSH); + final Button checkers = toolkit.createButton(comp, "Toggle enabled checkers", SWT.PUSH); checkers.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { @@ -212,12 +197,10 @@ public void run() { Shell activeShell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); //Map config = getConfigFromFields(); try { - CodeCheckEnvironmentChecker checkerEnv = new CodeCheckEnvironmentChecker(cCProject); - ArrayList checkersList = getCheckerList(checkerEnv); + ArrayList checkersList = getCheckerList(); CheckerView dialog = new CheckerView(activeShell, checkersList); int result = dialog.open(); - if (result == 0) { checkerListArg = checkerListToCheckerListArg(dialog.getCheckersList()); } @@ -229,46 +212,212 @@ public void run() { action.run(); } }); + checkers.setData("org.eclipse.swtbot.widget.checkersKey", "checkesButton"); if (!globalGui) { - recursiveSetEnabled(checkerConfigSection, !useGlobalSettings); + recursiveSetEnabled(form.getBody(), !useGlobalSettings); final Composite client3 = toolkit.createComposite(globalConfigSection); client3.setLayout(new GridLayout(2, true)); globalConfigSection.setClient(client3); globalcc = toolkit.createButton(client3, "Use global configuration", SWT.RADIO); - globalcc.setSelection(useGlobalSettings); globalcc.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (globalcc.getSelection()) { recursiveSetEnabled(checkerConfigSection, false); + recursiveSetEnabled(packageSection, false); useGlobalSettings = true; config = cCProject.getGlobal(); - setFields(config.get()); + setFields(); + locateCodeChecker(); } } }); + globalcc.setSelection(useGlobalSettings); projectcc = toolkit.createButton(client3, "Use project configuration", SWT.RADIO); - projectcc.setSelection(!useGlobalSettings); projectcc.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (projectcc.getSelection()) { recursiveSetEnabled(checkerConfigSection, true); + recursiveSetEnabled(packageSection, true); useGlobalSettings = false; config = cCProject.getLocal(); - setFields(config.get()); + setFields(); + changeDirectoryInputs(); + locateCodeChecker(); } } }); - + projectcc.setSelection(!useGlobalSettings); + changeDirectoryInputs(); } + setFields(); + locateCodeChecker(); return form.getBody(); } - /** - * Recursive control state modifier. - * If the control is {@link Composite} toggles it state and all of it's children {@link Control}. - * @param control The parent control. - * @param b The state to be set. - */ + /** + * Creates the resolution method group, and the package directory inputs. + * + * @param toolkit + * The toolkit to be used. + * @return The encapsulating Section. + */ + private Section createConfigSection(FormToolkit toolkit) { + + final Section packageConfigSection = toolkit.createSection(form.getBody(), + ExpandableComposite.SHORT_TITLE_BAR | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED); + packageConfigSection.setEnabled(true); + + final Composite client = toolkit.createComposite(packageConfigSection); + client.setLayout(new GridLayout(FORM_COLUMNS, false)); + + packageConfigSection.setClient(client); + packageConfigSection.setText("Configuration"); + + Group resolutionType = new Group(client, SWT.NULL); + resolutionType.setText("CodeChecker resolution method."); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(resolutionType); + GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER) + .span(FORM_COLUMNS, FORM_ONE_ROW).applyTo(resolutionType); + resolutionType.setBackground(client.getBackground()); + + ccDirClient = toolkit.createComposite(client); + GridLayoutFactory.fillDefaults().numColumns(FORM_COLUMNS).applyTo(ccDirClient); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(FORM_COLUMNS, FORM_ONE_ROW) + .applyTo(ccDirClient); + ccDirClient.setBackground(client.getBackground()); + + ccVenvClient = toolkit.createComposite(client); + GridLayoutFactory.fillDefaults().numColumns(FORM_COLUMNS).applyTo(ccVenvClient); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(FORM_COLUMNS, FORM_ONE_ROW) + .applyTo(ccVenvClient); + ccVenvClient.setBackground(client.getBackground()); + + pathCc = toolkit.createButton(resolutionType, "Search in PATH", SWT.RADIO); + pathCc.setData(ResolutionMethodTypes.PATH); + pathCc.addSelectionListener(new PackageResolutionSelectionAdapter()); + + preBuiltCc = toolkit.createButton(resolutionType, "Pre built package", SWT.RADIO); + preBuiltCc.setData(ResolutionMethodTypes.PRE); + preBuiltCc.addSelectionListener(new PackageResolutionSelectionAdapter()); + + customBuiltCc = toolkit.createButton(resolutionType, "Custom built package", SWT.RADIO); + customBuiltCc.setData(ResolutionMethodTypes.PY); + customBuiltCc.addSelectionListener(new PackageResolutionSelectionAdapter()); + + codeCheckerDirectoryField = addTextField(toolkit, ccDirClient, CC_BIN_LABEL, ""); + codeCheckerDirectoryField.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + locateCodeChecker(); + } + }); + + codeCheckerDirectoryFieldBrowse = new Button(ccDirClient, SWT.PUSH); + codeCheckerDirectoryFieldBrowse.setText(BROSWE); + codeCheckerDirectoryFieldBrowse.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + FileDialog dlg = new FileDialog(client.getShell()); + dlg.setFilterPath(codeCheckerDirectoryField.getText()); + dlg.setText("Browse CodeChecker binary"); + String dir = dlg.open(); + if (dir != null) { + codeCheckerDirectoryField.setText(dir); + locateCodeChecker(); + } + } + }); + + pythonEnvField = addTextField(toolkit, ccVenvClient, VENV_LABEL, ""); + pythonEnvField.addModifyListener(new ModifyListener() { + @Override + public void modifyText(ModifyEvent e) { + locateCodeChecker(); + } + }); + pythonEnvFieldBrowse = new Button(ccVenvClient, SWT.PUSH); + pythonEnvFieldBrowse.setText(BROSWE); + pythonEnvFieldBrowse.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + DirectoryDialog dlg = new DirectoryDialog(client.getShell()); + dlg.setFilterPath(codeCheckerDirectoryField.getText()); + dlg.setText("Browse python environment"); + String dir = dlg.open(); + if (dir != null) { + pythonEnvField.setText(dir); + locateCodeChecker(); + } + } + }); + changeDirectoryInputs(); + return packageConfigSection; + + } + + /** + * Changes directory input widgets depending on the resolution method radio + * group. + */ + public void changeDirectoryInputs() { + if (!useGlobalSettings) + switch (currentResMethod) { + case PATH: + recursiveSetEnabled(ccDirClient, false); + recursiveSetEnabled(ccVenvClient, false); + break; + case PRE: + recursiveSetEnabled(ccDirClient, true); + recursiveSetEnabled(ccVenvClient, false); + break; + case PY: + recursiveSetEnabled(ccDirClient, true); + recursiveSetEnabled(ccVenvClient, true); + break; + default: + break; + } + } + + /** + * Tries to find a CodeChecker package. + */ + public void locateCodeChecker() { + CodeCheckerLocatorService serv = null; + switch (currentResMethod) { + case PATH: + serv = new EnvCodeCheckerLocatorService(); + break; + case PRE: + serv = new PreBuiltCodeCheckerLocatorService(); + break; + case PY: + serv = new CustomBuiltCodeCheckerLocatorService(); + break; + default: + break; + } + ICodeChecker cc = null; + try { + cc = serv.findCodeChecker(Paths.get(codeCheckerDirectoryField.getText()), + Paths.get(pythonEnvField.getText()), new CodeCheckerFactory(), new ShellExecutorHelperFactory()); + form.setMessage(VALID_PACKAGE + cc.getLocation().toString(), IMessageProvider.INFORMATION); + if (globalGui || (!globalGui && !useGlobalSettings)) + recursiveSetEnabled(checkerConfigSection, true); + } catch (InvalidCodeCheckerException | IllegalArgumentException | ArrayIndexOutOfBoundsException e) { + recursiveSetEnabled(checkerConfigSection, false); + form.setMessage(e.getMessage(), IMessageProvider.ERROR); + } + this.codeChecker = cc; + } + + /** + * Recursive control state modifier. If the control is {@link Composite} toggles + * it state and all of it's children {@link Control}. + * + * @param control + * The parent control. + * @param b + * The state to be set. + */ public void recursiveSetEnabled(Control control, Boolean b) { if (control instanceof Composite) { Composite comp = (Composite) control; @@ -281,14 +430,13 @@ public void recursiveSetEnabled(Control control, Boolean b) { /** * Returns The all checkers from CodeChecker. - * @param ccec The Environment Checker to be used. * @return A list of all available checkers. */ - private ArrayList getCheckerList(CodeCheckEnvironmentChecker ccec) { + private ArrayList getCheckerList() { // ArrayList defaultCheckersList = new ArrayList<>(); ArrayList checkersList = new ArrayList<>(); // // new Checkers List - String s = ccec.getCheckerList(); + String s = codeChecker.getCheckers(); String[] newCheckersSplit = s.split("\n"); // old Checkers Command //String[] checkersCommand = checkerListArg.split(CHECKER_SEPARATOR); @@ -346,16 +494,30 @@ public Map loadConfig(boolean resetToDefault) { ret = config.get(); } else ret = config.getDefaultConfig(); - - setFields(ret); + currentResMethod = ResolutionMethodTypes.getFromString(config.get(ConfigTypes.RES_METHOD)); return ret; } /** * Sets the form fields with the given config maps values. - * @param config The config which values are taken. */ - public void setFields(Map config) { + public void setFields() { + pathCc.setSelection(false); + preBuiltCc.setSelection(false); + customBuiltCc.setSelection(false); + switch (currentResMethod) { + case PATH: + pathCc.setSelection(true); + break; + case PRE: + preBuiltCc.setSelection(true); + break; + case PY: + customBuiltCc.setSelection(true); + break; + default: + break; + } codeCheckerDirectoryField.setText(config.get(ConfigTypes.CHECKER_PATH)); checkerListArg = config.get(ConfigTypes.CHECKER_LIST); cLoggers.setText(config.get(ConfigTypes.COMPILERS)); @@ -384,6 +546,8 @@ public void saveConfig() { conf.put(ConfigTypes.CHECKER_LIST, checkerListArg); conf.put(ConfigTypes.ANAL_THREADS, numThreads.getText()); conf.put(ConfigTypes.COMPILERS, cLoggers.getText()); + conf.put(ConfigTypes.RES_METHOD, currentResMethod.toString()); + config.setCodeChecker(codeChecker); config.update(conf); if(!globalGui) cCProject.useGlobal(useGlobalSettings); @@ -420,4 +584,19 @@ public void init(IWorkbench workbench) { // TODO Auto-generated method stub } + /** + * Callback for the Resolution method selection listener. + */ + private class PackageResolutionSelectionAdapter extends SelectionAdapter { + @Override + public void widgetSelected(SelectionEvent event) { + boolean isSelected = ((Button) event.getSource()).getSelection(); + if (isSelected) { + currentResMethod = (ResolutionMethodTypes) event.widget.getData(); + changeDirectoryInputs(); + locateCodeChecker(); + } + } + + } } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java index bc75f3de..b47ca1c0 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java @@ -22,6 +22,8 @@ public class Config { public enum ConfigTypes { // Common configuration values CHECKER_PATH("codechecker_path"), + PYTHON_PATH(""), + RES_METHOD("PATH"), COMPILERS("gcc:g++:clang:clang++"), ANAL_THREADS("4"), CHECKER_LIST("enabled_checkers"), diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/project/CodeCheckerProject.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/project/CodeCheckerProject.java index 322f3c2c..a0fc844f 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/project/CodeCheckerProject.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/project/CodeCheckerProject.java @@ -94,12 +94,19 @@ private void setEnvironment() { environmentVariables.put(ev, ev.getDefaultValue()); } String checkerDir = current.get(ConfigTypes.CHECKER_PATH); + String checkerRootDir = ""; + try { + checkerRootDir = Paths.get(checkerDir).getParent().getParent().toAbsolutePath().toString(); + } catch (NullPointerException e) { + checkerRootDir = checkerDir; + } + environmentVariables.put(EnvironmentVariables.LD_LIBRARY_PATH, - checkerDir + EnvironmentVariables.LD_LIBRARY_PATH.getDefaultValue()); + checkerRootDir + EnvironmentVariables.LD_LIBRARY_PATH.getDefaultValue()); environmentVariables.put(EnvironmentVariables._, checkerDir + EnvironmentVariables._.getDefaultValue()); environmentVariables.put(EnvironmentVariables.CC_LOGGER_BIN, - checkerDir + EnvironmentVariables.CC_LOGGER_BIN.getDefaultValue()); + checkerRootDir + EnvironmentVariables.CC_LOGGER_BIN.getDefaultValue()); environmentVariables.put(EnvironmentVariables.CC_LOGGER_GCC_LIKE, current.get(ConfigTypes.COMPILERS)); // The current path to workspace is always handled by this project. diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java index 81e00d2e..f49acd9a 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java @@ -1,33 +1,31 @@ package org.codechecker.eclipse.plugin.report.job; -import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import org.codechecker.eclipse.plugin.Logger; +import org.codechecker.eclipse.plugin.config.CcConfigurationBase; +import org.codechecker.eclipse.plugin.config.CodeCheckerContext; +import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; -import com.google.common.base.Optional; - -import org.codechecker.eclipse.plugin.Logger; -import org.codechecker.eclipse.plugin.config.CodeCheckerContext; -import org.codechecker.eclipse.plugin.runtime.CodeCheckEnvironmentChecker; - /** * This class represents a CodeChecker analyze command. * */ public class AnalyzeJob extends Job { - private IProject project; - private CodeCheckEnvironmentChecker ccec; - + private CodeCheckerProject project; + private CcConfigurationBase config; + private Path logFile; /** * Hidden due analyze is meaningless without a project. * @param name unused. @@ -42,51 +40,69 @@ private AnalyzeJob(String name) { */ public AnalyzeJob(IProject project) { super("Running CodeChecker Analyze"); - this.project = project; - ccec = new CodeCheckEnvironmentChecker( - CodeCheckerContext.getInstance().getCcProject(project)); + this.project = CodeCheckerContext.getInstance().getCcProject(project); + config = this.project.getCurrentConfig(); } @Override protected IStatus run(IProgressMonitor monitor) { Logger.log(IStatus.INFO, "Running AnalyzeJob"); - - Optional analyzeLog = moveLogFile(); - if(analyzeLog.isPresent()) { - AtomicInteger taskCount = new AtomicInteger(0); - try { - //read the file - Files.lines(Paths.get(analyzeLog.get())).forEach(new Consumer() { + try { + copyLogFile(); + } catch (IOException e) { + Logger.log(IStatus.ERROR, "Couldn't copy logfile!"); + } - @Override - public void accept(String t) { - if ( t.contains("\"command\":")){ - taskCount.incrementAndGet(); - } + AtomicInteger taskCount = new AtomicInteger(0); + + // read the file + try { + Files.lines(logFile).forEach(new Consumer() { + + @Override + public void accept(String t) { + if (t.contains("\"command\":")) { + taskCount.incrementAndGet(); } - }); - } catch (IOException e) { - // isPresent() should render this unneeded. - } - monitor.beginTask("Starting Analysis...", taskCount.get()*2); - ccec.processLog(analyzeLog.get(), true, monitor, taskCount.get()*2); + } + }); + } catch (IOException e) { + Logger.log(IStatus.ERROR, "Couldn't read logFile!"); + } + + monitor.beginTask("Starting Analysis...", taskCount.get() * 2); + try { + config.getCodeChecker().analyze(logFile, true, monitor, taskCount.get() * 2, config); + } catch (NullPointerException e) { + // TODO: Notify the user somehow that the analyze couldn't be completed, because + // there is no CodeChecker configured. } + + deleteLogFile(); return Status.OK_STATUS; } /** - * Renames the logfile, to avoid concurrency issues. - * @return The path to the temporary logfile wrapped in an {@link Optional}. + * Creates a copy of the log file created by ld logger, to avoid concurrency + * issues. + * + * @throws IOException + * Thrown when the copying fails. */ - private Optional moveLogFile() { - String filename = CodeCheckerContext.getInstance().getCcProject(project).getLogFileLocation().toString(); - File f = new File(filename); - if (f.exists()) { - String newName = filename + System.nanoTime(); - f.renameTo(new File(newName)); + private void copyLogFile() throws IOException { + Path originalLogFile = project.getLogFileLocation(); + logFile = Paths.get(originalLogFile.toAbsolutePath().toString() + System.nanoTime()); + Files.copy(originalLogFile, logFile); + } - return Optional.of(newName); + /** + * Delete the temporary logfile after the analysis. + */ + public void deleteLogFile() { + try { + Files.delete(logFile); + } catch (IOException e) { + Logger.log(IStatus.ERROR, "Couldn't delete the temporary log file!"); } - return Optional.absent(); } } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentChecker.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentChecker.java deleted file mode 100644 index e51754b1..00000000 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentChecker.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import java.io.File; -import java.util.HashMap; -import java.util.Map; - -import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; -import org.codechecker.eclipse.plugin.config.global.CcGlobalConfiguration; -import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; -import org.eclipse.core.runtime.IProgressMonitor; - -import com.google.common.base.Optional; - -/** - * This class checks for Environments used by CodeChecker. - * - */ -public class CodeCheckEnvironmentChecker { - - private static final String CC_BINARY = "CC_BINARY"; - - private static final String HELP_ARGUMENT = "-h"; - private static final int WAIT_TIME_MULTIPLYER = 1000; // in milliseconds - private static final Map SYS_ENV = System.getenv(); - - public final String checkerDir; // root directory of CodeChecker - public final String codeCheckerCommand; // CodecCheker executable path - - private Map commandSubstitutionMap; - - private Map config; - private CodeCheckerProject project; - private String checkerList; - - /** - * - * @param project - * The project that will be used for constructing the Environment - * checker. - */ - public CodeCheckEnvironmentChecker(CodeCheckerProject project) { - this.project = project; - if (project != null) - config = project.getCurrentConfig().get(); - // This is bad design, but until further refactoring it should do. - else - config = CcGlobalConfiguration.getInstance().get(); - - //checkerList=getConfigValue(ConfigTypes.CHECKER_LIST); - checkerDir=getConfigValue(ConfigTypes.CHECKER_PATH); - codeCheckerCommand = checkerDir+"/bin/CodeChecker"; - - commandSubstitutionMap = new HashMap() {{ - put("CC_BIN", new File(codeCheckerCommand)); - }}; - if (project != null) - commandSubstitutionMap.put("RESULTS", - new File(project.getLogFileLocation().getParent().toString() + "/results/")); - - } - - /** - * @return The Config thats used in the CodeCheckEnvironmentChecker. - */ - public Map getConfig() { - return config; - } - - /** - * @param key - * The config key for the interesting value. - * @return The value for the key or an empty String if it can't be found. - */ - private String getConfigValue(ConfigTypes key) { - if (config.containsKey(key)) - return config.get(key); - else - return ""; - } - - /** - * Checks if the given path to CodeChecker is valid. - * @param config The Configuration to be used, - * populated with {@link ConfigTypes}. - * @param codeCheckerBinaryPath Path to CodeChecker. - * TODO This method doesn't need codeCheckerBinaryPath in its arguments as it's a field in this class. - */ - public static void getCheckerEnvironment( - Map config, String codeCheckerBinaryPath) { - - ShellExecutorHelper she = new ShellExecutorHelper(SYS_ENV); - - String cmd = "'${CC_BINARY}' " + HELP_ARGUMENT; - @SuppressWarnings("serial") - Map substitutinMap = new HashMap() {{ - put(CC_BINARY, new File(codeCheckerBinaryPath)); - }}; - - SLogger.log(LogI.INFO, "Testing " + substitutinMap.get(CC_BINARY).getAbsolutePath() + " -h"); - Optional ccEnvOutput = she.quickReturnOutput(cmd, substitutinMap); - double test = 0; - // TODO WTF -- check the twisted logic behind this, and simplify. - while(!ccEnvOutput.isPresent() && test <= 2){ - ccEnvOutput = she.quickReturnOutput(cmd, substitutinMap, Math.pow( 2.0 , test ) * WAIT_TIME_MULTIPLYER); - ++test; - } - if (!ccEnvOutput.isPresent()) { - SLogger.log(LogI.ERROR, "Cannot run CodeChecker command:" + - substitutinMap.get(CC_BINARY).getAbsolutePath() + " " + HELP_ARGUMENT); - throw new IllegalArgumentException("Couldn't run the specified CodeChecker for " + - "environment testing!"); - } - } - - @Override - public boolean equals(Object obj) { - if (obj == null) return false; - if (obj.getClass() != getClass()) { - return false; - } - CodeCheckEnvironmentChecker other = (CodeCheckEnvironmentChecker) obj; - return this.config.equals(other.getConfig()); - } - - public void setCheckerList(String list) { - this.checkerList = list; - } - - /** - * Creates a Codechecker analyze command. - * @param buildLog Path to the compile commands file, which the analyze command uses. - * @return The constructed analyze command. - */ - public String createAnalyzeCommmand(String buildLog) { - commandSubstitutionMap.put("LOG", new File(buildLog)); - return "'${CC_BIN}' analyze " + getConfigValue(ConfigTypes.CHECKER_LIST) + - " -j "+ getConfigValue(ConfigTypes.ANAL_THREADS) + " -n javarunner" + - " -o " + "'${RESULTS}' " + "'${LOG}'"; - } - - /** - * Executes CodeChecker check command - * on the build log received in the fileName parameter. - * @param buildLog Build log in the http://clang.llvm.org/docs/JSONCompilationDatabase.html format. - * @param logToConsole Flag for indicating console logging - * @param monitor ProgressMonitor for to be able to increment progress bar. - * @param taskCount How many analyze step to be taken. - * @return CodeChecker check command output - */ - public String processLog(String buildLog, boolean logToConsole, IProgressMonitor monitor, int taskCount) { - ShellExecutorHelper she = new ShellExecutorHelper(SYS_ENV); - String cmd = createAnalyzeCommmand(buildLog); - SLogger.log(LogI.INFO, "SERVER_SER_MSG >> processLog >> "+ cmd); - Optional ccOutput = she.progressableWaitReturnOutput(cmd, commandSubstitutionMap, logToConsole, monitor, taskCount); - if (ccOutput.isPresent()) { - // assume it succeeded, and delete the log file... - File f = new File(buildLog); - f.delete(); - } - return ccOutput.or(""); - } - - /** - * Returns the list of available checkers. - * Add the following for checker enability checking. - * CodeChecker checkers --details | cut -d " " -f "1-3" - * @return A String containing the checkers. One at a line. - */ - public String getCheckerList() { - ShellExecutorHelper she = new ShellExecutorHelper(SYS_ENV); - String cmd = "'${CC_BIN}' checkers"; - Optional ccOutput = she.waitReturnOutput(cmd, commandSubstitutionMap, false); - return ccOutput.or(""); - } - -} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocator.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocator.java deleted file mode 100644 index d202c3f2..00000000 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocator.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import com.google.common.base.Optional; - -import java.io.IOException; - -/** - * Locates a local CodeChecker installation. - * Either the CodeChecker executable is in the path, or the class is - * initialized with a path to the CodeChecker package root directory. - */ -public class CodeCheckerLocator { - - // Linux-specific path to CodeChecker executable in PATH - private final Optional systemCcExecutable; - // Linux-specific CodeChecker executable in CodeChecker package directory - // given by the user on the configuration panel - private final Optional customCcExecutable; - private ShellExecutorHelper shellExecutor; // TODO: inject? - - public CodeCheckerLocator(ShellExecutorHelper executor, Optional customCcExecutable) - throws IOException { - this.shellExecutor = executor; - this.systemCcExecutable = locateSystemCodeChecker(); - this.customCcExecutable = customCcExecutable; - } - - public Optional getRunnerCommand() { - return customCcExecutable.or(systemCcExecutable); - } - - public boolean foundCcExecutable() { - return customCcExecutable.isPresent() || systemCcExecutable.isPresent(); - } - - private Optional locateSystemCodeChecker() { - return shellExecutor.quickReturnFirstLine("/usr/bin/which CodeChecker", null); - } - -} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParser.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParser.java deleted file mode 100644 index c59d77b5..00000000 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParser.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import com.google.common.collect.ImmutableMap; - -/** - * Parses the output of /usr/bin/env into a String map - */ -public class EnvironmentParser { - - public ImmutableMap parse(String envOutput) { - ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - - for (String line : envOutput.split("\n")) { - String[] entry = line.trim().split("=", 2); - if (entry.length == 2) { - builder.put(entry[0], entry[1]); - } - } - - return builder.build(); - } -} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/IShellExecutorHelperFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/IShellExecutorHelperFactory.java new file mode 100644 index 00000000..d68dbf6f --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/IShellExecutorHelperFactory.java @@ -0,0 +1,17 @@ +package org.codechecker.eclipse.plugin.runtime; + +import java.util.Map; + +/** + * Interface for {@link ShellExecutorHelper} factory. + */ +public interface IShellExecutorHelperFactory { + /** + * Method for creating {@link ShellExecutorHelper}. + * + * @param env + * An environment to be used with the ShellExecutorHelper. + * @return A {@link ShellExecutorHelper} instance. + */ + public ShellExecutorHelper createShellExecutorHelper(Map env); +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/ShellExecutorHelperFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/ShellExecutorHelperFactory.java new file mode 100644 index 00000000..4115a6fe --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/ShellExecutorHelperFactory.java @@ -0,0 +1,15 @@ +package org.codechecker.eclipse.plugin.runtime; + +import java.util.Map; + +/** + * Implementation of {@link IShellExecutorHelperFactory}. + */ +public class ShellExecutorHelperFactory implements IShellExecutorHelperFactory { + + @Override + public ShellExecutorHelper createShellExecutorHelper(Map env) { + return new ShellExecutorHelper(env); + } + +} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/package-info.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/package-info.java new file mode 100644 index 00000000..c5c172a9 --- /dev/null +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/runtime/package-info.java @@ -0,0 +1,4 @@ +/** + * Command line related package. + */ +package org.codechecker.eclipse.plugin.runtime; \ No newline at end of file diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentCheckerTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentCheckerTest.java deleted file mode 100644 index d4ac1ee3..00000000 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckEnvironmentCheckerTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.codechecker.eclipse.plugin.config.CcConfiguration; -import org.codechecker.eclipse.plugin.config.CcConfigurationBase; -import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; -import org.codechecker.eclipse.plugin.config.project.CodeCheckerProject; -import org.codechecker.eclipse.rcp.shared.utils.Utils; -import org.junit.Test; - -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -/** - * Test for CodeCheckEnvironmentChecker class. - */ -public class CodeCheckEnvironmentCheckerTest { - - private static final String CODECHECKER = "CodeChecker"; - - /** - * The list of checkers that the stub Codechecker must return. - */ - @SuppressWarnings("serial") - private static final Set CHECKERS = new HashSet() {{ - add("core.uninitialized.Assign"); - add("cplusplus.NewDeleteLeaks"); - add("cplusplus.NewDelete"); - add("cppcoreguidelines-no-malloc"); - add("unix.Malloc"); - add("unix.MallocSizeof"); - }}; - - private Map config; - private CodeCheckEnvironmentChecker ccec; - - /** - * Check simple getCheckerList() commands succeeds. - */ - @Test - public void codeCheckerCheckersCommandSucceds() { - // initialize the environment with CodeChecker installed in a "safe" directory - initEnvirCheck(CODECHECKER); - String checkers = ccec.getCheckerList(); - assertThat(CHECKERS.stream().allMatch(str -> checkers.contains(str)), is(true)); - } - - /** - * Check more complex getCheckerList() commands succeeds. - */ - @Test - public void codeCheckerCheckersCommandSuccedsComplex() { - // initialize the environment with CodeChecker installed in a "unsafe" directory - // (contains spaces and parenthesis) - initEnvirCheck("Code Che(c)ker"); - String checkers = ccec.getCheckerList(); - assertThat(CHECKERS.stream().allMatch(str -> checkers.contains(str)), is(true)); - } - - /** - * Initializes the configuration map and the environment checker. - * - * @param dir - * The directory where CodeChecker runnable will be placed - */ - private void initEnvirCheck(String dir) { - Path testCCRoot = Utils.prepareCodeChecker(dir); - config = new HashMap<>(); - config.put(ConfigTypes.CHECKER_PATH, testCCRoot.toString()); - - // Use mockito for mocking CodeCheckerProject and CcConfiguration - CodeCheckerProject cProj = mock(CodeCheckerProject.class); - CcConfigurationBase configurationBase = mock(CcConfiguration.class); - // Prepare a sufficent configuration. For getting the checkers, a valid - // codechecker location is needed. - @SuppressWarnings("serial") - Map config = new HashMap() {{ - put(ConfigTypes.CHECKER_PATH, testCCRoot.toString()); - }}; - // Mock out the calls inside the Mocked classes. - when(configurationBase.get()).thenReturn(config); - when(cProj.getCurrentConfig()).thenReturn(configurationBase); - when(cProj.getLogFileLocation()).thenReturn(Paths.get("dummyPath", "inside")); - - //Initialize the EnvironmentChecker with the prepared instance - ccec = new CodeCheckEnvironmentChecker(cProj); - } - -} diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocatorTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocatorTest.java deleted file mode 100644 index c806b47b..00000000 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/CodeCheckerLocatorTest.java +++ /dev/null @@ -1,105 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import com.google.common.base.Optional; - -import org.codechecker.eclipse.plugin.runtime.CodeCheckerLocator; -import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; - -import org.junit.Test; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -public class CodeCheckerLocatorTest { - - @Test - public void noSystemLocatorWithoutEnv() throws IOException { - CodeCheckerLocator onlySystemLocatorWithoutEnv = new CodeCheckerLocator(new - ShellExecutorHelper(new HashMap()), Optional.absent()); - assertThat(onlySystemLocatorWithoutEnv.foundCcExecutable(), is(false)); - assertThat(onlySystemLocatorWithoutEnv.getRunnerCommand(), is(equalTo(Optional - .absent()))); - } - - /*@Test - public void findsInPath() throws IOException { - CodeCheckerLocator onlySystemLocatorWithEnv = new CodeCheckerLocator(new - ShellExecutorHelper(envWithPath(getExecutorDirectoryLocation("usage"))), Optional - .absent()); - assertThat(onlySystemLocatorWithEnv.foundCcExecutable(), is(true)); - assertThat(onlySystemLocatorWithEnv.getRunnerCommand(), is(equalTo(Optional.of - (getExecutorLocation("usage"))))); - }*/ - - /* @Test - public void findsSpecificLocatorWithSh() throws IOException { - CodeCheckerLocator specificLocator = new CodeCheckerLocator(new ShellExecutorHelper(new - HashMap()), Optional.of(getExecutorInitScriptLocation("usage"))); - assertThat(specificLocator.foundCcExecutable(), is(true)); - assertThat(specificLocator.getRunnerCommand(), is(equalTo(Optional.of("source " + - getExecutorInitScriptLocation("usage") + "; CodeChecker")))); - }*. - - /*@Test - public void findsSpecificLocatorWithDirectory() throws IOException { - CodeCheckerLocator specificLocator = new CodeCheckerLocator(new ShellExecutorHelper(new - HashMap()), Optional.of(getExecutorDirectoryLocation("usage"))); - assertThat(specificLocator.foundCcExecutable(), is(true)); - assertThat(specificLocator.getRunnerCommand(), is(equalTo(Optional.of("source " + - getExecutorInitScriptLocation("usage") + "; CodeChecker")))); - }*/ - - /* @Test - public void preferSpecificLocator() throws IOException { - CodeCheckerLocator specificLocator = new CodeCheckerLocator(new ShellExecutorHelper - (envWithPath(getExecutorDirectoryLocation("usage"))), Optional.of - (getExecutorDirectoryLocation("usage"))); - assertThat(specificLocator.foundCcExecutable(), is(true)); - assertThat(specificLocator.getRunnerCommand(), is(equalTo(Optional.of("source " + - getExecutorInitScriptLocation("usage") + "; CodeChecker")))); - }*/ - - /* @Test - public void handlesBadSpecificLocator() throws IOException { - CodeCheckerLocator specificLocator = new CodeCheckerLocator(new ShellExecutorHelper(new - HashMap()), Optional.of(getExecutorInitScriptLocation - ("bad-usage"))); - assertThat(specificLocator.foundCcExecutable(), is(false)); - assertThat(specificLocator.getRunnerCommand(), is(equalTo(Optional.absent()))); - }*/ - - /*@Test - public void findsSystemWithBadSpecific() throws IOException { - CodeCheckerLocator specificLocator = new CodeCheckerLocator(new ShellExecutorHelper - (envWithPath(getExecutorDirectoryLocation("usage"))), Optional.of - (getExecutorDirectoryLocation("bad-usage"))); - assertThat(specificLocator.foundCcExecutable(), is(true)); - assertThat(specificLocator.getRunnerCommand(), is(equalTo(Optional.of(getExecutorLocation - ("usage"))))); - }*/ - - private String getExecutorDirectoryLocation(String name) { - return getClass().getResource("/mock-codechecker/").getPath() + name; - } - - private String getExecutorInitScriptLocation(String name) { - return getExecutorDirectoryLocation(name) + "/init/init.sh"; - } - - private String getExecutorLocation(String name) { - return getExecutorDirectoryLocation(name) + "/CodeChecker"; - } - - private Map envWithPath(String path) { - HashMap hm = new HashMap(); - hm.put("PATH", path); - - return hm; - } - -} diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParserTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParserTest.java deleted file mode 100644 index 7bbbf29f..00000000 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/runtime/EnvironmentParserTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.codechecker.eclipse.plugin.runtime; - -import org.junit.Test; - -import com.google.common.collect.ImmutableMap; - -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; - -import org.codechecker.eclipse.plugin.runtime.EnvironmentParser; - -public class EnvironmentParserTest { - - @Test - public void testOneLine() { - EnvironmentParser ep = new EnvironmentParser(); - ImmutableMap result = ep.parse("ALMA=korte"); - assertThat(result.containsKey("ALMA"), is(true)); - assertThat(result.get("ALMA"), is(equalTo("korte"))); - } - - @Test - public void testTwoLine() { - EnvironmentParser ep = new EnvironmentParser(); - ImmutableMap result = ep.parse("ALMA=korte\nBARACK=nemalma"); - assertThat(result.containsKey("ALMA"), is(true)); - assertThat(result.get("ALMA"), is(equalTo("korte"))); - assertThat(result.containsKey("BARACK"), is(true)); - assertThat(result.get("BARACK"), is(equalTo("nemalma"))); - } -} From 25c970890168953e425ca16349a68cf44d22a2da Mon Sep 17 00:00:00 2001 From: Vodorok Date: Tue, 23 Jul 2019 16:22:20 +0200 Subject: [PATCH 2/3] Add tests for resolution logic New Unit tests and extended Integration tests. The CodeChecker class, and the locator logic is tested for PATH and Pre built package resolution. This is the same for the Integration tests, so only these two are tested. The Custom built CodeChecker package with virtual env needs a virtual environment emulation, which is not implemented yet. --- checkstyle.xml | 2 +- mavendeps/pom.xml | 1 + .../org.codechecker.eclipse.target.target | 1 + .../META-INF/MANIFEST.MF | 3 +- .../eclipse/plugin/IndicatorTest.java | 78 ++++++++++- .../eclipse/plugin/utils/GuiUtils.java | 77 +++++++++-- .../META-INF/MANIFEST.MF | 4 +- .../plugin/codechecker/CodeCheckerTest.java | 127 ++++++++++++++++++ .../locator/CodeCheckerLocatorTest.java | 112 +++++++++++++++ .../codechecker/locator/package-info.java | 4 + .../plugin/codechecker/package-info.java | 4 + 11 files changed, 394 insertions(+), 19 deletions(-) create mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerTest.java create mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java create mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java create mode 100644 tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/package-info.java diff --git a/checkstyle.xml b/checkstyle.xml index e527b198..3af1dd9d 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -9,7 +9,7 @@ - + diff --git a/mavendeps/pom.xml b/mavendeps/pom.xml index 00f8cdf4..58757309 100644 --- a/mavendeps/pom.xml +++ b/mavendeps/pom.xml @@ -20,6 +20,7 @@ javax.xml.parsers:jaxp-api:1.4.5 + com.github.stefanbirkner:system-rules:1.19.0 com.google.code.gson:gson:2.3.1 com.googlecode.plist:dd-plist:1.21 com.google.guava:guava:26.0-jre 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 d512e166..5edeb7f7 100644 --- a/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target +++ b/releng/org.codechecker.eclipse.target/org.codechecker.eclipse.target.target @@ -21,6 +21,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 a76b2877..53029831 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 @@ -12,4 +12,5 @@ Require-Bundle: org.junit;bundle-version="4.12.0", org.eclipse.swtbot.junit4_x;bundle-version="2.7.0", org.eclipse.swtbot.swt.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" + org.codechecker.eclipse.rcp.shared;bundle-version="1.0.0", + com.github.stefanbirkner.system-rules;bundle-version="1.19.0" 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 index c6f73cd9..a8ed0ca8 100644 --- 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 @@ -1,7 +1,11 @@ package org.codechecker.eclipse.plugin; import java.nio.file.Path; +import java.nio.file.Paths; +import org.codechecker.eclipse.plugin.codechecker.locator.EnvCodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.PreBuiltCodeCheckerLocatorService; +import org.codechecker.eclipse.plugin.codechecker.locator.ResolutionMethodTypes; import org.codechecker.eclipse.plugin.utils.GuiUtils; import org.codechecker.eclipse.rcp.shared.utils.Utils; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; @@ -13,6 +17,7 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; +import org.junit.contrib.java.lang.system.EnvironmentVariables; import org.junit.rules.ExpectedException; import static org.hamcrest.CoreMatchers.is; @@ -26,12 +31,20 @@ public class IndicatorTest { private static final int SHORT_WAIT_TIME = 500; // in milliseconds private static final String CODECHECKER = "CodeChecker"; + private static final String FORM_MESSAGE_CC_FOUND = "CodeChecker being used:"; + private static final String ENV_PATH = "PATH"; + private static final Path DUMMY = Paths.get("/home"); + + private static final String ERROR_NO_VALID_CC = "There was no valid CodeChecker message displayed"; private static SWTWorkbenchBot bot; @Rule public ExpectedException thrown = ExpectedException.none(); + @Rule + public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); + private SWTBotShell preferencesShell; /** @@ -52,21 +65,40 @@ public void openPreferences() { } /** - * Test that with unconfigured CodeChecker, a warning message is displayed. + * Test that with path option selected, the proper warning message is displayed. */ @Test - public void testNoCodeCheckerFound() { + public void testNoCodeCheckerFoundInPath() { SWTBotCLabel label = null; try { - label = bot.clabel("CodeChecker package directory is invalid"); + label = bot.clabel(EnvCodeCheckerLocatorService.ERROR); } catch (WidgetNotFoundException e) { System.out.println(e.getMessage()); } - assertThat("There was no invalid CodeChecker message displayed", label, is(IsNull.notNullValue())); + assertThat(ERROR_NO_VALID_CC, label, is(IsNull.notNullValue())); preferencesShell.close(); } + /** + * Test that with prebuilt option selected, the proper warning message is + * displayed. + */ + @Test + public void testNoCodeCheckerFoundPre() { + GuiUtils.setCCBinDir(ResolutionMethodTypes.PRE, DUMMY, bot, false); + + SWTBotCLabel label = null; + try { + label = bot.clabel(PreBuiltCodeCheckerLocatorService.ERROR); + } catch (WidgetNotFoundException e) { + System.out.println(e.getMessage()); + } + assertThat(ERROR_NO_VALID_CC, label, is(IsNull.notNullValue())); + + preferencesShell.close(); + } + /** * Test that with CodeChecker configured, a confirmation message is displayed. */ @@ -75,14 +107,48 @@ public void testCodeCheckerFound() { Path ccDir = Utils.prepareCodeChecker(); GuiUtils.setCCBinDir(ccDir, bot); + bot.sleep(SHORT_WAIT_TIME); + SWTBotCLabel label = null; try { - label = bot.clabel("CodeChecker package directory is valid"); + label = new SWTBotCLabel(GuiUtils.findCLabel(FORM_MESSAGE_CC_FOUND, bot)); } catch (WidgetNotFoundException e) { System.out.println(e.getMessage()); } - assertThat("There was no valid CodeChecker message displayed", label, is(IsNull.notNullValue())); + assertThat(ERROR_NO_VALID_CC, label, is(IsNull.notNullValue())); preferencesShell.close(); } + + /** + * Test that with CodeChecker added to PATH environment variable, the Plugin + * picks it up as a valid package and a confirmation message is displayed. + */ + @Test + public void testCodeCheckerFoundInPath() { + GuiUtils.applyClosePreferences(preferencesShell, bot); + Path ccDir = Utils.prepareCodeChecker(); + + // prepare PATH envval + String origPath = System.getenv(ENV_PATH); + String newPath = origPath.concat(":" + ccDir.toAbsolutePath().toString() + "/bin/"); + + // Set the prepared PATH + environmentVariables.set(ENV_PATH, newPath); + + preferencesShell = GuiUtils.getPreferencesTab(CODECHECKER, bot); + GuiUtils.setCCBinDir(ResolutionMethodTypes.PATH, null, bot, false); + SWTBotCLabel label = null; + try { + label = new SWTBotCLabel(GuiUtils.findCLabel(FORM_MESSAGE_CC_FOUND, bot)); + } catch (WidgetNotFoundException e) { + System.out.println(e.getMessage()); + } + assertThat(ERROR_NO_VALID_CC, label, is(IsNull.notNullValue())); + + preferencesShell.close(); + + // reset env + environmentVariables.set(ENV_PATH, origPath); + } } 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 index aab527ef..e158eb6a 100644 --- 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 @@ -1,15 +1,22 @@ package org.codechecker.eclipse.plugin.utils; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import org.codechecker.eclipse.plugin.codechecker.locator.ResolutionMethodTypes; +import org.eclipse.swt.custom.CLabel; 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.matchers.WidgetMatcherFactory; import org.eclipse.swtbot.swt.finder.results.VoidResult; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotRadio; import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.ui.PlatformUI; +import org.hamcrest.Matcher; /** * Helper functions for navigating the gui. @@ -39,16 +46,18 @@ public final class GuiUtils { 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 CC_DIR_WIDGET = "CodeChecker binary:"; 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 THREAD_WIDGET = "Number of analysis threads"; + public static final String PY_DIR_WIDGET = "Virtual env:"; 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 + public static final int LONG_TIME_OUT = 10000; /** * Not called. */ @@ -97,23 +106,56 @@ public static void applyCloseProperties(SWTBotShell propertiesShell, SWTWorkbenc closeShell(propertiesShell, true, bot); } + /** + * Convenience method with pre built package. + * + * @param ccDir + * Path to the CodeChecker Root directory. + * @param bot + * The bot to be guided. + */ + public static void setCCBinDir(Path ccDir, SWTWorkbenchBot bot) { + setCCBinDir(ResolutionMethodTypes.PRE, ccDir, bot, true); + } + /** * 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 method + * The associated radio button to the {@link ResolutionMethodTypes} + * will be clicked on the preferences/properties page. * @param ccDir * Path to the CodeChecker Root directory. * @param bot * The bot to be guided. + * @param root + * TODO */ - public static void setCCBinDir(Path ccDir, SWTWorkbenchBot bot) { - SWTBotText text = bot.textWithLabel(GuiUtils.CC_DIR_WIDGET); - text.setText(ccDir.toString()); - // text.setFocus(); - // bot.textWithLabel(THREAD_WIDGET).setFocus(); - - // bot.sleep(SHORT_WAIT_TIME); + public static void setCCBinDir(ResolutionMethodTypes method, Path ccDir, SWTWorkbenchBot bot, boolean root) { + SWTBotRadio radio = null; + switch (method) { + case PATH: + radio = bot.radio("Search in PATH"); + break; + case PRE: + radio = bot.radio("Pre built package"); + break; + case PY: + radio = bot.radio("Custom built package"); + break; + default: + break; + } + radio.click(); + if (method != ResolutionMethodTypes.PATH || ccDir != null) { + SWTBotText text = bot.textWithLabel(GuiUtils.CC_DIR_WIDGET); + if (root) + ccDir = Paths.get(ccDir.toAbsolutePath().toString(), BIN, CODECHECKER); + text.setText(ccDir.toString()); + bot.sleep(SHORT_WAIT_TIME); + } } /** @@ -134,7 +176,7 @@ public static void deleteProject(String projectName, boolean deleteFromDisk, SWT if (deleteFromDisk) bot.checkBox("Delete project contents on disk (cannot be undone)").select(); bot.button("OK").click(); - bot.waitUntil(Conditions.shellCloses(shell)); + bot.waitUntil(Conditions.shellCloses(shell), LONG_TIME_OUT); } /** @@ -194,7 +236,7 @@ public void run() { * @param tab * The desired preferences tab. * @param bot - * the workbench bot to be used. + * The workbench bot to be used. * @return The newly opened shell. */ public static SWTBotShell getPreferencesTab(String tab, SWTWorkbenchBot bot) { @@ -204,4 +246,19 @@ public static SWTBotShell getPreferencesTab(String tab, SWTWorkbenchBot bot) { bot.tree().getTreeItem(tab).select(); return shell; } + + /** + * Designed to find the message header CLabel in an SWT From. + * + * @param prefix + * This prefix will be searched. + * @param bot + * The workbench bot to be used. + * @return returns the CLabel instance. + */ + public static CLabel findCLabel(String prefix, SWTWorkbenchBot bot) { + Matcher matcher = WidgetMatcherFactory.widgetOfType(CLabel.class); + List widgets = bot.widgets(matcher); + return widgets.stream().filter(item -> item.getText().startsWith(prefix)).findFirst().get(); + } } 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 66cae430..2a4e45d1 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 @@ -11,6 +11,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.codechecker.eclipse.rcp.shared;bundle-version="1.0.0" + org.codechecker.eclipse.rcp.shared;bundle-version="1.0.0", + com.google.guava, + com.github.stefanbirkner.system-rules;bundle-version="1.19.0" Bundle-ClassPath: ., resources/ diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerTest.java new file mode 100644 index 00000000..d6d896d5 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/CodeCheckerTest.java @@ -0,0 +1,127 @@ +package org.codechecker.eclipse.plugin.codechecker; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; +import org.codechecker.eclipse.plugin.config.CcConfigurationBase; +import org.codechecker.eclipse.plugin.config.Config.ConfigTypes; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelperFactory; +import org.codechecker.eclipse.rcp.shared.utils.Utils; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.mockito.Mockito; + +import com.google.common.base.Optional; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Tests to test functionality of {@link CodeChecker}. + */ +public class CodeCheckerTest { + private static final int RUN_COUNT = 123; + + private static final String DUMMY = "/home"; + private static final String ERROR_COULDNT_CREATE_CC = "Couldn't create CodeChecker instance!"; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private Path codeCheckerPath = Utils.prepareCodeChecker(); + private Path notACodeCheckerPath = Paths.get(DUMMY); + private ShellExecutorHelper she; + + /** + * Initialitze a CodeChecker test package and also a dummy path, and a + * {@link ShellExecutorHelper} with a default system environment. + */ + @Before + public void init() { + codeCheckerPath = Utils.prepareCodeChecker().resolve(Paths.get("bin", "CodeChecker")); + notACodeCheckerPath = Paths.get(DUMMY); + she = new ShellExecutorHelperFactory().createShellExecutorHelper(System.getenv()); + } + + /** + * Test that an exception is thrown when a CodeChecker is tred to be constructed + * with an invalid(no codechecker at that location). + * + * @throws InvalidCodeCheckerException + * For testing purposes. + */ + @Test + public void testInvalidPath() throws InvalidCodeCheckerException { + thrown.expect(InvalidCodeCheckerException.class); + new CodeChecker(notACodeCheckerPath, she); + } + + /** + * Test that the version string is returned. + */ + @Test + public void testVersionReturned() { + ICodeChecker codeChecker = null; + try { + codeChecker = new CodeChecker(codeCheckerPath, she); + } catch (InvalidCodeCheckerException e) { + fail(ERROR_COULDNT_CREATE_CC); + } + + try { + String version = codeChecker.getVersion(); + assertThat("Missing Version String", version.startsWith("CodeChecker analyzer version:")); + } catch (InvalidCodeCheckerException e) { + fail("An exception was thrown after a successful initialization!"); + } + } + + /** + * Test that the correct path is returned. + */ + @Test + public void testPathIsCorrect() { + ICodeChecker codeChecker = null; + try { + codeChecker = new CodeChecker(codeCheckerPath, she); + } catch (InvalidCodeCheckerException e) { + fail(ERROR_COULDNT_CREATE_CC); + } + assertThat("Path to CodeChecker wasn't the same", codeCheckerPath.compareTo(codeChecker.getLocation()) == 0); + } + + /** + * Simple test for running an analysis. + */ + @SuppressWarnings("unchecked") + @Test + public void analyzeTest() { + ICodeChecker codeChecker = null; + ShellExecutorHelper mockShe = Mockito.spy(new ShellExecutorHelper(System.getenv())); + try { + codeChecker = new CodeChecker(codeCheckerPath, mockShe); + } catch (InvalidCodeCheckerException e) { + fail(ERROR_COULDNT_CREATE_CC); + } + CcConfigurationBase configMock = mock(CcConfigurationBase.class); + final String cores = "3 "; + final String checkers = "-e Checker 1, -e Checker2 "; + final String analyzeMockString = "Running analysis! with" + cores + checkers; + when(configMock.get(ConfigTypes.ANAL_THREADS)).thenReturn(cores); + when(configMock.get(ConfigTypes.CHECKER_LIST)).thenReturn(checkers); + NullProgressMonitor mon = new NullProgressMonitor(); + when(mockShe.progressableWaitReturnOutput(anyString(), Mockito.anyMap(), Mockito.anyBoolean(), Mockito.eq(mon), + Mockito.eq(RUN_COUNT))) + .thenReturn(Optional.of(analyzeMockString)); + String analyzeResult = codeChecker.analyze(Paths.get(DUMMY), true, mon, RUN_COUNT, configMock); + assertThat("Analyze result isn't the same as specified", analyzeResult.equals(analyzeMockString)); + } +} diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java new file mode 100644 index 00000000..cdabc234 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java @@ -0,0 +1,112 @@ +package org.codechecker.eclipse.plugin.codechecker.locator; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.codechecker.eclipse.plugin.codechecker.CodeCheckerFactory; +import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; +import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; +import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelperFactory; +import org.codechecker.eclipse.rcp.shared.utils.Utils; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.EnvironmentVariables; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.fail; + +/** + * {@link CodeCheckerLocatorService} tests. + */ +public class CodeCheckerLocatorTest { + + private static final String ENV_PATH = "PATH"; + private static final String DUMMY = "/home"; + private static final String ERROR_COULDNT_CREATE_CC = "Couldn't create CodeChecker instance!"; + private static final Path CC_PATH = Utils.prepareCodeChecker(); + private static final Path PATH_CC_PATH = Utils.prepareCodeChecker(); + private static final Path NOT_CC_PATH = Paths.get(DUMMY); + // TODO implement virtual environment emulation + // private static final Path venvPath = Paths.get(DUMMY); + private static final ICodeCheckerFactory CC_FACTORY = new CodeCheckerFactory(); + private static final IShellExecutorHelperFactory SHEF = new ShellExecutorHelperFactory(); + + private static CodeCheckerLocatorFactory cclf; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); + + /** + * This factory can be used for the entire test. + */ + @BeforeClass + public static void setUpBeforeClass() { + cclf = new CodeCheckerLocatorFactory(); + } + + /** + * Test {@link EnvCodeCheckerLocatorService}. + * + * @throws InvalidCodeCheckerException + * For testing purposes. + */ + @Test + public void testPath() throws InvalidCodeCheckerException { + CodeCheckerLocatorService serv = cclf.create(ResolutionMethodTypes.PATH); + thrown.expect(InvalidCodeCheckerException.class); + thrown.expectMessage(EnvCodeCheckerLocatorService.ERROR); + + serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + // prepare PATH envval + String origPath = System.getenv(ENV_PATH); + String newPath = origPath.concat(":" + PATH_CC_PATH.toAbsolutePath().toString() + "/bin/"); + + // Set the prepared PATH + environmentVariables.set(ENV_PATH, newPath); + + serv = cclf.create(ResolutionMethodTypes.PATH); + try { + serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + } catch (InvalidCodeCheckerException e) { + fail(ERROR_COULDNT_CREATE_CC); + } + // reset env + environmentVariables.set(ENV_PATH, origPath); + } + + /** + * Test {@link PreBuiltCodeCheckerLocatorService}. + * + * @throws InvalidCodeCheckerException + * For testing purposes. + */ + @Test + public void testPre() throws InvalidCodeCheckerException { + CodeCheckerLocatorService serv = cclf.create(ResolutionMethodTypes.PRE); + + thrown.expect(RuntimeException.class); + thrown.expectMessage(PreBuiltCodeCheckerLocatorService.INVALID); + // Test null + serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + + thrown.expect(InvalidCodeCheckerException.class); + thrown.expectMessage(PreBuiltCodeCheckerLocatorService.ERROR); + // Test garbage + serv.findCodeChecker(Paths.get("gdfsg"), null, CC_FACTORY, SHEF); + + // Test not valid + serv.findCodeChecker(NOT_CC_PATH, null, CC_FACTORY, SHEF); + + // Test valid + serv = cclf.create(ResolutionMethodTypes.PATH); + try { + serv.findCodeChecker(CC_PATH, null, CC_FACTORY, SHEF); + } catch (InvalidCodeCheckerException e) { + fail(ERROR_COULDNT_CREATE_CC); + } + } +} diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java new file mode 100644 index 00000000..7483a6d9 --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/package-info.java @@ -0,0 +1,4 @@ +/** + * Unit tests. + */ +package org.codechecker.eclipse.plugin.codechecker.locator; \ No newline at end of file diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/package-info.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/package-info.java new file mode 100644 index 00000000..2c9cec3d --- /dev/null +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/package-info.java @@ -0,0 +1,4 @@ +/** + * Unit tests. + */ +package org.codechecker.eclipse.plugin.codechecker; \ No newline at end of file From 720b1a432da9d69e9f5169dd1969852286d9613a Mon Sep 17 00:00:00 2001 From: Vodorok Date: Mon, 2 Sep 2019 19:49:54 +0200 Subject: [PATCH 3/3] python virtual env stripping and fixing --- .../plugin/codechecker/CodeChecker.java | 26 +++++--- .../plugin/codechecker/ICodeChecker.java | 13 ++-- .../locator/CodeCheckerLocatorFactory.java | 2 - .../locator/CodeCheckerLocatorService.java | 5 +- .../CustomBuiltCodeCheckerLocatorService.java | 58 ------------------ .../locator/EnvCodeCheckerLocatorService.java | 8 +-- .../PreBuiltCodeCheckerLocatorService.java | 12 ++-- .../locator/ResolutionMethodTypes.java | 35 +---------- .../eclipse/plugin/config/CommonGui.java | 60 ++----------------- .../eclipse/plugin/config/Config.java | 1 - .../eclipse/plugin/report/job/AnalyzeJob.java | 5 +- .../eclipse/plugin/IndicatorTest.java | 4 +- .../eclipse/plugin/utils/GuiUtils.java | 10 +--- .../locator/CodeCheckerLocatorTest.java | 20 +++---- 14 files changed, 63 insertions(+), 196 deletions(-) delete mode 100644 bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java index d7fd6678..c524dc9f 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/CodeChecker.java @@ -13,6 +13,7 @@ import org.codechecker.eclipse.plugin.runtime.SLogger; import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; import com.google.common.base.Optional; @@ -21,6 +22,15 @@ */ public class CodeChecker implements ICodeChecker { + private static final String LOCATION_KEY = "location"; + private static final String RESULTS_KEY = "results"; + private static final String LOGFILE_KEY = "logFile"; + private static final String LOCATION_SUB = "${location}"; + private static final String RESULTS_SUB = "${results}"; + private static final String LOGFILE_SUB = "${logFile}"; + + private static final String RESULTS_FOLDER = RESULTS_KEY; + private Path location; private ShellExecutorHelper she; private Map subMap; @@ -39,20 +49,22 @@ public CodeChecker(Path path, ShellExecutorHelper she) throws InvalidCodeChecker location = path; this.she = she; subMap = new HashMap(); - subMap.put("location", path.toAbsolutePath().toFile()); + subMap.put(LOCATION_KEY, path.toAbsolutePath().toFile()); getVersion(); } @Override + @NonNull public String getCheckers() { - String cmd = "${location} checkers"; + String cmd = LOCATION_SUB + " checkers"; Optional ccOutput = she.waitReturnOutput(cmd, subMap, false); return ccOutput.or("No Checkers found"); } @Override + @NonNull public String getVersion() throws InvalidCodeCheckerException { - String cmd = "${location} version"; + String cmd = LOCATION_SUB + " version"; Optional ccOutput = she.waitReturnOutput(cmd, subMap, false); if (!ccOutput.isPresent() || ccOutput.get().isEmpty()) throw new InvalidCodeCheckerException("Couldn't run CodeChecker version!"); @@ -68,11 +80,11 @@ public Path getLocation() { public String analyze(Path logFile, boolean logToConsole, IProgressMonitor monitor, int taskCount, CcConfigurationBase config) { - subMap.put("results", logFile.getParent().toAbsolutePath().resolve(Paths.get("results")).toFile()); - subMap.put("logFile", logFile.toAbsolutePath().toFile()); - String cmd = "${location} analyze " + config.get(ConfigTypes.CHECKER_LIST) + " -j " + subMap.put(RESULTS_KEY, logFile.getParent().toAbsolutePath().resolve(Paths.get(RESULTS_FOLDER)).toFile()); + subMap.put(LOGFILE_KEY, logFile.toAbsolutePath().toFile()); + String cmd = LOCATION_SUB + " analyze " + config.get(ConfigTypes.CHECKER_LIST) + " -j " + config.get(ConfigTypes.ANAL_THREADS) + " -n javarunner" + " -o " - + "${results} ${logFile}"; + + RESULTS_SUB + " " + LOGFILE_SUB; SLogger.log(LogI.INFO, "Running analyze Command: " + cmd); Optional ccOutput = she.progressableWaitReturnOutput(cmd, subMap, logToConsole, monitor, taskCount); diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java index f8075d4b..e96a8503 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/ICodeChecker.java @@ -5,6 +5,7 @@ import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; import org.codechecker.eclipse.plugin.config.CcConfigurationBase; import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; /** * Interface representing a CodeChecker package. @@ -15,30 +16,34 @@ public interface ICodeChecker { * * @return The checker list. */ + @NonNull public String getCheckers(); /** - * Returns the full and complete version string of the CodeChecker package. + * Returns the full and complete version string of the CodeChecker package. The + * returned String will never be empty. * * @return The version String. * @throws InvalidCodeCheckerException * Thrown when no version string can be returned. */ + @NonNull public String getVersion() throws InvalidCodeCheckerException; /** - * To get the location of the CodeChecker binary. + * To get the location of the CodeChecker binary. The returned String will never + * be empty. * * @return The path. */ public Path getLocation(); /** - * Executes CodeChecker check command on the build log received in the fileName + * Executes CodeChecker check command on the build log received in the logFile * parameter. * * @param logFile - * A Path to the build log in the followin format: + * A Path to the build log in the following format: * http://clang.llvm.org/docs/JSONCompilationDatabase.html . * @param logToConsole * Flag for indicating console logging. diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java index f2e7a75f..988c98e6 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorFactory.java @@ -18,8 +18,6 @@ public CodeCheckerLocatorService create(ResolutionMethodTypes t) { return new EnvCodeCheckerLocatorService(); case PRE: return new PreBuiltCodeCheckerLocatorService(); - case PY: - return new CustomBuiltCodeCheckerLocatorService(); default: return null; } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java index f81b75d7..6f103398 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorService.java @@ -14,8 +14,6 @@ public abstract class CodeCheckerLocatorService { /** * @param pathToBin * Path to CodeChecker package root. - * @param pathToVenv - * Path to the root of the virtual environment. * @param ccfactory * An {@link ICodeCheckerFactory} that will create the CodeChecker. * @param sheFactory @@ -24,7 +22,6 @@ public abstract class CodeCheckerLocatorService { * @throws InvalidCodeCheckerException * Thrown when the {@link ICodeChecker} instantiation fails. */ - public abstract ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, ICodeCheckerFactory ccfactory, - IShellExecutorHelperFactory sheFactory) + public abstract ICodeChecker findCodeChecker(Path pathToBin, ICodeCheckerFactory ccfactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException; } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java deleted file mode 100644 index 9d722a6a..00000000 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/CustomBuiltCodeCheckerLocatorService.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.codechecker.eclipse.plugin.codechecker.locator; - -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; -import org.codechecker.eclipse.plugin.codechecker.ICodeCheckerFactory; -import org.codechecker.eclipse.plugin.runtime.IShellExecutorHelperFactory; -import org.codechecker.eclipse.plugin.runtime.ShellExecutorHelper; - -import com.google.common.base.Optional; - -/** - * Provides a CodeChecker instance which is tied to a Custom built CodeChecker - * package. - */ -public class CustomBuiltCodeCheckerLocatorService extends CodeCheckerLocatorService { - public static final String ERROR = "Couldn't find CodeChecker at the given destination!"; - public static final String ENV_ERROR = "There was an error when reading the given python environment!"; - - @Override - public ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, - ICodeCheckerFactory ccfactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { - - ShellExecutorHelper she = sheFactory.createShellExecutorHelper(System.getenv()); - Map subMap = new HashMap(); - subMap.put("venv", pathToVenv.resolve(Paths.get("bin", "activate")).toFile()); - Optional output = she - .quickReturnOutput("source ${venv} ; env", subMap); - if (!output.isPresent()) - throw new IllegalArgumentException(); - try { - Map env = parseEnvironment(output.get()); - ShellExecutorHelper pyShe = sheFactory.createShellExecutorHelper(env); - return ccfactory.createCodeChecker(pathToBin, pyShe); - } catch (ArrayIndexOutOfBoundsException e) { - throw new ArrayIndexOutOfBoundsException(ENV_ERROR); - } catch (InvalidCodeCheckerException e) { - throw new InvalidCodeCheckerException(ERROR); - } - } - - /** - * Returns a String - String map from a raw "Key=Value\n..." String. - * @param envOutput The String input. - * @return A Map containing all the environment variables. - */ - private Map parseEnvironment(String envOutput){ - Map map = Stream.of(envOutput.split("\n")).map(String::trim).map(line -> line.split("=")) - .collect(Collectors.toMap(k -> k[0], v -> v.length < 2 ? "" : v[1])); - return map; - } -} diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java index 26e2bf2e..ff65eb53 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/EnvCodeCheckerLocatorService.java @@ -13,18 +13,18 @@ * "which CodeChecker". */ public class EnvCodeCheckerLocatorService extends CodeCheckerLocatorService { - public static final String ERROR = "CodeChecker wasn't found in PATH environment variable!"; + public static final String CC_NOT_FOUND = "CodeChecker wasn't found in PATH environment variable!"; @Override - public ICodeChecker findCodeChecker(Path path, Path pathToVenv, - ICodeCheckerFactory ccFactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { + public ICodeChecker findCodeChecker(Path path, ICodeCheckerFactory ccFactory, + IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { ShellExecutorHelper she = sheFactory.createShellExecutorHelper(System.getenv()); String location = she.quickReturnFirstLine("which CodeChecker", null).or(""); try { return ccFactory.createCodeChecker(Paths.get(location), she); } catch (InvalidCodeCheckerException e) { - throw new InvalidCodeCheckerException(ERROR); + throw new InvalidCodeCheckerException(CC_NOT_FOUND); } } } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java index 4ff90c00..96ab25ae 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/PreBuiltCodeCheckerLocatorService.java @@ -11,18 +11,18 @@ * package. */ public class PreBuiltCodeCheckerLocatorService extends CodeCheckerLocatorService { - public static final String INVALID = "The path to the CodeChecker binary is not valid"; - public static final String ERROR = "Couldn't find CodeChecker at the given destination!"; + public static final String CC_INVALID = "The path to the CodeChecker binary is not valid"; + public static final String CC_NOT_FOUND = "Couldn't find CodeChecker at the given destination!"; @Override - public ICodeChecker findCodeChecker(Path pathToBin, Path pathToVenv, - ICodeCheckerFactory ccfactory, IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { + public ICodeChecker findCodeChecker(Path pathToBin, ICodeCheckerFactory ccfactory, + IShellExecutorHelperFactory sheFactory) throws InvalidCodeCheckerException { if (pathToBin == null) - throw new IllegalArgumentException(INVALID); + throw new IllegalArgumentException(CC_INVALID); try { return ccfactory.createCodeChecker(pathToBin, sheFactory.createShellExecutorHelper(System.getenv())); } catch (InvalidCodeCheckerException e) { - throw new InvalidCodeCheckerException(ERROR); + throw new InvalidCodeCheckerException(CC_NOT_FOUND); } } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java index f989c2b3..d3d6557c 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/codechecker/locator/ResolutionMethodTypes.java @@ -4,38 +4,5 @@ * This enum represents the available types of CodeChecker resolution methods. */ public enum ResolutionMethodTypes { - PATH("PATH"), PRE("PRE"), PY("PY"); - - private String value; - - /** - * - * @param def utility method for setting the default value. - */ - private ResolutionMethodTypes(String def) { - this.value = def; - } - - /** - * - * @return Returns the value associated with the enum. - */ - public String getDefaultValue() { - return value; - } - - /** - * - * @param s - * The query string. - * @return The matching ResolutionMethodTypes if exists null otherwise. - */ - public static ResolutionMethodTypes getFromString(String s) { - for (ResolutionMethodTypes r : ResolutionMethodTypes.values()) { - if (s.equals(r.toString())) - return r; - } - return null; - } - + PATH, PRE; } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java index 8e67e90f..5be09873 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/CommonGui.java @@ -10,7 +10,6 @@ import org.codechecker.eclipse.plugin.codechecker.CodeCheckerFactory; import org.codechecker.eclipse.plugin.codechecker.ICodeChecker; import org.codechecker.eclipse.plugin.codechecker.locator.CodeCheckerLocatorService; -import org.codechecker.eclipse.plugin.codechecker.locator.CustomBuiltCodeCheckerLocatorService; import org.codechecker.eclipse.plugin.codechecker.locator.EnvCodeCheckerLocatorService; import org.codechecker.eclipse.plugin.codechecker.locator.InvalidCodeCheckerException; import org.codechecker.eclipse.plugin.codechecker.locator.PreBuiltCodeCheckerLocatorService; @@ -38,7 +37,6 @@ import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; @@ -59,7 +57,6 @@ public class CommonGui { public static final String CC_BIN_LABEL = "CodeChecker binary:"; - public static final String VENV_LABEL = "Virtual env:"; private static final String VALID_PACKAGE = "CodeChecker being used: "; private static final String BROSWE = "Browse"; @@ -81,13 +78,10 @@ public class CommonGui { private Button pathCc; private Button preBuiltCc; - private Button customBuiltCc; + private Composite ccDirClient; private Text codeCheckerDirectoryField;// codechecker dir - private Button codeCheckerDirectoryFieldBrowse; - private Composite ccVenvClient; - private Text pythonEnvField;// CodeChecker python env - private Button pythonEnvFieldBrowse; + private ResolutionMethodTypes currentResMethod; private Section checkerConfigSection; @@ -286,12 +280,6 @@ private Section createConfigSection(FormToolkit toolkit) { .applyTo(ccDirClient); ccDirClient.setBackground(client.getBackground()); - ccVenvClient = toolkit.createComposite(client); - GridLayoutFactory.fillDefaults().numColumns(FORM_COLUMNS).applyTo(ccVenvClient); - GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(FORM_COLUMNS, FORM_ONE_ROW) - .applyTo(ccVenvClient); - ccVenvClient.setBackground(client.getBackground()); - pathCc = toolkit.createButton(resolutionType, "Search in PATH", SWT.RADIO); pathCc.setData(ResolutionMethodTypes.PATH); pathCc.addSelectionListener(new PackageResolutionSelectionAdapter()); @@ -300,10 +288,6 @@ private Section createConfigSection(FormToolkit toolkit) { preBuiltCc.setData(ResolutionMethodTypes.PRE); preBuiltCc.addSelectionListener(new PackageResolutionSelectionAdapter()); - customBuiltCc = toolkit.createButton(resolutionType, "Custom built package", SWT.RADIO); - customBuiltCc.setData(ResolutionMethodTypes.PY); - customBuiltCc.addSelectionListener(new PackageResolutionSelectionAdapter()); - codeCheckerDirectoryField = addTextField(toolkit, ccDirClient, CC_BIN_LABEL, ""); codeCheckerDirectoryField.addModifyListener(new ModifyListener() { @Override @@ -312,7 +296,7 @@ public void modifyText(ModifyEvent e) { } }); - codeCheckerDirectoryFieldBrowse = new Button(ccDirClient, SWT.PUSH); + Button codeCheckerDirectoryFieldBrowse = new Button(ccDirClient, SWT.PUSH); codeCheckerDirectoryFieldBrowse.setText(BROSWE); codeCheckerDirectoryFieldBrowse.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { @@ -327,27 +311,6 @@ public void widgetSelected(SelectionEvent event) { } }); - pythonEnvField = addTextField(toolkit, ccVenvClient, VENV_LABEL, ""); - pythonEnvField.addModifyListener(new ModifyListener() { - @Override - public void modifyText(ModifyEvent e) { - locateCodeChecker(); - } - }); - pythonEnvFieldBrowse = new Button(ccVenvClient, SWT.PUSH); - pythonEnvFieldBrowse.setText(BROSWE); - pythonEnvFieldBrowse.addSelectionListener(new SelectionAdapter() { - public void widgetSelected(SelectionEvent event) { - DirectoryDialog dlg = new DirectoryDialog(client.getShell()); - dlg.setFilterPath(codeCheckerDirectoryField.getText()); - dlg.setText("Browse python environment"); - String dir = dlg.open(); - if (dir != null) { - pythonEnvField.setText(dir); - locateCodeChecker(); - } - } - }); changeDirectoryInputs(); return packageConfigSection; @@ -362,15 +325,9 @@ public void changeDirectoryInputs() { switch (currentResMethod) { case PATH: recursiveSetEnabled(ccDirClient, false); - recursiveSetEnabled(ccVenvClient, false); break; case PRE: recursiveSetEnabled(ccDirClient, true); - recursiveSetEnabled(ccVenvClient, false); - break; - case PY: - recursiveSetEnabled(ccDirClient, true); - recursiveSetEnabled(ccVenvClient, true); break; default: break; @@ -389,16 +346,13 @@ public void locateCodeChecker() { case PRE: serv = new PreBuiltCodeCheckerLocatorService(); break; - case PY: - serv = new CustomBuiltCodeCheckerLocatorService(); - break; default: break; } ICodeChecker cc = null; try { cc = serv.findCodeChecker(Paths.get(codeCheckerDirectoryField.getText()), - Paths.get(pythonEnvField.getText()), new CodeCheckerFactory(), new ShellExecutorHelperFactory()); + new CodeCheckerFactory(), new ShellExecutorHelperFactory()); form.setMessage(VALID_PACKAGE + cc.getLocation().toString(), IMessageProvider.INFORMATION); if (globalGui || (!globalGui && !useGlobalSettings)) recursiveSetEnabled(checkerConfigSection, true); @@ -494,7 +448,7 @@ public Map loadConfig(boolean resetToDefault) { ret = config.get(); } else ret = config.getDefaultConfig(); - currentResMethod = ResolutionMethodTypes.getFromString(config.get(ConfigTypes.RES_METHOD)); + currentResMethod = ResolutionMethodTypes.valueOf(config.get(ConfigTypes.RES_METHOD)); return ret; } @@ -504,7 +458,6 @@ public Map loadConfig(boolean resetToDefault) { public void setFields() { pathCc.setSelection(false); preBuiltCc.setSelection(false); - customBuiltCc.setSelection(false); switch (currentResMethod) { case PATH: pathCc.setSelection(true); @@ -512,9 +465,6 @@ public void setFields() { case PRE: preBuiltCc.setSelection(true); break; - case PY: - customBuiltCc.setSelection(true); - break; default: break; } diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java index b47ca1c0..cde6cfa5 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/config/Config.java @@ -22,7 +22,6 @@ public class Config { public enum ConfigTypes { // Common configuration values CHECKER_PATH("codechecker_path"), - PYTHON_PATH(""), RES_METHOD("PATH"), COMPILERS("gcc:g++:clang:clang++"), ANAL_THREADS("4"), diff --git a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java index f49acd9a..830f17b2 100644 --- a/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java +++ b/bundles/org.codechecker.eclipse.plugin/src/org/codechecker/eclipse/plugin/report/job/AnalyzeJob.java @@ -72,7 +72,10 @@ public void accept(String t) { monitor.beginTask("Starting Analysis...", taskCount.get() * 2); try { - config.getCodeChecker().analyze(logFile, true, monitor, taskCount.get() * 2, config); + // TODO make numberOfAnalyzers a parameter depending on the turned on analyzer + // engines. + int numberOfAnalyzers = 2; + config.getCodeChecker().analyze(logFile, true, monitor, taskCount.get() * numberOfAnalyzers, config); } catch (NullPointerException e) { // TODO: Notify the user somehow that the analyze couldn't be completed, because // there is no CodeChecker configured. 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 index a8ed0ca8..9e82baa9 100644 --- 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 @@ -71,7 +71,7 @@ public void openPreferences() { public void testNoCodeCheckerFoundInPath() { SWTBotCLabel label = null; try { - label = bot.clabel(EnvCodeCheckerLocatorService.ERROR); + label = bot.clabel(EnvCodeCheckerLocatorService.CC_NOT_FOUND); } catch (WidgetNotFoundException e) { System.out.println(e.getMessage()); } @@ -90,7 +90,7 @@ public void testNoCodeCheckerFoundPre() { SWTBotCLabel label = null; try { - label = bot.clabel(PreBuiltCodeCheckerLocatorService.ERROR); + label = bot.clabel(PreBuiltCodeCheckerLocatorService.CC_NOT_FOUND); } catch (WidgetNotFoundException e) { System.out.println(e.getMessage()); } 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 index e158eb6a..81ff0682 100644 --- 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 @@ -52,7 +52,6 @@ public final class GuiUtils { public static final String ENVIR_LOGGER_FILE = "CC_LOGGER_FILE"; public static final String LDOGGER = "ldlogger"; public static final String THREAD_WIDGET = "Number of analysis threads"; - public static final String PY_DIR_WIDGET = "Virtual env:"; public static final String GLOBAL_RADIO = "Use global configuration"; public static final String PROJECT_RADIO = "Use project configuration"; @@ -142,18 +141,15 @@ public static void setCCBinDir(ResolutionMethodTypes method, Path ccDir, SWTWork case PRE: radio = bot.radio("Pre built package"); break; - case PY: - radio = bot.radio("Custom built package"); - break; default: break; } radio.click(); if (method != ResolutionMethodTypes.PATH || ccDir != null) { SWTBotText text = bot.textWithLabel(GuiUtils.CC_DIR_WIDGET); - if (root) - ccDir = Paths.get(ccDir.toAbsolutePath().toString(), BIN, CODECHECKER); - text.setText(ccDir.toString()); + // if the given path is the package root, extend it to the concrete binary else + // it could be used directly. + text.setText(root ? ccDir.resolve(Paths.get(BIN, CODECHECKER)).toString() : ccDir.toString()); bot.sleep(SHORT_WAIT_TIME); } } diff --git a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java index cdabc234..7a7a4c7c 100644 --- a/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java +++ b/tests/org.codechecker.eclipse.rcp.unit.tests/src/org/codechecker/eclipse/plugin/codechecker/locator/CodeCheckerLocatorTest.java @@ -27,8 +27,6 @@ public class CodeCheckerLocatorTest { private static final Path CC_PATH = Utils.prepareCodeChecker(); private static final Path PATH_CC_PATH = Utils.prepareCodeChecker(); private static final Path NOT_CC_PATH = Paths.get(DUMMY); - // TODO implement virtual environment emulation - // private static final Path venvPath = Paths.get(DUMMY); private static final ICodeCheckerFactory CC_FACTORY = new CodeCheckerFactory(); private static final IShellExecutorHelperFactory SHEF = new ShellExecutorHelperFactory(); @@ -58,9 +56,9 @@ public static void setUpBeforeClass() { public void testPath() throws InvalidCodeCheckerException { CodeCheckerLocatorService serv = cclf.create(ResolutionMethodTypes.PATH); thrown.expect(InvalidCodeCheckerException.class); - thrown.expectMessage(EnvCodeCheckerLocatorService.ERROR); + thrown.expectMessage(EnvCodeCheckerLocatorService.CC_NOT_FOUND); - serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + serv.findCodeChecker(null, CC_FACTORY, SHEF); // prepare PATH envval String origPath = System.getenv(ENV_PATH); String newPath = origPath.concat(":" + PATH_CC_PATH.toAbsolutePath().toString() + "/bin/"); @@ -70,7 +68,7 @@ public void testPath() throws InvalidCodeCheckerException { serv = cclf.create(ResolutionMethodTypes.PATH); try { - serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + serv.findCodeChecker(null, CC_FACTORY, SHEF); } catch (InvalidCodeCheckerException e) { fail(ERROR_COULDNT_CREATE_CC); } @@ -89,22 +87,22 @@ public void testPre() throws InvalidCodeCheckerException { CodeCheckerLocatorService serv = cclf.create(ResolutionMethodTypes.PRE); thrown.expect(RuntimeException.class); - thrown.expectMessage(PreBuiltCodeCheckerLocatorService.INVALID); + thrown.expectMessage(PreBuiltCodeCheckerLocatorService.CC_INVALID); // Test null - serv.findCodeChecker(null, null, CC_FACTORY, SHEF); + serv.findCodeChecker(null, CC_FACTORY, SHEF); thrown.expect(InvalidCodeCheckerException.class); - thrown.expectMessage(PreBuiltCodeCheckerLocatorService.ERROR); + thrown.expectMessage(PreBuiltCodeCheckerLocatorService.CC_NOT_FOUND); // Test garbage - serv.findCodeChecker(Paths.get("gdfsg"), null, CC_FACTORY, SHEF); + serv.findCodeChecker(Paths.get("gdfsg"), CC_FACTORY, SHEF); // Test not valid - serv.findCodeChecker(NOT_CC_PATH, null, CC_FACTORY, SHEF); + serv.findCodeChecker(NOT_CC_PATH, CC_FACTORY, SHEF); // Test valid serv = cclf.create(ResolutionMethodTypes.PATH); try { - serv.findCodeChecker(CC_PATH, null, CC_FACTORY, SHEF); + serv.findCodeChecker(CC_PATH, CC_FACTORY, SHEF); } catch (InvalidCodeCheckerException e) { fail(ERROR_COULDNT_CREATE_CC); }