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("rulesets/java/basic.xml");
220         URL url2 = getClass().getClassLoader().getResource("rulesets/java/unusedcode.xml");
221         URL url3 = getClass().getClassLoader().getResource("rulesets/java/imports.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 =
233                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-basic.xml");
234         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
235 
236         generatedFile =
237                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-unusedcode.xml");
238         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
239 
240         generatedFile =
241                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-imports.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(str.contains("suppressiontype=\"nopmd\" msg=\"Avoid unused private fields such as 'unusedVar2'.\""));
428 
429         // check if there's a link to the JXR files
430         str = readFile(generatedReport);
431 
432         assertTrue(str.contains("/xref/def/configuration/AppSample.html#L27"));
433         // suppressed violation
434         assertTrue(str.contains("Avoid unused private fields such as 'unusedVar2'."));
435     }
436 
437     public void testSuppressMarkerConfigurationWithoutRendering() throws Exception {
438         File generatedReport =
439                 generateReport("pmd", "default-configuration/pmd-with-suppressMarker-no-render-plugin-config.xml");
440         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
441 
442         // check if the PMD files were generated
443         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
444         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
445 
446         String str = readFile(generatedFile);
447 
448         // check that there is no violation reported for "unusedVar2" - as it is suppressed
449         assertFalse(str.contains("Avoid unused private fields such as 'unusedVar2'.\n </violation>"));
450         // but it appears as suppressed
451         assertTrue(str.contains("suppressiontype=\"nopmd\" msg=\"Avoid unused private fields such as 'unusedVar2'.\""));
452 
453         // check if there's a link to the JXR files
454         str = readFile(generatedReport);
455 
456         assertTrue(str.contains("/xref/def/configuration/AppSample.html#L27"));
457         // suppressed violations are not rendered
458         assertFalse(str.contains("Avoid unused private fields such as 'unusedVar2'."));
459     }
460 
461     public void testJspConfiguration() throws Exception {
462         File generatedReport = generateReport("pmd", "default-configuration/jsp-configuration-plugin-config.xml");
463         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
464 
465         // check if the PMD files were generated
466         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
467         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
468 
469         // these are the rulesets, that have been applied...
470         generatedFile = new File(
471                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-bestpractices.xml");
472         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
473 
474         generatedFile =
475                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-codestyle.xml");
476         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
477 
478         generatedFile =
479                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-design.xml");
480         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
481 
482         generatedFile =
483                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/004-errorprone.xml");
484         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
485 
486         generatedFile =
487                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/005-security.xml");
488         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
489 
490         String str = readFile(generatedReport);
491         assertTrue(str.contains("JSP file should use UTF-8 encoding"));
492         assertTrue(str.contains("Using unsanitized JSP expression can lead to Cross Site Scripting (XSS) attacks"));
493         assertTrue(str.contains("Avoid having style information in JSP files."));
494     }
495 
496     public void testPMDProcessingError() throws Exception {
497         try {
498             generateReport("pmd", "processing-error/pmd-processing-error-plugin-config.xml");
499             fail("Expected exception");
500         } catch (RuntimeException e) {
501             assertTrue(e.getMessage().endsWith("Found 1 PMD processing errors"));
502         }
503     }
504 
505     public void testPMDProcessingErrorWithDetailsSkipped() throws Exception {
506         File generatedReport = generateReport("pmd", "processing-error/pmd-processing-error-skip-plugin-config.xml");
507         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
508 
509         String output = CapturingPrintStream.getOutput();
510         assertTrue(output.contains("There are 1 PMD processing errors:"));
511 
512         File generatedFile = new File(getBasedir(), "target/test/unit/parse-error/target/pmd.xml");
513         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
514         String str = readFile(generatedFile);
515         assertTrue(str.contains("Error while parsing"));
516         // The parse exception must be in the XML report
517         assertTrue(str.contains("ParseException: Encountered \"\" at line 23, column 5."));
518 
519         str = readFile(generatedReport);
520         // The parse exception must also be in the HTML report
521         assertTrue(str.contains("ParseException: Encountered \"\" at line 23, column 5."));
522     }
523 
524     public void testPMDProcessingErrorWithDetailsNoReport() throws Exception {
525         File generatedReport =
526                 generateReport("pmd", "processing-error/pmd-processing-error-no-report-plugin-config.xml");
527         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
528 
529         String output = CapturingPrintStream.getOutput();
530         assertTrue(output.contains("There are 1 PMD processing errors:"));
531 
532         File generatedFile = new File(getBasedir(), "target/test/unit/parse-error/target/pmd.xml");
533         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
534         String str = readFile(generatedFile);
535         assertTrue(str.contains("Error while parsing"));
536         // The parse exception must be in the XML report
537         assertTrue(str.contains("ParseException: Encountered \"\" at line 23, column 5."));
538 
539         str = readFile(generatedReport);
540         // The parse exception must NOT be in the HTML report, since reportProcessingErrors is false
541         assertFalse(str.contains("ParseException: Encountered \"\" at line 23, column 5."));
542     }
543 
544     public void testPMDExcludeRootsShouldExcludeSubdirectories() throws Exception {
545         generateReport("pmd", "exclude-roots/pmd-exclude-roots-plugin-config.xml");
546 
547         File generatedFile = new File(getBasedir(), "target/test/unit/exclude-roots/target/pmd.xml");
548         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
549         String str = readFile(generatedFile);
550 
551         assertTrue("Seems like all directories are excluded now", str.contains("ForLoopShouldBeWhileLoop"));
552         assertFalse(
553                 "Exclusion of an exact source directory not working", str.contains("OverrideBothEqualsAndHashcode"));
554         assertFalse(
555                 "Exclusion of basedirectory with subdirectories not working (MPMD-178)",
556                 str.contains("JumbledIncrementer"));
557     }
558 
559     public void testViolationExclusion() throws Exception {
560         generateReport("pmd", "default-configuration/pmd-report-pmd-exclusions-configuration-plugin-config.xml");
561 
562         File generatedFile = new File(getBasedir(), "target/test/unit/default-configuration/target/pmd.xml");
563         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
564         String str = readFile(generatedFile);
565 
566         assertEquals(0, StringUtils.countMatches(str, "<violation"));
567     }
568 
569     public void testCustomRenderer() throws MavenReportException {
570         final Renderer renderer = PmdExecutor.createRenderer("net.sourceforge.pmd.renderers.TextRenderer", "UTF-8");
571         assertNotNull(renderer);
572     }
573 
574     public void testCodeClimateRenderer() throws MavenReportException {
575         final Renderer renderer =
576                 PmdExecutor.createRenderer("net.sourceforge.pmd.renderers.CodeClimateRenderer", "UTF-8");
577         assertNotNull(renderer);
578     }
579 
580     public void testPmdReportCustomRulesNoExternalInfoUrl() throws Exception {
581         FileUtils.copyDirectoryStructure(
582                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
583                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
584 
585         File generatedReport = generateReport("pmd", "default-configuration/pmd-report-custom-rules.xml");
586         assertTrue(FileUtils.fileExists(generatedReport.getAbsolutePath()));
587 
588         String str = readFile(generatedReport);
589 
590         // custom rule without link
591         assertEquals(2, StringUtils.countMatches(str, "<td align=\"left\">CustomRule</td>"));
592         // standard rule with link
593         assertEquals(4, StringUtils.countMatches(str, "\">UnusedPrivateField</a></td>"));
594     }
595 
596     public void testPmdReportResolveRulesets() throws Exception {
597         int port = determineFreePort();
598         WireMockServer mockServer = new WireMockServer(port);
599         mockServer.start();
600 
601         String sonarRuleset = IOUtils.toString(
602                 getClass()
603                         .getClassLoader()
604                         .getResourceAsStream("unit/default-configuration/rulesets/sonar-way-ruleset.xml"),
605                 StandardCharsets.UTF_8);
606 
607         final String sonarProfileUrl = "/profiles/export?format=pmd&language=java&name=Sonar%2520way";
608         final String sonarExportRulesetUrl = "http://localhost:" + mockServer.port() + sonarProfileUrl;
609         final String myRulesetBaseUrl = "/config/my-ruleset.xml";
610         final String myRulesetUrl = "http://localhost:" + mockServer.port() + myRulesetBaseUrl;
611         final String notAInternalRulesetBaseUrl =
612                 "/projects/OURPROJECT/repos/ourproject-pmd/raw/InProgressRuleset.xml?at=refs%2Fheads%2Fmaster";
613         final String notAInternalRulesetUrl = "http://localhost:" + mockServer.port() + notAInternalRulesetBaseUrl;
614 
615         WireMock.configureFor("localhost", port);
616         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(sonarProfileUrl))
617                 .willReturn(WireMock.aResponse()
618                         .withStatus(200)
619                         .withHeader("Content-Type", "text/xml")
620                         .withBody(sonarRuleset)));
621         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(myRulesetBaseUrl))
622                 .willReturn(WireMock.aResponse()
623                         .withStatus(200)
624                         .withHeader("Content-Type", "text/xml")
625                         .withBody(sonarRuleset)));
626         WireMock.stubFor(WireMock.get(WireMock.urlEqualTo(notAInternalRulesetBaseUrl))
627                 .willReturn(WireMock.aResponse()
628                         .withStatus(200)
629                         .withHeader("Content-Type", "text/xml")
630                         .withBody(sonarRuleset)));
631 
632         FileUtils.copyDirectoryStructure(
633                 new File(getBasedir(), "src/test/resources/unit/default-configuration/jxr-files"),
634                 new File(getBasedir(), "target/test/unit/default-configuration/target/site"));
635 
636         File testPom =
637                 new File(getBasedir(), "src/test/resources/unit/default-configuration/pmd-report-resolve-rulesets.xml");
638         PmdReport mojo = (PmdReport) createReportMojo("pmd", testPom);
639         mojo.rulesets[3] = sonarExportRulesetUrl;
640         mojo.rulesets[4] = myRulesetUrl;
641         mojo.rulesets[5] = notAInternalRulesetUrl;
642         generateReport(mojo, testPom);
643 
644         // these are the rulesets, that have been copied to target/pmd/rulesets
645         File generatedFile = new File(
646                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/001-custom-rules.xml");
647         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
648 
649         generatedFile = new File(
650                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/002-bestpractices.xml");
651         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
652 
653         generatedFile = new File(
654                 getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/003-java-design.xml");
655         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
656 
657         generatedFile = new File(
658                 getBasedir(),
659                 "target/test/unit/default-configuration/target/pmd/rulesets/004-export_format_pmd_language_java_name_Sonar_2520way.xml");
660         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
661 
662         generatedFile =
663                 new File(getBasedir(), "target/test/unit/default-configuration/target/pmd/rulesets/005-my-ruleset.xml");
664         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
665 
666         generatedFile = new File(
667                 getBasedir(),
668                 "target/test/unit/default-configuration/target/pmd/rulesets/006-InProgressRuleset.xml_at_refs_2Fheads_2Fmaster.xml");
669         assertTrue(FileUtils.fileExists(generatedFile.getAbsolutePath()));
670 
671         mockServer.stop();
672     }
673 }