]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR 1076 - Run PMD on Unit Tests
authorDavid Gageot <david@gageot.net>
Fri, 27 Apr 2012 12:45:13 +0000 (14:45 +0200)
committerDavid Gageot <david@gageot.net>
Fri, 27 Apr 2012 12:59:00 +0000 (14:59 +0200)
57 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ViolationsDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewViolationsDecorator.java
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd.properties
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitAssertionsShouldIncludeMessage.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitSpelling.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitStaticSuite.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/JUnitTestsShouldIncludeAssert.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/SimplifyBooleanAssertion.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/TestClassWithoutTestCases.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UnnecessaryBooleanAssertion.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertEqualsInsteadOfAssertTrue.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertNullInsteadOfAssertTrue.html [new file with mode: 0644]
plugins/sonar-l10n-en-plugin/src/main/resources/org/sonar/l10n/pmd/rules/pmd-unit-tests/UseAssertSameInsteadOfAssertTrue.html [new file with mode: 0644]
plugins/sonar-pmd-plugin/pom.xml
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/JavaCpdMapping.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConfiguration.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdConstants.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdExecutor.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdLevelUtils.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdPlugin.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdProfileExporter.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdSensor.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdTemplate.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepository.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdVersion.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdViolationToRuleViolation.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayProfile.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfile.java
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/SunConventionsProfile.java
plugins/sonar-pmd-plugin/src/main/resources/org/sonar/plugins/pmd/rules-unit-tests.xml [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdConfigurationTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdExecutorTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdLevelUtilsTest.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdPluginTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileImporterTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfilesTest.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdSensorTest.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdTemplateTest.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdUnitTestsRuleRepositoryTest.java [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdVersionTest.java
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayProfileTest.java [deleted file]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SonarWayWithFindbugsProfileTest.java [deleted file]
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/SunConventionsProfileTest.java [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/failIfConfigurationToReuseDoesNotExist/pom.xml [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/findConfigurationToReuse/pom.xml [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdConfigurationTest/writeConfigurationToWorkingDir/pom.xml [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/pmd.xml [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src1/FirstClass.java [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/PmdExecutorTest/executeOnManySourceDirs/src2/SecondClass.java [deleted file]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/junit.xml [new file with mode: 0644]
plugins/sonar-pmd-plugin/src/test/resources/org/sonar/plugins/pmd/test_xml_complete.xml [deleted file]
plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/DoesNotCompile.java [deleted file]
plugins/sonar-pmd-plugin/test-resources/ignorePmdFailures/pmd.xml [deleted file]
sonar-server/src/main/java/org/sonar/server/ui/DefaultPages.java

index eb4ade51a1832af8789c86e8ffd2277fbc6e5c70..2f16051638b8e92882e07ca6579320b7c2ea9890 100644 (file)
@@ -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
index 4cd71f04f5d9254c3692b7d71a5176b24574e466..18e10114331a4a35a08270f8f5ede1ee159f13aa 100644 (file)
@@ -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) {
index 6c780de2d15c37e3c25b6ff6604cacc611a8d1ab..167b7897d1eed4cace95690d88e4503cd65ca45e 100644 (file)
@@ -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 (file)
index 0000000..ec742d6
--- /dev/null
@@ -0,0 +1,8 @@
+JUnit assertions should include a message - i.e., use the three argument version of assertEquals(), not the two argument version.
+<pre>
+public class Foo extends TestCase {
+  public void testSomething() {
+    assertEquals("foo", "bar"); // violation, should be assertEquals("Foo does not equals bar", "foo", "bar");
+  }
+}
+</pre>
\ 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 (file)
index 0000000..48bdfb2
--- /dev/null
@@ -0,0 +1,9 @@
+Some JUnit framework methods are easy to misspell.
+<pre>
+import junit.framework.*;
+
+public class Foo extends TestCase {
+  public void setup() {} // violation, should be setUp()
+  public void TearDown() {} // violation, should be tearDown()
+}
+</pre>
\ 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 (file)
index 0000000..916d6de
--- /dev/null
@@ -0,0 +1,9 @@
+The suite() method in a JUnit test needs to be both public and static.
+<pre>
+import junit.framework.*;
+
+public class Foo extends TestCase {
+  public void suite() {} // violation, should be static
+  private static void suite() {} // violation, should be public
+}
+</pre>
\ 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 (file)
index 0000000..ad6b125
--- /dev/null
@@ -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.
+<pre>
+public class Foo extends TestCase {
+  public void testSomething() {
+    Bar b = findBar();
+    b.work();
+    // violation, we could use assertNotNull("bar not found", b);
+  }
+}
+</pre>
\ 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 (file)
index 0000000..093b4fc
--- /dev/null
@@ -0,0 +1,9 @@
+Avoid negation in an assertTrue or assertFalse test. For example, rephrase: assertTrue(!expr); as: assertFalse(expr);
+<pre>
+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())
+  }
+}
+</pre>
\ 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 (file)
index 0000000..891dde7
--- /dev/null
@@ -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.
+<pre>
+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
+  }
+}
+</pre>
\ 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 (file)
index 0000000..83356d4
--- /dev/null
@@ -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.
+<pre>
+public class SimpleTest extends TestCase {
+  public void testX() {
+    assertTrue(true); // violation
+  }
+}</pre>
\ 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 (file)
index 0000000..0887fb7
--- /dev/null
@@ -0,0 +1,10 @@
+This rule detects JUnit assertions in object equality. These assertions should be made by more specific methods, like assertEquals.
+<pre>
+public class FooTest extends TestCase {
+  void testCode() {
+    Object a, b;
+
+    assertTrue(a.equals(b)); // violation
+    assertEquals("a should equals b", a, b); // good usage
+  }
+}</pre>
\ 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 (file)
index 0000000..947ebd5
--- /dev/null
@@ -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.
+<pre>
+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
+  }
+}
+</pre>
\ 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 (file)
index 0000000..d2d317b
--- /dev/null
@@ -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.
+<pre>
+public class FooTest extends TestCase {
+  void testCode() {
+    Object a, b;
+
+    assertTrue(a==b); // violation
+    assertSame(a, b); // good usage
+  }
+}
+</pre>
\ No newline at end of file
index f947805fa8104cc4f1ebad0daff1d752862e2b2b..2215dc3700ad62659d18bd6459f97690d5b723e4 100644 (file)
       <artifactId>sonar-testing-harness</artifactId>
       <scope>test</scope>
     </dependency>
+
+    <dependency>
+      <groupId>org.codehaus.sonar.plugins</groupId>
+      <artifactId>sonar-l10n-en-plugin</artifactId>
+      <version>${project.version}</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
index 545a99c099a9de78c0fe188cdc7d6f0a58553de7..e4da4b06537ff10551e2ba9a233c5586eb119429 100644 (file)
  */
 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;
index 3485b970892af9f6ebd478033772d93256decbc3..c2331b8b7696ae5ea82e9ce4637a4e473cb1fae2 100644 (file)
  */
 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<String> 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();
   }
 }
