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