From 675710d0e790def5ffdb521d95ab3e3892b0f5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 25 Nov 2022 11:04:54 +0100 Subject: [PATCH] Cleanup Cli tests Remove some deprecated things left over by #4059 --- .../internal/AbstractPmdSubcommand.java | 4 +- .../pmd/cli/commands/internal/CpdCommand.java | 10 +- .../commands/internal/DesignerCommand.java | 6 +- .../pmd/cli/commands/internal/PmdCommand.java | 14 +- .../cli/commands/internal/PmdRootCommand.java | 2 +- .../commands/internal/TreeExportCommand.java | 8 +- .../pmd/cli/internal/CliExitCode.java | 49 +++ .../pmd/cli/internal/ExecutionResult.java | 25 -- .../net/sourceforge/pmd/cli/BaseCliTest.java | 131 +++++++- .../net/sourceforge/pmd/cli/CpdCliTest.java | 27 +- .../net/sourceforge/pmd/cli/PmdCliTest.java | 38 ++- .../pmd/cli/TreeExportCliTest.java | 33 +- .../net/sourceforge/pmd/cli/CoreCliTest.java | 286 ------------------ .../java/net/sourceforge/pmd/cli/CLITest.java | 31 -- 14 files changed, 235 insertions(+), 429 deletions(-) create mode 100644 pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/CliExitCode.java delete mode 100644 pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/ExecutionResult.java delete mode 100644 pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java delete mode 100644 pmd-javascript/src/test/java/net/sourceforge/pmd/cli/CLITest.java diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractPmdSubcommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractPmdSubcommand.java index f3385db824..05a8ef9b75 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractPmdSubcommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/AbstractPmdSubcommand.java @@ -9,7 +9,7 @@ import java.util.concurrent.Callable; import org.slf4j.LoggerFactory; import org.slf4j.event.Level; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration; import picocli.CommandLine.Model.CommandSpec; @@ -46,7 +46,7 @@ public abstract class AbstractPmdSubcommand implements Callable { // no-op, children may override } - protected abstract ExecutionResult execute(); + protected abstract CliExitCode execute(); private void setupCliLogger() { // only reconfigure logging, if debug flag was used on command line diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java index 2b809050db..68614cec2e 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/CpdCommand.java @@ -17,7 +17,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sourceforge.pmd.cli.commands.typesupport.internal.CpdLanguageTypeSupport; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.cpd.CPD; import net.sourceforge.pmd.cpd.CPDConfiguration; import net.sourceforge.pmd.cpd.CPDReport; @@ -127,7 +127,7 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand { } @Override - protected ExecutionResult execute() { + protected CliExitCode execute() { final Logger logger = LoggerFactory.getLogger(CpdCommand.class); // TODO : Create a new CpdAnalysis to match PmdAnalysis @@ -141,15 +141,15 @@ public class CpdCommand extends AbstractAnalysisPmdSubcommand { configuration.getCPDReportRenderer().render(report, IOUtil.createWriter(Charset.defaultCharset(), null)); if (cpd.getMatches().hasNext() && configuration.isFailOnViolation()) { - return ExecutionResult.VIOLATIONS_FOUND; + return CliExitCode.VIOLATIONS_FOUND; } } catch (IOException | RuntimeException e) { logger.debug(e.toString(), e); logger.error(LogMessages.errorDetectedMessage(1, "cpd")); - return ExecutionResult.ERROR; + return CliExitCode.ERROR; } - return ExecutionResult.OK; + return CliExitCode.OK; } /** diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/DesignerCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/DesignerCommand.java index 68aabc4b37..8c53634b69 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/DesignerCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/DesignerCommand.java @@ -4,7 +4,7 @@ package net.sourceforge.pmd.cli.commands.internal; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.util.fxdesigner.DesignerStarter; import net.sourceforge.pmd.util.fxdesigner.DesignerStarter.ExitStatus; import net.sourceforge.pmd.util.fxdesigner.DesignerVersion; @@ -23,11 +23,11 @@ public class DesignerCommand extends AbstractPmdSubcommand { private boolean versionRequested; @Override - protected ExecutionResult execute() { + protected CliExitCode execute() { final String[] rawArgs = spec.commandLine().getParseResult().expandedArgs().toArray(new String[0]); final ExitStatus status = DesignerStarter.launchGui(rawArgs); - return status == ExitStatus.OK ? ExecutionResult.OK : ExecutionResult.ERROR; + return status == ExitStatus.OK ? CliExitCode.OK : CliExitCode.ERROR; } } diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java index 87fcc9f557..fb792d0686 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdCommand.java @@ -26,7 +26,7 @@ import net.sourceforge.pmd.benchmark.TimingReport; import net.sourceforge.pmd.benchmark.TimingReportRenderer; import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageTypeSupport; import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageVersionTypeSupport; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.internal.LogMessages; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageVersion; @@ -304,7 +304,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand { } @Override - protected ExecutionResult execute() { + protected CliExitCode execute() { if (benchmark) { TimeTracker.startGlobalTracking(); } @@ -319,18 +319,18 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand { pmd = PmdAnalysis.create(configuration); } catch (final Exception e) { pmdReporter.errorEx("Could not initialize analysis", e); - return ExecutionResult.ERROR; + return CliExitCode.ERROR; } pmdReporter.log(Level.DEBUG, "Current classpath:\n{0}", System.getProperty("java.class.path")); final ReportStats stats = pmd.runAndReturnStats(); if (pmdReporter.numErrors() > 0) { // processing errors are ignored - return ExecutionResult.ERROR; + return CliExitCode.ERROR; } else if (stats.getNumViolations() > 0 && configuration.isFailOnViolation()) { - return ExecutionResult.VIOLATIONS_FOUND; + return CliExitCode.VIOLATIONS_FOUND; } else { - return ExecutionResult.OK; + return CliExitCode.OK; } } finally { if (pmd != null) { @@ -341,7 +341,7 @@ public class PmdCommand extends AbstractAnalysisPmdSubcommand { } catch (final Exception e) { pmdReporter.errorEx("Exception while running PMD.", e); printErrorDetected(pmdReporter, 1); - return ExecutionResult.ERROR; + return CliExitCode.ERROR; } finally { finishBenchmarker(pmdReporter); } diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdRootCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdRootCommand.java index 380b46929a..ef15d504fd 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdRootCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/PmdRootCommand.java @@ -12,7 +12,7 @@ import picocli.CommandLine.IVersionProvider; @Command(name = "pmd", mixinStandardHelpOptions = true, versionProvider = PMDVersionProvider.class, exitCodeListHeading = "Exit Codes:%n", - exitCodeList = { "0:Succesful analysis, no violations found", "1:An unexpected error occurred during execution", + exitCodeList = { "0:Successful analysis, no violations found", "1:An unexpected error occurred during execution", "2:Usage error, please refer to the command help", "4:Successful analysis, at least 1 violation found" }, subcommands = { PmdCommand.class, CpdCommand.class, DesignerCommand.class, CpdGuiCommand.class, TreeExportCommand.class }) public class PmdRootCommand { diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java index 7b51057dd5..c034682f07 100644 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/commands/internal/TreeExportCommand.java @@ -15,7 +15,7 @@ import org.slf4j.LoggerFactory; import net.sourceforge.pmd.cli.commands.mixins.internal.EncodingMixin; import net.sourceforge.pmd.cli.commands.typesupport.internal.PmdLanguageTypeSupport; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.internal.LogMessages; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.properties.PropertyDescriptor; @@ -106,16 +106,16 @@ public class TreeExportCommand extends AbstractPmdSubcommand { } @Override - protected ExecutionResult execute() { + protected CliExitCode execute() { final TreeExporter exporter = new TreeExporter(toConfiguration()); try { exporter.export(); - return ExecutionResult.OK; + return CliExitCode.OK; } catch (final IOException e) { final SimpleMessageReporter reporter = new SimpleMessageReporter(LoggerFactory.getLogger(TreeExportCommand.class)); reporter.error(e, LogMessages.errorDetectedMessage(1, "ast-dump")); - return ExecutionResult.ERROR; + return CliExitCode.ERROR; } } diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/CliExitCode.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/CliExitCode.java new file mode 100644 index 0000000000..5de3ae60f6 --- /dev/null +++ b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/CliExitCode.java @@ -0,0 +1,49 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.cli.internal; + +import net.sourceforge.pmd.PMDConfiguration; + +/** + * The execution result of any given command. + */ +public enum CliExitCode { + /** No errors, no violations. This is exit code {@code 0}. */ + OK(0), + /** + * Errors were detected, PMD may have not run to the end. + * This is exit code {@code 1}. + */ + ERROR(1), + // Todo + USAGE_ERROR(2), + /** + * No errors, but PMD found violations. This is exit code {@code 4}. + * This is only returned if {@link PMDConfiguration#isFailOnViolation()} + * is set (CLI flag {@code --failOnViolation}). + */ + VIOLATIONS_FOUND(4); + + private final int exitCode; + + CliExitCode(int exitCode) { + this.exitCode = exitCode; + } + + public int getExitCode() { + return exitCode; + } + + public static CliExitCode fromInt(int i) { + switch (i) { + case 0: return OK; + case 1: return ERROR; + case 2: return USAGE_ERROR; + case 4: return VIOLATIONS_FOUND; + default: + throw new IllegalArgumentException("Not a known exit code: " + i); + } + } +} diff --git a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/ExecutionResult.java b/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/ExecutionResult.java deleted file mode 100644 index 8b0da06648..0000000000 --- a/pmd-cli/src/main/java/net/sourceforge/pmd/cli/internal/ExecutionResult.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.cli.internal; - -/** - * The execution result of any given command. - */ -public enum ExecutionResult { - OK(0), - ERROR(1), - USAGE_ERROR(2), - VIOLATIONS_FOUND(4); - - private final int exitCode; - - ExecutionResult(int exitCode) { - this.exitCode = exitCode; - } - - public int getExitCode() { - return exitCode; - } -} diff --git a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/BaseCliTest.java b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/BaseCliTest.java index 89d16c0996..039080a581 100644 --- a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/BaseCliTest.java +++ b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/BaseCliTest.java @@ -4,16 +4,22 @@ package net.sourceforge.pmd.cli; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; import static org.junit.jupiter.api.Assertions.assertEquals; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import org.hamcrest.Matcher; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; +import org.opentest4j.AssertionFailedError; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import com.github.stefanbirkner.systemlambda.SystemLambda; @@ -23,28 +29,127 @@ abstract class BaseCliTest { static void disablePicocliAnsi() { System.setProperty("picocli.ansi", "false"); } - + @AfterAll static void resetPicocliAnsi() { System.clearProperty("picocli.ansi"); } - - protected String runCliSuccessfully(String... args) throws Exception { - return runCli(ExecutionResult.OK, args); + + protected CliExecutionResult runCliSuccessfully(String... args) throws Exception { + return runCli(CliExitCode.OK, args); } - protected String runCli(ExecutionResult expectedExitCode, String... args) throws Exception { + protected CliExecutionResult runCli(CliExitCode expectedExitCode, String... args) throws Exception { final List argList = new ArrayList<>(); argList.addAll(cliStandardArgs()); argList.addAll(Arrays.asList(args)); - - return SystemLambda.tapSystemErrAndOut(() -> { - final int actualExitCode = SystemLambda.catchSystemExit(() -> { - PmdCli.main(argList.toArray(new String[0])); - }); - assertEquals(expectedExitCode.getExitCode(), actualExitCode, "Exit code"); - }); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ByteArrayOutputStream err = new ByteArrayOutputStream(); + + final PrintStream formerOut = System.out; + final PrintStream formerErr = System.err; + + CliExitCode exitCode; + try { + System.out.println("running: pmd " + String.join(" ", argList)); + System.setOut(new PrintStream(out)); + System.setErr(new PrintStream(err)); + int actualExitCode = SystemLambda.catchSystemExit( + // restoring system properties: --debug might change logging properties + () -> SystemLambda.restoreSystemProperties( + () -> PmdCli.main(argList.toArray(new String[0])) + ) + ); + exitCode = CliExitCode.fromInt(actualExitCode); + + } finally { + System.setOut(formerOut); + System.setErr(formerErr); + } + + return new CliExecutionResult( + out, err, exitCode + ).verify(e -> assertEquals(expectedExitCode, e.exitCode)); } protected abstract List cliStandardArgs(); + + + static class CliExecutionResult { + + private final ByteArrayOutputStream out; + private final ByteArrayOutputStream err; + private final CliExitCode exitCode; + + CliExecutionResult(ByteArrayOutputStream out, + ByteArrayOutputStream err, + CliExitCode exitCode) { + this.out = out; + this.err = err; + this.exitCode = exitCode; + } + + public String getOut() { + return out.toString(); + } + + public String getErr() { + return err.toString(); + } + + + public void checkOk() { + assertEquals(CliExitCode.OK, exitCode); + } + + public void checkFailed() { + assertEquals(CliExitCode.ERROR, exitCode); + } + + public void checkNoErrorOutput() { + checkStdErr(equalTo("")); + } + + public void checkStdOut(Matcher matcher) { + assertThat(getOut(), matcher); + } + + public void checkStdErr(Matcher matcher) { + assertThat(getErr(), matcher); + } + + /** + * Use this method to wrap assertions. + */ + public CliExecutionResult verify(ThrowingConsumer actions) { + try { + actions.accept(this); + } catch (Exception | AssertionError e) { + System.out.println("TEST FAILED"); + System.out.println("> Return code: " + exitCode); + System.out.println("> Standard output -------------------------"); + System.err.println(out.toString()); + System.err.flush(); + System.out.println("> Standard error --------------------------"); + System.err.println(err.toString()); + System.err.flush(); + System.out.println("> -----------------------------------------"); + + if (e instanceof Exception) { + throw new AssertionFailedError("Expected no exception to be thrown", e); + } + throw (AssertionError) e; + } + return this; + } + + + @FunctionalInterface + interface ThrowingConsumer { + + void accept(T t) throws Exception; + } + } + } diff --git a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/CpdCliTest.java b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/CpdCliTest.java index eee70a4104..f42db94afe 100644 --- a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/CpdCliTest.java +++ b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/CpdCliTest.java @@ -4,7 +4,6 @@ package net.sourceforge.pmd.cli; -import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -17,7 +16,7 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration; import com.github.stefanbirkner.systemlambda.SystemLambda; @@ -39,34 +38,34 @@ class CpdCliTest extends BaseCliTest { void debugLogging() throws Exception { // restoring system properties: --debug might change logging properties SystemLambda.restoreSystemProperties(() -> { - String log = runCliSuccessfully("--debug", "--minimum-tokens", "340", "--dir", SRC_DIR); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE")); + CliExecutionResult result = runCliSuccessfully("--debug", "--minimum-tokens", "340", "--dir", SRC_DIR); + result.checkStdOut(containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE")); }); } @Test void defaultLogging() throws Exception { - String log = runCliSuccessfully("--minimum-tokens", "340", "--dir", SRC_DIR); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO")); + CliExecutionResult result = runCliSuccessfully("--minimum-tokens", "340", "--dir", SRC_DIR); + result.checkStdOut(containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO")); } @Test void testMissingminimumTokens() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR); - assertThat(log, containsString("Missing required option: '--minimum-tokens='")); + final CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR); + result.checkStdErr(containsString("Missing required option: '--minimum-tokens='")); } @Test void testMissingSource() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR, "--minimum-tokens", "340"); - assertThat(log, containsString("Please provide a parameter for source root directory")); + final CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR, "--minimum-tokens", "340"); + result.checkStdErr(containsString("Please provide a parameter for source root directory")); } @Test void testWrongCliOptionsDoPrintUsage() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR, "--invalid", "--minimum-tokens", "340", "-d", SRC_DIR); - assertThat(log, containsString("Unknown option: '--invalid'")); - assertThat(log, containsString("Usage: pmd cpd")); + final CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR, "--invalid", "--minimum-tokens", "340", "-d", SRC_DIR); + result.checkStdErr(containsString("Unknown option: '--invalid'")); + result.checkStdErr(containsString("Usage: pmd cpd")); } @Test @@ -79,7 +78,7 @@ class CpdCliTest extends BaseCliTest { SRC_DIR, "--format", "xml", }); }); - assertEquals(ExecutionResult.OK.getExitCode(), statusCode); + assertEquals(CliExitCode.OK.getExitCode(), statusCode); }); }); final Path absoluteSrcDir = Paths.get(SRC_DIR).toAbsolutePath(); diff --git a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java index 6679d8d8d5..5f7015a566 100644 --- a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java +++ b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java @@ -26,7 +26,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import net.sourceforge.pmd.cli.internal.ExecutionResult; +import net.sourceforge.pmd.cli.internal.CliExitCode; import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration; import com.github.stefanbirkner.systemlambda.SystemLambda; @@ -144,7 +144,7 @@ class PmdCliTest extends BaseCliTest { assertFalse(Files.exists(absoluteReportFile), "Report file must not exist yet! " + absoluteReportFile); try { - runCliSuccessfully("-d", srcDir.toString(), "-R", DUMMY_RULESET, "-r", reportFile.toString()); + runCliSuccessfully("-d", srcDir.toString(), "-R", DUMMY_RULESET, "-r", reportFile); assertTrue(Files.exists(absoluteReportFile), "Report file should have been created"); } finally { Files.deleteIfExists(absoluteReportFile); @@ -168,42 +168,40 @@ class PmdCliTest extends BaseCliTest { @Test void debugLogging() throws Exception { - // restoring system properties: --debug might change logging properties - SystemLambda.restoreSystemProperties(() -> { - String log = runCliSuccessfully("--debug", "--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE")); - }); + CliExecutionResult result = runCliSuccessfully("--debug", "--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); + result.checkStdErr(containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE")); } @Test void defaultLogging() throws Exception { - String log = runCliSuccessfully("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO")); + CliExecutionResult result = runCliSuccessfully("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); + result.checkStdErr(containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO")); } @Test void testDeprecatedRulesetSyntaxOnCommandLine() throws Exception { - String log = runCli(ExecutionResult.VIOLATIONS_FOUND, "--dir", srcDir.toString(), "--rulesets", "dummy-basic"); - assertThat(log, containsString("Ruleset reference 'dummy-basic' uses a deprecated form, use 'rulesets/dummy/basic.xml' instead")); + CliExecutionResult result = runCli(CliExitCode.VIOLATIONS_FOUND, "--dir", srcDir.toString(), "--rulesets", "dummy-basic"); + result.checkStdErr(containsString("Ruleset reference 'dummy-basic' uses a deprecated form, use 'rulesets/dummy/basic.xml' instead")); } @Test void testMissingRuleset() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR); - assertThat(log, containsString("Missing required option: '--rulesets='")); + CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR); + result.checkStdErr(containsString("Missing required option: '--rulesets='")); } @Test void testMissingSource() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR, "--rulesets", DUMMY_RULESET); - assertThat(log, containsString("Please provide a parameter for source root directory")); + CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR, "--rulesets", DUMMY_RULESET); + result.checkStdErr(containsString("Please provide a parameter for source root directory")); } - + @Test void testWrongCliOptionsDoPrintUsage() throws Exception { - final String log = runCli(ExecutionResult.USAGE_ERROR, "--invalid", "--rulesets", DUMMY_RULESET, "-d", srcDir.toString()); - assertThat(log, containsString("Unknown option: '--invalid'")); - assertThat(log, containsString("Usage: pmd check")); + CliExecutionResult result = runCli(CliExitCode.USAGE_ERROR, "--invalid", "--rulesets", DUMMY_RULESET, "-d", srcDir.toString()); + result.checkStdErr(containsString("Unknown option: '--invalid'")); + result.checkStdErr(containsString("Usage: pmd check")); + result.checkStdErr(not(containsStringIgnoringCase("Available report formats and"))); } // utilities @@ -232,8 +230,6 @@ class PmdCliTest extends BaseCliTest { // Always run against dummy language without logging not cache to remove all logging noise argList.add("check"); - argList.add("--use-version"); - argList.add("dummy-1.0"); argList.add("--no-cache"); argList.add("--no-progress"); diff --git a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/TreeExportCliTest.java b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/TreeExportCliTest.java index 47cab84e42..cae2b8f485 100644 --- a/pmd-cli/src/test/java/net/sourceforge/pmd/cli/TreeExportCliTest.java +++ b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/TreeExportCliTest.java @@ -4,8 +4,7 @@ package net.sourceforge.pmd.cli; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import java.io.BufferedWriter; import java.io.File; @@ -29,27 +28,27 @@ class TreeExportCliTest extends BaseCliTest { @Test void testReadStandardInput() throws Exception { SystemLambda.withTextFromSystemIn("(a(b))").execute(() -> { - final String output = runCliSuccessfully("-i", "-f", "xml", "-PlineSeparator=LF"); - - assertThat(output, containsString("\n" - + "\n" - + " \n" - + " \n" - + " \n" - + "")); + final CliExecutionResult output = runCliSuccessfully("-i", "-f", "xml", "-PlineSeparator=LF"); + + output.checkStdOut(equalTo("\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "")); }); } @Test void testReadFile() throws Exception { File file = newFileWithContents("(a(b))"); - final String output = runCliSuccessfully("--file", file.getAbsolutePath(), "-f", "xml", "-PlineSeparator=LF"); - assertThat(output, containsString("\n" - + "\n" - + " \n" - + " \n" - + " \n" - + "")); + final CliExecutionResult result = runCliSuccessfully("--file", file.getAbsolutePath(), "-f", "xml", "-PlineSeparator=LF"); + result.checkStdOut(equalTo("\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "")); } private File newFileWithContents(String data) throws IOException { diff --git a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java b/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java deleted file mode 100644 index 480cdf67f4..0000000000 --- a/pmd-core/src/test/java/net/sourceforge/pmd/cli/CoreCliTest.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.cli; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.containsStringIgnoringCase; -import static org.hamcrest.Matchers.not; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.PMD.StatusCode; -import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration; -import net.sourceforge.pmd.util.IOUtil; - -import com.github.stefanbirkner.systemlambda.SystemLambda; - -/** - * - */ -class CoreCliTest { - - @TempDir - private Path tempDir; - - private static final String DUMMY_RULESET = "net/sourceforge/pmd/cli/FakeRuleset.xml"; - private static final String STRING_TO_REPLACE = "__should_be_replaced__"; - - private Path srcDir; - - @AfterAll - static void resetLogging() { - // reset logging in case "--debug" changed the logging properties - // See also Slf4jSimpleConfigurationForAnt - Slf4jSimpleConfiguration.reconfigureDefaultLogLevel(null); - } - - @BeforeEach - void setup() throws IOException { - // set current directory to wd - Path root = tempRoot(); - System.setProperty("user.dir", root.toString()); - - // create a few files - srcDir = Files.createDirectories(root.resolve("src")); - writeString(srcDir.resolve("someSource.dummy"), "dummy text"); - } - - - @Test - void testPreExistingReportFile() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - // now we create the file - Files.createDirectories(reportFile.getParent()); - writeString(reportFile, STRING_TO_REPLACE); - - assertTrue(Files.exists(reportFile), "Report file should exist"); - - runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, "-r", reportFile); - - assertNotEquals(readString(reportFile), STRING_TO_REPLACE); - } - - @Test - void testPreExistingReportFileLongOption() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - // now we create the file - Files.createDirectories(reportFile.getParent()); - writeString(reportFile, STRING_TO_REPLACE); - - assertTrue(Files.exists(reportFile), "Report file should exist"); - - runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile); - - assertNotEquals(readString(reportFile), STRING_TO_REPLACE, "Report file should have been overwritten"); - } - - @Test - void testNonExistentReportFile() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - - assertFalse(Files.exists(reportFile), "Report file should not exist"); - - try { - runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, "-r", reportFile); - assertTrue(Files.exists(reportFile), "Report file should have been created"); - } finally { - Files.deleteIfExists(reportFile); - } - } - - @Test - void testNonExistentReportFileLongOption() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - - assertFalse(Files.exists(reportFile), "Report file should not exist"); - - runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile); - - assertTrue(Files.exists(reportFile), "Report file should have been created"); - } - - @Test - void testFileCollectionWithUnknownFiles() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - Files.createFile(srcDir.resolve("foo.not_analysable")); - assertFalse(Files.exists(reportFile), "Report file should not exist"); - - // restoring system properties: --debug might change logging properties - SystemLambda.restoreSystemProperties(() -> { - runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile, "--debug"); - }); - - assertTrue(Files.exists(reportFile), "Report file should have been created"); - String reportText = IOUtil.readToString(Files.newBufferedReader(reportFile, StandardCharsets.UTF_8)); - assertThat(reportText, not(containsStringIgnoringCase("error"))); - } - - @Test - void testNonExistentReportFileDeprecatedOptions() throws Exception { - Path reportFile = tempRoot().resolve("out/reportFile.txt"); - - assertFalse(Files.exists(reportFile), "Report file should not exist"); - - String log = runPmdSuccessfully("-no-cache", "-dir", srcDir, "-rulesets", DUMMY_RULESET, "-reportfile", reportFile); - - assertTrue(Files.exists(reportFile), "Report file should have been created"); - assertTrue(log.contains("Some deprecated options were used on the command-line, including -rulesets")); - assertTrue(log.contains("Consider replacing it with --rulesets (or -R)")); - // only one parameter is logged - assertFalse(log.contains("Some deprecated options were used on the command-line, including -reportfile")); - assertFalse(log.contains("Consider replacing it with --report-file")); - } - - /** - * This tests to create the report file in the current working directory. - * - *