index b7b7ea14f9b5102ea2bcc5eb102098013ba9cee6..613903da2e8c3fdc8e96d2f3019e0569f1e9bc9a 100644 (file)
@@ -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";
index 0f485f897efee4419a1d7f35d285b951cd0e7004..c0dd7de8a1eb24278dd0e1b3c51905a869589e01 100644 (file)
  */
 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<InputFile> 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<String> 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));
   }
 }
index 7a793037422bbdd807c7b1eb24eba677cec15cb7..dc56a9ca29ba5874b8ef6a73a3d8e08c1f559c96 100644 (file)
  */
 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<RulePriority, String> 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);
   }
 }
index dff7b9f85bca4401a14053a9af5f2fc3fe64b81c..5206ed9a54948ea6ffde936d7b2e48b7854bf165 100644 (file)
@@ -26,19 +26,20 @@ import org.sonar.api.SonarPlugin;
 import java.util.List;
 
 public class PmdPlugin extends SonarPlugin {
-
+  @SuppressWarnings("unchecked")
   public List<Class<? extends Extension>> 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);
   }
 }
index 83a4a648694197cba2f8a1f0ee64f301d5902002..d295f6b9c07917089bf70589a9f2e8ead03a1f46 100644 (file)
  */
 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<ActiveRule> 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<ActiveRule> 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<PmdProperty> properties = new ArrayList<PmdProperty>();
           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");
