From: David Gageot Date: Fri, 27 Apr 2012 12:45:13 +0000 (+0200) Subject: SONAR 1076 - Run PMD on Unit Tests X-Git-Tag: 3.1~327 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=1a6a18a5c4e73987a72b8176f398477f13074d29;p=sonarqube.git SONAR 1076 - Run PMD on Unit Tests --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java index eb4ade51a18..2f16051638b 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java @@ -26,7 +26,6 @@ import org.sonar.api.batch.*; import org.sonar.api.measures.*; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -import org.sonar.api.resources.ResourceUtils; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.Violation; @@ -44,7 +43,7 @@ public class ViolationsDecorator implements Decorator { } private boolean shouldDecorateResource(Resource resource) { - return !ResourceUtils.isUnitTestClass(resource); + return true; } @DependedUpon diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java index 4cd71f04f5d..18e10114331 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java @@ -96,8 +96,7 @@ public class NewViolationsDecorator implements Decorator { private boolean shouldDecorateResource(Resource resource, DecoratorContext context) { return (StringUtils.equals(Scopes.PROJECT, resource.getScope()) || StringUtils.equals(Scopes.DIRECTORY, resource.getScope()) || StringUtils .equals(Scopes.FILE, resource.getScope())) - && !ResourceUtils.isUnitTestClass(resource) - && context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null; + && (context.getMeasure(CoreMetrics.NEW_VIOLATIONS) == null); } private void computeNewViolations(DecoratorContext context) { diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties index 6c780de2d15..167b7897d1e 100644 --- a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties @@ -275,3 +275,13 @@ rule.pmd.UseConcurrentHashMap.name=Use ConcurrentHashMap rule.pmd.DoNotHardCodeSDCard.name=Android - Do Not Hard Code SD Card rule.pmd.DontCallThreadRun.name=Dont Call Thread Run rule.pmd.GuardDebugLogging.name=Guard Debug Logging +rule.pmd-unit-tests.JUnitStaticSuite.name=JUnit static suite +rule.pmd-unit-tests.JUnitSpelling.name= JUnit spelling +rule.pmd-unit-tests.JUnitAssertionsShouldIncludeMessage.name=JUnit assertions should include a message +rule.pmd-unit-tests.JUnitTestsShouldIncludeAssert.name=JUnit tests should include an assert +rule.pmd-unit-tests.TestClassWithoutTestCases.name=Test class without test cases +rule.pmd-unit-tests.UnnecessaryBooleanAssertion.name=Unnecessary boolean assertion +rule.pmd-unit-tests.UseAssertEqualsInsteadOfAssertTrue.name=Use assertEquals instead of assertTrue +rule.pmd-unit-tests.UseAssertSameInsteadOfAssertTrue.name=Use assertSame instead of assertTrue +rule.pmd-unit-tests.UseAssertNullInsteadOfAssertTrue.name=Use assertNull instead of assertTrue +rule.pmd-unit-tests.SimplifyBooleanAssertion.name=Simplify boolean assertion diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html new file mode 100644 index 00000000000..ec742d69cc4 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html @@ -0,0 +1,8 @@ +JUnit assertions should include a message - i.e., use the three argument version of assertEquals(), not the two argument version. +
+public class Foo extends TestCase {
+  public void testSomething() {
+    assertEquals("foo", "bar"); // violation, should be assertEquals("Foo does not equals bar", "foo", "bar");
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html new file mode 100644 index 00000000000..48bdfb21fa3 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html @@ -0,0 +1,9 @@ +Some JUnit framework methods are easy to misspell. +
+import junit.framework.*;
+
+public class Foo extends TestCase {
+  public void setup() {} // violation, should be setUp()
+  public void TearDown() {} // violation, should be tearDown()
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html new file mode 100644 index 00000000000..916d6dea758 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html @@ -0,0 +1,9 @@ +The suite() method in a JUnit test needs to be both public and static. +
+import junit.framework.*;
+
+public class Foo extends TestCase {
+  public void suite() {} // violation, should be static
+  private static void suite() {} // violation, should be public
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html new file mode 100644 index 00000000000..ad6b1256de4 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html @@ -0,0 +1,10 @@ +JUnit tests should include at least one assertion. This makes the tests more robust, and using assert with messages provide the developer a clearer idea of what the test does. +
+public class Foo extends TestCase {
+  public void testSomething() {
+    Bar b = findBar();
+    b.work();
+    // violation, we could use assertNotNull("bar not found", b);
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html new file mode 100644 index 00000000000..093b4fcef89 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html @@ -0,0 +1,9 @@ +Avoid negation in an assertTrue or assertFalse test. For example, rephrase: assertTrue(!expr); as: assertFalse(expr); +
+public class SimpleTest extends TestCase {
+  public void testX() {
+    assertTrue("not empty", !r.isEmpty()); // violation, replace with assertFalse("not empty", r.isEmpty())
+    assertFalse(!r.isEmpty()); // violation, replace with assertTrue("empty", r.isEmpty())
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html new file mode 100644 index 00000000000..891dde75b7f --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html @@ -0,0 +1,9 @@ +Test classes end with the suffix Test. Having a non-test class with that name is not a good practice, since most people will assume it is a test case. Test classes have test methods named testXXX. +
+public class CarTest { // violation, consider changing the name of the class if it is not a test
+  // consider adding test methods if it is a test
+  public static void main(String[] args) {
+    // do something
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html new file mode 100644 index 00000000000..83356d46679 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html @@ -0,0 +1,7 @@ +A JUnit test assertion with a boolean literal is unnecessary since it always will eval to the same thing. Consider using flow control (in case of assertTrue(false) or similar) or simply removing statements like assertTrue(true) and assertFalse(false). If you just want a test to halt, use the fail method. +
+public class SimpleTest extends TestCase {
+  public void testX() {
+    assertTrue(true); // violation
+  }
+}
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html new file mode 100644 index 00000000000..0887fb74827 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html @@ -0,0 +1,10 @@ +This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals. +
+public class FooTest extends TestCase {
+  void testCode() {
+    Object a, b;
+
+    assertTrue(a.equals(b)); // violation
+    assertEquals("a should equals b", a, b); // good usage
+  }
+}
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html new file mode 100644 index 00000000000..947ebd5bde9 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html @@ -0,0 +1,13 @@ +This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertNull, assertNotNull. +
+public class FooTest extends TestCase {
+  void testCode() {
+    Object a = doSomething();
+
+    assertTrue(a==null); // violation
+    assertNull(a);  // good usage
+    assertTrue(a != null); // violation
+    assertNotNull(a);  // good usage
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html new file mode 100644 index 00000000000..d2d317b37f8 --- /dev/null +++ b/plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html @@ -0,0 +1,11 @@ +This rule detects JUnit assertions in object references equality. These assertions should be made by more specific methods, like assertSame, assertNotSame. +
+public class FooTest extends TestCase {
+  void testCode() {
+    Object a, b;
+
+    assertTrue(a==b); // violation
+    assertSame(a, b); // good usage
+  }
+}
+
\ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/pom.xml b/plugins/sonar-pmd-plugin/pom.xml index f947805fa81..2215dc3700a 100644 --- a/plugins/sonar-pmd-plugin/pom.xml +++ b/plugins/sonar-pmd-plugin/pom.xml @@ -65,6 +65,13 @@ sonar-testing-harness test + + + org.codehaus.sonar.plugins + sonar-l10n-en-plugin + ${project.version} + test + diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java index 545a99c099a..e4da4b06537 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java @@ -19,37 +19,36 @@ */ package org.sonar.plugins.pmd; -import java.io.File; -import java.util.List; -import java.util.Properties; - import net.sourceforge.pmd.cpd.JavaTokenizer; import net.sourceforge.pmd.cpd.Tokenizer; - import org.sonar.api.CoreProperties; import org.sonar.api.batch.CpdMapping; +import org.sonar.api.config.Settings; import org.sonar.api.resources.Java; import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Language; -import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; -public class JavaCpdMapping implements CpdMapping { +import java.io.File; +import java.util.List; +import java.util.Properties; - private String ignore_literals; - private String ignore_identifiers; +import static com.google.common.base.Objects.firstNonNull; - public JavaCpdMapping(Project project) { - ignore_literals = project.getConfiguration().getString(CoreProperties.CPD_IGNORE_LITERALS_PROPERTY, - CoreProperties.CPD_IGNORE_LITERALS_DEFAULT_VALUE); - ignore_identifiers = project.getConfiguration().getString(CoreProperties.CPD_IGNORE_IDENTIFIERS_PROPERTY, - CoreProperties.CPD_IGNORE_IDENTIFIERS_DEFAULT_VALUE); +public class JavaCpdMapping implements CpdMapping { + private final String ignore_literals; + private final String ignore_identifiers; + + public JavaCpdMapping(Settings settings) { + ignore_literals = firstNonNull(settings.getString(CoreProperties.CPD_IGNORE_LITERALS_PROPERTY), CoreProperties.CPD_IGNORE_LITERALS_DEFAULT_VALUE); + ignore_identifiers = firstNonNull(settings.getString(CoreProperties.CPD_IGNORE_IDENTIFIERS_PROPERTY), CoreProperties.CPD_IGNORE_IDENTIFIERS_DEFAULT_VALUE); } public Tokenizer getTokenizer() { Properties props = new Properties(); props.setProperty(JavaTokenizer.IGNORE_LITERALS, ignore_literals); props.setProperty(JavaTokenizer.IGNORE_IDENTIFIERS, ignore_identifiers); + JavaTokenizer tokenizer = new JavaTokenizer(); tokenizer.setProperties(props); return tokenizer; diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java index 3485b970892..c2331b8b769 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java @@ -19,18 +19,20 @@ */ package org.sonar.plugins.pmd; +import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.renderers.Renderer; +import net.sourceforge.pmd.renderers.XMLRenderer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.sonar.api.BatchExtension; import org.sonar.api.Property; import org.sonar.api.config.Settings; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.Project; +import org.sonar.api.resources.ProjectFileSystem; import org.sonar.api.utils.SonarException; import java.io.File; import java.io.IOException; import java.io.StringWriter; -import java.util.Arrays; -import java.util.List; @org.sonar.api.Properties({ @Property( @@ -42,40 +44,65 @@ import java.util.List; ) }) public class PmdConfiguration implements BatchExtension { + private static final Logger LOG = LoggerFactory.getLogger(PmdConfiguration.class); public static final String PROPERTY_GENERATE_XML = "sonar.pmd.generateXml"; + public static final String PMD_RESULT_XML = "pmd-result.xml"; - private PmdProfileExporter pmdProfileExporter; - private RulesProfile rulesProfile; - private Project project; - private Settings settings; + private final ProjectFileSystem projectFileSystem; + private final Settings settings; - public PmdConfiguration(PmdProfileExporter pmdRulesRepository, RulesProfile rulesProfile, Project project, Settings settings) { - this.pmdProfileExporter = pmdRulesRepository; - this.rulesProfile = rulesProfile; - this.project = project; + public PmdConfiguration(ProjectFileSystem projectFileSystem, Settings settings) { + this.projectFileSystem = projectFileSystem; this.settings = settings; } - public List getRulesets() { - return Arrays.asList(saveXmlFile().getAbsolutePath()); + public File getTargetXMLReport() { + if (settings.getBoolean(PROPERTY_GENERATE_XML)) { + return projectFileSystem.resolvePath(PMD_RESULT_XML); + } + return null; } - private File saveXmlFile() { + public File dumpXmlRuleSet(String repositoryKey, String rulesXml) { try { - StringWriter pmdConfiguration = new StringWriter(); - pmdProfileExporter.exportProfile(rulesProfile, pmdConfiguration); - return project.getFileSystem().writeToWorkingDirectory(pmdConfiguration.toString(), "pmd.xml"); + File configurationFile = projectFileSystem.writeToWorkingDirectory(rulesXml, repositoryKey + ".xml"); + + LOG.info("PMD configuration: " + configurationFile.getAbsolutePath()); + return configurationFile; } catch (IOException e) { throw new SonarException("Fail to save the PMD configuration", e); } } - public File getTargetXMLReport() { - if (settings.getBoolean(PROPERTY_GENERATE_XML)) { - return new File(project.getFileSystem().getSonarWorkingDirectory(), "pmd-result.xml"); + public File dumpXmlReport(Report report) { + if (!settings.getBoolean(PROPERTY_GENERATE_XML)) { + return null; } - return null; + + try { + String reportAsString = reportToString(report); + + File reportFile = projectFileSystem.writeToWorkingDirectory(reportAsString, PMD_RESULT_XML); + + LOG.info("PMD output report: " + reportFile.getAbsolutePath()); + + return reportFile; + } catch (IOException e) { + throw new SonarException("Fail to save the PMD report", e); + } + } + + private static String reportToString(Report report) throws IOException { + StringWriter output = new StringWriter(); + + Renderer xmlRenderer = new XMLRenderer(); + xmlRenderer.setWriter(output); + xmlRenderer.start(); + xmlRenderer.renderFileReport(report); + xmlRenderer.end(); + + return output.toString(); } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java index b7b7ea14f9b..613903da2e8 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java @@ -24,6 +24,8 @@ import org.sonar.api.CoreProperties; public final class PmdConstants { public static final String REPOSITORY_KEY = CoreProperties.PMD_PLUGIN; public static final String REPOSITORY_NAME = "PMD"; + public static final String TEST_REPOSITORY_KEY = "pmd-unit-tests"; + public static final String TEST_REPOSITORY_NAME = "PMD Unit Tests"; public static final String PLUGIN_NAME = "PMD"; public static final String PLUGIN_KEY = CoreProperties.PMD_PLUGIN; public static final String XPATH_CLASS = "net.sourceforge.pmd.rules.XPathRule"; diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java index 0f485f897ef..c0dd7de8a1e 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java @@ -19,166 +19,105 @@ */ package org.sonar.plugins.pmd; -import net.sourceforge.pmd.PMD; -import net.sourceforge.pmd.PMDException; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.io.Closeables; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; -import net.sourceforge.pmd.SourceType; -import net.sourceforge.pmd.renderers.Renderer; -import net.sourceforge.pmd.renderers.XMLRenderer; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.sonar.api.BatchExtension; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.InputFile; import org.sonar.api.resources.Java; import org.sonar.api.resources.Project; -import org.sonar.api.utils.SonarException; +import org.sonar.api.resources.ProjectFileSystem; import org.sonar.api.utils.TimeProfiler; import org.sonar.java.api.JavaUtils; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; +import java.io.ByteArrayInputStream; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; +import java.nio.charset.Charset; import java.util.List; public class PmdExecutor implements BatchExtension { - - private static final Logger LOG = LoggerFactory.getLogger(PmdExecutor.class); - - private final PmdConfiguration configuration; private final Project project; + private final ProjectFileSystem projectFileSystem; + private final RulesProfile rulesProfile; + private final PmdProfileExporter pmdProfileExporter; + private final PmdConfiguration pmdConfiguration; - public PmdExecutor(Project project, PmdConfiguration configuration) { + public PmdExecutor(Project project, ProjectFileSystem projectFileSystem, RulesProfile rulesProfile, PmdProfileExporter pmdProfileExporter, PmdConfiguration pmdConfiguration) { this.project = project; - this.configuration = configuration; + this.projectFileSystem = projectFileSystem; + this.rulesProfile = rulesProfile; + this.pmdProfileExporter = pmdProfileExporter; + this.pmdConfiguration = pmdConfiguration; } - public Report execute() throws IOException { + public Report execute() { TimeProfiler profiler = new TimeProfiler().start("Execute PMD " + PmdVersion.getVersion()); ClassLoader initialClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); try { - PMD pmd = new PMD(); - setJavaVersion(pmd, project); - RuleContext ruleContext = new RuleContext(); - Report report = new Report(); - ruleContext.setReport(report); + Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - RuleSets rulesets = createRulesets(); + return executePmd(); + } finally { + Thread.currentThread().setContextClassLoader(initialClassLoader); + profiler.stop(); + } + } - for (File file : project.getFileSystem().getSourceFiles(Java.INSTANCE)) { - ruleContext.setSourceCodeFilename(file.getAbsolutePath()); - Reader fileReader = new InputStreamReader(new FileInputStream(file), project.getFileSystem().getSourceCharset()); - try { - pmd.processFile(fileReader, rulesets, ruleContext); + private Report executePmd() { + Report report = new Report(); - } catch (PMDException e) { - LOG.error("Fail to execute PMD. Following file is ignored: " + file, e.getCause()); + RuleContext context = new RuleContext(); + context.setReport(report); - } catch (Exception e) { - LOG.error("Fail to execute PMD. Following file is ignored: " + file, e); + PmdTemplate pmdFactory = createPmdTemplate(); + executeRules(pmdFactory, context, projectFileSystem.mainFiles(Java.KEY), PmdConstants.REPOSITORY_KEY); + executeRules(pmdFactory, context, projectFileSystem.testFiles(Java.KEY), PmdConstants.TEST_REPOSITORY_KEY); - } finally { - IOUtils.closeQuietly(fileReader); - } - } + pmdConfiguration.dumpXmlReport(report); - writeXmlReport(report); + return report; + } - return report; + public void executeRules(PmdTemplate pmdFactory, RuleContext ruleContext, List files, String repositoryKey) { + if (files.isEmpty()) { + return; // Nothing to analyse + } - } finally { - profiler.stop(); - Thread.currentThread().setContextClassLoader(initialClassLoader); + Charset encoding = projectFileSystem.getSourceCharset(); + RuleSets rulesets = createRulesets(repositoryKey); + + for (InputFile file : files) { + pmdFactory.process(file.getFile(), encoding, rulesets, ruleContext); } } - private RuleSets createRulesets() { - RuleSets rulesets = new RuleSets(); - RuleSetFactory ruleSetFactory = new RuleSetFactory(); + private RuleSets createRulesets(String repositoryKey) { + String rulesXml = pmdProfileExporter.exportProfile(repositoryKey, rulesProfile); - List rulesetPaths = configuration.getRulesets(); - LOG.info("PMD configuration: " + StringUtils.join(rulesetPaths, ", ")); + pmdConfiguration.dumpXmlRuleSet(repositoryKey, rulesXml); - for (String rulesetPath : rulesetPaths) { - InputStream rulesInput = openRuleset(rulesetPath); - rulesets.addRuleSet(ruleSetFactory.createRuleSet(rulesInput)); - IOUtils.closeQuietly(rulesInput); - } - return rulesets; + return new RuleSets(readRuleSet(rulesXml)); } - private InputStream openRuleset(String rulesetPath) { + private static RuleSet readRuleSet(String rulesXml) { + InputStream rulesInput = null; try { - File file = new File(rulesetPath); - boolean found; - if (file.exists()) { - found = true; - } else { - file = new File(project.getFileSystem().getBasedir(), rulesetPath); - found = file.exists(); - } - if (found) { - return new FileInputStream(file); - } - InputStream stream = PmdExecutor.class.getResourceAsStream(rulesetPath); - if (stream == null) { - throw new SonarException("The PMD ruleset can not be found: " + rulesetPath); - } - return stream; - - } catch (FileNotFoundException e) { - throw new SonarException("The PMD ruleset can not be found: " + rulesetPath, e); - } - } + rulesInput = new ByteArrayInputStream(rulesXml.getBytes()); - private void writeXmlReport(Report report) throws IOException { - File xmlReport = configuration.getTargetXMLReport(); - if (xmlReport != null) { - Renderer xmlRenderer = new XMLRenderer(); - Writer stringwriter = new StringWriter(); - xmlRenderer.setWriter(stringwriter); - xmlRenderer.start(); - xmlRenderer.renderFileReport(report); - xmlRenderer.end(); - - LOG.info("PMD output report: " + xmlReport.getAbsolutePath()); - FileUtils.write(xmlReport, stringwriter.toString()); - } - } - - static String getNormalizedJavaVersion(String javaVersion) { - if (StringUtils.equals("1.1", javaVersion) || StringUtils.equals("1.2", javaVersion)) { - javaVersion = "1.3"; - } else if (StringUtils.equals("5", javaVersion)) { - javaVersion = "1.5"; - } else if (StringUtils.equals("6", javaVersion)) { - javaVersion = "1.6"; + return new RuleSetFactory().createRuleSet(rulesInput); + } finally { + Closeables.closeQuietly(rulesInput); } - return javaVersion; } - private void setJavaVersion(PMD pmd, Project project) { - String javaVersion = getNormalizedJavaVersion(JavaUtils.getSourceVersion(project)); - if (javaVersion != null) { - SourceType sourceType = SourceType.getSourceTypeForId("java " + javaVersion); - if (sourceType != null) { - LOG.info("Java version: " + javaVersion); - pmd.setJavaVersion(sourceType); - } else { - throw new SonarException("Unsupported Java version for PMD: " + javaVersion); - } - } + @VisibleForTesting + PmdTemplate createPmdTemplate() { + return new PmdTemplate(JavaUtils.getSourceVersion(project)); } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java index 7a793037422..dc56a9ca29b 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java @@ -19,49 +19,29 @@ */ package org.sonar.plugins.pmd; +import com.google.common.collect.BiMap; +import com.google.common.collect.EnumHashBiMap; import org.sonar.api.rules.RulePriority; +import static com.google.common.collect.ImmutableMap.of; + public final class PmdLevelUtils { + private static final BiMap LEVELS_PER_PRIORITY = EnumHashBiMap.create(of( + RulePriority.BLOCKER, "1", + RulePriority.CRITICAL, "2", + RulePriority.MAJOR, "3", + RulePriority.MINOR, "4", + RulePriority.INFO, "5")); private PmdLevelUtils() { // only static methods } public static RulePriority fromLevel(String level) { - if ("1".equals(level)) { - return RulePriority.BLOCKER; - } - if ("2".equals(level)) { - return RulePriority.CRITICAL; - } - if ("3".equals(level)) { - return RulePriority.MAJOR; - } - if ("4".equals(level)) { - return RulePriority.MINOR; - } - if ("5".equals(level)) { - return RulePriority.INFO; - } - return null; + return LEVELS_PER_PRIORITY.inverse().get(level); } public static String toLevel(RulePriority priority) { - if (priority.equals(RulePriority.BLOCKER)) { - return "1"; - } - if (priority.equals(RulePriority.CRITICAL)) { - return "2"; - } - if (priority.equals(RulePriority.MAJOR)) { - return "3"; - } - if (priority.equals(RulePriority.MINOR)) { - return "4"; - } - if (priority.equals(RulePriority.INFO)) { - return "5"; - } - throw new IllegalArgumentException("Level not supported: " + priority); + return LEVELS_PER_PRIORITY.get(priority); } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java index dff7b9f85bc..5206ed9a549 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java @@ -26,19 +26,20 @@ import org.sonar.api.SonarPlugin; import java.util.List; public class PmdPlugin extends SonarPlugin { - + @SuppressWarnings("unchecked") public List> getExtensions() { return ImmutableList.of( PmdSensor.class, PmdConfiguration.class, PmdExecutor.class, PmdRuleRepository.class, + PmdUnitTestsRuleRepository.class, PmdProfileExporter.class, PmdProfileImporter.class, SonarWayProfile.class, SonarWayWithFindbugsProfile.class, SunConventionsProfile.class, - JavaCpdMapping.class - ); + JavaCpdMapping.class, + PmdViolationToRuleViolation.class); } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java index 83a4a648694..d295f6b9c07 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java @@ -19,12 +19,7 @@ */ package org.sonar.plugins.pmd; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; - +import com.google.common.annotations.VisibleForTesting; import org.jdom.CDATA; import org.jdom.Document; import org.jdom.Element; @@ -40,8 +35,13 @@ import org.sonar.plugins.pmd.xml.PmdProperty; import org.sonar.plugins.pmd.xml.PmdRule; import org.sonar.plugins.pmd.xml.PmdRuleset; -public class PmdProfileExporter extends ProfileExporter { +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; +public class PmdProfileExporter extends ProfileExporter { public PmdProfileExporter() { super(PmdConstants.REPOSITORY_KEY, PmdConstants.PLUGIN_NAME); setSupportedLanguages(Java.KEY); @@ -51,21 +51,25 @@ public class PmdProfileExporter extends ProfileExporter { @Override public void exportProfile(RulesProfile profile, Writer writer) { try { - PmdRuleset tree = createPmdRuleset(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY), profile.getName()); - String xmlModules = exportPmdRulesetToXml(tree); + String xmlModules = exportProfile(PmdConstants.REPOSITORY_KEY, profile); writer.append(xmlModules); } catch (IOException e) { throw new SonarException("Fail to export the profile " + profile, e); } } - protected PmdRuleset createPmdRuleset(List activeRules, String profileName) { + public String exportProfile(String repositoryKey, RulesProfile profile) { + PmdRuleset tree = createPmdRuleset(repositoryKey, profile.getActiveRulesByRepository(repositoryKey), profile.getName()); + return exportPmdRulesetToXml(tree); + } + + private PmdRuleset createPmdRuleset(String repositoryKey, List activeRules, String profileName) { PmdRuleset ruleset = new PmdRuleset(profileName); for (ActiveRule activeRule : activeRules) { - if (activeRule.getRule().getRepositoryKey().equals(PmdConstants.REPOSITORY_KEY)) { + if (activeRule.getRule().getRepositoryKey().equals(repositoryKey)) { String configKey = activeRule.getRule().getConfigKey(); PmdRule rule = new PmdRule(configKey, PmdLevelUtils.toLevel(activeRule.getSeverity())); - if (activeRule.getActiveRuleParams() != null && !activeRule.getActiveRuleParams().isEmpty()) { + if ((activeRule.getActiveRuleParams() != null) && !activeRule.getActiveRuleParams().isEmpty()) { List properties = new ArrayList(); for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) { properties.add(new PmdProperty(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue())); @@ -79,7 +83,8 @@ public class PmdProfileExporter extends ProfileExporter { return ruleset; } - protected void processXPathRule(String sonarRuleKey, PmdRule rule) { + @VisibleForTesting + void processXPathRule(String sonarRuleKey, PmdRule rule) { if (PmdConstants.XPATH_CLASS.equals(rule.getRef())) { rule.setRef(null); PmdProperty xpathMessage = rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM); @@ -98,7 +103,7 @@ public class PmdProfileExporter extends ProfileExporter { } } - protected String exportPmdRulesetToXml(PmdRuleset pmdRuleset) { + private String exportPmdRulesetToXml(PmdRuleset pmdRuleset) { Element eltRuleset = new Element("ruleset"); for (PmdRule pmdRule : pmdRuleset.getPmdRules()) { Element eltRule = new Element("rule"); diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java index 7b6ad0a8763..3b91268754b 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java @@ -30,10 +30,8 @@ import java.io.File; import java.util.List; public final class PmdRuleRepository extends RuleRepository { - - // for user extensions - private ServerFileSystem fileSystem; - private XMLRuleParser xmlRuleParser; + private final ServerFileSystem fileSystem; + private final XMLRuleParser xmlRuleParser; public PmdRuleRepository(ServerFileSystem fileSystem, XMLRuleParser xmlRuleParser) { super(PmdConstants.REPOSITORY_KEY, Java.KEY); diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java index 2b406deb787..834679ba52e 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java @@ -21,70 +21,52 @@ package org.sonar.plugins.pmd; import net.sourceforge.pmd.IRuleViolation; import net.sourceforge.pmd.Report; -import org.sonar.api.CoreProperties; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.Java; -import org.sonar.api.resources.JavaFile; import org.sonar.api.resources.Project; -import org.sonar.api.resources.Resource; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.Violation; import org.sonar.api.utils.XmlParserException; import java.util.Iterator; public class PmdSensor implements Sensor { + private final RulesProfile profile; + private final PmdExecutor executor; + private final PmdViolationToRuleViolation pmdViolationToRuleViolation; - private RulesProfile profile; - private RuleFinder rulesFinder; - private PmdExecutor executor; - - public PmdSensor(RulesProfile profile, RuleFinder rulesFinder, PmdExecutor executor) { + public PmdSensor(RulesProfile profile, PmdExecutor executor, PmdViolationToRuleViolation pmdViolationToRuleViolation) { this.profile = profile; - this.rulesFinder = rulesFinder; this.executor = executor; + this.pmdViolationToRuleViolation = pmdViolationToRuleViolation; + } + + public boolean shouldExecuteOnProject(Project project) { + return (!project.getFileSystem().mainFiles(Java.KEY).isEmpty() && !profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty()) + || (!project.getFileSystem().testFiles(Java.KEY).isEmpty() && !profile.getActiveRulesByRepository(PmdConstants.TEST_REPOSITORY_KEY).isEmpty()); } public void analyse(Project project, SensorContext context) { try { Report report = executor.execute(); - analyseReport(report, project, context); - + reportViolations(report.iterator(), context); } catch (Exception e) { - // TOFIX throw new XmlParserException(e); } } - private void analyseReport(Report report, Project project, SensorContext context) { - Iterator pmdViolationIter = report.iterator(); - while (pmdViolationIter.hasNext()) { - IRuleViolation pmdViolation = pmdViolationIter.next(); - int lineId = pmdViolation.getBeginLine(); - String ruleKey = pmdViolation.getRule().getName(); - String message = pmdViolation.getDescription(); - String filename = pmdViolation.getFilename(); - Resource resource = JavaFile.fromAbsolutePath(filename, project.getFileSystem().getSourceDirs(), false); - // Save violations only for existing resources - if (context.getResource(resource) != null) { - Rule rule = rulesFinder.findByKey(CoreProperties.PMD_PLUGIN, ruleKey); - // Save violations only for enabled rules - if (rule != null) { - Violation violation = Violation.create(rule, resource).setLineId(lineId).setMessage(message); - context.saveViolation(violation); - } + private void reportViolations(Iterator violations, SensorContext context) { + while (violations.hasNext()) { + IRuleViolation pmdViolation = violations.next(); + + Violation violation = pmdViolationToRuleViolation.toViolation(pmdViolation, context); + if (null != violation) { + context.saveViolation(violation); } } } - public boolean shouldExecuteOnProject(Project project) { - return !project.getFileSystem().mainFiles(Java.KEY).isEmpty() && - !profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty(); - } - @Override public String toString() { return getClass().getSimpleName(); diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java new file mode 100644 index 00000000000..c24d1fa21ed --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java @@ -0,0 +1,98 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Functions; +import com.google.common.collect.ImmutableMap; +import com.google.common.io.Closeables; +import net.sourceforge.pmd.PMD; +import net.sourceforge.pmd.PMDException; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleSets; +import net.sourceforge.pmd.SourceType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.utils.SonarException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Map; + +public class PmdTemplate { + private static final Logger LOG = LoggerFactory.getLogger(PmdTemplate.class); + + private static final Map JAVA_VERSIONS = ImmutableMap.of( + "1.1", "1.3", + "1.2", "1.3", + "5", "1.5", + "6", "1.6"); + + private final PMD pmd; + + public PmdTemplate(String javaVersion) { + pmd = new PMD(); + setJavaVersion(pmd, javaVersion); + } + + public void process(File file, Charset encoding, RuleSets rulesets, RuleContext ruleContext) { + ruleContext.setSourceCodeFilename(file.getAbsolutePath()); + + InputStream inputStream = null; + try { + inputStream = new FileInputStream(file); + + pmd.processFile(inputStream, encoding.displayName(), rulesets, ruleContext); + } catch (PMDException e) { + LOG.error("Fail to execute PMD. Following file is ignored: " + file, e.getCause()); + } catch (Exception e) { + LOG.error("Fail to execute PMD. Following file is ignored: " + file, e); + } finally { + Closeables.closeQuietly(inputStream); + } + } + + @VisibleForTesting + static void setJavaVersion(PMD pmd, String javaVersion) { + String version = normalize(javaVersion); + if (version == null) { + return; // Do nothing + } + + SourceType sourceType = SourceType.getSourceTypeForId("java " + version); + if (sourceType == null) { + throw new SonarException("Unsupported Java version for PMD: " + version); + } + + LOG.info("Java version: " + version); + pmd.setJavaVersion(sourceType); + } + + private static String normalize(String version) { + return Functions.forMap(JAVA_VERSIONS, version).apply(version); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java new file mode 100644 index 00000000000..c76c794a196 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java @@ -0,0 +1,44 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import org.sonar.api.resources.Java; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleRepository; +import org.sonar.api.rules.XMLRuleParser; + +import java.io.InputStream; +import java.util.List; + +public final class PmdUnitTestsRuleRepository extends RuleRepository { + private final XMLRuleParser xmlRuleParser; + + public PmdUnitTestsRuleRepository(XMLRuleParser xmlRuleParser) { + super(PmdConstants.TEST_REPOSITORY_KEY, Java.KEY); + setName(PmdConstants.TEST_REPOSITORY_NAME); + this.xmlRuleParser = xmlRuleParser; + } + + @Override + public List createRules() { + InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/rules-unit-tests.xml"); + return xmlRuleParser.parse(input); + } +} diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java index b4be1c627fa..abbb79a34e9 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java @@ -19,7 +19,7 @@ */ package org.sonar.plugins.pmd; -import org.apache.commons.io.IOUtils; +import com.google.common.io.Closeables; import org.slf4j.LoggerFactory; import java.io.IOException; @@ -37,18 +37,22 @@ public enum PmdVersion { } private PmdVersion() { - InputStream input = getClass().getResourceAsStream(PROPERTIES_PATH); + version = readVersion(); + } + + public String readVersion() { + Properties properties = new Properties(); + + InputStream input = null; try { - Properties properties = new Properties(); + input = getClass().getResourceAsStream(PROPERTIES_PATH); properties.load(input); - this.version = properties.getProperty("pmd.version"); - } catch (IOException e) { LoggerFactory.getLogger(getClass()).warn("Can not load the PMD version from the file " + PROPERTIES_PATH); - this.version = ""; - } finally { - IOUtils.closeQuietly(input); + Closeables.closeQuietly(input); } + + return properties.getProperty("pmd.version", ""); } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java new file mode 100644 index 00000000000..f1d40dbb420 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java @@ -0,0 +1,82 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import net.sourceforge.pmd.IRuleViolation; +import org.sonar.api.BatchExtension; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.resources.JavaFile; +import org.sonar.api.resources.ProjectFileSystem; +import org.sonar.api.resources.Resource; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.Violation; + +import java.io.File; +import java.util.List; + +public class PmdViolationToRuleViolation implements BatchExtension { + private final ProjectFileSystem projectFileSystem; + private final RuleFinder ruleFinder; + + public PmdViolationToRuleViolation(ProjectFileSystem projectFileSystem, RuleFinder ruleFinder) { + this.projectFileSystem = projectFileSystem; + this.ruleFinder = ruleFinder; + } + + public Violation toViolation(IRuleViolation pmdViolation, SensorContext context) { + Resource resource = findResourceFor(pmdViolation); + if (context.getResource(resource) == null) { + return null; // Save violations only for existing resources + } + + Rule rule = findRuleFor(pmdViolation); + if (rule == null) { + return null; // Save violations only for enabled rules + } + + int lineId = pmdViolation.getBeginLine(); + String message = pmdViolation.getDescription(); + + return Violation.create(rule, resource).setLineId(lineId).setMessage(message); + } + + private Resource findResourceFor(IRuleViolation violation) { + List allSources = ImmutableList.copyOf(Iterables.concat(projectFileSystem.getSourceDirs(), projectFileSystem.getTestDirs())); + + return JavaFile.fromAbsolutePath(violation.getFilename(), allSources, true); + } + + private Rule findRuleFor(IRuleViolation violation) { + String ruleKey = violation.getRule().getName(); + Rule rule = ruleFinder.findByKey(PmdConstants.REPOSITORY_KEY, ruleKey); + if (rule != null) { + return rule; + } + return ruleFinder.findByKey(PmdConstants.TEST_REPOSITORY_KEY, ruleKey); + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } +} diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java index ad340db9b83..b21d5d725a8 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java @@ -19,16 +19,16 @@ */ package org.sonar.plugins.pmd; -import java.io.InputStreamReader; -import java.io.Reader; - +import com.google.common.io.Closeables; import org.sonar.api.profiles.ProfileDefinition; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.Java; import org.sonar.api.utils.ValidationMessages; -public final class SonarWayProfile extends ProfileDefinition { +import java.io.InputStreamReader; +import java.io.Reader; +public final class SonarWayProfile extends ProfileDefinition { private final PmdProfileImporter importer; public SonarWayProfile(PmdProfileImporter importer) { @@ -36,11 +36,18 @@ public final class SonarWayProfile extends ProfileDefinition { } @Override - public RulesProfile createProfile(ValidationMessages messages) { - Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sonar-way.xml")); - RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages); - profile.setLanguage(Java.KEY); - profile.setName(RulesProfile.SONAR_WAY_NAME); - return profile; + public RulesProfile createProfile(ValidationMessages validation) { + Reader config = null; + try { + config = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sonar-way.xml")); + + RulesProfile profile = importer.importProfile(config, validation); + profile.setLanguage(Java.KEY); + profile.setName(RulesProfile.SONAR_WAY_NAME); + + return profile; + } finally { + Closeables.closeQuietly(config); + } } } diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java index 6a6d371620f..f2553b80c9d 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java @@ -25,20 +25,19 @@ import org.sonar.api.resources.Java; import org.sonar.api.utils.ValidationMessages; public class SonarWayWithFindbugsProfile extends ProfileDefinition { - - private SonarWayProfile sonarWay; + private final SonarWayProfile sonarWay; public SonarWayWithFindbugsProfile(SonarWayProfile sonarWay) { this.sonarWay = sonarWay; } - @Override - public RulesProfile createProfile(ValidationMessages validationMessages) { - RulesProfile profile = sonarWay.createProfile(validationMessages); + public RulesProfile createProfile(ValidationMessages validation) { + RulesProfile profile = sonarWay.createProfile(validation); + profile.setName(RulesProfile.SONAR_WAY_FINDBUGS_NAME); profile.setLanguage(Java.KEY); + return profile; } } - diff --git a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java index c4f869725c1..aa147db5586 100644 --- a/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java +++ b/plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java @@ -19,16 +19,16 @@ */ package org.sonar.plugins.pmd; -import java.io.InputStreamReader; -import java.io.Reader; - +import com.google.common.io.Closeables; import org.sonar.api.profiles.ProfileDefinition; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.resources.Java; import org.sonar.api.utils.ValidationMessages; -public final class SunConventionsProfile extends ProfileDefinition { +import java.io.InputStreamReader; +import java.io.Reader; +public final class SunConventionsProfile extends ProfileDefinition { private final PmdProfileImporter importer; public SunConventionsProfile(PmdProfileImporter importer) { @@ -36,12 +36,18 @@ public final class SunConventionsProfile extends ProfileDefinition { } @Override - public RulesProfile createProfile(ValidationMessages messages) { - Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream( - "/org/sonar/plugins/pmd/profile-sun-conventions.xml")); - RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages); - profile.setName(RulesProfile.SUN_CONVENTIONS_NAME); - profile.setLanguage(Java.KEY); - return profile; + public RulesProfile createProfile(ValidationMessages validation) { + Reader config = null; + try { + config = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sun-conventions.xml")); + + RulesProfile profile = importer.importProfile(config, validation); + profile.setLanguage(Java.KEY); + profile.setName(RulesProfile.SUN_CONVENTIONS_NAME); + + return profile; + } finally { + Closeables.closeQuietly(config); + } } } diff --git a/plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml b/plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml new file mode 100644 index 00000000000..938bcf1a733 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml @@ -0,0 +1,42 @@ + + + MAJOR + + + + MAJOR + + + + MINOR + + + + MAJOR + + + + MAJOR + + + + MINOR + + + + MINOR + + + + MINOR + + + + MINOR + + + + MINOR + + + \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java index 127cf94c85a..1964f5c9538 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java @@ -19,51 +19,90 @@ */ package org.sonar.plugins.pmd; -import org.apache.commons.io.FileUtils; +import net.sourceforge.pmd.Report; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.sonar.api.config.Settings; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.resources.Project; import org.sonar.api.resources.ProjectFileSystem; -import org.sonar.api.test.MavenTestUtils; +import org.sonar.api.utils.SonarException; import java.io.File; import java.io.IOException; -import java.util.List; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.matches; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class PmdConfigurationTest { + PmdConfiguration configuration; + + Settings settings = new Settings(); + ProjectFileSystem fs = mock(ProjectFileSystem.class); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Before + public void setUpPmdConfiguration() { + configuration = new PmdConfiguration(fs, settings); + } + + @Test + public void should_return_default_target_xml_report_when_property_is_not_set() { + File targetXMLReport = configuration.getTargetXMLReport(); + + assertThat(targetXMLReport).isNull(); + } + + @Test + public void should_set_target_xml_report() { + when(fs.resolvePath("pmd-result.xml")).thenReturn(new File("/workingDir/pmd-result.xml")); + + settings.setProperty(PmdConfiguration.PROPERTY_GENERATE_XML, true); + File targetXMLReport = configuration.getTargetXMLReport(); + + assertThat(targetXMLReport).isEqualTo(new File("/workingDir/pmd-result.xml")); + } @Test - public void writeConfigurationToWorkingDir() throws IOException { - Project project = MavenTestUtils.loadProjectFromPom(getClass(), "writeConfigurationToWorkingDir/pom.xml"); + public void should_dump_xml_rule_set() throws IOException { + when(fs.writeToWorkingDirectory("", "pmd.xml")).thenReturn(new File("/workingDir/pmd.xml")); - PmdConfiguration configuration = new PmdConfiguration(new PmdProfileExporter(), RulesProfile.create(), project, null); - List rulesets = configuration.getRulesets(); + File rulesFile = configuration.dumpXmlRuleSet("pmd", ""); - assertThat(rulesets.size(), is(1)); - File xmlFile = new File(rulesets.get(0)); - assertThat(xmlFile.exists(), is(true)); - assertThat(FileUtils.readFileToString(xmlFile), is("\r\n\r\n\r\n")); + assertThat(rulesFile).isEqualTo(new File("/workingDir/pmd.xml")); } @Test - public void shouldReturnTargetXMLReport() { - Project project = new Project("key"); - ProjectFileSystem fs = mock(ProjectFileSystem.class); - when(fs.getSonarWorkingDirectory()).thenReturn(new File("/tmp")); - project.setFileSystem(fs); - Settings settings = new Settings(); - PmdConfiguration configuration = new PmdConfiguration(null, null, project, settings); + public void should_fail_to_dump_xml_rule_set() throws IOException { + when(fs.writeToWorkingDirectory("", "pmd.xml")).thenThrow(new IOException("BUG")); - assertThat(configuration.getTargetXMLReport(), nullValue()); + expectedException.expect(SonarException.class); + expectedException.expectMessage("Fail to save the PMD configuration"); + + configuration.dumpXmlRuleSet("pmd", ""); + } + + @Test + public void should_dump_xml_report() throws IOException { + when(fs.writeToWorkingDirectory(matches(".*[\r\n]*"), eq("pmd-result.xml"))).thenReturn(new File("/workingDir/pmd-result.xml")); settings.setProperty(PmdConfiguration.PROPERTY_GENERATE_XML, true); - assertThat(configuration.getTargetXMLReport(), equalTo(new File("/tmp/pmd-result.xml"))); + File reportFile = configuration.dumpXmlReport(new Report()); + + assertThat(reportFile).isEqualTo(new File("/workingDir/pmd-result.xml")); } + @Test + public void should_ignore_xml_report_when_property_is_not_set() { + File reportFile = configuration.dumpXmlReport(new Report()); + + assertThat(reportFile).isNull(); + verifyZeroInteractions(fs); + } } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java index a45a7426075..7da11466987 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java @@ -20,90 +20,109 @@ package org.sonar.plugins.pmd; import com.google.common.base.Charsets; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; -import org.junit.Rule; +import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleSets; +import org.junit.Before; import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.mockito.Mockito; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.InputFile; import org.sonar.api.resources.Java; import org.sonar.api.resources.Project; import org.sonar.api.resources.ProjectFileSystem; +import org.sonar.test.TestUtils; import java.io.File; -import java.io.IOException; import java.util.Arrays; +import java.util.Collections; -import static org.hamcrest.Matchers.nullValue; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; public class PmdExecutorTest { + PmdExecutor pmdExecutor; - @Rule - public TemporaryFolder temp = new TemporaryFolder(); + Project project = mock(Project.class); + ProjectFileSystem projectFileSystem = mock(ProjectFileSystem.class); + RulesProfile rulesProfile = mock(RulesProfile.class); + PmdProfileExporter pmdProfileExporter = mock(PmdProfileExporter.class); + PmdConfiguration pmdConfiguration = mock(PmdConfiguration.class); + PmdTemplate pmdTemplate = mock(PmdTemplate.class); + + @Before + public void setUpPmdExecutor() { + pmdExecutor = Mockito.spy(new PmdExecutor(project, projectFileSystem, rulesProfile, pmdProfileExporter, pmdConfiguration)); + + doReturn(pmdTemplate).when(pmdExecutor).createPmdTemplate(); + } @Test - public void executeOnManySourceDirs() throws IOException { - File workDir = temp.getRoot(); - Project project = new Project("two-source-dirs"); - - ProjectFileSystem fs = mock(ProjectFileSystem.class); - File root = new File(getClass().getResource("/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/").toURI()); - when(fs.getSourceFiles(Java.INSTANCE)).thenReturn(Arrays.asList(new File(root, "src1/FirstClass.java"), new File(root, "src2/SecondClass.java"))); - when(fs.getSourceCharset()).thenReturn(Charsets.UTF_8); - when(fs.getSonarWorkingDirectory()).thenReturn(workDir); - project.setFileSystem(fs); - - PmdConfiguration conf = mock(PmdConfiguration.class); - File file = FileUtils.toFile(getClass().getResource("/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml").toURI().toURL()); - when(conf.getRulesets()).thenReturn(Arrays.asList(file.getAbsolutePath())); - File xmlReport = new File(workDir, "pmd-result.xml"); - when(conf.getTargetXMLReport()).thenReturn(xmlReport); - - PmdExecutor executor = new PmdExecutor(project, conf); - executor.execute(); - assertThat(xmlReport.exists(), is(true)); - - String xml = FileUtils.readFileToString(xmlReport); - - // errors on the two source files - assertThat(StringUtils.countMatches(xml, " emptyList()); + + pmdExecutor.execute(); + + verify(pmdTemplate).process(eq(new File("src/Class.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class)); + verifyNoMoreInteractions(pmdTemplate); + } + + static InputFile file(String path) { + InputFile inputFile = mock(InputFile.class); + when(inputFile.getFile()).thenReturn(new File(path)); + return inputFile; + } } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java new file mode 100644 index 00000000000..2b4fad4fbc2 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java @@ -0,0 +1,47 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import org.junit.Test; +import org.sonar.api.rules.RulePriority; + +import static org.fest.assertions.Assertions.assertThat; + +public class PmdLevelUtilsTest { + @Test + public void should_get_priority_from_level() { + assertThat(PmdLevelUtils.fromLevel("1")).isSameAs(RulePriority.BLOCKER); + assertThat(PmdLevelUtils.fromLevel("2")).isSameAs(RulePriority.CRITICAL); + assertThat(PmdLevelUtils.fromLevel("3")).isSameAs(RulePriority.MAJOR); + assertThat(PmdLevelUtils.fromLevel("4")).isSameAs(RulePriority.MINOR); + assertThat(PmdLevelUtils.fromLevel("5")).isSameAs(RulePriority.INFO); + assertThat(PmdLevelUtils.fromLevel("?")).isNull(); + assertThat(PmdLevelUtils.fromLevel(null)).isNull(); + } + + @Test + public void should_get_level_from_priority() { + assertThat(PmdLevelUtils.toLevel(RulePriority.BLOCKER)).isEqualTo("1"); + assertThat(PmdLevelUtils.toLevel(RulePriority.CRITICAL)).isEqualTo("2"); + assertThat(PmdLevelUtils.toLevel(RulePriority.MAJOR)).isEqualTo("3"); + assertThat(PmdLevelUtils.toLevel(RulePriority.MINOR)).isEqualTo("4"); + assertThat(PmdLevelUtils.toLevel(RulePriority.INFO)).isEqualTo("5"); + } +} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java index 90c7e31cbf8..4a0902a4bae 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java @@ -19,17 +19,20 @@ */ package org.sonar.plugins.pmd; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; - import org.junit.Test; +import org.sonar.api.Extension; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; public class PmdPluginTest { + PmdPlugin plugin = new PmdPlugin(); @Test - public void testGetExtensions() { - PmdPlugin plugin = new PmdPlugin(); - assertThat(plugin.getExtensions().size(), greaterThan(1)); - } + public void should_contain_both_rule_repositories() { + List> extensions = plugin.getExtensions(); + assertThat(extensions).contains(PmdRuleRepository.class, PmdUnitTestsRuleRepository.class); + } } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java index 7dac4cc592e..ab0044010af 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java @@ -19,12 +19,9 @@ */ package org.sonar.plugins.pmd; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.input.CharSequenceReader; -import org.apache.commons.lang.StringUtils; -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.sonar.api.platform.ServerFileSystem; import org.sonar.api.profiles.RulesProfile; import org.sonar.api.rules.ActiveRule; @@ -38,144 +35,109 @@ import org.sonar.plugins.pmd.xml.PmdProperty; import org.sonar.plugins.pmd.xml.PmdRule; import org.sonar.test.TestUtils; -import java.io.Reader; import java.io.StringReader; -import java.io.StringWriter; -import java.util.Collection; import java.util.List; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.sonar.test.MoreConditions.equalsIgnoreEOL; public class PmdProfileExporterTest { - - private final PmdProfileExporter exporter = new PmdProfileExporter(); + PmdProfileExporter exporter = new PmdProfileExporter(); @Test - public void testExportProfile() { - ServerFileSystem fileSystem = mock(ServerFileSystem.class); - PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser()); - List rules = repository.createRules(); + public void should_export_pmd_profile() { + String importedXml = TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_simple.xml"); - RuleFinder ruleFinder = new FakeRuleFinder(rules); - PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); - RulesProfile rulesProfile = importer.importProfile(reader, ValidationMessages.create()); + String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, importProfile(importedXml)); - StringWriter xmlOutput = new StringWriter(); - exporter.exportProfile(rulesProfile, xmlOutput); + assertThat(exportedXml).satisfies(equalsIgnoreEOL(importedXml)); + } - assertThat(xmlOutput.toString(), new IsEqualIgnoringEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_simple.xml"))); + @Test + public void should_export_empty_configuration_as_xml() { + String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, RulesProfile.create()); + + assertThat(exportedXml).satisfies(equalsIgnoreEOL("")); } @Test - public void testExportXPathRule() { - StringWriter xmlOutput = new StringWriter(); + public void should_export_xPath_rule() { + Rule rule = Rule.create(PmdConstants.REPOSITORY_KEY, "MyOwnRule", "This is my own xpath rule.") + .setConfigKey(PmdConstants.XPATH_CLASS) + .setRepositoryKey(PmdConstants.REPOSITORY_KEY); + rule.createParameter(PmdConstants.XPATH_EXPRESSION_PARAM); + rule.createParameter(PmdConstants.XPATH_MESSAGE_PARAM); + RulesProfile profile = RulesProfile.create(); - Rule xpathTemplate = Rule.create(PmdConstants.REPOSITORY_KEY, "MyOwnRule", "This is my own xpath rule.") - .setConfigKey(PmdConstants.XPATH_CLASS).setRepositoryKey(PmdConstants.REPOSITORY_KEY); - xpathTemplate.createParameter(PmdConstants.XPATH_EXPRESSION_PARAM); - xpathTemplate.createParameter(PmdConstants.XPATH_MESSAGE_PARAM); - ActiveRule xpath = profile.activateRule(xpathTemplate, null); + ActiveRule xpath = profile.activateRule(rule, null); xpath.setParameter(PmdConstants.XPATH_EXPRESSION_PARAM, "//FieldDeclaration"); xpath.setParameter(PmdConstants.XPATH_MESSAGE_PARAM, "This is bad"); - exporter.exportProfile(profile, xmlOutput); - assertThat(xmlOutput.toString(), new IsEqualIgnoringEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml"))); - } - private static class IsEqualIgnoringEOL extends TypeSafeMatcher { - private final String expected; + String exportedXml = exporter.exportProfile(PmdConstants.REPOSITORY_KEY, profile); - public IsEqualIgnoringEOL(CharSequence expected) { - this.expected = normalize(expected); - } - - public void describeTo(Description description) { - description.appendText("string equal ").appendText(expected); - } - - @Override - public boolean matchesSafely(CharSequence item) { - return StringUtils.equals(expected, normalize(item)); - } - - private static String normalize(CharSequence charSequence) { - return StringUtils.join(IOUtils.lineIterator(new CharSequenceReader(charSequence)), IOUtils.LINE_SEPARATOR_UNIX); - } + assertThat(exportedXml).satisfies(equalsIgnoreEOL(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml"))); } @Test(expected = SonarException.class) - public void shouldFailIfMessageNotProvidedForXPathRule() { - String xpathExpression = "xpathExpression"; - + public void should_fail_if_message_not_provided_for_xPath_rule() { PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS); - rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, xpathExpression)); + + rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, "xpathExpression")); rule.setName("MyOwnRule"); exporter.processXPathRule("xpathKey", rule); } - @Test(expected = SonarException.class) - public void shouldFailIfXPathNotProvidedForXPathRule() { - String message = "This is bad"; - + @Test + public void should_process_xPath_rule() { PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS); - rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, message)); rule.setName("MyOwnRule"); + rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, "xpathExpression")); + rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, "message")); exporter.processXPathRule("xpathKey", rule); - } - @Test - public void testProcessingXPathRule() { - String message = "This is bad"; - String xpathExpression = "xpathExpression"; + assertThat(rule.getMessage()).isEqualTo("message"); + assertThat(rule.getRef()).isNull(); + assertThat(rule.getClazz()).isEqualTo(PmdConstants.XPATH_CLASS); + assertThat(rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM)).isNull(); + assertThat(rule.getName()).isEqualTo("xpathKey"); + assertThat(rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM).getValue()).isEqualTo("xpathExpression"); + } + @Test(expected = SonarException.class) + public void should_fail_if_xPath_not_provided() { PmdRule rule = new PmdRule(PmdConstants.XPATH_CLASS); - rule.addProperty(new PmdProperty(PmdConstants.XPATH_EXPRESSION_PARAM, xpathExpression)); - rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, message)); rule.setName("MyOwnRule"); + rule.addProperty(new PmdProperty(PmdConstants.XPATH_MESSAGE_PARAM, "This is bad")); exporter.processXPathRule("xpathKey", rule); - - assertThat(rule.getMessage(), is(message)); - assertThat(rule.getRef(), is(nullValue())); - assertThat(rule.getClazz(), is(PmdConstants.XPATH_CLASS)); - assertThat(rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM), is(nullValue())); - assertThat(rule.getName(), is("xpathKey")); - assertThat(rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM).getValue(), is(xpathExpression)); } - private static class FakeRuleFinder implements RuleFinder { - - private final List rules; - - public FakeRuleFinder(List rules) { - this.rules = rules; - } - - public Rule findById(int ruleId) { - throw new UnsupportedOperationException(); - } - - public Rule findByKey(String repositoryKey, String key) { - throw new UnsupportedOperationException(); - } + static RulesProfile importProfile(String configuration) { + PmdRuleRepository pmdRuleRepository = new PmdRuleRepository(mock(ServerFileSystem.class), new XMLRuleParser()); + RuleFinder ruleFinder = createRuleFinder(pmdRuleRepository.createRules()); + PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); - public Collection findAll(RuleQuery query) { - throw new UnsupportedOperationException(); - } + return importer.importProfile(new StringReader(configuration), ValidationMessages.create()); + } - public Rule find(RuleQuery query) { - for (Rule rule : rules) { - if (query.getConfigKey().equals(rule.getConfigKey())) { - rule.setRepositoryKey(PmdConstants.REPOSITORY_KEY); - return rule; + static RuleFinder createRuleFinder(final List rules) { + RuleFinder ruleFinder = mock(RuleFinder.class); + when(ruleFinder.find(any(RuleQuery.class))).then(new Answer() { + public Rule answer(InvocationOnMock invocation) { + RuleQuery query = (RuleQuery) invocation.getArguments()[0]; + for (Rule rule : rules) { + if (query.getConfigKey().equals(rule.getConfigKey())) { + return rule.setRepositoryKey(PmdConstants.REPOSITORY_KEY); + } } + return null; } - return null; - } + }); + return ruleFinder; } } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java index 69c35da419c..1920a580140 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java @@ -24,7 +24,11 @@ import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rules.*; +import org.sonar.api.rules.ActiveRule; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.RulePriority; +import org.sonar.api.rules.RuleQuery; import org.sonar.api.utils.ValidationMessages; import org.sonar.plugins.pmd.xml.PmdRuleset; import org.sonar.test.TestUtils; @@ -32,127 +36,135 @@ import org.sonar.test.TestUtils; import java.io.Reader; import java.io.StringReader; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class PmdProfileImporterTest { - - private PmdProfileImporter importer; - private ValidationMessages messages; + PmdProfileImporter importer; + ValidationMessages messages; @Before - public void before() { + public void setUpImporter() { messages = ValidationMessages.create(); - RuleFinder finder = createRuleFinder(); - importer = new PmdProfileImporter(finder); + importer = new PmdProfileImporter(createRuleFinder()); } @Test - public void testBuildPmdRuleset() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); + public void should_import_pmd_ruleset() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + PmdRuleset pmdRuleset = importer.parsePmdRuleset(reader, messages); - assertThat(pmdRuleset.getPmdRules().size(), is(3)); + + assertThat(pmdRuleset.getPmdRules()).hasSize(3); } @Test - public void testImportingSimpleProfile() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); + public void should_import_simple_profile() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + RulesProfile profile = importer.importProfile(reader, messages); - assertThat(profile.getActiveRules().size(), is(3)); - assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports")); - assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify")); - assertThat(messages.hasErrors(), is(false)); + assertThat(profile.getActiveRules()).hasSize(3); + assertThat(profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports")).isNotNull(); + assertThat(profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify")).isNotNull(); + assertThat(messages.hasErrors()).isFalse(); } @Test - public void testImportingProfileWithXPathRule() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/export_xpath_rules.xml")); + public void should_import_profile_with_xpath_rule() { + Reader reader = read("/org/sonar/plugins/pmd/export_xpath_rules.xml"); + RulesProfile profile = importer.importProfile(reader, messages); - assertThat(profile.getActiveRules().size(), is(0)); - assertThat(messages.hasWarnings(), is(true)); + assertThat(profile.getActiveRules()).isEmpty(); + assertThat(messages.hasWarnings()).isTrue(); } @Test - public void testImportingParameters() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); - RulesProfile profile = importer.importProfile(reader, messages); + public void should_import_parameter() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + RulesProfile profile = importer.importProfile(reader, messages); ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports"); - assertThat(activeRule.getActiveRuleParams().size(), is(1)); - assertThat(activeRule.getParameter("max"), is("30")); + + assertThat(activeRule.getParameter("max")).isEqualTo("30"); } @Test - public void testImportingDefaultPriority() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); - RulesProfile profile = importer.importProfile(reader, messages); + public void should_import_default_priority() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + RulesProfile profile = importer.importProfile(reader, messages); ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports"); - assertThat(activeRule.getSeverity(), is(RulePriority.BLOCKER)); // reuse the rule default priority + + assertThat(activeRule.getSeverity()).isSameAs(RulePriority.BLOCKER); } @Test - public void testImportingPriority() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); + public void should_import_priority() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + RulesProfile profile = importer.importProfile(reader, messages); ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify"); - assertThat(activeRule.getSeverity(), is(RulePriority.MINOR)); + assertThat(activeRule.getSeverity()).isSameAs(RulePriority.MINOR); activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects"); - assertThat(activeRule.getSeverity(), is(RulePriority.CRITICAL)); + assertThat(activeRule.getSeverity()).isSameAs(RulePriority.CRITICAL); } @Test - public void testImportingPmdConfigurationWithUnknownNodes() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/complex-with-unknown-nodes.xml")); + public void should_import_pmd_configuration_with_unknown_nodes() { + Reader reader = read("/org/sonar/plugins/pmd/complex-with-unknown-nodes.xml"); + RulesProfile profile = importer.importProfile(reader, messages); - assertThat(profile.getActiveRules().size(), is(3)); + assertThat(profile.getActiveRules()).hasSize(3); } @Test - public void testUnsupportedProperty() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); - RulesProfile profile = importer.importProfile(reader, messages); + public void should_deal_with_unsupported_property() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + RulesProfile profile = importer.importProfile(reader, messages); ActiveRule check = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects"); - assertThat(check.getParameter("threshold"), nullValue()); - assertThat(messages.getWarnings().size(), is(1)); + + assertThat(check.getParameter("threshold")).isNull(); + assertThat(messages.getWarnings()).hasSize(1); } @Test - public void testUnvalidXML() { + public void should_fail_on_invalid_xml() { Reader reader = new StringReader("not xml"); + importer.importProfile(reader, messages); - assertThat(messages.getErrors().size(), is(1)); + + assertThat(messages.getErrors()).hasSize(1); } @Test - public void testImportingUnknownRules() { - Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); + public void should_warn_on_unknown_rule() { + Reader reader = read("/org/sonar/plugins/pmd/simple.xml"); + importer = new PmdProfileImporter(mock(RuleFinder.class)); RulesProfile profile = importer.importProfile(reader, messages); - assertThat(profile.getActiveRules().size(), is(0)); - assertThat(messages.getWarnings().size(), is(3)); + assertThat(profile.getActiveRules()).isEmpty(); + assertThat(messages.getWarnings()).hasSize(3); } - private RuleFinder createRuleFinder() { - RuleFinder ruleFinder = mock(RuleFinder.class); - when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer() { + static Reader read(String path) { + return new StringReader(TestUtils.getResourceContent(path)); + } - public Rule answer(InvocationOnMock iom) throws Throwable { - RuleQuery query = (RuleQuery) iom.getArguments()[0]; - Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) - .setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER); + static RuleFinder createRuleFinder() { + RuleFinder ruleFinder = mock(RuleFinder.class); + when(ruleFinder.find((RuleQuery) anyObject())).then(new Answer() { + public Rule answer(InvocationOnMock invocation) { + RuleQuery query = (RuleQuery) invocation.getArguments()[0]; + Rule rule = Rule.create(query.getRepositoryKey(), "", "").setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER); if (rule.getConfigKey().equals("rulesets/coupling.xml/ExcessiveImports")) { rule.createParameter("max"); } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java new file mode 100644 index 00000000000..b1c5f731bc8 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java @@ -0,0 +1,80 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import org.junit.Test; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.sonar.api.profiles.ProfileDefinition; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.rules.RuleQuery; +import org.sonar.api.utils.ValidationMessages; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PmdProfilesTest { + ValidationMessages validation = ValidationMessages.create(); + + @Test + public void should_create_sun_convention_profile() { + SunConventionsProfile sunConvention = new SunConventionsProfile(new PmdProfileImporter(ruleFinder())); + + RulesProfile profile = sunConvention.createProfile(validation); + + assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty(); + assertThat(validation.hasErrors()).isFalse(); + } + + @Test + public void should_create_sonar_way_profile() { + ProfileDefinition sonarWay = new SonarWayProfile(new PmdProfileImporter(ruleFinder())); + + RulesProfile profile = sonarWay.createProfile(validation); + + assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty(); + assertThat(validation.hasErrors()).isFalse(); + } + + @Test + public void should_create_sonar_way_with_findbugs_profile() { + ProfileDefinition sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(new PmdProfileImporter(ruleFinder()))); + + RulesProfile profile = sonarWayWithFindbugs.createProfile(validation); + + assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY)).isNotEmpty(); + assertThat(validation.hasErrors()).isFalse(); + } + + static RuleFinder ruleFinder() { + RuleFinder ruleFinder = mock(RuleFinder.class); + when(ruleFinder.find(any(RuleQuery.class))).then(new Answer() { + public Rule answer(InvocationOnMock invocation) { + RuleQuery query = (RuleQuery) invocation.getArguments()[0]; + return Rule.create(query.getRepositoryKey(), "", ""); + } + }); + return ruleFinder; + } +} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java index 64ad90b8bc4..036f5b48743 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java @@ -19,41 +19,68 @@ */ package org.sonar.plugins.pmd; -import org.apache.commons.io.FileUtils; +import org.junit.Before; import org.junit.Test; import org.sonar.api.platform.ServerFileSystem; import org.sonar.api.rules.Rule; import org.sonar.api.rules.XMLRuleParser; +import org.sonar.test.TestUtils; +import org.sonar.test.i18n.RuleRepositoryTestHelper; import java.io.File; -import java.util.Collections; +import java.util.Arrays; import java.util.List; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; public class PmdRuleRepositoryTest { + PmdRuleRepository repository; + + ServerFileSystem fileSystem = mock(ServerFileSystem.class); + + @Before + public void setUpRuleRepository() { + repository = new PmdRuleRepository(fileSystem, new XMLRuleParser()); + } @Test - public void testLoadRepositoryFromXml() { - ServerFileSystem fileSystem = mock(ServerFileSystem.class); - PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser()); + public void should_have_correct_name_and_key() { + assertThat(repository.getKey()).isEqualTo("pmd"); + assertThat(repository.getLanguage()).isEqualTo("java"); + assertThat(repository.getName()).isEqualTo("PMD"); + } + + @Test + public void should_load_repository_from_xml() { List rules = repository.createRules(); - assertThat(rules.size(), greaterThan(100)); + + assertThat(rules.size()).isGreaterThan(100); } @Test - public void shouldLoadExtensions() { - ServerFileSystem fileSystem = mock(ServerFileSystem.class); - File file = FileUtils.toFile(getClass().getResource("/org/sonar/plugins/pmd/rules-extension.xml")); - when(fileSystem.getExtensions("pmd", "xml")).thenReturn(Collections.singletonList(file)); - PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser()); + public void should_load_extensions() { + File file = TestUtils.getResource("/org/sonar/plugins/pmd/rules-extension.xml"); + when(fileSystem.getExtensions("pmd", "xml")).thenReturn(Arrays.asList(file)); + List rules = repository.createRules(); - assertThat(rules.size(), greaterThan(100)); - assertThat(rules.get(rules.size() - 1).getKey(), is("Extension")); + + assertThat(rules).onProperty("key").contains("Extension"); } + @Test + public void should_exclude_junit_rules() { + List rules = repository.createRules(); + + assertThat(rules).onProperty("key").excludes("JUnitStaticSuite"); + } + + @Test + public void should_provide_a_name_and_description_for_each_rule() { + List rules = RuleRepositoryTestHelper.createRulesWithNameAndDescription("pmd", repository); + + assertThat(rules).onProperty("name").excludes(null, ""); + assertThat(rules).onProperty("description").excludes(null, ""); + } } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java new file mode 100644 index 00000000000..50e7f46106a --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java @@ -0,0 +1,126 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import com.google.common.collect.Iterators; +import net.sourceforge.pmd.IRuleViolation; +import net.sourceforge.pmd.Report; +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.batch.SensorContext; +import org.sonar.api.profiles.RulesProfile; +import org.sonar.api.resources.Java; +import org.sonar.api.resources.Project; +import org.sonar.api.rules.Violation; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class PmdSensorTest { + PmdSensor pmdSensor; + + Project project = mock(Project.class, RETURNS_DEEP_STUBS); + RulesProfile profile = mock(RulesProfile.class, RETURNS_DEEP_STUBS); + PmdExecutor executor = mock(PmdExecutor.class); + PmdViolationToRuleViolation pmdViolationToRuleViolation = mock(PmdViolationToRuleViolation.class); + SensorContext sensorContext = mock(SensorContext.class); + Violation violation = mock(Violation.class); + + @Before + public void setUpPmdSensor() { + pmdSensor = new PmdSensor(profile, executor, pmdViolationToRuleViolation); + } + + @Test + public void should_execute_on_project_with_main_files_and_active_rules() { + boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project); + + assertThat(shouldExecute).isTrue(); + } + + @Test + public void should_not_execute_on_project_without_files() { + when(project.getFileSystem().mainFiles(Java.KEY).isEmpty()).thenReturn(true); + when(project.getFileSystem().testFiles(Java.KEY).isEmpty()).thenReturn(true); + + boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project); + + assertThat(shouldExecute).isFalse(); + } + + @Test + public void should_not_execute_on_project_without_active_rules() { + when(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).isEmpty()).thenReturn(true); + when(profile.getActiveRulesByRepository(PmdConstants.TEST_REPOSITORY_KEY).isEmpty()).thenReturn(true); + + boolean shouldExecute = pmdSensor.shouldExecuteOnProject(project); + + assertThat(shouldExecute).isFalse(); + } + + @Test + public void should_report_violations() { + IRuleViolation pmdViolation = violation(); + Report report = report(pmdViolation); + when(executor.execute()).thenReturn(report); + when(pmdViolationToRuleViolation.toViolation(pmdViolation, sensorContext)).thenReturn(violation); + + pmdSensor.analyse(project, sensorContext); + + verify(sensorContext).saveViolation(violation); + } + + @Test + public void shouldnt_report_zero_violation() { + Report report = report(); + when(executor.execute()).thenReturn(report); + + pmdSensor.analyse(project, sensorContext); + + verifyZeroInteractions(sensorContext); + } + + @Test + public void shouldnt_report_invalid_violation() { + IRuleViolation pmdViolation = violation(); + Report report = report(pmdViolation); + when(executor.execute()).thenReturn(report); + when(report.iterator()).thenReturn(Iterators.forArray(pmdViolation)); + when(pmdViolationToRuleViolation.toViolation(pmdViolation, sensorContext)).thenReturn(null); + + pmdSensor.analyse(project, sensorContext); + + verifyZeroInteractions(sensorContext); + } + + static IRuleViolation violation() { + return mock(IRuleViolation.class); + } + + static Report report(IRuleViolation... violations) { + Report report = mock(Report.class); + when(report.iterator()).thenReturn(Iterators.forArray(violations)); + return report; + } +} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java new file mode 100644 index 00000000000..016fa3f02a6 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java @@ -0,0 +1,59 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import net.sourceforge.pmd.PMD; +import net.sourceforge.pmd.SourceType; +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +public class PmdTemplateTest { + PMD pmd = mock(PMD.class); + + @Test + public void should_set_java11_version() { + PmdTemplate.setJavaVersion(pmd, "1.1"); + + verify(pmd).setJavaVersion(SourceType.JAVA_13); + } + + @Test + public void should_set_java12_version() { + PmdTemplate.setJavaVersion(pmd, "1.2"); + + verify(pmd).setJavaVersion(SourceType.JAVA_13); + } + + @Test + public void should_set_java5_version() { + PmdTemplate.setJavaVersion(pmd, "5"); + + verify(pmd).setJavaVersion(SourceType.JAVA_15); + } + + @Test + public void should_set_java6_version() { + PmdTemplate.setJavaVersion(pmd, "6"); + + verify(pmd).setJavaVersion(SourceType.JAVA_16); + } +} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java new file mode 100644 index 00000000000..e0dc1d3d749 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java @@ -0,0 +1,71 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * Sonar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.plugins.pmd; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.XMLRuleParser; +import org.sonar.test.i18n.RuleRepositoryTestHelper; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class PmdUnitTestsRuleRepositoryTest { + PmdUnitTestsRuleRepository repository; + + @Before + public void setUpRuleRepository() { + repository = new PmdUnitTestsRuleRepository(new XMLRuleParser()); + } + + @Test + public void should_have_correct_name_and_key() { + assertThat(repository.getKey()).isEqualTo("pmd-unit-tests"); + assertThat(repository.getLanguage()).isEqualTo("java"); + assertThat(repository.getName()).isEqualTo("PMD Unit Tests"); + } + + @Test + public void should_load_repository_from_xml() { + List rules = repository.createRules(); + + assertThat(rules).onProperty("key").containsOnly( + "JUnitStaticSuite", + "JUnitSpelling", + "JUnitAssertionsShouldIncludeMessage", + "JUnitTestsShouldIncludeAssert", + "TestClassWithoutTestCases", + "UnnecessaryBooleanAssertion", + "UseAssertEqualsInsteadOfAssertTrue", + "UseAssertSameInsteadOfAssertTrue", + "UseAssertNullInsteadOfAssertTrue", + "SimplifyBooleanAssertion"); + } + + @Test + public void should_provide_a_name_and_description_for_each_rule() { + List rules = RuleRepositoryTestHelper.createRulesWithNameAndDescription("pmd", repository); + + assertThat(rules).onProperty("name").excludes(null, ""); + assertThat(rules).onProperty("description").excludes(null, ""); + } +} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java index f0426d6bdee..2b325d5e7e7 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java @@ -21,15 +21,11 @@ package org.sonar.plugins.pmd; import org.junit.Test; -import static junit.framework.Assert.assertEquals; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; +import static org.fest.assertions.Assertions.assertThat; public class PmdVersionTest { @Test - public void getCheckstyleVersion() { - assertThat(PmdVersion.getVersion().length(), greaterThan(1)); - assertEquals(PmdVersion.getVersion(), PmdVersion.getVersion()); + public void should_get_pmd_version() { + assertThat(PmdVersion.getVersion()).isNotEmpty().isSameAs(PmdVersion.getVersion()); } - } diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java deleted file mode 100644 index a56b0830383..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.pmd; - -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.profiles.ProfileDefinition; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.RuleQuery; -import org.sonar.api.utils.ValidationMessages; - -import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SonarWayProfileTest { - - @Test - public void shouldCreateProfile() { - ProfileDefinition sonarWay = new SonarWayProfile(createPmdProfileImporter()); - ValidationMessages validation = ValidationMessages.create(); - RulesProfile profile = sonarWay.createProfile(validation); - assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); - assertThat(validation.hasErrors(), is(false)); - } - - private PmdProfileImporter createPmdProfileImporter() { - - RuleFinder ruleFinder = mock(RuleFinder.class); - when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer() { - - public Rule answer(InvocationOnMock iom) throws Throwable { - RuleQuery query = (RuleQuery) iom.getArguments()[0]; - Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) - .setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER); - return rule; - } - }); - PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); - return importer; - } -} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java deleted file mode 100644 index 5c3b4d75a7c..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.pmd; - -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.RuleQuery; -import org.sonar.api.utils.ValidationMessages; - -import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SonarWayWithFindbugsProfileTest { - - @Test - public void shouldCreateProfile() { - SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(createPmdProfileImporter())); - ValidationMessages validation = ValidationMessages.create(); - RulesProfile profile = sonarWayWithFindbugs.createProfile(validation); - assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); - assertThat(validation.hasErrors(), is(false)); - } - - private PmdProfileImporter createPmdProfileImporter() { - - RuleFinder ruleFinder = mock(RuleFinder.class); - when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer() { - - public Rule answer(InvocationOnMock iom) throws Throwable { - RuleQuery query = (RuleQuery) iom.getArguments()[0]; - Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) - .setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER); - return rule; - } - }); - PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); - return importer; - } -} diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SunConventionsProfileTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SunConventionsProfileTest.java deleted file mode 100644 index 37065b395e1..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SunConventionsProfileTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * Sonar is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.plugins.pmd; - -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; -import org.sonar.api.profiles.RulesProfile; -import org.sonar.api.rules.Rule; -import org.sonar.api.rules.RuleFinder; -import org.sonar.api.rules.RulePriority; -import org.sonar.api.rules.RuleQuery; -import org.sonar.api.utils.ValidationMessages; - -import static org.hamcrest.core.Is.is; -import static org.hamcrest.number.OrderingComparisons.greaterThan; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class SunConventionsProfileTest { - @Test - public void shouldCreateProfile() { - SunConventionsProfile sunConvention = new SunConventionsProfile(createPmdProfileImporter()); - ValidationMessages validation = ValidationMessages.create(); - RulesProfile profile = sunConvention.createProfile(validation); - assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); - assertThat(validation.hasErrors(), is(false)); - } - - private PmdProfileImporter createPmdProfileImporter() { - - RuleFinder ruleFinder = mock(RuleFinder.class); - when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer() { - - public Rule answer(InvocationOnMock iom) throws Throwable { - RuleQuery query = (RuleQuery) iom.getArguments()[0]; - Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) - .setConfigKey(query.getConfigKey()).setSeverity(RulePriority.BLOCKER); - return rule; - } - }); - PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); - return importer; - } - -} diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml deleted file mode 100644 index 385ec10f124..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml +++ /dev/null @@ -1,22 +0,0 @@ - - 4.0.0 - fake.group - fake.artifactId - jar - 1.0-SNAPSHOT - - - true - - - - - - org.apache.maven.plugins - maven-pmd-plugin - - - - - \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml deleted file mode 100644 index 38a87b789e6..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - fake.group - fake.artifactId - jar - 1.0-SNAPSHOT - - - true - - - - - - org.apache.maven.plugins - maven-pmd-plugin - - - ruleset/maven.xml - ruleset/basic.xml - - - - - - \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml deleted file mode 100644 index b4e9f41a04c..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml +++ /dev/null @@ -1,8 +0,0 @@ - - 4.0.0 - fake.group - fake.artifactId - jar - 1.0-SNAPSHOT - \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml deleted file mode 100644 index 10a7f93fb6f..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml +++ /dev/null @@ -1,263 +0,0 @@ - - - - Sonar way - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 5 - - - 4 - - - 4 - - - 3 - - - 3 - - - 3 - - - 3 - - - 2 - - - 2 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 3 - - - 4 - - - 3 - - - 2 - - - 3 - - - 3 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 3 - - - 2 - - - 2 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 4 - - - 4 - - - 3 - - - 4 - - - 3 - - - 3 - - - - - - 3 - - - - - - 4 - - - 3 - - - 3 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 2 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java deleted file mode 100644 index 4eab1611997..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java +++ /dev/null @@ -1,9 +0,0 @@ -public class FirstClass { - - private FirstClass() { - int unused= new Integer(0); - if (true) { - unused += new Integer(12345); - } - } -} diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java deleted file mode 100644 index 3d2c603fffa..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java +++ /dev/null @@ -1,9 +0,0 @@ -public class SecondClass { - - private SecondClass() { - int unused= 0; - if (true) { - unused += 12345; - } - } -} diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml new file mode 100644 index 00000000000..f07fbeb4615 --- /dev/null +++ b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml @@ -0,0 +1,7 @@ + + + Sonar PMD Unit Tests rules + + 2 + + \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml b/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml deleted file mode 100644 index 39634039cfd..00000000000 --- a/plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - A test profile - - 2 - - - - - - 3 - - - - - - 4 - - \ No newline at end of file diff --git a/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java b/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java deleted file mode 100644 index 82169659624..00000000000 --- a/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java +++ /dev/null @@ -1,5 +0,0 @@ -public class DoesNotCompile { - - / not java / - Yeeaah ! -} diff --git a/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml b/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml deleted file mode 100644 index 10a7f93fb6f..00000000000 --- a/plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml +++ /dev/null @@ -1,263 +0,0 @@ - - - - Sonar way - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 5 - - - 4 - - - 4 - - - 3 - - - 3 - - - 3 - - - 3 - - - 2 - - - 2 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 2 - - - 3 - - - 2 - - - 3 - - - 3 - - - 4 - - - 3 - - - 2 - - - 3 - - - 3 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 3 - - - 2 - - - 2 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 4 - - - 4 - - - 3 - - - 4 - - - 3 - - - 3 - - - - - - 3 - - - - - - 4 - - - 3 - - - 3 - - - 3 - - - 4 - - - 3 - - - 3 - - - 3 - - - 2 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - - 3 - - \ No newline at end of file diff --git a/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java b/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java index 1dc992e0856..9c22c5ab0ff 100644 --- a/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java +++ b/sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java @@ -96,8 +96,8 @@ public final class DefaultPages { CoreMetrics.NEW_VIOLATIONS_KEY, CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY, CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY, CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY, CoreMetrics.NEW_MINOR_VIOLATIONS_KEY, CoreMetrics.NEW_INFO_VIOLATIONS_KEY, CoreMetrics.ACTIVE_REVIEWS_KEY, CoreMetrics.UNASSIGNED_REVIEWS_KEY, CoreMetrics.UNPLANNED_REVIEWS_KEY, CoreMetrics.FALSE_POSITIVE_REVIEWS_KEY, CoreMetrics.UNREVIEWED_VIOLATIONS_KEY, CoreMetrics.NEW_UNREVIEWED_VIOLATIONS_KEY}) - @ResourceQualifier({Qualifiers.VIEW, Qualifiers.SUBVIEW, Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.PACKAGE, Qualifiers.DIRECTORY, Qualifiers.FILE, Qualifiers.CLASS}) - /* all exept unit tests...*/ + @ResourceQualifier({Qualifiers.VIEW, Qualifiers.SUBVIEW, Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.PACKAGE, Qualifiers.DIRECTORY, Qualifiers.FILE, Qualifiers.CLASS, + Qualifiers.UNIT_TEST_FILE}) @UserRole(UserRole.CODEVIEWER) private static final class ViolationsTab implements RubyRailsPage { public String getTemplate() {