Merge branch 'pmd6-improve-pmd-analysis' into pmd7-merge-master

This commit is contained in:
Clément Fournier 2022-03-05 15:34:41 +01:00
commit e414e2119c
No known key found for this signature in database
GPG Key ID: 4D8D42402E4F47E2
18 changed files with 240 additions and 105 deletions

View File

@ -75,6 +75,7 @@ The CLI itself remains compatible, if you run PMD via command-line, no action is
{% jdoc core::PMDConfiguration#setRuleSets(java.util.List) %},
{% jdoc core::PMDConfiguration#addRuleSet(java.lang.String) %},
and {% jdoc core::PMDConfiguration#getRuleSetPaths() %}.
* Several members of {% jdoc test::cli.BaseCLITest %} have been deprecated with replacements.
#### Experimental APIs

View File

@ -20,7 +20,8 @@ import org.slf4j.LoggerFactory;
import org.slf4j.event.Level;
import net.sourceforge.pmd.Report.GlobalReportBuilderListener;
import net.sourceforge.pmd.ReportStatsListener.ReportStats;
import net.sourceforge.pmd.reporting.ReportStatsListener;
import net.sourceforge.pmd.reporting.ReportStats;
import net.sourceforge.pmd.benchmark.TextTimingReportRenderer;
import net.sourceforge.pmd.benchmark.TimeTracker;
import net.sourceforge.pmd.benchmark.TimingReport;
@ -70,7 +71,7 @@ public final class PMD {
}
private static ReportStatsListener.ReportStats runAndReturnStats(PmdAnalysis pmd) {
private static ReportStats runAndReturnStats(PmdAnalysis pmd) {
if (pmd.getRulesets().isEmpty()) {
return ReportStats.empty();
}

View File

@ -354,6 +354,9 @@ public class PMDConfiguration extends AbstractConfiguration {
@Deprecated
@DeprecatedUntil700
public String getRuleSets() {
if (ruleSets.isEmpty()) {
return null;
}
return StringUtils.join(ruleSets, ",");
}

View File

@ -80,6 +80,8 @@ public final class PmdAnalysis implements AutoCloseable {
private final PmdLogger reporter;
private boolean closed;
/**
* Constructs a new instance. The files paths (input files, filelist,
* exclude list, etc) given in the configuration are collected into
@ -238,7 +240,8 @@ public final class PmdAnalysis implements AutoCloseable {
* All files collected in the {@linkplain #files() file collector} are
* processed. This does not return a report, as the analysis results
* are consumed by {@link GlobalAnalysisListener} instances (of which
* Renderers are a special case).
* Renderers are a special case). Note that this does
* not throw, errors are instead accumulated into a {@link PmdLogger}.
*/
public void performAnalysis() {
performAnalysisImpl(Collections.emptyList());
@ -248,7 +251,8 @@ public final class PmdAnalysis implements AutoCloseable {
* Run PMD with the current state of this instance. This will start
* and finish the registered renderers. All files collected in the
* {@linkplain #files() file collector} are processed. Returns the
* output report.
* output report. Note that this does not throw, errors are instead
* accumulated into a {@link PmdLogger}.
*/
public Report performAnalysisAndCollectReport() {
try (GlobalReportBuilderListener reportBuilder = new GlobalReportBuilderListener()) {
@ -364,6 +368,10 @@ public final class PmdAnalysis implements AutoCloseable {
@Override
public void close() {
if (closed) {
return;
}
closed = true;
collector.close();
/*

View File

@ -28,7 +28,7 @@ import net.sourceforge.pmd.util.datasource.DataSource;
* and configuration errors.
*
* <p>A report may be created by a {@link GlobalReportBuilderListener} that you
* use as the {@link GlobalAnalysisListener} in {@linkplain PMD#processFiles(PMDConfiguration, List, List, GlobalAnalysisListener) PMD's entry point}.
* use as the {@linkplain GlobalAnalysisListener} in {@link PmdAnalysis#performAnalysisAndCollectReport() PMD's entry point}.
* You can also create one manually with {@link #buildReport(Consumer)}.
*/
public final class Report {

View File

@ -19,6 +19,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.Language;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.util.CollectionUtil;
@ -192,8 +193,12 @@ public final class RuleSetLoader {
/**
* Loads a list of rulesets, if any has an error, report it on the contextual
* error reporter instead of aborting, and continue loading the rest.
*
* <p>Internal API: might be published later, or maybe in PMD 7 this
* will be the default behaviour of every method of this class.
*/
List<RuleSet> loadRuleSetsWithoutException(List<String> rulesetPaths) {
@InternalApi
public List<RuleSet> loadRuleSetsWithoutException(List<String> rulesetPaths) {
List<RuleSet> ruleSets = new ArrayList<>(rulesetPaths.size());
boolean anyRules = false;
for (String path : rulesetPaths) {
@ -203,12 +208,17 @@ public final class RuleSetLoader {
printRulesInDebug(path, ruleset);
ruleSets.add(ruleset);
} catch (RuleSetLoadException e) {
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e);
if (e.getCause() != null) {
// eg RuleSetNotFoundException
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e.getCause());
} else {
reporter.errorEx("Cannot load ruleset {0}", new Object[] { path }, e);
}
}
}
if (!anyRules) {
reporter.warning("No rules found. Maybe you misspelled a rule name? ({0})",
StringUtils.join(rulesetPaths, ','));
reporter.warn("No rules found. Maybe you misspelled a rule name? ({0})",
StringUtils.join(rulesetPaths, ','));
}
return ruleSets;
}
@ -221,7 +231,7 @@ public final class RuleSetLoader {
}
}
if (ruleset.getRules().isEmpty()) {
reporter.warning("No rules found in ruleset {0}", path);
reporter.warn("No rules found in ruleset {0}", path);
}
}

View File

@ -6,7 +6,7 @@ package net.sourceforge.pmd.ant.internal;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.StringJoiner;
@ -23,10 +23,7 @@ import org.slf4j.event.Level;
import net.sourceforge.pmd.PMDConfiguration;
import net.sourceforge.pmd.PmdAnalysis;
import net.sourceforge.pmd.Rule;
import net.sourceforge.pmd.RulePriority;
import net.sourceforge.pmd.RuleSet;
import net.sourceforge.pmd.RuleSetLoadException;
import net.sourceforge.pmd.RuleSetLoader;
import net.sourceforge.pmd.ant.Formatter;
import net.sourceforge.pmd.ant.PMDTask;
@ -37,7 +34,8 @@ import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.LanguageVersion;
import net.sourceforge.pmd.reporting.FileAnalysisListener;
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
import net.sourceforge.pmd.reporting.GlobalAnalysisListener.ViolationCounterListener;
import net.sourceforge.pmd.reporting.ReportStats;
import net.sourceforge.pmd.reporting.ReportStatsListener;
import net.sourceforge.pmd.util.ClasspathClassLoader;
import net.sourceforge.pmd.util.IOUtil;
import net.sourceforge.pmd.util.datasource.DataSource;
@ -50,6 +48,7 @@ public class PMDTaskImpl {
private final List<FileSet> filesets = new ArrayList<>();
private final PMDConfiguration configuration = new PMDConfiguration();
private final String rulesetPaths;
private boolean failOnError;
private boolean failOnRuleViolation;
private int maxRuleViolations = 0;
private String failuresPropertyName;
@ -60,6 +59,7 @@ public class PMDTaskImpl {
if (task.getSuppressMarker() != null) {
configuration.setSuppressMarker(task.getSuppressMarker());
}
this.failOnError = task.isFailOnError();
this.failOnRuleViolation = task.isFailOnRuleViolation();
this.maxRuleViolations = task.getMaxRuleViolations();
if (this.maxRuleViolations > 0) {
@ -98,26 +98,23 @@ public class PMDTaskImpl {
private void doTask() {
setupClassLoader();
// Setup RuleSetFactory and validate RuleSets
RuleSetLoader rulesetLoader = RuleSetLoader.fromPmdConfig(configuration)
.loadResourcesWith(setupResourceLoader());
List<RuleSet> rules = loadRulesets(rulesetLoader);
if (configuration.getSuppressMarker() != null) {
project.log("Setting suppress marker to be " + configuration.getSuppressMarker(), Project.MSG_VERBOSE);
}
@SuppressWarnings("PMD.CloseResource")
ViolationCounterListener reportSizeListener = new ViolationCounterListener();
final List<String> reportShortNamesPaths = new ArrayList<>();
@SuppressWarnings("PMD.CloseResource") final List<String> reportShortNamesPaths = new ArrayList<>();
StringJoiner fullInputPath = new StringJoiner(",");
List<String> ruleSetPaths = expandRuleSetPaths();
// don't let PmdAnalysis.create create rulesets itself.
configuration.setRuleSets(Collections.emptyList());
ReportStats stats;
try (PmdAnalysis pmd = PmdAnalysis.create(configuration)) {
for (RuleSet ruleSet : rules) {
pmd.addRuleSet(ruleSet);
}
RuleSetLoader rulesetLoader =
pmd.newRuleSetLoader().loadResourcesWith(setupResourceLoader());
pmd.addRuleSets(rulesetLoader.loadRuleSetsWithoutException(ruleSetPaths));
for (FileSet fileset : filesets) {
DirectoryScanner ds = fileset.getDirectoryScanner(project);
@ -132,11 +129,17 @@ public class PMDTaskImpl {
}
}
pmd.addListener(getListener(reportSizeListener, reportShortNamesPaths, fullInputPath.toString()));
ReportStatsListener reportStatsListener = new ReportStatsListener();
pmd.addListener(getListener(reportStatsListener, reportShortNamesPaths, fullInputPath.toString()));
pmd.performAnalysis();
stats = reportStatsListener.getResult();
if (failOnError && pmd.getLog().numErrors() > 0) {
throw new BuildException("Some errors occurred while running PMD");
}
}
int problemCount = reportSizeListener.getResult();
int problemCount = stats.getNumViolations();
project.log(problemCount + " problems found", Project.MSG_VERBOSE);
if (failuresPropertyName != null && problemCount > 0) {
@ -149,25 +152,17 @@ public class PMDTaskImpl {
}
}
private List<RuleSet> loadRulesets(RuleSetLoader rulesetLoader) {
try {
// This is just used to validate and display rules. Each thread will create its own ruleset
// Substitute env variables/properties
String ruleSetString = project.replaceProperties(rulesetPaths);
List<String> rulesets = Arrays.asList(ruleSetString.split(","));
List<RuleSet> rulesetList = rulesetLoader.loadFromResources(rulesets);
if (rulesetList.isEmpty()) {
throw new BuildException("No rulesets");
}
logRulesUsed(rulesetList);
return rulesetList;
} catch (RuleSetLoadException e) {
throw new BuildException(e.getMessage(), e);
private List<String> expandRuleSetPaths() {
List<String> paths = new ArrayList<>(configuration.getRuleSetPaths());
for (int i = 0; i < paths.size(); i++) {
paths.set(i, project.replaceProperties(paths.get(i)));
}
return paths;
}
private @NonNull GlobalAnalysisListener getListener(ViolationCounterListener reportSizeListener, List<String> reportShortNamesPaths, String inputPaths) {
private @NonNull GlobalAnalysisListener getListener(ReportStatsListener reportSizeListener,
List<String> reportShortNamesPaths,
String inputPaths) {
List<GlobalAnalysisListener> renderers = new ArrayList<>(formatters.size() + 1);
try {
renderers.add(makeLogListener(inputPaths));
@ -254,13 +249,4 @@ public class PMDTaskImpl {
}
}
private void logRulesUsed(List<RuleSet> rulesets) {
project.log("Using these rulesets: " + rulesetPaths, Project.MSG_VERBOSE);
for (RuleSet ruleSet : rulesets) {
for (Rule rule : ruleSet.getRules()) {
project.log("Using rule " + rule.getName(), Project.MSG_VERBOSE);
}
}
}
}

View File

@ -8,6 +8,7 @@ import java.util.Properties;
import java.util.stream.Collectors;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PMD.StatusCode;
import net.sourceforge.pmd.PMDVersion;
import net.sourceforge.pmd.annotation.InternalApi;
import net.sourceforge.pmd.lang.Language;
@ -28,13 +29,39 @@ import com.beust.jcommander.ParameterException;
@InternalApi
public final class PMDCommandLineInterface {
@Deprecated
public static final String PROG_NAME = "pmd";
/**
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
*/
@Deprecated
public static final String NO_EXIT_AFTER_RUN = "net.sourceforge.pmd.cli.noExit";
/**
* @deprecated This is used for testing, but support for it will be removed in PMD 7.
* Use {@link PMD#runPmd(String...)} or an overload to avoid exiting the VM. In PMD 7,
* {@link PMD#main(String[])} will call {@link System#exit(int)} always.
*/
@Deprecated
public static final String STATUS_CODE_PROPERTY = "net.sourceforge.pmd.cli.status";
/**
* @deprecated Use {@link StatusCode#OK}
*/
@Deprecated
public static final int NO_ERRORS_STATUS = 0;
/**
* @deprecated Use {@link StatusCode#ERROR}
*/
@Deprecated
public static final int ERROR_STATUS = 1;
/**
* @deprecated Use {@link StatusCode#VIOLATIONS_FOUND}
*/
@Deprecated
public static final int VIOLATIONS_FOUND = 4;
private PMDCommandLineInterface() { }
@ -126,7 +153,10 @@ public final class PMDCommandLineInterface {
* For testing purpose only...
*
* @param args
*
* @deprecated Use {@link PMD#runPmd(String...)}
*/
@Deprecated
public static void main(String[] args) {
System.out.println(PMDCommandLineInterface.buildUsageText());
}

View File

@ -169,9 +169,9 @@ public final class FileCollectionUtil {
String source = IOUtils.toString(sourceCode);
collector.addSourceFile(source, falseFilePath);
} catch (SQLException ex) {
collector.getLog().warningEx("Cannot get SourceCode for {} - skipping ...",
new Object[] { falseFilePath},
ex);
collector.getLog().warnEx("Cannot get SourceCode for {} - skipping ...",
new Object[] { falseFilePath},
ex);
}
}
} catch (ClassNotFoundException e) {

View File

@ -0,0 +1,38 @@
/*
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.reporting;
/**
* Summarized info about a report.
*
* @author Clément Fournier
*/
public final class ReportStats {
private final int numErrors;
private final int numViolations;
ReportStats(int numErrors, int numViolations) {
this.numErrors = numErrors;
this.numViolations = numViolations;
}
public static ReportStats empty() {
return new ReportStats(0, 0);
}
public int getNumErrors() {
return numErrors;
}
public int getNumViolations() {
return numViolations;
}
@Override
public String toString() {
return "ReportStats{numErrors=" + numErrors + ", numViolations=" + numViolations + '}';
}
}

View File

@ -2,23 +2,21 @@
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
package net.sourceforge.pmd.reporting;
import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.pmd.Report.ProcessingError;
import net.sourceforge.pmd.ReportStatsListener.ReportStats;
import net.sourceforge.pmd.reporting.FileAnalysisListener;
import net.sourceforge.pmd.reporting.GlobalAnalysisListener;
import net.sourceforge.pmd.RuleViolation;
import net.sourceforge.pmd.util.BaseResultProducingCloseable;
import net.sourceforge.pmd.util.datasource.DataSource;
/**
* Counts processing errors.
* Collects summarized info about a PMD run.
*
* @author Clément Fournier
*/
final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats> implements GlobalAnalysisListener {
public final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats> implements GlobalAnalysisListener {
private final AtomicInteger numErrors = new AtomicInteger(0);
private final AtomicInteger numViolations = new AtomicInteger(0);
@ -62,31 +60,4 @@ final class ReportStatsListener extends BaseResultProducingCloseable<ReportStats
}
static final class ReportStats {
private final int numErrors;
private final int numViolations;
ReportStats(int numErrors, int numViolations) {
this.numErrors = numErrors;
this.numViolations = numViolations;
}
public static ReportStats empty() {
return new ReportStats(0, 0);
}
public int getNumErrors() {
return numErrors;
}
public int getNumViolations() {
return numViolations;
}
@Override
public String toString() {
return "ReportStats{numErrors=" + numErrors + ", numViolations=" + numViolations + '}';
}
}
}

View File

@ -4,6 +4,10 @@
package net.sourceforge.pmd.util;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
@ -513,6 +517,13 @@ public final class StringUtil {
return retval.toString();
}
/**
* Escape the string so that it appears literally when interpreted
* by a {@link MessageFormat}.
*/
public static String quoteMessageFormat(String str) {
return str.replaceAll("'", "''");
}
public enum CaseConvention {
/** SCREAMING_SNAKE_CASE. */

View File

@ -36,7 +36,7 @@ public interface PmdLogger {
logEx(Level.WARN, message, new Object[0], error);
}
default void warningEx(String message, Object[] formatArgs, Throwable error) {
default void warnEx(String message, Object[] formatArgs, Throwable error) {
logEx(Level.WARN, message, formatArgs, error);
}
@ -52,6 +52,12 @@ public interface PmdLogger {
logEx(Level.ERROR, message, formatArgs, error);
}
/**
* Returns the number of errors reported on this instance.
* Any call to {@link #log(Level, String, Object...)} or
* {@link #logEx(Level, String, Object[], Throwable)} with a level
* of {@link Level#ERROR} should increment this number.
*/
int numErrors();
}

View File

@ -9,6 +9,8 @@ import java.text.MessageFormat;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.event.Level;
import net.sourceforge.pmd.util.StringUtil;
/**
* Base implementation.
*
@ -41,9 +43,15 @@ abstract class PmdLoggerBase implements PmdLogger {
public void logEx(Level level, String message, Object[] formatArgs, Throwable error) {
if (isLoggable(level)) {
message = MessageFormat.format(message, formatArgs);
log(level, message + ": " + error.getMessage());
String errorMessage = error.getMessage();
if (errorMessage == null) {
errorMessage = error.getClass().getSimpleName();
}
errorMessage = StringUtil.quoteMessageFormat(errorMessage);
log(level, message + ": " + errorMessage);
if (isLoggable(Level.DEBUG)) {
log(Level.DEBUG, ExceptionUtils.getStackTrace(error));
String stackTrace = StringUtil.quoteMessageFormat(ExceptionUtils.getStackTrace(error));
log(Level.DEBUG, stackTrace);
}
}
}

View File

@ -4,9 +4,13 @@
package net.sourceforge.pmd;
import static net.sourceforge.pmd.util.CollectionUtil.listOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@ -16,6 +20,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Properties;
import org.junit.Assert;
@ -111,6 +116,25 @@ public class ConfigurationTest {
Assert.assertArrayEquals(expectedUris, uris);
}
@Test
public void testRuleSetsLegacy() {
PMDConfiguration configuration = new PMDConfiguration();
assertNull("Default RuleSets", configuration.getRuleSets());
configuration.setRuleSets("/rulesets/basic.xml");
assertEquals("Changed RuleSets", "/rulesets/basic.xml", configuration.getRuleSets());
}
@Test
public void testRuleSets() {
PMDConfiguration configuration = new PMDConfiguration();
assertThat(configuration.getRuleSetPaths(), empty());
configuration.setRuleSets(listOf("/rulesets/basic.xml"));
assertEquals(listOf("/rulesets/basic.xml"), configuration.getRuleSetPaths());
configuration.addRuleSet("foo.xml");
assertEquals(listOf("/rulesets/basic.xml", "foo.xml"), configuration.getRuleSetPaths());
configuration.setRuleSets(Collections.<String>emptyList());
assertThat(configuration.getRuleSetPaths(), empty());
}
@Test
public void testMinimumPriority() {

View File

@ -16,6 +16,8 @@ import org.junit.rules.TestRule;
import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration;
import net.sourceforge.pmd.PMD.StatusCode;
/**
* @author Romain Pelisse &lt;belaran@gmail.com&gt;
*
@ -75,21 +77,21 @@ public class CLITest extends BaseCLITest {
@Test
public void exitStatusWithViolations() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", };
String log = runTest(4, args);
String log = runTest(StatusCode.VIOLATIONS_FOUND, args);
assertThat(log, containsString("Avoid empty if"));
}
@Test
public void exitStatusWithViolationsAndWithoutFailOnViolations() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", "-failOnViolation", "false", };
String log = runTest(0, args);
String log = runTest(StatusCode.OK, args);
assertThat(log, containsString("Avoid empty if"));
}
@Test
public void exitStatusWithViolationsAndWithoutFailOnViolationsLongOption() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/errorprone.xml", "--fail-on-violation", "false", };
String log = runTest(0, args);
String log = runTest(StatusCode.OK, args);
assertThat(log, containsString("Avoid empty if"));
}
@ -99,7 +101,7 @@ public class CLITest extends BaseCLITest {
@Test
public void testWrongRuleset() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/designn.xml", };
String log = runTest(1, args);
String log = runTest(StatusCode.ERROR, args);
assertThat(log, containsString("Can't find resource 'category/java/designn.xml' for rule 'null'."
+ " Make sure the resource is a valid file"));
}
@ -110,7 +112,7 @@ public class CLITest extends BaseCLITest {
@Test
public void testWrongRulesetWithRulename() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/designn.xml/UseCollectionIsEmpty", };
String log = runTest(1, args);
String log = runTest(StatusCode.ERROR, args);
assertThat(log, containsString("Can't find resource 'category/java/designn.xml' for rule "
+ "'UseCollectionIsEmpty'."));
}
@ -121,7 +123,7 @@ public class CLITest extends BaseCLITest {
@Test
public void testWrongRulename() {
String[] args = { "-d", SOURCE_FOLDER, "-f", "text", "-R", "category/java/design.xml/ThisRuleDoesNotExist", };
String log = runTest(1, args);
String log = runTest(StatusCode.OK, args);
assertThat(log, containsString("No rules found. Maybe you misspelled a rule name?"
+ " (category/java/design.xml/ThisRuleDoesNotExist)"));
}

View File

@ -25,6 +25,7 @@ import org.junit.BeforeClass;
import net.sourceforge.pmd.PMD;
import net.sourceforge.pmd.PMD.StatusCode;
import net.sourceforge.pmd.internal.util.AssertionUtil;
/**
* @author Romain Pelisse &lt;belaran@gmail.com&gt;
@ -79,11 +80,19 @@ public abstract class BaseCLITest {
}
}
/**
* @deprecated Use {@link #runTest(String...)}, note that
* it returns the log while this returns the name of a file containing the log.
*/
@Deprecated
protected String runTest(String[] args, String testname) {
return runTest(args);
return runTest(args, testname, 0);
}
/**
* @deprecated Use {@link #runTest(StatusCode, String...)}, note that
* it returns the log while this returns the name of a file containing the log.
*/
@Deprecated
protected String runTest(String[] args, String testname, int expectedExitCode) {
String filename = TEST_OUPUT_DIRECTORY + testname + ".txt";
@ -100,27 +109,49 @@ public abstract class BaseCLITest {
* Returns the log output.
*/
protected String runTest(String... args) {
return runTest(0, args);
return runTest(StatusCode.OK, args);
}
/**
* Returns the log output.
*
* @deprecated Use {@link #runTest(StatusCode, String...)}
*/
@Deprecated
protected String runTest(int expectedExitCode, String... args) {
switch (expectedExitCode) {
case 0:
return runTest(StatusCode.OK, args);
case 1:
return runTest(StatusCode.ERROR, args);
case 4:
return runTest(StatusCode.VIOLATIONS_FOUND, args);
default:
throw AssertionUtil.shouldNotReachHere("unknown status code " + expectedExitCode);
}
}
protected String runTest(StatusCode expectedExitCode, String... args) {
ByteArrayOutputStream console = new ByteArrayOutputStream();
PrintStream out = new PrintStream(console);
System.setOut(out);
System.setErr(out);
StatusCode statusCode = PMD.runPmd(args);
assertEquals(expectedExitCode, statusCode.toInt());
assertEquals(expectedExitCode, statusCode);
return console.toString();
}
/**
* @deprecated Use {@link #runTest(StatusCode, String...)}
*/
@Deprecated
protected void runPMDWith(String[] args) {
PMD.main(args);
}
/**
* @deprecated Use {@link #runTest(StatusCode, String...)} instead of checking the return code manually
*/
@Deprecated
protected void checkStatusCode(int expectedExitCode) {
int statusCode = getStatusCode();
@ -129,6 +160,10 @@ public abstract class BaseCLITest {
}
}
/**
* @deprecated Use {@link #runTest(StatusCode, String...)} instead
* of checking the return code manually
*/
@Deprecated
protected int getStatusCode() {
return Integer.parseInt(System.getProperty(PMDCommandLineInterface.STATUS_CODE_PROPERTY));

View File

@ -14,6 +14,7 @@ import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.PMD.StatusCode;
import net.sourceforge.pmd.cli.BaseCLITest;
public class XmlCliTest extends BaseCLITest {
@ -36,19 +37,19 @@ public class XmlCliTest extends BaseCLITest {
@Test
public void analyzeSingleXmlWithoutForceLanguage() {
String log = runTest(0, createArgs("/src/file1.ext"));
String log = runTest(StatusCode.OK, createArgs("/src/file1.ext"));
assertRuleMessage(0, log);
}
@Test
public void analyzeSingleXmlWithForceLanguage() {
String log = runTest(4, createArgs("/src/file1.ext", "-force-language", "xml"));
String log = runTest(StatusCode.VIOLATIONS_FOUND, createArgs("/src/file1.ext", "-force-language", "xml"));
assertRuleMessage(1, log);
}
@Test
public void analyzeDirectoryWithForceLanguage() {
String log = runTest(4, createArgs("/src/", "-force-language", "xml"));
String log = runTest(StatusCode.VIOLATIONS_FOUND, createArgs("/src/", "-force-language", "xml"));
assertRuleMessage(3, log);
}