index 7b6ad0a876321f12e664df66bb1b9565cfdf2a33..3b91268754b2c9aa466a01f274393f795cc2cb62 100644 (file)
@@ -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);
index 2b406deb78746173b2decb7f31b8144fd0c6f8df..834679ba52e0ebed935dcbc2916eee687873ff4b 100644 (file)
@@ -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<IRuleViolation> 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<IRuleViolation> 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 (file)
index 0000000..c24d1fa
--- /dev/null
@@ -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<String, String> 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 (file)
index 0000000..c76c794
--- /dev/null
@@ -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<Rule> createRules() {
+    InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/rules-unit-tests.xml");
+    return xmlRuleParser.parse(input);
+  }
+}
index b4be1c627fa827f52794ff1b306e6bdfadb34621..abbb79a34e9bbc03ff254106ea7a7e7f117e291c 100644 (file)
@@ -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 (file)
index 0000000..f1d40db
--- /dev/null
@@ -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<File> 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();
+  }
+}
index ad340db9b83deb5139f7836573c2472930ce3a4b..b21d5d725a8e9223724dfa5f26190b631bb03b26 100644 (file)
  */
 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);
+    }
   }
 }
index 6a6d371620fc7eb16a2d55176ec74bbcb47a9242..f2553b80c9d5d64a36350cad04d2d3da33d7d7ea 100644 (file)
@@ -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;
   }
 }
-
index c4f869725c1375bfe007ec02753920dec18d6b6a..aa147db558692ebf92c8619bbb76b1be3b059ed7 100644 (file)
  */
 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 (file)
index 0000000..938bcf1
--- /dev/null
@@ -0,0 +1,42 @@
+<rules>
+  <rule key="JUnitStaticSuite">
+    <priority>MAJOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/JUnitStaticSuite]]></configKey>
+  </rule>
+  <rule key="JUnitSpelling">
+    <priority>MAJOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/JUnitSpelling]]></configKey>
+  </rule>
+  <rule key="JUnitAssertionsShouldIncludeMessage">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/JUnitAssertionsShouldIncludeMessage]]></configKey>
+  </rule>
+  <rule key="JUnitTestsShouldIncludeAssert">
+    <priority>MAJOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/JUnitTestsShouldIncludeAssert]]></configKey>
+  </rule>
+  <rule key="TestClassWithoutTestCases">
+    <priority>MAJOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/TestClassWithoutTestCases]]></configKey>
+  </rule>
+  <rule key="UnnecessaryBooleanAssertion">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/UnnecessaryBooleanAssertion]]></configKey>
+  </rule>
+  <rule key="UseAssertEqualsInsteadOfAssertTrue">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/UseAssertEqualsInsteadOfAssertTrue]]></configKey>
+  </rule>
+  <rule key="UseAssertSameInsteadOfAssertTrue">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/UseAssertSameInsteadOfAssertTrue]]></configKey>
+  </rule>
+  <rule key="UseAssertNullInsteadOfAssertTrue">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/UseAssertNullInsteadOfAssertTrue]]></configKey>
+  </rule>
+  <rule key="SimplifyBooleanAssertion">
+    <priority>MINOR</priority>
+    <configKey><![CDATA[rulesets/junit.xml/SimplifyBooleanAssertion]]></configKey>
+  </rule>
+</rules>
\ No newline at end of file
index 127cf94c85aa72ef9ab9103899c15a3fc90df6ba..1964f5c9538e3cba00e2db4ba00b6cb6fc6f7780 100644 (file)
  */
 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("<rules>", "pmd.xml")).thenReturn(new File("/workingDir/pmd.xml"));
 
-    PmdConfiguration configuration = new PmdConfiguration(new PmdProfileExporter(), RulesProfile.create(), project, null);
-    List<String> rulesets = configuration.getRulesets();
+    File rulesFile = configuration.dumpXmlRuleSet("pmd", "<rules>");
 
