From 52d2616181a63328b40655c4477a0c774e8da7d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Mart=C3=ADn=20Sotuyo=20Dodero?= Date: Wed, 17 Aug 2022 14:47:31 -0300 Subject: [PATCH] Add basic CLI test --- pmd-cli/pom.xml | 11 + .../net/sourceforge/pmd/cli/PmdCliTest.java | 251 ++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java diff --git a/pmd-cli/pom.xml b/pmd-cli/pom.xml index d8edbdc297..2a9b53f3c1 100644 --- a/pmd-cli/pom.xml +++ b/pmd-cli/pom.xml @@ -284,6 +284,17 @@ system-lambda test + + + + net.sourceforge.pmd + pmd-core + ${project.version} + test + tests + test-jar + + me.tongfei 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 new file mode 100644 index 0000000000..143d1eb7dd --- /dev/null +++ b/pmd-cli/src/test/java/net/sourceforge/pmd/cli/PmdCliTest.java @@ -0,0 +1,251 @@ +/* + * 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 java.io.IOException; +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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +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.cli.internal.ExecutionResult; +import net.sourceforge.pmd.internal.Slf4jSimpleConfiguration; + +import com.github.stefanbirkner.systemlambda.SystemLambda; + +class PmdCliTest { + + @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("-d", srcDir.toString(), "-R", DUMMY_RULESET, "-r", reportFile.toString()); + + 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("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET, "--report-file", reportFile.toString()); + + 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("-d", srcDir.toString(), "-R", DUMMY_RULESET, "-r", reportFile.toString()); + 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("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET, "--report-file", reportFile.toString()); + + 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("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET, "--report-file", reportFile.toString(), "--debug"); + }); + + assertTrue(Files.exists(reportFile), "Report file should have been created"); + String reportText = readString(reportFile); + assertThat(reportText, not(containsStringIgnoringCase("error"))); + } + + /** + * 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("-d", srcDir.toString(), "-R", DUMMY_RULESET, "-r", reportFile.toString()); + 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("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET, "--report-file", reportFile.toString()); + 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", "--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); + assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at TRACE")); + }); + } + + @Test + void defaultLogging() throws Exception { + String log = runPmdSuccessfully("--dir", srcDir.toString(), "--rulesets", DUMMY_RULESET); + assertThat(log, containsString("[main] INFO net.sourceforge.pmd.cli.commands.internal.AbstractPmdSubcommand - Log level is at INFO")); + } + + @Test + void testDeprecatedRulesetSyntaxOnCommandLine() throws Exception { + String log = SystemLambda.tapSystemErrAndOut(() -> { + runPmd(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")); + } + + + @Test + void testWrongCliOptionsDoNotPrintUsage() throws Exception { + final String log = SystemLambda.tapSystemErrAndOut(() -> { + final int actualExitCode = SystemLambda.catchSystemExit(() -> { + PmdCli.main(new String[] { "run", "--invalid" }); + }); + assertEquals(2, actualExitCode); + }); + assertThat(log, not(containsStringIgnoringCase("Available report formats and"))); + } + + // utilities + private Path tempRoot() { + return tempDir; + } + + + private static String runPmdSuccessfully(String... args) throws Exception { + return SystemLambda.tapSystemErrAndOut(() -> { + runPmd(ExecutionResult.OK, args); + }); + } + + // 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(ExecutionResult expectedExitCode, String... args) throws Exception { + final int actualExitCode = SystemLambda.catchSystemExit(() -> { + final List argList = new ArrayList<>(); + + // Always run against dummy language without logging not cache to remove all logging noise + argList.add("run"); + argList.add("--use-version"); + argList.add("dummy"); + argList.add("--no-cache"); + argList.add("--no-progress"); + + argList.addAll(Arrays.asList(args)); + + PmdCli.main(argList.toArray(new String[0])); + }); + assertEquals(expectedExitCode.getExitCode(), actualExitCode, "Exit code"); + } + + +}