1 package org.apache.maven.plugins.pmd;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23 import java.io.ByteArrayOutputStream;
24 import java.io.File;
25 import java.io.FileReader;
26 import java.io.IOException;
27 import java.io.PrintStream;
28 import java.net.ServerSocket;
29 import java.net.URL;
30 import java.nio.charset.StandardCharsets;
31 import java.util.Locale;
32
33 import org.apache.commons.io.IOUtils;
34 import org.apache.commons.lang3.StringUtils;
35 import org.codehaus.plexus.util.FileUtils;
36
37 import com.github.tomakehurst.wiremock.WireMockServer;
38 import com.github.tomakehurst.wiremock.client.WireMock;
39
40
41
42
43
44 public class PmdReportTest
45 extends AbstractPmdReportTest
46 {
47
48
49
50 @Override
51 protected void setUp()
52 throws Exception
53 {
54 super.setUp();
55 FileUtils.deleteDirectory( new File( getBasedir(), "target/test/unit" ) );
56 }
57
58 public void testDefaultConfiguration()
59 throws Exception
60 {
61 FileUtils.copyDirectoryStructure( new File( getBasedir(),
62 "src/test/resources/unit/default-configuration/jxr-files" ),
63 new File( getBasedir(), "target/test/unit/default-configuration/target/site" ) );
64
65 File testPom =
66 new File( getBasedir(),
67 "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml" );
68 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
69 mojo.execute();
70
71
72 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
73 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
74
75
76 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/maven-pmd-plugin-default.xml" );
77 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
78
79 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
80 renderer( mojo, generatedFile );
81 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
82
83
84 String str = readFile( generatedFile );
85
86 assertTrue( str.contains( "/xref/def/configuration/App.html#L31" ) );
87
88 assertTrue( str.contains( "/xref/def/configuration/AppSample.html#L45" ) );
89 }
90
91 public void testDefaultConfigurationWithAnalysisCache()
92 throws Exception
93 {
94 FileUtils.copyDirectoryStructure( new File( getBasedir(),
95 "src/test/resources/unit/default-configuration/jxr-files" ),
96 new File( getBasedir(), "target/test/unit/pmd-with-analysis-cache-plugin-config/target/site" ) );
97
98 File testPom =
99 new File( getBasedir(),
100 "src/test/resources/unit/default-configuration/pmd-with-analysis-cache-plugin-config.xml" );
101 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
102 mojo.execute();
103
104
105 File cacheFile = new File( getBasedir(), "target/test/unit/pmd-with-analysis-cache-plugin-config/target/pmd/pmd.cache" );
106 assertTrue( FileUtils.fileExists( cacheFile.getAbsolutePath() ) );
107 }
108
109 public void testJavascriptConfiguration()
110 throws Exception
111 {
112 File testPom =
113 new File( getBasedir(),
114 "src/test/resources/unit/default-configuration/javascript-configuration-plugin-config.xml" );
115 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
116 mojo.execute();
117
118
119 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
120 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
121
122
123 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/bestpractices.xml" );
124 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
125
126 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/codestyle.xml" );
127 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
128
129 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/errorprone.xml" );
130 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
131
132 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
133 renderer( mojo, generatedFile );
134 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
135
136 String str = readFile( generatedFile );
137 assertTrue( str.contains( "Avoid using global variables" ) );
138 }
139
140 public void testFileURL()
141 throws Exception
142 {
143 FileUtils.copyDirectoryStructure( new File( getBasedir(),
144 "src/test/resources/unit/default-configuration/jxr-files" ),
145 new File( getBasedir(), "target/test/unit/default-configuration/target/site" ) );
146
147 File testPom =
148 new File( getBasedir(),
149 "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml" );
150 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
151
152
153 int port = determineFreePort();
154 WireMockServer mockServer = new WireMockServer( port );
155 mockServer.start();
156
157 String sonarRuleset =
158 IOUtils.toString( getClass().getClassLoader().getResourceAsStream( "unit/default-configuration/rulesets/sonar-way-ruleset.xml" ),
159 StandardCharsets.UTF_8 );
160
161 String sonarMainPageHtml =
162 IOUtils.toString( getClass().getClassLoader().getResourceAsStream( "unit/default-configuration/rulesets/sonar-main-page.html" ),
163 StandardCharsets.UTF_8 );
164
165 final String sonarBaseUrl = "/profiles";
166 final String sonarProfileUrl = sonarBaseUrl + "/export?format=pmd&language=java&name=Sonar%2520way";
167 final String sonarExportRulesetUrl = "http://localhost:" + mockServer.port() + sonarProfileUrl;
168
169 mockServer.stubFor( WireMock.get( WireMock.urlEqualTo( sonarBaseUrl ) ).willReturn( WireMock.aResponse().withStatus( 200 ).withHeader( "Content-Type",
170 "text/html" ).withBody( sonarMainPageHtml ) ) );
171
172 mockServer.stubFor( WireMock.get( WireMock.urlEqualTo( sonarProfileUrl ) ).willReturn( WireMock.aResponse().withStatus( 200 ).withHeader( "Content-Type",
173 "text/xml" ).withBody( sonarRuleset ) ) );
174
175 URL url = getClass().getClassLoader().getResource( "rulesets/java/basic.xml" );
176 URL url2 = getClass().getClassLoader().getResource( "rulesets/java/unusedcode.xml" );
177 URL url3 = getClass().getClassLoader().getResource( "rulesets/java/imports.xml" );
178 mojo.setRulesets( new String[] { url.toString(), url2.toString(), url3.toString(), sonarExportRulesetUrl } );
179
180 mojo.execute();
181
182
183 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
184 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
185
186 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/basic.xml" );
187 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
188
189 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/imports.xml" );
190 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
191
192 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/unusedcode.xml" );
193 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
194
195 generatedFile =
196 new File( getBasedir(),
197 "target/test/unit/default-configuration/target/export_format_pmd_language_java_name_Sonar_2520way.xml" );
198 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
199
200 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
201 renderer( mojo, generatedFile );
202 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
203
204
205 String str = readFile( generatedFile );
206
207 assertTrue( str.contains( "/xref/def/configuration/App.html#L31" ) );
208
209 assertTrue( str.contains( "/xref/def/configuration/AppSample.html#L45" ) );
210
211 mockServer.stop();
212 }
213
214 private int determineFreePort()
215 {
216 try (ServerSocket socket = new ServerSocket(0)) {
217 return socket.getLocalPort();
218 } catch (IOException e) {
219 throw new RuntimeException( "Couldn't find a free port.", e );
220 }
221 }
222
223
224
225
226
227
228 public void testCustomConfiguration()
229 throws Exception
230 {
231 File testPom =
232 new File( getBasedir(),
233 "src/test/resources/unit/custom-configuration/custom-configuration-plugin-config.xml" );
234
235 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
236 mojo.execute();
237
238
239 File generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/pmd.csv" );
240 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
241
242 generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/custom.xml" );
243 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
244
245 generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/site/pmd.html" );
246 renderer( mojo, generatedFile );
247 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
248
249
250 String str = readFile( generatedFile );
251 assertTrue( lowerCaseContains( str, "Avoid using if statements without curly braces" ) );
252
253
254 assertFalse( lowerCaseContains( str, "Avoid using if...else statements without curly braces" ) );
255
256 assertFalse( "unnecessary constructor should not be triggered because of low priority",
257 lowerCaseContains( str, "Avoid unnecessary constructors - the compiler will generate these for you" ) );
258
259
260 assertTrue( lowerCaseContains( str, "veryLongVariableNameWithViolation" ) );
261
262 assertFalse( lowerCaseContains( str, "notSoLongVariableName" ) );
263 }
264
265
266
267
268
269
270 public void testSkipConfiguration()
271 throws Exception
272 {
273 File testPom = new File( getBasedir(), "src/test/resources/unit/custom-configuration/skip-plugin-config.xml" );
274 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
275 mojo.execute();
276
277
278 File generatedFile = new File( getBasedir(), "target/test/unit/skip-configuration/target/pmd.csv" );
279 assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
280
281 generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/custom.xml" );
282 assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
283
284 generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/site/pmd.html" );
285 assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
286 }
287
288 public void testSkipEmptyReportConfiguration()
289 throws Exception
290 {
291 File testPom =
292 new File( getBasedir(), "src/test/resources/unit/empty-report/skip-empty-report-plugin-config.xml" );
293 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
294 mojo.execute();
295
296
297 File generatedFile = new File( getBasedir(), "target/test/unit/empty-report/target/site/pmd.html" );
298 assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
299 }
300
301 public void testEmptyReportConfiguration()
302 throws Exception
303 {
304 File testPom = new File( getBasedir(), "src/test/resources/unit/empty-report/empty-report-plugin-config.xml" );
305 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
306 mojo.execute();
307
308
309 File generatedFile = new File( getBasedir(), "target/test/unit/empty-report/target/site/pmd.html" );
310 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
311 String str = readFile( generatedFile );
312 assertFalse( lowerCaseContains( str, "Hello.java" ) );
313 }
314
315 public void testInvalidFormat()
316 throws Exception
317 {
318 try
319 {
320 File testPom =
321 new File( getBasedir(), "src/test/resources/unit/invalid-format/invalid-format-plugin-config.xml" );
322 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
323 setVariableValueToObject( mojo, "compileSourceRoots", mojo.project.getCompileSourceRoots() );
324 mojo.executeReport( Locale.ENGLISH );
325
326 fail( "Must throw MavenReportException." );
327 }
328 catch ( Exception e )
329 {
330 assertTrue( true );
331 }
332 }
333
334 public void testInvalidTargetJdk()
335 throws Exception
336 {
337 try
338 {
339 File testPom =
340 new File( getBasedir(), "src/test/resources/unit/invalid-format/invalid-target-jdk-plugin-config.xml" );
341 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
342 mojo.execute();
343
344 fail( "Must throw MavenReportException." );
345 }
346 catch ( Exception e )
347 {
348 assertTrue( true );
349 }
350 }
351
352
353
354
355
356 public void testIncludeXmlInSite()
357 throws Exception
358 {
359 File testPom = new File( getBasedir(), "src/test/resources/unit/default-configuration/pmd-report-include-xml-in-site-plugin-config.xml" );
360 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
361 mojo.execute();
362
363 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
364 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
365
366 File generatedXmlFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.xml" );
367 assertTrue( FileUtils.fileExists( generatedXmlFile.getAbsolutePath() ) );
368
369 String pmdXmlTarget = readFile( new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" ) );
370 assertTrue( pmdXmlTarget.contains( "</pmd>" ) );
371
372
373 String pmdXml = readFile( generatedXmlFile );
374 assertTrue( pmdXml.contains( "</pmd>" ) );
375 }
376
377
378
379
380
381
382
383
384 private String readFile( File file )
385 throws IOException
386 {
387 try ( BufferedReader reader = new BufferedReader( new FileReader( file ) ) )
388 {
389 final StringBuilder str = new StringBuilder( (int) file.length() );
390
391 for ( String line = reader.readLine(); line != null; line = reader.readLine() )
392 {
393 str.append( ' ' );
394 str.append( line );
395 str.append( '\n' );
396 }
397 return str.toString();
398 }
399 }
400
401
402
403
404
405
406 public void testLocationTemp()
407 throws Exception
408 {
409
410 File testPom =
411 new File( getBasedir(),
412 "src/test/resources/unit/default-configuration/default-configuration-plugin-config.xml" );
413 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
414
415 assertEquals( "locationTemp is not correctly encoding filename",
416 "export_format_pmd_language_java_name_some_2520name.xml",
417 mojo.getLocationTemp( "http://nemo.sonarsource.org/sonar/profiles/export?format=pmd&language=java&name=some%2520name" ) );
418
419 }
420
421
422
423
424
425
426 public void testSuppressMarkerConfiguration()
427 throws Exception
428 {
429 File testPom =
430 new File( getBasedir(),
431 "src/test/resources/unit/default-configuration/pmd-with-suppressMarker-plugin-config.xml" );
432 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
433 mojo.execute();
434
435
436 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
437 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
438
439 String str = readFile( generatedFile );
440
441
442 assertFalse( str.contains( "Avoid unused private fields such as 'unusedVar2'." ) );
443 }
444
445 public void testJspConfiguration()
446 throws Exception
447 {
448 File testPom = new File( getBasedir(),
449 "src/test/resources/unit/default-configuration/jsp-configuration-plugin-config.xml" );
450 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
451 mojo.execute();
452
453
454 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
455 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
456
457
458 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/bestpractices.xml" );
459 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
460
461 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/codestyle.xml" );
462 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
463
464 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/design.xml" );
465 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
466
467 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/errorprone.xml" );
468 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
469
470 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/security.xml" );
471 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
472
473 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
474 renderer( mojo, generatedFile );
475 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
476
477 String str = readFile( generatedFile );
478 assertTrue(str.contains("JSP file should use UTF-8 encoding"));
479 assertTrue(str.contains("Using unsanitized JSP expression can lead to Cross Site Scripting (XSS) attacks"));
480 assertTrue(str.contains("Avoid having style information in JSP files."));
481 }
482
483 public void testPMDProcessingError()
484 throws Exception
485 {
486 File testPom = new File( getBasedir(),
487 "src/test/resources/unit/processing-error/pmd-processing-error-plugin-config.xml" );
488 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
489 try {
490 mojo.execute();
491 fail("Expected exception");
492 } catch (RuntimeException e) {
493 assertTrue( e.getMessage().endsWith( "Found 1 PMD processing errors" ) );
494 }
495 }
496
497 public void testPMDProcessingErrorWithDetailsSkipped()
498 throws Exception
499 {
500 File testPom = new File( getBasedir(),
501 "src/test/resources/unit/processing-error/pmd-processing-error-skip-plugin-config.xml" );
502 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
503
504 PrintStream originalOut = System.out;
505 ByteArrayOutputStream logging = new ByteArrayOutputStream();
506 System.setOut( new PrintStream( logging ) );
507
508 try {
509 mojo.execute();
510 String output = logging.toString();
511 assertTrue ( output.contains( "There are 1 PMD processing errors:" ) );
512
513 File generatedFile = new File( getBasedir(), "target/test/unit/parse-error/target/pmd.xml" );
514 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
515 String str = readFile( generatedFile );
516 assertTrue( str.contains( "Error while parsing" ) );
517
518 assertTrue( str.contains( "ParseException: Encountered \"\" at line 23, column 5." ) );
519
520 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
521 renderer( mojo, generatedFile );
522 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
523 str = readFile( generatedFile );
524
525 assertTrue( str.contains( "ParseException: Encountered \"\" at line 23, column 5." ) );
526
527 } finally {
528 System.setOut( originalOut );
529 System.out.println( logging.toString() );
530 }
531 }
532
533 public void testPMDProcessingErrorWithDetailsNoReport()
534 throws Exception
535 {
536 File testPom = new File( getBasedir(),
537 "src/test/resources/unit/processing-error/pmd-processing-error-no-report-plugin-config.xml" );
538 PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
539
540 PrintStream originalOut = System.out;
541 ByteArrayOutputStream logging = new ByteArrayOutputStream();
542 System.setOut( new PrintStream( logging ) );
543
544 try {
545 mojo.execute();
546 String output = logging.toString();
547 assertTrue ( output.contains( "There are 1 PMD processing errors:" ) );
548
549 File generatedFile = new File( getBasedir(), "target/test/unit/parse-error/target/pmd.xml" );
550 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
551 String str = readFile( generatedFile );
552 assertTrue( str.contains( "Error while parsing" ) );
553
554 assertTrue( str.contains( "ParseException: Encountered \"\" at line 23, column 5." ) );
555
556 generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/pmd.html" );
557 renderer( mojo, generatedFile );
558 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
559 str = readFile( generatedFile );
560
561 assertFalse( str.contains( "ParseException: Encountered \"\" at line 23, column 5." ) );
562
563 } finally {
564 System.setOut( originalOut );
565 System.out.println( logging.toString() );
566 }
567 }
568
569 public void testPMDExcludeRootsShouldExcludeSubdirectories() throws Exception {
570 File testPom = new File(getBasedir(), "src/test/resources/unit/exclude-roots/pmd-exclude-roots-plugin-config.xml");
571 PmdReport mojo = (PmdReport) lookupMojo ("pmd", testPom);
572 mojo.execute();
573
574 File generatedFile = new File( getBasedir(), "target/test/unit/exclude-roots/target/pmd.xml" );
575 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
576 String str = readFile( generatedFile );
577
578 assertTrue( "Seems like all directories are excluded now", str.contains("ForLoopShouldBeWhileLoop") );
579 assertFalse( "Exclusion of an exact source directory not working", str.contains( "OverrideBothEqualsAndHashcode" ) );
580 assertFalse( "Exclusion of basedirectory with subdirectories not working (MPMD-178)", str.contains( "JumbledIncrementer") );
581 }
582
583 public void testViolationExclusion()
584 throws Exception
585 {
586 File testPom =
587 new File( getBasedir(),
588 "src/test/resources/unit/default-configuration/pmd-report-pmd-exclusions-configuration-plugin-config.xml" );
589 final PmdReport mojo = (PmdReport) lookupMojo( "pmd", testPom );
590 mojo.execute();
591
592 File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/pmd.xml" );
593 assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
594 String str = readFile( generatedFile );
595
596 assertEquals(0, StringUtils.countMatches(str, "<violation"));
597 }
598 }