-    assertThat(rulesets.size(), is(1));
-    File xmlFile = new File(rulesets.get(0));
-    assertThat(xmlFile.exists(), is(true));
-    assertThat(FileUtils.readFileToString(xmlFile), is("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n<ruleset />\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("<xml>", "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", "<xml>");
+  }
+
+  @Test
+  public void should_dump_xml_report() throws IOException {
+    when(fs.writeToWorkingDirectory(matches(".*[\r\n]*<pmd.*[\r\n].*</pmd>"), 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);
+  }
 }
index a45a7426075fe563497c8257d310087fb7f09840..7da11466987883a49d2694fe0894fca7fa311177 100644 (file)
 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, "<file"), is(2));
-    assertThat(StringUtils.countMatches(xml, "<violation"), greaterThan(2));
+  public void should_execute_pmd_on_source_files_and_test_files() {
+    InputFile srcFile = file("src/Class.java");
+    InputFile tstFile = file("test/ClassTest.java");
+    when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
+    when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
+    when(projectFileSystem.getSourceCharset()).thenReturn(Charsets.UTF_8);
+    when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
+    when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Arrays.asList(tstFile));
+
+    Report report = pmdExecutor.execute();
+
+    verify(pmdTemplate).process(eq(new File("src/Class.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class));
+    verify(pmdTemplate).process(eq(new File("test/ClassTest.java")), eq(Charsets.UTF_8), any(RuleSets.class), any(RuleContext.class));
+    assertThat(report).isNotNull();
   }
 
   @Test
-  public void ignorePmdFailures() throws IOException {
-    final File workDir = temp.getRoot();
-    Project project = new Project("ignorePmdFailures");
-
-    ProjectFileSystem fs = mock(ProjectFileSystem.class);
-    when(fs.getSourceFiles(Java.INSTANCE)).thenReturn(Arrays.asList(new File("test-resources/ignorePmdFailures/DoesNotCompile.java")));
-    when(fs.getSourceCharset()).thenReturn(Charsets.UTF_8);
-    when(fs.getSonarWorkingDirectory()).thenReturn(workDir);
-    project.setFileSystem(fs);
-
-    PmdConfiguration conf = mock(PmdConfiguration.class);
-    when(conf.getRulesets()).thenReturn(Arrays.asList(new File("test-resources/ignorePmdFailures/pmd.xml").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));
+  public void should_dump_configuration_as_xml() {
+    when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
+    when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
+
+    Report report = pmdExecutor.execute();
+
+    verify(pmdConfiguration).dumpXmlReport(report);
   }
 
   @Test
-  public void shouldNormalizeJavaVersion() {
-    assertThat(PmdExecutor.getNormalizedJavaVersion(null), nullValue());
-    assertThat(PmdExecutor.getNormalizedJavaVersion(""), is(""));
-    assertThat(PmdExecutor.getNormalizedJavaVersion("1.1"), is("1.3"));
-    assertThat(PmdExecutor.getNormalizedJavaVersion("1.2"), is("1.3"));
-    assertThat(PmdExecutor.getNormalizedJavaVersion("1.4"), is("1.4"));
-    assertThat(PmdExecutor.getNormalizedJavaVersion("5"), is("1.5"));
-    assertThat(PmdExecutor.getNormalizedJavaVersion("6"), is("1.6"));
+  public void should_dump_ruleset_as_xml() {
+    InputFile srcFile = file("src/Class.java");
+    InputFile tstFile = file("test/ClassTest.java");
+    when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
+    when(pmdProfileExporter.exportProfile(PmdConstants.TEST_REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
+    when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
+    when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Arrays.asList(tstFile));
+
+    pmdExecutor.execute();
+
+    verify(pmdConfiguration).dumpXmlRuleSet(PmdConstants.REPOSITORY_KEY, TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
+    verify(pmdConfiguration).dumpXmlRuleSet(PmdConstants.TEST_REPOSITORY_KEY, TestUtils.getResourceContent("/org/sonar/plugins/pmd/junit.xml"));
   }
 
+  @Test
+  public void should_ignore_empty_test_dir() {
+    InputFile srcFile = file("src/Class.java");
+    doReturn(pmdTemplate).when(pmdExecutor).createPmdTemplate();
+    when(pmdProfileExporter.exportProfile(PmdConstants.REPOSITORY_KEY, rulesProfile)).thenReturn(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml"));
+    when(projectFileSystem.getSourceCharset()).thenReturn(Charsets.UTF_8);
+    when(projectFileSystem.mainFiles(Java.KEY)).thenReturn(Arrays.asList(srcFile));
+    when(projectFileSystem.testFiles(Java.KEY)).thenReturn(Collections.<InputFile> 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 (file)
index 0000000..2b4fad4
--- /dev/null
@@ -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");
+  }
+}
index 90c7e31cbf8c87656ca04ae27a26a2abc80147da..4a0902a4baeaefc0fd7c84dabee6b449f20991b0 100644 (file)
  */
 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<Class<? extends Extension>> extensions = plugin.getExtensions();
 
+    assertThat(extensions).contains(PmdRuleRepository.class, PmdUnitTestsRuleRepository.class);
+  }
 }
index 7dac4cc592e2fc1033e62a105cf669b1fe58472a..ab0044010af1de1b224497994e6bedb5b8c6c0fe 100644 (file)
  */
 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<Rule> 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?><ruleset />"));
   }
 
   @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<CharSequence> {
-    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<Rule> rules;
-
-    public FakeRuleFinder(List<Rule> 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<Rule> 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<Rule> rules) {
+    RuleFinder ruleFinder = mock(RuleFinder.class);
+    when(ruleFinder.find(any(RuleQuery.class))).then(new Answer<Rule>() {
+      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;
   }
 }
index 69c35da419c06774adac19a84313491c632da1f6..1920a5801401d960f0bb5bf0f3fa0b56958f1733 100644 (file)
@@ -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<Rule>() {
+  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<Rule>() {
+      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 (file)
index 0000000..b1c5f73
--- /dev/null
@@ -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<Rule>() {
+      public Rule answer(InvocationOnMock invocation) {
+        RuleQuery query = (RuleQuery) invocation.getArguments()[0];
+        return Rule.create(query.getRepositoryKey(), "", "");
+      }
+    });
+    return ruleFinder;
+  }
+}
index 64ad90b8bc4b947148d2a770c4c83088ec5a2f0b..036f5b487434a283c77108836b5f4d797729d465 100644 (file)
  */
 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<Rule> 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<Rule> 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<Rule> rules = repository.createRules();
+
+    assertThat(rules).onProperty("key").excludes("JUnitStaticSuite");
+  }
+
+  @Test
+  public void should_provide_a_name_and_description_for_each_rule() {
+    List<Rule> 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 (file)
index 0000000..50e7f46
--- /dev/null
@@ -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 (file)
index 0000000..016fa3f
--- /dev/null
@@ -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 (file)
index 0000000..e0dc1d3
--- /dev/null
@@ -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<Rule> 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<Rule> rules = RuleRepositoryTestHelper.createRulesWithNameAndDescription("pmd", repository);
+
+    assertThat(rules).onProperty("name").excludes(null, "");
+    assertThat(rules).onProperty("description").excludes(null, "");
+  }
+}
index f0426d6bdeea897516a358aaf37c5f37db09a14b..2b325d5e7e73d59f552f449c506123a6ea2cb3e0 100644 (file)
@@ -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 (file)
index a56b083..0000000
+++ /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<Rule>() {
-
-      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 (file)
index 5c3b4d7..0000000
+++ /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<Rule>() {
-
-      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 (file)
index 37065b3..0000000
+++ /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<Rule>() {
-
-      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 (file)
index 385ec10..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>fake.group</groupId>
-  <artifactId>fake.artifactId</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0-SNAPSHOT</version>
-
-  <properties>
-    <sonar.reuseExistingRulesConfiguration>true</sonar.reuseExistingRulesConfiguration>
-  </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-pmd-plugin</artifactId>
-        <!-- rulesets are not set in <configuration> -->
-      </plugin>
-    </plugins>
-  </build>
-</project>
\ 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 (file)
index 38a87b7..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>fake.group</groupId>
-  <artifactId>fake.artifactId</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0-SNAPSHOT</version>
-
-  <properties>
-    <sonar.reuseExistingRulesConfiguration>true</sonar.reuseExistingRulesConfiguration>
-  </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-pmd-plugin</artifactId>
-        <configuration>
-          <rulesets>
-            <ruleset>ruleset/maven.xml</ruleset>
-            <ruleset>ruleset/basic.xml</ruleset>
-          </rulesets>
-        </configuration>
-      </plugin>
-    </plugins>
-  </build>
-</project>
\ 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 (file)
index b4e9f41..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <groupId>fake.group</groupId>
-  <artifactId>fake.artifactId</artifactId>
-  <packaging>jar</packaging>
-  <version>1.0-SNAPSHOT</version>
-</project>
\ 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 (file)
index 10a7f93..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- generated by Sonar -->
-<ruleset>
-  <description>Sonar way</description>
-  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/AvoidCallingFinalize">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/FinalizeOverloaded">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/FinalizeDoesNotCallSuperFinalize">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/EmptyFinalizer">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/controversial.xml/UnusedModifier">
-    <priority>5</priority>
-  </rule>
-  <rule ref="rulesets/controversial.xml/DontImportSun">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/SingularField">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/coupling.xml/LooseCoupling">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/UseArrayListInsteadOfVector">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/UseArraysAsList">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/AvoidArrayLoops">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyIfStmt">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyWhileStmt">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyTryBlock">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyFinallyBlock">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptySwitchStatements">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptySynchronizedBlock">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyStaticInitializer">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UnconditionalIfStatement">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BooleanInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/CollapsibleIfStatements">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UselessOverridingMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/ClassCastExceptionWithToArray">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UselessOperationOnImmutable">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UnusedNullCheckInEquals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BrokenNullCheck">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BigIntegerInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/ConstructorCallsOverridableMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/FinalFieldCouldBeStatic">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/CloseResource">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/EqualsNull">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/InstantiationToGetClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/IdempotentOperations">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/MissingStaticMethodInNonInstantiatableClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/AvoidInstanceofChecksInCatchClause">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/SimplifyConditional">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/CompareObjectsWithEquals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/UnnecessaryLocalBeforeReturn">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/PreserveStackTrace">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/sunsecure.xml/ArrayIsStoredDirectly">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidCatchingThrowable">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/SignatureDeclareThrowsException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/ExceptionAsFlowControl">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidCatchingNPE">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidThrowingRawExceptionTypes">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidThrowingNullPointerException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidRethrowingException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/AvoidDuplicateLiterals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringToString">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/InefficientStringBuffering">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UnnecessaryCaseChange">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UseStringBufferLength">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UseIndexOfChar">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UselessStringValueOf">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringBufferInstantiationWithChar">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/codesize.xml/NcssMethodCount">
-    <priority>3</priority>
-    <properties>
-      <property name="minimum" value="50"/>
-    </properties>
-  </rule>
-  <rule ref="rulesets/codesize.xml/NcssTypeCount">
-    <priority>3</priority>
-    <properties>
-      <property name="minimum" value="800"/>
-    </properties>
-  </rule>
-  <rule ref="rulesets/imports.xml/DontImportJavaLang">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/clone.xml/CloneThrowsCloneNotSupportedException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-jakarta-commons.xml/UseCorrectExceptionLogging">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/ClassNamingConventions">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/AvoidDollarSigns">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/MethodWithSameNameAsEnclosingClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousHashcodeMethodName">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousConstantFieldName">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousEqualsMethodName">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceVectorWithList">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceHashtableWithMap">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceEnumerationWithIterator">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/AvoidEnumAsIdentifier">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/AvoidAssertAsIdentifier">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/IntegerInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-java.xml/SystemPrintln">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-java.xml/AvoidPrintStackTrace">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/IfStmtsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/WhileLoopsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/IfElseStmtsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/ForLoopsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-</ruleset>
\ 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 (file)
index 4eab161..0000000
+++ /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 (file)
index 3d2c603..0000000
+++ /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 (file)
index 0000000..f07fbeb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+    <description>Sonar PMD Unit Tests rules</description>
+    <rule ref="rulesets/junit.xml/SimplifyBooleanAssertion">
+        <priority>2</priority>
+    </rule>
+</ruleset>
\ 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 (file)
index 3963403..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Sonar PMD rules generated configuration -->
-<ruleset>
-    <description>A test profile</description>
-    <rule ref="rulesets/coupling.xml/CouplingBetweenObjects">
-        <priority>2</priority>
-        <properties>
-            <property name="threshold" value="20"/>
-        </properties>
-    </rule>
-    <rule ref="rulesets/coupling.xml/ExcessiveImports">
-        <priority>3</priority>
-        <properties>
-            <property name="max" value="30"/>
-        </properties>
-    </rule>
-    <rule ref="rulesets/design.xml/UseNotifyAllInsteadOfNotify">
-        <priority>4</priority>
-    </rule>
-</ruleset>
\ 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 (file)
index 8216965..0000000
+++ /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 (file)
index 10a7f93..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- generated by Sonar -->
-<ruleset>
-  <description>Sonar way</description>
-  <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/AvoidCallingFinalize">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedPrivateField">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/FinalizeOverloaded">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/FinalizeDoesNotCallSuperFinalize">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/finalizers.xml/EmptyFinalizer">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedPrivateMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/unusedcode.xml/UnusedFormalParameter">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/controversial.xml/UnusedModifier">
-    <priority>5</priority>
-  </rule>
-  <rule ref="rulesets/controversial.xml/DontImportSun">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/SingularField">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/coupling.xml/LooseCoupling">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/UseArrayListInsteadOfVector">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/UseArraysAsList">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/optimizations.xml/AvoidArrayLoops">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyIfStmt">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyWhileStmt">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyTryBlock">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyFinallyBlock">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptySwitchStatements">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptySynchronizedBlock">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/EmptyStaticInitializer">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UnconditionalIfStatement">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BooleanInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/CollapsibleIfStatements">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UselessOverridingMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/ClassCastExceptionWithToArray">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/AvoidDecimalLiteralsInBigDecimalConstructor">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UselessOperationOnImmutable">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/UnusedNullCheckInEquals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BrokenNullCheck">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/basic.xml/BigIntegerInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/ConstructorCallsOverridableMethod">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/FinalFieldCouldBeStatic">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/CloseResource">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/EqualsNull">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/InstantiationToGetClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/IdempotentOperations">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/MissingStaticMethodInNonInstantiatableClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/AvoidInstanceofChecksInCatchClause">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/SimplifyConditional">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/CompareObjectsWithEquals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/UnnecessaryLocalBeforeReturn">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/design.xml/PreserveStackTrace">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/sunsecure.xml/ArrayIsStoredDirectly">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidCatchingThrowable">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/SignatureDeclareThrowsException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/ExceptionAsFlowControl">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidCatchingNPE">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidThrowingRawExceptionTypes">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidThrowingNullPointerException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strictexception.xml/AvoidRethrowingException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/AvoidDuplicateLiterals">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringToString">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/InefficientStringBuffering">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UnnecessaryCaseChange">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UseStringBufferLength">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UseIndexOfChar">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/UselessStringValueOf">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/strings.xml/StringBufferInstantiationWithChar">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/codesize.xml/NcssMethodCount">
-    <priority>3</priority>
-    <properties>
-      <property name="minimum" value="50"/>
-    </properties>
-  </rule>
-  <rule ref="rulesets/codesize.xml/NcssTypeCount">
-    <priority>3</priority>
-    <properties>
-      <property name="minimum" value="800"/>
-    </properties>
-  </rule>
-  <rule ref="rulesets/imports.xml/DontImportJavaLang">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/clone.xml/CloneThrowsCloneNotSupportedException">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-jakarta-commons.xml/UseCorrectExceptionLogging">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/ClassNamingConventions">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/AvoidDollarSigns">
-    <priority>4</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/MethodWithSameNameAsEnclosingClass">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousHashcodeMethodName">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousConstantFieldName">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/naming.xml/SuspiciousEqualsMethodName">
-    <priority>2</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceVectorWithList">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceHashtableWithMap">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/ReplaceEnumerationWithIterator">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/AvoidEnumAsIdentifier">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/AvoidAssertAsIdentifier">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/migrating.xml/IntegerInstantiation">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-java.xml/SystemPrintln">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/logging-java.xml/AvoidPrintStackTrace">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/IfStmtsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/WhileLoopsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/IfElseStmtsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-  <rule ref="rulesets/braces.xml/ForLoopsMustUseBraces">
-    <priority>3</priority>
-  </rule>
-</ruleset>
\ No newline at end of file
index 1dc992e0856febb5419796b61672ee6387107dfb..9c22c5ab0ff114a2af76a5838de7ea138fa8e699 100644 (file)
@@ -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() {