View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.pmd;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.net.ServerSocket;
24  import java.net.URL;
25  import java.nio.charset.StandardCharsets;
26  import java.util.Locale;
27  
28  import com.github.tomakehurst.wiremock.WireMockServer;
29  import com.github.tomakehurst.wiremock.client.WireMock;
30  import net.sourceforge.pmd.renderers.Renderer;
31  import org.apache.commons.io.IOUtils;
32  import org.apache.commons.lang3.StringUtils;
33  import org.apache.maven.plugins.pmd.exec.PmdExecutor;
34  import org.apache.maven.reporting.MavenReportException;
35  import org.codehaus.plexus.util.FileUtils;
36  
37  /**
38   * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
39   * @version $Id$
40   */
41  public class PmdReportTest extends AbstractPmdReportTestCase {
42  
43      /**
44       * {@inheritDoc}
45       */
46      @Override
47      protected void setUp() throws Exception {
48          super.setUp();
49          Locale.setDefault(Locale.ENGLISH);
50          FileUtils.deleteDirectory(new File(getBasedir(), "target/test/unit"));
51      }
52  
53      public void testDefaultConfiguration() throws Exception {
54          FileUtils.copyDirectoryStructure(
55                  new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
56                  new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
57  
58          File generatedReport = generateReport("pmd", "default-configuration/default-configuration-plugin-config.xml");
59          assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
60  
61          // check if the PMD files were generated
62          File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
63          assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
64  
65          // check if the rulesets, that have been applied, have been copied
66          generatedFile = new File(
67                  getBasedir(),
68                  "target/test/unit/default-configuration/target/pmd/rulesets/001-maven-pmd-plugin-default.xml");
69          assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
70  
71          // check if there's a link to the JXR files
72          String str = readFile(generatedReport);
73  
74          assertTrue(str.contains("/xref/def/configuration/App.html#L31"));
75  
76          assertTrue(str.contains("/xref/def/configuration/AppSample.html#L45"));
77  
78          // check if there's a priority column
79          assertTrue(str.contains("<th>Priority</th>"));
80  
81          // there should be a rule column
82          assertTrue(str.contains("<th>Rule</th>"));
83          // along with a link to the rule
84          assertTrue(str.contains("pmd_rules_java_bestpractices.html#unusedprivatefield\">UnusedPrivateField</a>"));
85  
86          // there should be the section Violations By Priority
87          assertTrue(str.contains("Violations By Priority</h3>"));
88          assertTrue(str.contains("Priority 3</h4>"));
89          assertTrue(str.contains("Priority 4</h4>"));
90          // the file App.java is mentioned 3 times: in prio 3, in prio 4 and in the files section
91          assertEquals(3, StringUtils.countMatches(str, "def/configuration/App.java"));
92  
93          // there must be no warnings (like deprecated rules) in the log output
94          String output = CapturingPrintStream.getOutput();
95          assertFalse(output.contains("deprecated Rule name"));
96          assertFalse(output.contains("Discontinue using Rule name"));
97          assertFalse(output.contains("is referenced multiple times"));
98  
99          // the version should be logged
100         assertTrue(output.contains("PMD version: " + AbstractPmdReport.getPmdVersion()));
101     }
102 
103     public void testDefaultConfigurationNotRenderRuleViolationPriority() throws Exception {
104         FileUtils.copyDirectoryStructure(
105                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
106                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
107 
108         File generatedReport =
109                 generateReport("pmd", "default-configuration/pmd-report-not-render-rule-priority-plugin-config.xml");
110         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
111 
112         String str = readFile(generatedReport);
113 
114         // check that there's no priority column
115         assertFalse(str.contains("<th>Priority</th>"));
116     }
117 
118     public void testDefaultConfigurationNoRenderViolationsByPriority() throws Exception {
119         FileUtils.copyDirectoryStructure(
120                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
121                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
122 
123         File generatedReport =
124                 generateReport("pmd", "default-configuration/pmd-report-no-render-violations-by-priority.xml");
125         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
126 
127         String str = readFile(generatedReport);
128 
129         // there should be no section Violations By Priority
130         assertFalse(str.contains("Violations By Priority</h2>"));
131         assertFalse(str.contains("Priority 3</h3>"));
132         assertFalse(str.contains("Priority 4</h3>"));
133         // the file App.java is mentioned once: in the files section
134         assertEquals(1, StringUtils.countMatches(str, "def/configuration/App.java"));
135     }
136 
137     public void testDefaultConfigurationWithAnalysisCache() throws Exception {
138         FileUtils.copyDirectoryStructure(
139                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
140                 new File(getBasedir(), "target/test/unit/pmd-with-analysis-cache-plugin-config/target/site"));
141 
142         generateReport("pmd", "default-configuration/pmd-with-analysis-cache-plugin-config.xml");
143 
144         // check if the PMD analysis cache file has been generated
145         File cacheFile =
146                 new File(getBasedir(), "target/test/unit/pmd-with-analysis-cache-plugin-config/target/pmd/pmd.cache");
147         assertTrue(FileUtils.fileExists(cacheFile.getAbsolutePath()));
148     }
149 
150     public void testJavascriptConfiguration() throws Exception {
151         File generatedReport =
152                 generateReport("pmd", "default-configuration/javascript-configuration-plugin-config.xml");
153         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
154 
155         // check if the PMD files were generated
156         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
157         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
158 
159         // these are the rulesets, that have been applied...
160         generatedFile = new File(
161                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-bestpractices.xml");
162         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
163 
164         generatedFile =
165                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-codestyle.xml");
166         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
167 
168         generatedFile =
169                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-errorprone.xml");
170         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
171 
172         String str = readFile(generatedReport);
173         assertTrue(str.contains("Avoid using global variables"));
174     }
175 
176     public void testFileURL() throws Exception {
177         FileUtils.copyDirectoryStructure(
178                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
179                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
180 
181         File testPom = new File(
182                 getBasedir(), "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml");
183         PmdReport mojo = (PmdReport) createReportMojo("pmd", testPom);
184 
185         // Additional test case for MPMD-174 (https://issues.apache.org/jira/browse/MPMD-174).
186         int port = determineFreePort();
187         WireMockServer mockServer = new WireMockServer(port);
188         mockServer.start();
189 
190         String sonarRuleset = IOUtils.toString(
191                 getClass()
192                         .getClassLoader()
193                         .getResourceAsStream("unit/default-configuration/rulesets/sonar-way-ruleset.xml"),
194                 StandardCharsets.UTF_8);
195 
196         String sonarMainPageHtml = IOUtils.toString(
197                 getClass()
198                         .getClassLoader()
199                         .getResourceAsStream("unit/default-configuration/rulesets/sonar-main-page.html"),
200                 StandardCharsets.UTF_8);
201 
202         final String sonarBaseUrl = "/profiles";
203         final String sonarProfileUrl = sonarBaseUrl + "/export?format=pmd&language=java&name=Sonar%2520way";
204         final String sonarExportRulesetUrl = "http://localhost:" + mockServer.port() + sonarProfileUrl;
205 
206         WireMock.configureFor("localhost", port);
207         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(sonarBaseUrl))
208                 .willReturn(WireMock.aResponse()
209                         .withStatus(200)
210                         .withHeader("Content-Type", "text/html")
211                         .withBody(sonarMainPageHtml)));
212 
213         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(sonarProfileUrl))
214                 .willReturn(WireMock.aResponse()
215                         .withStatus(200)
216                         .withHeader("Content-Type", "text/xml")
217                         .withBody(sonarRuleset)));
218 
219         URL url = getClass().getClassLoader().getResource("category/java/bestpractices.xml");
220         URL url2 = getClass().getClassLoader().getResource("category/java/codestyle.xml");
221         URL url3 = getClass().getClassLoader().getResource("category/java/errorprone.xml");
222         mojo.setRulesets(new String[] {url.toString(), url2.toString(), url3.toString(), sonarExportRulesetUrl});
223 
224         File generatedReport = generateReport(mojo, testPom);
225         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
226 
227         // check if the PMD files were generated
228         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
229         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
230 
231         // the resolved and extracted rulesets
232         generatedFile = new File(
233                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-bestpractices.xml");
234         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
235 
236         generatedFile =
237                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-codestyle.xml");
238         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
239 
240         generatedFile =
241                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-errorprone.xml");
242         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
243 
244         generatedFile = new File(
245                 getBasedir(),
246                 "target/test/unit/default-configuration/target/pmd/rulesets/004-export_format_pmd_language_java_name_Sonar_2520way.xml");
247         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
248 
249         // check if there's a link to the JXR files
250         String str = readFile(generatedReport);
251 
252         assertTrue(str.contains("/xref/def/configuration/App.html#L31"));
253 
254         assertTrue(str.contains("/xref/def/configuration/AppSample.html#L45"));
255 
256         mockServer.stop();
257     }
258 
259     private int determineFreePort() {
260         try (ServerSocket socket = new ServerSocket(0)) {
261             return socket.getLocalPort();
262         } catch (IOException e) {
263             throw new RuntimeException("Couldn't find a free port.", e);
264         }
265     }
266 
267     /**
268      * With custom rulesets
269      *
270      * @throws Exception
271      */
272     public void testCustomConfiguration() throws Exception {
273         File generatedReport = generateReport("pmd", "custom-configuration/custom-configuration-plugin-config.xml");
274         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
275 
276         // check the generated files
277         File generatedFile = new File(getBasedir(), "target/test/unit/custom-configuration/target/pmd.csv");
278         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
279 
280         // 001-maven-pmd-plugin-default.xml is also generated, so we get 002-custom.xml
281         generatedFile =
282                 new File(getBasedir(), "target/test/unit/custom-configuration/target/pmd/rulesets/002-custom.xml");
283         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
284 
285         // check if custom ruleset was applied
286         String str = readFile(generatedReport);
287 
288         // codestyle.xml/ControlStatementBraces:
289         assertTrue(lowerCaseContains(str, "This statement should have braces"));
290 
291         // Must be false as codestyle.xml/ControlStatementBraces with checkIfElseStmt=false is used
292         assertFalse(lowerCaseContains(str, "Avoid using if...else statements without curly braces"));
293 
294         assertFalse(
295                 "unnecessary constructor should not be triggered because of low priority",
296                 lowerCaseContains(str, "Avoid unnecessary constructors - the compiler will generate these for you"));
297 
298         // veryLongVariableNameWithViolation is really too long
299         assertTrue(lowerCaseContains(str, "veryLongVariableNameWithViolation"));
300         // notSoLongVariableName should not be reported
301         assertFalse(lowerCaseContains(str, "notSoLongVariableName"));
302     }
303 
304     /**
305      * Verify skip parameter
306      *
307      * @throws Exception
308      */
309     public void testSkipConfiguration() throws Exception {
310         File generatedReport = generateReport("pmd", "custom-configuration/skip-plugin-config.xml");
311         assertFalse(FileUtils.fileExists(generatedReport.getAbsolutePath()));
312 
313         // verify the generated files do not exist because PMD was skipped
314         File generatedFile = new File(getBasedir(), "target/test/unit/skip-configuration/target/pmd.csv");
315         assertFalse(FileUtils.fileExists(generatedFile.getAbsolutePath()));
316 
317         generatedFile = new File(getBasedir(), "target/test/unit/custom-configuration/target/custom.xml");
318         assertFalse(FileUtils.fileExists(generatedFile.getAbsolutePath()));
319 
320         // the fact, the PMD execution has been skipped, should be logged
321         String output = CapturingPrintStream.getOutput();
322         assertTrue(output.contains("Skipping PMD execution"));
323     }
324 
325     public void testSkipEmptyReportConfiguration() throws Exception {
326         // verify the generated files do not exist because PMD was skipped
327         File generatedReport = generateReport("pmd", "empty-report/skip-empty-report-plugin-config.xml");
328         assertFalse(FileUtils.fileExists(generatedReport.getAbsolutePath()));
329     }
330 
331     public void testEmptyReportConfiguration() throws Exception {
332         File generatedReport = generateReport("pmd", "empty-report/empty-report-plugin-config.xml");
333         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
334 
335         // verify the generated files do exist, even if there are no violations
336         String str = readFile(generatedReport);
337         assertFalse(lowerCaseContains(str, "Hello.java"));
338         assertEquals(1, StringUtils.countMatches(str, "PMD found no problems in your source code."));
339         // no sections files or violations by priority
340         assertFalse(str.contains("Files</h2>"));
341         assertFalse(str.contains("Violations By Priority</h2>"));
342     }
343 
344     public void testInvalidFormat() throws Exception {
345         try {
346             File testPom =
347                     new File(getBasedir(), "src/test/resources/unit/invalid-format/invalid-format-plugin-config.xml");
348             AbstractPmdReport mojo = createReportMojo("pmd", testPom);
349             setVariableValueToObject(
350                     mojo, "compileSourceRoots", mojo.getProject().getCompileSourceRoots());
351             generateReport(mojo, testPom);
352 
353             fail("Must throw MavenReportException.");
354         } catch (Exception e) {
355             assertTrue(true);
356         }
357     }
358 
359     public void testInvalidTargetJdk() throws Exception {
360         try {
361             generateReport("pmd", "empty-report/invalid-format/invalid-target-jdk-plugin-config.xml");
362 
363             fail("Must throw MavenReportException.");
364         } catch (Exception e) {
365             assertTrue(true);
366         }
367     }
368 
369     /**
370      * verify the pmd.xml file is included in the site when requested.
371      * @throws Exception
372      */
373     public void testIncludeXmlInSite() throws Exception {
374         File generatedReport =
375                 generateReport("pmd", "default-configuration/pmd-report-include-xml-in-site-plugin-config.xml");
376         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
377 
378         // verify the pmd file is included in site
379         File generatedXmlFile = new File(getBasedir(), "target/test/unit/default-configuration/target/site/pmd.xml");
380         assertTrue(FileUtils.fileExists(generatedXmlFile.getAbsolutePath()));
381 
382         String pmdXmlTarget = readFile(new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml"));
383         assertTrue(pmdXmlTarget.contains("</pmd>"));
384 
385         // check that pmd.xml file has the closing element
386         String pmdXml = readFile(generatedXmlFile);
387         assertTrue(pmdXml.contains("</pmd>"));
388     }
389 
390     /**
391      * Verify the correct working of the locationTemp method
392      *
393      * @throws Exception
394      */
395     public void testLocationTemp() throws Exception {
396 
397         File testPom = new File(
398                 getBasedir(), "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml");
399         PmdReport mojo = (PmdReport) lookupMojo("pmd", testPom);
400 
401         assertEquals(
402                 "locationTemp is not correctly encoding filename",
403                 "001-export_format_pmd_language_java_name_some_2520name.xml",
404                 mojo.getLocationTemp(
405                         "http://nemo.sonarsource.org/sonar/profiles/export?format=pmd&language=java&name=some%2520name",
406                         1));
407     }
408 
409     /**
410      * Verify that suppressMarker works
411      *
412      * @throws Exception
413      */
414     public void testSuppressMarkerConfiguration() throws Exception {
415         File generatedReport = generateReport("pmd", "default-configuration/pmd-with-suppressMarker-plugin-config.xml");
416         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
417 
418         // check if the PMD files were generated
419         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
420         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
421 
422         String str = readFile(generatedFile);
423 
424         // check that there is no violation reported for "unusedVar2" - as it is suppressed
425         assertFalse(str.contains("Avoid unused private fields such as 'unusedVar2'.\n </violation>"));
426         // but it appears as suppressed
427         assertTrue(
428                 str.contains("suppressiontype=\"//nopmd\" msg=\"Avoid unused private fields such as 'unusedVar2'.\""));
429 
430         // check if there's a link to the JXR files
431         str = readFile(generatedReport);
432 
433         assertTrue(str.contains("/xref/def/configuration/AppSample.html#L27"));
434         // suppressed violation
435         assertTrue(str.contains("Avoid unused private fields such as 'unusedVar2'."));
436     }
437 
438     public void testSuppressMarkerConfigurationWithoutRendering() throws Exception {
439         File generatedReport =
440                 generateReport("pmd", "default-configuration/pmd-with-suppressMarker-no-render-plugin-config.xml");
441         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
442 
443         // check if the PMD files were generated
444         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
445         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
446 
447         String str = readFile(generatedFile);
448 
449         // check that there is no violation reported for "unusedVar2" - as it is suppressed
450         assertFalse(str.contains("Avoid unused private fields such as 'unusedVar2'.\n </violation>"));
451         // but it appears as suppressed
452         assertTrue(
453                 str.contains("suppressiontype=\"//nopmd\" msg=\"Avoid unused private fields such as 'unusedVar2'.\""));
454 
455         // check if there's a link to the JXR files
456         str = readFile(generatedReport);
457 
458         assertTrue(str.contains("/xref/def/configuration/AppSample.html#L27"));
459         // suppressed violations are not rendered
460         assertFalse(str.contains("Avoid unused private fields such as 'unusedVar2'."));
461     }
462 
463     public void testJspConfiguration() throws Exception {
464         File generatedReport = generateReport("pmd", "default-configuration/jsp-configuration-plugin-config.xml");
465         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
466 
467         // check if the PMD files were generated
468         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
469         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
470 
471         // these are the rulesets, that have been applied...
472         generatedFile = new File(
473                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-bestpractices.xml");
474         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
475 
476         generatedFile =
477                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-codestyle.xml");
478         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
479 
480         generatedFile =
481                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-design.xml");
482         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
483 
484         generatedFile =
485                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/004-errorprone.xml");
486         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
487 
488         generatedFile =
489                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/005-security.xml");
490         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
491 
492         String str = readFile(generatedReport);
493         assertTrue(str.contains("JSP file should use UTF-8 encoding"));
494         assertTrue(str.contains("Using unsanitized JSP expression can lead to Cross Site Scripting (XSS) attacks"));
495         assertTrue(str.contains("Avoid having style information in JSP files."));
496     }
497 
498     public void testPMDProcessingError() throws Exception {
499         try {
500             generateReport("pmd", "processing-error/pmd-processing-error-plugin-config.xml");
501             fail("Expected exception");
502         } catch (RuntimeException e) {
503             assertTrue(e.getMessage().endsWith("Found 1 PMD processing errors"));
504         }
505     }
506 
507     public void testPMDProcessingErrorWithDetailsSkipped() throws Exception {
508         File generatedReport = generateReport("pmd", "processing-error/pmd-processing-error-skip-plugin-config.xml");
509         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
510 
511         String output = CapturingPrintStream.getOutput();
512         assertTrue(output.contains("There are 1 PMD processing errors:"));
513 
514         File generatedFile = new File(getBasedir(), "target/test/unit/parse-error/target/pmd.xml");
515         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
516         String str = readFile(generatedFile);
517         assertTrue(str.contains("ParseException:"));
518         // The parse exception must be in the XML report
519         assertTrue(str.contains("at line 23, column 5: Encountered"));
520 
521         str = readFile(generatedReport);
522         // The parse exception must also be in the HTML report
523         assertTrue(str.contains("ParseException:"));
524         assertTrue(str.contains("at line 23, column 5: Encountered"));
525     }
526 
527     public void testPMDProcessingErrorWithDetailsNoReport() throws Exception {
528         File generatedReport =
529                 generateReport("pmd", "processing-error/pmd-processing-error-no-report-plugin-config.xml");
530         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
531 
532         String output = CapturingPrintStream.getOutput();
533         assertTrue(output.contains("There are 1 PMD processing errors:"));
534 
535         File generatedFile = new File(getBasedir(), "target/test/unit/parse-error/target/pmd.xml");
536         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
537         String str = readFile(generatedFile);
538         // The parse exception must be in the XML report
539         assertTrue(str.contains("ParseException:"));
540         assertTrue(str.contains("at line 23, column 5: Encountered"));
541 
542         str = readFile(generatedReport);
543         // The parse exception must NOT be in the HTML report, since reportProcessingErrors is false
544         assertFalse(str.contains("ParseException:"));
545         assertFalse(str.contains("at line 23, column 5: Encountered"));
546     }
547 
548     public void testPMDExcludeRootsShouldExcludeSubdirectories() throws Exception {
549         generateReport("pmd", "exclude-roots/pmd-exclude-roots-plugin-config.xml");
550 
551         File generatedFile = new File(getBasedir(), "target/test/unit/exclude-roots/target/pmd.xml");
552         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
553         String str = readFile(generatedFile);
554 
555         assertTrue("Seems like all directories are excluded now", str.contains("ForLoopShouldBeWhileLoop"));
556         assertFalse(
557                 "Exclusion of an exact source directory not working", str.contains("OverrideBothEqualsAndHashcode"));
558         assertFalse(
559                 "Exclusion of basedirectory with subdirectories not working (MPMD-178)",
560                 str.contains("JumbledIncrementer"));
561     }
562 
563     public void testViolationExclusion() throws Exception {
564         generateReport("pmd", "default-configuration/pmd-report-pmd-exclusions-configuration-plugin-config.xml");
565 
566         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
567         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
568         String str = readFile(generatedFile);
569 
570         assertEquals(0, StringUtils.countMatches(str, "<violation"));
571     }
572 
573     public void testCustomRenderer() throws MavenReportException {
574         final Renderer renderer = PmdExecutor.createRenderer("net.sourceforge.pmd.renderers.TextRenderer", "UTF-8");
575         assertNotNull(renderer);
576     }
577 
578     public void testCodeClimateRenderer() throws MavenReportException {
579         final Renderer renderer =
580                 PmdExecutor.createRenderer("net.sourceforge.pmd.renderers.CodeClimateRenderer", "UTF-8");
581         assertNotNull(renderer);
582     }
583 
584     public void testPmdReportCustomRulesNoExternalInfoUrl() throws Exception {
585         FileUtils.copyDirectoryStructure(
586                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
587                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
588 
589         File generatedReport = generateReport("pmd", "default-configuration/pmd-report-custom-rules.xml");
590         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
591 
592         String str = readFile(generatedReport);
593 
594         // custom rule without link
595         assertEquals(2, StringUtils.countMatches(str, "<td align=\"left\">CustomRule</td>"));
596         // standard rule with link
597         assertEquals(4, StringUtils.countMatches(str, "\">UnusedPrivateField</a></td>"));
598     }
599 
600     public void testPmdReportResolveRulesets() throws Exception {
601         int port = determineFreePort();
602         WireMockServer mockServer = new WireMockServer(port);
603         mockServer.start();
604 
605         String sonarRuleset = IOUtils.toString(
606                 getClass()
607                         .getClassLoader()
608                         .getResourceAsStream("unit/default-configuration/rulesets/sonar-way-ruleset.xml"),
609                 StandardCharsets.UTF_8);
610 
611         final String sonarProfileUrl = "/profiles/export?format=pmd&language=java&name=Sonar%2520way";
612         final String sonarExportRulesetUrl = "http://localhost:" + mockServer.port() + sonarProfileUrl;
613         final String myRulesetBaseUrl = "/config/my-ruleset.xml";
614         final String myRulesetUrl = "http://localhost:" + mockServer.port() + myRulesetBaseUrl;
615         final String notAInternalRulesetBaseUrl =
616                 "/projects/OURPROJECT/repos/ourproject-pmd/raw/InProgressRuleset.xml?at=refs%2Fheads%2Fmaster";
617         final String notAInternalRulesetUrl = "http://localhost:" + mockServer.port() + notAInternalRulesetBaseUrl;
618 
619         WireMock.configureFor("localhost", port);
620         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(sonarProfileUrl))
621                 .willReturn(WireMock.aResponse()
622                         .withStatus(200)
623                         .withHeader("Content-Type", "text/xml")
624                         .withBody(sonarRuleset)));
625         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(myRulesetBaseUrl))
626                 .willReturn(WireMock.aResponse()
627                         .withStatus(200)
628                         .withHeader("Content-Type", "text/xml")
629                         .withBody(sonarRuleset)));
630         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(notAInternalRulesetBaseUrl))
631                 .willReturn(WireMock.aResponse()
632                         .withStatus(200)
633                         .withHeader("Content-Type", "text/xml")
634                         .withBody(sonarRuleset)));
635 
636         FileUtils.copyDirectoryStructure(
637                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
638                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
639 
640         File testPom =
641                 new File(getBasedir(), "src/test/resources/unit/default-configuration/pmd-report-resolve-rulesets.xml");
642         PmdReport mojo = (PmdReport) createReportMojo("pmd", testPom);
643         mojo.rulesets[3] = sonarExportRulesetUrl;
644         mojo.rulesets[4] = myRulesetUrl;
645         mojo.rulesets[5] = notAInternalRulesetUrl;
646         generateReport(mojo, testPom);
647 
648         // these are the rulesets, that have been copied to target/pmd/rulesets
649         File generatedFile = new File(
650                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-custom-rules.xml");
651         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
652 
653         generatedFile = new File(
654                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-bestpractices.xml");
655         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
656 
657         generatedFile =
658                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-design.xml");
659         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
660 
661         generatedFile = new File(
662                 getBasedir(),
663                 "target/test/unit/default-configuration/target/pmd/rulesets/004-export_format_pmd_language_java_name_Sonar_2520way.xml");
664         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
665 
666         generatedFile =
667                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/005-my-ruleset.xml");
668         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
669 
670         generatedFile = new File(
671                 getBasedir(),
672                 "target/test/unit/default-configuration/target/pmd/rulesets/006-InProgressRuleset.xml_at_refs_2Fheads_2Fmaster.xml");
673         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
674 
675         mockServer.stop();
676     }
677 }