diff --git a/src/test/java/rife/bld/extension/PmdOperationTest.java b/src/test/java/rife/bld/extension/PmdOperationTest.java deleted file mode 100644 index 77321d6..0000000 --- a/src/test/java/rife/bld/extension/PmdOperationTest.java +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright 2023-2025 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package rife.bld.extension; - -import net.sourceforge.pmd.PMDConfiguration; -import net.sourceforge.pmd.lang.LanguageRegistry; -import net.sourceforge.pmd.lang.rule.RulePriority; -import org.assertj.core.api.AutoCloseableSoftAssertions; -import org.junit.jupiter.api.Test; -import rife.bld.BaseProject; -import rife.bld.operations.exceptions.ExitStatusException; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Properties; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; - -/** - * PmdOperationTest class - * - * @author Erik C. Thauvin - * @since 1.0 - */ -class PmdOperationTest { - static final String BAR = "bar"; - static final String CATEGORY_FOO = "category/foo.xml"; - static final Path CODE_STYLE_SAMPLE = Path.of("src/test/resources/java/CodeStyle.java"); - static final String CODE_STYLE_XML = "category/java/codestyle.xml"; - static final String COMMAND_NAME = "pmd"; - static final String DESIGN_XML = "category/java/design.xml"; - static final String DOCUMENTATION_XML = "category/java/documentation.xml"; - static final Path ERROR_PRONE_SAMPLE = Path.of("src/test/resources/java/ErrorProne.java"); - static final String ERROR_PRONE_XML = "category/java/errorprone.xml"; - static final File FILE_BAR = new File(BAR); - static final String FOO = "foo"; - static final File FILE_FOO = new File(FOO); - static final Path PATH_BAR = Path.of(BAR); - static final Path PATH_FOO = Path.of(FOO); - static final String PERFORMANCE_XML = "category/java/performance.xml"; - static final String SECURITY_XML = "category/java/security.xml"; - static final String TEST = "test"; - - PmdOperation newPmdOperation() { - return new PmdOperation() - .inputPaths(Path.of("src/main"), Path.of("src/test")) - .cache("build/" + COMMAND_NAME + "/pmd-cache") - .failOnViolation(false) - .reportFile(Paths.get("build", COMMAND_NAME, "pmd-test-report.txt")); - } - - @Test - void testAddExcludes() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludes(PATH_FOO); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(PATH_FOO); - - pmd = pmd.addExcludes(PATH_BAR); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); - } - - @Test - void testAddExcludesFiles() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludesFiles(FILE_FOO); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath()); - - pmd = pmd.addExcludesFiles(FILE_BAR); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath(), FILE_BAR.toPath()); - } - - @Test - void testAddExcludesStrings() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludesStrings(FOO); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(PATH_FOO); - - pmd = pmd.addExcludesStrings(BAR); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); - } - - @Test - void testAddInputPaths() throws ExitStatusException { - var project = new BaseProject(); - var pmd = new PmdOperation().fromProject(project); - - assertThat(pmd.inputPaths()).as("default").containsExactly(project.srcMainDirectory().toPath(), - project.srcTestDirectory().toPath()); - - var err = pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPaths(project.srcMainDirectory(), project.srcTestDirectory()); - - assertThat(pmd.inputPaths()).as("File...").containsExactly(project.srcMainDirectory().toPath(), - project.srcTestDirectory().toPath()); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPathsFiles(List.of(project.srcMainDirectory(), project.srcTestDirectory())); - - assertThat(pmd.inputPaths()).as("List(File...)") - .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPaths(project.srcMainDirectory().getAbsolutePath(), - project.srcTestDirectory().getAbsolutePath()); - - assertThat(pmd.inputPaths()).as("String...") - .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPathsStrings( - List.of(project.srcMainDirectory().getAbsolutePath(), project.srcTestDirectory().getAbsolutePath())); - - assertThat(pmd.inputPaths()).as("List(String...)") - .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPaths(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - assertThat(pmd.inputPaths()).as("Path...") - .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - pmd.inputPaths().clear(); - pmd = pmd.addInputPaths(List.of(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath())); - - assertThat(pmd.inputPaths()).as("List(Path)") - .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); - - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .isGreaterThan(0).isEqualTo(err); - } - - @Test - void testAddRuleSets() throws ExitStatusException { - var pmd = new PmdOperation().fromProject(new BaseProject()); - - assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT); - - pmd.addRuleSet(ERROR_PRONE_XML); - - assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML); - - var err = pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); - - pmd.ruleSets().clear(); - - pmd.addRuleSet(List.of(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML)); - - assertThat(pmd.ruleSets()).as("collection") - .containsExactly(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML); - - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .isGreaterThan(0).isEqualTo(err); - } - - @Test - void testCache() throws ExitStatusException { - var cache = Path.of("build/pmd/temp-cache"); - var pmd = newPmdOperation() - .ruleSets(CODE_STYLE_XML) - .inputPaths(List.of(CODE_STYLE_SAMPLE)) - .cache(cache); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - var f = cache.toFile(); - assertThat(f.exists()).as("file exits").isTrue(); - assertThat(f.delete()).as("delete file").isTrue(); - } - - @Test - void testEncoding() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).encoding("UTF-16"); - PMDConfiguration config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getSourceEncoding()).as("UTF-16").isEqualTo(StandardCharsets.UTF_16); - - pmd = pmd.encoding(StandardCharsets.ISO_8859_1); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getSourceEncoding()).as("ISO_8859").isEqualTo(StandardCharsets.ISO_8859_1); - } - - @Test - void testExcludes() { - var foz = Path.of("foz/baz"); - var baz = Path.of("baz/foz"); - - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludes(PATH_FOO, PATH_BAR); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(pmd.excludes()).containsExactly(List.of(PATH_FOO, PATH_BAR).toArray(new Path[0])); - assertThat(config.getExcludes()).containsExactly(List.of(PATH_FOO, PATH_BAR).toArray(new Path[0])); - - var excludes = List.of(List.of(PATH_FOO, PATH_BAR), List.of(foz, baz)); - for (var exclude : excludes) { - pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludes(exclude); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(exclude.toArray(new Path[0])); - } - } - - @Test - void testExcludesFiles() { - var foz = new File("foz"); - var baz = new File("baz"); - - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesFiles(FILE_FOO, FILE_BAR); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath(), FILE_BAR.toPath()); - - var excludes = List.of(List.of(FILE_FOO, FILE_BAR), List.of(foz, baz)); - for (var exclude : excludes) { - pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesFiles(exclude); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(exclude.stream().map(File::toPath).toArray(Path[]::new)); - } - } - - @Test - void testExcludesStrings() { - var foz = "foz"; - var baz = "baz"; - - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesStrings(FOO, BAR); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(pmd.excludes()).containsExactly(PATH_FOO, PATH_BAR); - assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); - - var excludes = List.of(List.of(FOO, BAR), List.of(foz, baz)); - for (var exclude : excludes) { - pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesStrings(exclude); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getExcludes()).containsExactly(exclude.stream().map(Paths::get).toArray(Path[]::new)); - } - } - - @Test - void testExecute() throws ExitStatusException { - var pmd = new PmdOperation().fromProject(new BaseProject()); - - assertThat(pmd.inputPaths()).containsExactly(Paths.get("src/main").toAbsolutePath(), - Paths.get("src/test").toAbsolutePath()); - - pmd.inputPaths().clear(); - pmd.inputPaths("src/main/java", "src/test/java") - .ruleSets("config/pmd.xml"); - - assertThat(pmd.ruleSets()).containsExactly("config/pmd.xml"); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - } - - @Test - void testExecuteNoProject() { - var pmd = new PmdOperation(); - assertThatCode(pmd::execute).isInstanceOf(ExitStatusException.class); - } - - @Test - void testFailOnError() { - var pmd = newPmdOperation().ruleSets("src/test/resources/xml/old.xml") - .inputPaths(Path.of("src/test/resources/java/Documentation.java")); - assertThatCode(() -> pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .isInstanceOf(ExitStatusException.class); - assertThatCode(() -> pmd.failOnError(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .doesNotThrowAnyException(); - } - - @Test - void testFailOnValidation() { - var pmd = newPmdOperation().ruleSets(DOCUMENTATION_XML) - .inputPaths(Path.of("src/test/resources/java/Documentation.java")); - assertThatCode(() -> pmd.failOnViolation(true).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .isInstanceOf(ExitStatusException.class); - assertThatCode(() -> pmd.failOnViolation(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .doesNotThrowAnyException(); - } - - @Test - void testIgnoreFile() throws ExitStatusException { - var pmd = newPmdOperation() - .ruleSets(ERROR_PRONE_XML, CODE_STYLE_XML) - .ignoreFile(Path.of("src/test/resources/ignore.txt")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - pmd.inputPaths().clear(); - pmd.inputPaths(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - - pmd.ruleSets().clear(); - pmd.inputPaths().clear(); - assertThat(pmd.inputPaths(ERROR_PRONE_SAMPLE) - .ignoreFile(new File("src/test/resources/ignore-single.txt")) - .performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - } - - @Test - void testIncrementalAnalysis() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).incrementalAnalysis(true); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.isIgnoreIncrementalAnalysis()).isFalse(); - } - - @Test - void testInputPaths() throws ExitStatusException { - var pmd = newPmdOperation() - .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) - .inputPaths(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.inputPaths()).as("Path....").containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - pmd = newPmdOperation() - .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) - .inputPaths(ERROR_PRONE_SAMPLE.toFile(), CODE_STYLE_SAMPLE.toFile()); - assertThat(pmd.inputPaths()).as("File...").containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - pmd = newPmdOperation() - .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) - .inputPaths(ERROR_PRONE_SAMPLE.toString(), CODE_STYLE_SAMPLE.toString()); - assertThat(pmd.inputPaths()).as("String...").containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - pmd = newPmdOperation() - .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) - .inputPathsFiles(List.of(ERROR_PRONE_SAMPLE.toFile(), CODE_STYLE_SAMPLE.toFile())); - assertThat(pmd.inputPaths()).as("List(Path...)").containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - pmd = newPmdOperation() - .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) - .inputPathsStrings(List.of(ERROR_PRONE_SAMPLE.toString(), CODE_STYLE_SAMPLE.toString())); - assertThat(pmd.inputPaths()).as("List(String...)").containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaBestPractices() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets("category/java/bestpractices.xml") - .inputPaths(Path.of("src/test/resources/java/BestPractices.java")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaCodeStyle() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML).inputPaths(CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaCodeStyleAndErrorProne() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML).inputPaths(CODE_STYLE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .as("code style").isGreaterThan(0); - - pmd = pmd.ruleSets(ERROR_PRONE_XML).inputPaths(ERROR_PRONE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .as("code style + error prone").isGreaterThan(0); - } - - @Test - void testJavaDesign() throws ExitStatusException { - var pmd = newPmdOperation() - .ruleSets(DESIGN_XML) - .inputPaths("src/test/resources/java/Design.java") - .cache(new File("build/pmd/design-cache")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaDocumentation() throws ExitStatusException { - var pmd = newPmdOperation() - .ruleSets(DOCUMENTATION_XML) - .inputPaths(Path.of("src/test/resources/java/Documentation.java")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaErrorProne() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).inputPaths(ERROR_PRONE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaMultiThreading() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets("category/java/multithreading.xml") - .inputPaths(Path.of("src/test/resources/java/MultiThreading.java")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaPerformance() throws ExitStatusException { - var pmd = newPmdOperation() - .ruleSets(PERFORMANCE_XML) - .inputPaths(Path.of("src/test/resources/java/Performance.java")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaQuickStart() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(PmdOperation.RULE_SET_DEFAULT) - .inputPaths(new File("src/test/resources/java/")); - assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testJavaSecurity() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(SECURITY_XML) - .inputPaths(Path.of("src/test/resources/java/Security.java")); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testLanguageVersions() throws ExitStatusException { - var language = LanguageRegistry.PMD.getLanguageById("java"); - assertThat(language).isNotNull(); - - var pmd = newPmdOperation() - .forceLanguageVersion(language.getLatestVersion()) - .defaultLanguageVersions(language.getVersions()) - .languageVersions(language.getDefaultVersion()) - .ruleSets(PmdOperation.RULE_SET_DEFAULT); - assertThat(pmd.languageVersions()).contains(language.getDefaultVersion()); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - - assertThat(pmd.defaultLanguageVersions(language.getVersion("17"), language.getVersion("21")) - .languageVersions(language.getVersions()).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) - .as("17 & 21").isGreaterThan(0); - - } - - @Test - void testMainOperation() throws ExitStatusException { - var pmd = newPmdOperation().inputPaths(new File("src/main")) - .performPmdAnalysis(TEST, newPmdOperation().initConfiguration(COMMAND_NAME)); - assertThat(pmd).isEqualTo(0); - } - - @Test - void testPrependAuxClasspath() { - var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).prependAuxClasspath(FOO, BAR); - assertThat(pmd.prependAuxClasspath()).isEqualTo(FOO + File.pathSeparator + BAR); - } - - @Test - void testPriority() throws ExitStatusException { - var pmd = newPmdOperation().inputPaths(CODE_STYLE_SAMPLE).minimumPriority(RulePriority.HIGH); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - } - - @Test - void testRelativizeRoots() { - var baz = Path.of("baz/foz"); - - var pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)).relativizeRoots(PATH_FOO). - relativizeRoots(PATH_BAR.toFile()).relativizeRoots(baz.toString()) - .relativizeRoots(List.of(PATH_FOO, PATH_BAR, baz)); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getRelativizeRoots()).isEqualTo(pmd.relativizeRoots()) - .containsExactly(PATH_FOO, PATH_BAR, baz, PATH_FOO, PATH_BAR, baz); - - pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)) - .relativizeRootsFiles(List.of(PATH_FOO.toFile(), PATH_BAR.toFile(), baz.toFile())); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getRelativizeRoots()).as("List(File...)").isEqualTo(pmd.relativizeRoots()) - .containsExactly(PATH_FOO, PATH_BAR, baz); - - pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)) - .relativizeRootsStrings(List.of(PATH_FOO.toString(), PATH_BAR.toString(), baz.toString())); - config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getRelativizeRoots()).as("List(String....)").isEqualTo(pmd.relativizeRoots()) - .containsExactly(PATH_FOO, PATH_BAR, baz); - } - - @Test - void testReportFile() throws FileNotFoundException, ExitStatusException { - var report = new File("build", "pmd-report-file"); - report.deleteOnExit(); - var pmd = newPmdOperation().ruleSets(List.of(ERROR_PRONE_XML, DESIGN_XML)).reportFile(report); - pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); - assertThat(report).exists(); - - try (var writer = new PrintWriter(report)) { - writer.write(""); - } - assertThat(report).isEmpty(); - - pmd.reportFile(report.getAbsolutePath()).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); - assertThat(report).isNotEmpty(); - } - - @Test - void testReportFormat() throws IOException, ExitStatusException { - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).reportFormat("xml").inputPaths(ERROR_PRONE_SAMPLE); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - try (var softly = new AutoCloseableSoftAssertions()) { - try (var br = Files.newBufferedReader(pmd.reportFile())) { - softly.assertThat(br.readLine()).as("xml report") - .startsWith(""); - } - } - } - - @Test - void testReportProperties() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML, ERROR_PRONE_XML) - .includeLineNumber(true) - .reportProperties(new Properties()); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } - - @Test - void testRuleSetsConfigFile() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets("src/test/resources/pmd.xml") - .ignoreFile("src/test/resources/ignore-all.txt"); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - } - - @Test - void testRuleSetsEmpty() throws ExitStatusException { - var pmd = newPmdOperation().ruleSets("").failOnError(false); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isEqualTo(0); - } - - @Test - void testShowSuppressed() { - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).showSuppressed(true); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.isShowSuppressedViolations()).isTrue(); - } - - @Test - void testSuppressedMarker() { - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).suppressedMarker(TEST); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getSuppressMarker()).isEqualTo(TEST); - } - - @Test - void testThreads() { - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).threads(5); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getThreads()).isEqualTo(5); - } - - @Test - void testUri() throws URISyntaxException { - var uri = new URI("https://example.com"); - var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).uri(uri); - var config = pmd.initConfiguration(COMMAND_NAME); - assertThat(config.getUri()).isEqualTo(uri); - } - - @Test - void testXml() throws ExitStatusException { - var pmd = newPmdOperation().addInputPaths("src/test/resources/pmd.xml") - .ruleSets("src/test/resources/xml/basic.xml"); - assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))).isGreaterThan(0); - } -} diff --git a/src/test/java/rife/bld/extension/PmdOperationTests.java b/src/test/java/rife/bld/extension/PmdOperationTests.java new file mode 100644 index 0000000..3808fd2 --- /dev/null +++ b/src/test/java/rife/bld/extension/PmdOperationTests.java @@ -0,0 +1,658 @@ +/* + * Copyright 2023-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package rife.bld.extension; + +import net.sourceforge.pmd.PMDConfiguration; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.rule.RulePriority; +import org.assertj.core.api.AutoCloseableSoftAssertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import rife.bld.BaseProject; +import rife.bld.operations.exceptions.ExitStatusException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.PrintWriter; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.Properties; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; + +/** + * PmdOperationTests class + * + * @author Erik C. Thauvin + * @since 1.0 + */ +class PmdOperationTests { + static final String ANALYSIS_FAILURE = "analysis should fail"; + static final String ANALYSIS_SUCCESS = "analysis should succeed"; + static final String BAR = "bar"; + static final String CATEGORY_FOO = "category/foo.xml"; + static final Path CODE_STYLE_SAMPLE = Path.of("src/test/resources/java/CodeStyle.java"); + static final String CODE_STYLE_XML = "category/java/codestyle.xml"; + static final String COMMAND_NAME = "pmd"; + static final String DESIGN_XML = "category/java/design.xml"; + static final String DOCUMENTATION_XML = "category/java/documentation.xml"; + static final Path ERROR_PRONE_SAMPLE = Path.of("src/test/resources/java/ErrorProne.java"); + static final String ERROR_PRONE_XML = "category/java/errorprone.xml"; + static final File FILE_BAR = new File(BAR); + static final String FOO = "foo"; + static final File FILE_FOO = new File(FOO); + static final Path PATH_BAR = Path.of(BAR); + static final Path PATH_FOO = Path.of(FOO); + static final String PERFORMANCE_XML = "category/java/performance.xml"; + static final String SECURITY_XML = "category/java/security.xml"; + static final String TEST = "test"; + + PmdOperation newPmdOperation() { + return new PmdOperation() + .inputPaths(Path.of("src/main"), Path.of("src/test")) + .cache("build/" + COMMAND_NAME + "/pmd-cache") + .failOnViolation(false) + .reportFile(Paths.get("build", COMMAND_NAME, "pmd-test-report.txt")); + } + + @Nested + @DisplayName("Configuration Tests") + class ConfigurationTests { + @Test + void cache() throws ExitStatusException { + var cache = Path.of("build/pmd/temp-cache"); + var pmd = newPmdOperation() + .ruleSets(CODE_STYLE_XML) + .inputPaths(List.of(CODE_STYLE_SAMPLE)) + .cache(cache); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + var f = cache.toFile(); + assertThat(f.exists()).as("cache should exist").isTrue(); + assertThat(f.delete()).as("cache should be deleted").isTrue(); + } + + @Test + void encoding() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).encoding("UTF-16"); + PMDConfiguration config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getSourceEncoding()).as("encoding should be UTF-16").isEqualTo(StandardCharsets.UTF_16); + + pmd = pmd.encoding(StandardCharsets.ISO_8859_1); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getSourceEncoding()).as("encoding should be ISO_8859") + .isEqualTo(StandardCharsets.ISO_8859_1); + } + + @Test + void ignoreFile() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(ERROR_PRONE_XML, CODE_STYLE_XML) + .ignoreFile(Path.of("src/test/resources/ignore.txt")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("%s for error prone and code style", ANALYSIS_FAILURE).isGreaterThan(0); + + pmd.inputPaths().clear(); + pmd.inputPaths(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("%s for error prone and code style samples", ANALYSIS_SUCCESS).isEqualTo(0); + + pmd.ruleSets().clear(); + pmd.inputPaths().clear(); + assertThat(pmd.inputPaths(ERROR_PRONE_SAMPLE) + .ignoreFile(new File("src/test/resources/ignore-single.txt")) + .performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("%s for error prone sample", ANALYSIS_SUCCESS).isEqualTo(0); + } + + @Test + void incrementalAnalysis() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).incrementalAnalysis(true); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.isIgnoreIncrementalAnalysis()).isFalse(); + } + + @Test + void languageVersions() throws ExitStatusException { + var language = LanguageRegistry.PMD.getLanguageById("java"); + assertThat(language).isNotNull(); + + var pmd = newPmdOperation() + .forceLanguageVersion(language.getLatestVersion()) + .defaultLanguageVersions(language.getVersions()) + .languageVersions(language.getDefaultVersion()) + .ruleSets(PmdOperation.RULE_SET_DEFAULT); + + assertThat(pmd.languageVersions()).as("should contain default language version") + .contains(language.getDefaultVersion()); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + + assertThat(pmd.defaultLanguageVersions(language.getVersion("17"), language.getVersion("21")) + .languageVersions(language.getVersions()) + .performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("%s with language versions 17 & 21", ANALYSIS_FAILURE).isGreaterThan(0); + + } + + @Test + void prependAuxClasspath() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).prependAuxClasspath(FOO, BAR); + assertThat(pmd.prependAuxClasspath()).isEqualTo(FOO + File.pathSeparator + BAR); + } + + @Test + void priority() throws ExitStatusException { + var pmd = newPmdOperation().inputPaths(CODE_STYLE_SAMPLE).minimumPriority(RulePriority.HIGH); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_SUCCESS).isEqualTo(0); + } + + @Test + void relativizeRoots() { + var baz = Path.of("baz/foz"); + + var pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)).relativizeRoots(PATH_FOO). + relativizeRoots(PATH_BAR.toFile()).relativizeRoots(baz.toString()) + .relativizeRoots(List.of(PATH_FOO, PATH_BAR, baz)); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getRelativizeRoots()).as("multiple roots").isEqualTo(pmd.relativizeRoots()) + .containsExactly(PATH_FOO, PATH_BAR, baz, PATH_FOO, PATH_BAR, baz); + + pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)) + .relativizeRootsFiles(List.of(PATH_FOO.toFile(), PATH_BAR.toFile(), baz.toFile())); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getRelativizeRoots()).as("List(File...)").isEqualTo(pmd.relativizeRoots()) + .containsExactly(PATH_FOO, PATH_BAR, baz); + + pmd = newPmdOperation().ruleSets(List.of(CATEGORY_FOO)) + .relativizeRootsStrings(List.of(PATH_FOO.toString(), PATH_BAR.toString(), baz.toString())); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getRelativizeRoots()).as("List(String....)").isEqualTo(pmd.relativizeRoots()) + .containsExactly(PATH_FOO, PATH_BAR, baz); + } + + @Test + void showSuppressed() { + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).showSuppressed(true); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.isShowSuppressedViolations()).isTrue(); + } + + @Test + void suppressedMarker() { + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).suppressedMarker(TEST); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getSuppressMarker()).isEqualTo(TEST); + } + + @Test + void threads() { + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).threads(5); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getThreads()).isEqualTo(5); + } + + @Test + void uri() throws URISyntaxException { + var uri = new URI("https://example.com"); + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).uri(uri); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getUri()).isEqualTo(uri); + } + } + + @Nested + @DisplayName("Exclusion Tests") + class ExclusionTests { + @Test + void addExcludes() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludes(PATH_FOO); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(PATH_FOO); + + pmd = pmd.addExcludes(PATH_BAR); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); + } + + @Test + void addExcludesFiles() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludesFiles(FILE_FOO); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath()); + + pmd = pmd.addExcludesFiles(FILE_BAR); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath(), FILE_BAR.toPath()); + } + + @Test + void addExcludesStrings() { + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).addExcludesStrings(FOO); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(PATH_FOO); + + pmd = pmd.addExcludesStrings(BAR); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); + } + + @Test + void excludes() { + var foz = Path.of("foz/baz"); + var baz = Path.of("baz/foz"); + + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludes(PATH_FOO, PATH_BAR); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(pmd.excludes()).containsExactly(List.of(PATH_FOO, PATH_BAR).toArray(new Path[0])); + assertThat(config.getExcludes()).containsExactly(List.of(PATH_FOO, PATH_BAR).toArray(new Path[0])); + + var excludes = List.of(List.of(PATH_FOO, PATH_BAR), List.of(foz, baz)); + for (var exclude : excludes) { + pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludes(exclude); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(exclude.toArray(new Path[0])); + } + } + + @Test + void excludesFiles() { + var foz = new File("foz"); + var baz = new File("baz"); + + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesFiles(FILE_FOO, FILE_BAR); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(FILE_FOO.toPath(), FILE_BAR.toPath()); + + var excludes = List.of(List.of(FILE_FOO, FILE_BAR), List.of(foz, baz)); + for (var exclude : excludes) { + pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesFiles(exclude); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(exclude.stream().map(File::toPath).toArray(Path[]::new)); + } + } + + @Test + void excludesStrings() { + var foz = "foz"; + var baz = "baz"; + + var pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesStrings(FOO, BAR); + var config = pmd.initConfiguration(COMMAND_NAME); + assertThat(pmd.excludes()).containsExactly(PATH_FOO, PATH_BAR); + assertThat(config.getExcludes()).containsExactly(PATH_FOO, PATH_BAR); + + var excludes = List.of(List.of(FOO, BAR), List.of(foz, baz)); + for (var exclude : excludes) { + pmd = newPmdOperation().ruleSets(CATEGORY_FOO).excludesStrings(exclude); + config = pmd.initConfiguration(COMMAND_NAME); + assertThat(config.getExcludes()).containsExactly(exclude.stream().map(Paths::get).toArray(Path[]::new)); + } + } + } + + @Nested + @DisplayName("Execution Tests") + class ExecutionTests { + @Test + void execute() throws ExitStatusException { + var pmd = new PmdOperation().fromProject(new BaseProject()); + + assertThat(pmd.inputPaths()).containsExactly(Paths.get("src/main").toAbsolutePath(), + Paths.get("src/test").toAbsolutePath()); + + pmd.inputPaths().clear(); + pmd.inputPaths("src/main/java", "src/test/java") + .ruleSets("config/pmd.xml"); + + assertThat(pmd.ruleSets()).containsExactly("config/pmd.xml"); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_SUCCESS).isEqualTo(0); + } + + @Test + void executeNoProject() { + var pmd = new PmdOperation(); + assertThatCode(pmd::execute).isInstanceOf(ExitStatusException.class); + } + } + + @Nested + @DisplayName("Failure Tests") + class FailureTests { + @Test + void failOnError() { + var pmd = newPmdOperation().ruleSets("src/test/resources/xml/old.xml") + .inputPaths(Path.of("src/test/resources/java/Documentation.java")); + assertThatCode(() -> pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .isInstanceOf(ExitStatusException.class); + assertThatCode(() -> pmd.failOnError(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .doesNotThrowAnyException(); + } + + @Test + void failOnValidation() { + var pmd = newPmdOperation().ruleSets(DOCUMENTATION_XML) + .inputPaths(Path.of("src/test/resources/java/Documentation.java")); + assertThatCode(() -> pmd.failOnViolation(true).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .isInstanceOf(ExitStatusException.class); + assertThatCode(() -> pmd.failOnViolation(false).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .doesNotThrowAnyException(); + } + } + + @Nested + @DisplayName("Input Paths Tests") + class InputPathsTests { + @Test + void addInputPaths() throws ExitStatusException { + var project = new BaseProject(); + var pmd = new PmdOperation().fromProject(project); + + assertThat(pmd.inputPaths()).as("default input paths") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + var err = pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPaths(project.srcMainDirectory(), project.srcTestDirectory()); + + assertThat(pmd.inputPaths()).as("File...").containsExactly(project.srcMainDirectory().toPath(), + project.srcTestDirectory().toPath()); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPathsFiles(List.of(project.srcMainDirectory(), project.srcTestDirectory())); + + assertThat(pmd.inputPaths()).as("List(File...)") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPaths(project.srcMainDirectory().getAbsolutePath(), + project.srcTestDirectory().getAbsolutePath()); + + assertThat(pmd.inputPaths()).as("String...") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPathsStrings( + List.of(project.srcMainDirectory().getAbsolutePath(), project.srcTestDirectory().getAbsolutePath())); + + assertThat(pmd.inputPaths()).as("List(String...)") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPaths(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + assertThat(pmd.inputPaths()).as("Path...") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + pmd.inputPaths().clear(); + pmd = pmd.addInputPaths(List.of(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath())); + + assertThat(pmd.inputPaths()).as("List(Path)") + .containsExactly(project.srcMainDirectory().toPath(), project.srcTestDirectory().toPath()); + + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0).isEqualTo(err); + } + + @Test + void fileArray() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) + .inputPaths(ERROR_PRONE_SAMPLE.toFile(), CODE_STYLE_SAMPLE.toFile()); + assertThat(pmd.inputPaths()).containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void mainOperation() throws ExitStatusException { + var pmd = newPmdOperation().inputPaths(new File("src/main")) + .performPmdAnalysis(TEST, newPmdOperation().initConfiguration(COMMAND_NAME)); + assertThat(pmd).as(ANALYSIS_SUCCESS).isEqualTo(0); + } + + @Test + void pathArray() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) + .inputPaths(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.inputPaths()).containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void pathList() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) + .inputPathsFiles(List.of(ERROR_PRONE_SAMPLE.toFile(), CODE_STYLE_SAMPLE.toFile())); + assertThat(pmd.inputPaths()).containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void stringArray() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) + .inputPaths(ERROR_PRONE_SAMPLE.toString(), CODE_STYLE_SAMPLE.toString()); + assertThat(pmd.inputPaths()).containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void stringList() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PmdOperation.RULE_SET_DEFAULT, CODE_STYLE_XML) + .inputPathsStrings(List.of(ERROR_PRONE_SAMPLE.toString(), CODE_STYLE_SAMPLE.toString())); + assertThat(pmd.inputPaths()).containsExactly(ERROR_PRONE_SAMPLE, CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void xml() throws ExitStatusException { + var pmd = newPmdOperation().addInputPaths("src/test/resources/pmd.xml") + .ruleSets("src/test/resources/xml/basic.xml"); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + } + + @Nested + @DisplayName("Reporting Tests") + class ReportingTests { + @Test + void reportFile() throws FileNotFoundException, ExitStatusException { + var report = new File("build", "pmd-report-file"); + report.deleteOnExit(); + var pmd = newPmdOperation().ruleSets(List.of(ERROR_PRONE_XML, DESIGN_XML)).reportFile(report); + pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); + assertThat(report).as("report should exist").exists(); + + try (var writer = new PrintWriter(report)) { + writer.write(""); + } + assertThat(report).as("report should not be empty").isEmpty(); + + pmd.reportFile(report.getAbsolutePath()).performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); + assertThat(report).as("report should not be empty").isNotEmpty(); + } + + @Test + void reportFormat() throws IOException, ExitStatusException { + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).reportFormat("xml").inputPaths(ERROR_PRONE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + try (var softly = new AutoCloseableSoftAssertions()) { + try (var br = Files.newBufferedReader(pmd.reportFile())) { + softly.assertThat(br.readLine()).as("XML report for %s", pmd.reportFile().toString()) + .startsWith(""); + } + } + } + + @Test + void reportProperties() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML, ERROR_PRONE_XML) + .includeLineNumber(true) + .reportProperties(new Properties()); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + } + + @Nested + @DisplayName("RuleSets Tests") + class RuleSetsTests { + @Test + void addRuleSets() throws ExitStatusException { + var pmd = new PmdOperation().fromProject(new BaseProject()); + + assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT); + + pmd.addRuleSet(ERROR_PRONE_XML); + + assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML); + + var err = pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME)); + + pmd.ruleSets().clear(); + + pmd.addRuleSet(List.of(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML)); + + assertThat(pmd.ruleSets()).as("rulesets as collection") + .containsExactly(PmdOperation.RULE_SET_DEFAULT, ERROR_PRONE_XML); + + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0).isEqualTo(err); + } + + @Test + void javaBestPractices() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets("category/java/bestpractices.xml") + .inputPaths(Path.of("src/test/resources/java/BestPractices.java")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaCodeStyle() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML).inputPaths(CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaCodeStyleAndErrorProne() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(CODE_STYLE_XML).inputPaths(CODE_STYLE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("analysis with code style").isGreaterThan(0); + + pmd = pmd.ruleSets(ERROR_PRONE_XML).inputPaths(ERROR_PRONE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as("analysis with code style and error prone").isGreaterThan(0); + } + + @Test + void javaDesign() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(DESIGN_XML) + .inputPaths("src/test/resources/java/Design.java") + .cache(new File("build/pmd/design-cache")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaDocumentation() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(DOCUMENTATION_XML) + .inputPaths(Path.of("src/test/resources/java/Documentation.java")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaErrorProne() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(ERROR_PRONE_XML).inputPaths(ERROR_PRONE_SAMPLE); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaMultiThreading() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets("category/java/multithreading.xml") + .inputPaths(Path.of("src/test/resources/java/MultiThreading.java")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaPerformance() throws ExitStatusException { + var pmd = newPmdOperation() + .ruleSets(PERFORMANCE_XML) + .inputPaths(Path.of("src/test/resources/java/Performance.java")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaQuickStart() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(PmdOperation.RULE_SET_DEFAULT) + .inputPaths(new File("src/test/resources/java/")); + assertThat(pmd.ruleSets()).containsExactly(PmdOperation.RULE_SET_DEFAULT); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void javaSecurity() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets(SECURITY_XML) + .inputPaths(Path.of("src/test/resources/java/Security.java")); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_FAILURE).isGreaterThan(0); + } + + @Test + void ruleSetsConfigFile() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets("src/test/resources/pmd.xml") + .ignoreFile("src/test/resources/ignore-all.txt"); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_SUCCESS).isEqualTo(0); + } + + @Test + void ruleSetsEmpty() throws ExitStatusException { + var pmd = newPmdOperation().ruleSets("").failOnError(false); + assertThat(pmd.performPmdAnalysis(TEST, pmd.initConfiguration(COMMAND_NAME))) + .as(ANALYSIS_SUCCESS).isEqualTo(0); + } + } +}