Note: We can't change the cwd in the running VM, so the file will not be created - * in the temporary folder, but really in the cwd. The test fails if a file already exists - * and makes sure to cleanup the file afterwards. - */ - @Test - void testRelativeReportFile() throws Exception { - String reportFile = "reportFile.txt"; - Path absoluteReportFile = FileSystems.getDefault().getPath(reportFile).toAbsolutePath(); - // verify the file doesn't exist yet - we will delete the file at the end! - assertFalse(Files.exists(absoluteReportFile), "Report file must not exist yet! " + absoluteReportFile); - - try { - runPmdSuccessfully("--no-cache", "-d", srcDir, "-R", DUMMY_RULESET, "-r", reportFile); - assertTrue(Files.exists(absoluteReportFile), "Report file should have been created"); - } finally { - Files.deleteIfExists(absoluteReportFile); - } - } - - @Test - void testRelativeReportFileLongOption() throws Exception { - String reportFile = "reportFile.txt"; - Path absoluteReportFile = FileSystems.getDefault().getPath(reportFile).toAbsolutePath(); - // verify the file doesn't exist yet - we will delete the file at the end! - assertFalse(Files.exists(absoluteReportFile), "Report file must not exist yet!"); - - try { - runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET, "--report-file", reportFile); - assertTrue(Files.exists(absoluteReportFile), "Report file should have been created"); - } finally { - Files.deleteIfExists(absoluteReportFile); - } - } - - @Test - void debugLogging() throws Exception { - // restoring system properties: --debug might change logging properties - SystemLambda.restoreSystemProperties(() -> { - String log = runPmdSuccessfully("--debug", "--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.PMD - Log level is at TRACE")); - }); - } - - @Test - void defaultLogging() throws Exception { - String log = runPmdSuccessfully("--no-cache", "--dir", srcDir, "--rulesets", DUMMY_RULESET); - assertThat(log, containsString("[main] INFO net.sourceforge.pmd.PMD - Log level is at INFO")); - } - - @Test - void testDeprecatedRulesetSyntaxOnCommandLine() throws Exception { - String log = SystemLambda.tapSystemErrAndOut(() -> { - runPmd(StatusCode.VIOLATIONS_FOUND, "--no-cache", "--dir", srcDir, "--rulesets", "dummy-basic"); - }); - assertThat(log, containsString("Ruleset reference 'dummy-basic' uses a deprecated form, use 'rulesets/dummy/basic.xml' instead")); - } - - @Test - void testReportToStdoutNotClosing() throws Exception { - PrintStream originalOut = System.out; - PrintStream out = new PrintStream(new FilterOutputStream(originalOut) { - @Override - public void close() { - fail("Stream must not be closed"); - } - }); - try { - System.setOut(out); - SystemLambda.tapSystemErrAndOut(() -> { - runPmd(StatusCode.VIOLATIONS_FOUND, "--no-cache", "--dir", srcDir, "--rulesets", "dummy-basic"); - }); - } finally { - System.setOut(originalOut); - } - } - - @Test - void testWrongCliOptionsDoNotPrintUsage() throws Exception { - String[] args = { "-invalid" }; - PmdParametersParseResult params = PmdParametersParseResult.extractParameters(args); - assertTrue(params.isError(), "Expected invalid args"); - - String log = SystemLambda.tapSystemErrAndOut(() -> { - StatusCode code = PMD.runPmd(args); - assertEquals(StatusCode.ERROR, code); - }); - assertThat(log, not(containsStringIgnoringCase("Available report formats and"))); - } - - // utilities - private Path tempRoot() { - return tempDir; - } - - - private static String runPmdSuccessfully(Object... args) throws Exception { - return SystemLambda.tapSystemErrAndOut(() -> { - runPmd(StatusCode.OK, args); - }); - } - - private static String[] argsToString(Object... args) { - String[] result = new String[args.length]; - for (int i = 0; i < args.length; i++) { - result[i] = args[i].toString(); - } - return result; - } - - // available in Files on java 11+ - private static void writeString(Path path, String text) throws IOException { - ByteBuffer encoded = StandardCharsets.UTF_8.encode(text); - Files.write(path, encoded.array()); - } - - - // available in Files on java 11+ - private static String readString(Path path) throws IOException { - byte[] bytes = Files.readAllBytes(path); - ByteBuffer buf = ByteBuffer.wrap(bytes); - return StandardCharsets.UTF_8.decode(buf).toString(); - } - - private static void runPmd(StatusCode expectedExitCode, Object... args) { - StatusCode actualExitCode = PMD.runPmd(argsToString(args)); - assertEquals(expectedExitCode, actualExitCode, "Exit code"); - } - -} diff --git a/pmd-javascript/src/test/java/net/sourceforge/pmd/cli/CLITest.java b/pmd-javascript/src/test/java/net/sourceforge/pmd/cli/CLITest.java deleted file mode 100644 index 463b396604..0000000000 --- a/pmd-javascript/src/test/java/net/sourceforge/pmd/cli/CLITest.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * BSD-style license; for more info see http://pmd.sourceforge.net/license.html - */ - -package net.sourceforge.pmd.cli; - -import static org.hamcrest.MatcherAssert.assertThat; - -import org.junit.Test; - -import net.sourceforge.pmd.PMD.StatusCode; - -/** - * @author Romain Pelisse <belaran@gmail.com> - * - */ -public class CLITest extends BaseCLITest { - @Test - public void useEcmaScript() { - String log = runTest(StatusCode.VIOLATIONS_FOUND, - "-d", - SOURCE_FOLDER, - "-f", - "xml", - "-R", - "rulesets/testing/js-rset1.xml", - "--no-progress", - "--debug"); - assertThat(log, containsPattern("Adding file .*\\.js \\(lang: ecmascript ES6\\)")); - } -}