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.util.ArrayList;
27  import java.util.Iterator;
28  import java.util.List;
29  
30  import javax.xml.parsers.DocumentBuilder;
31  import javax.xml.parsers.DocumentBuilderFactory;
32  
33  import net.sourceforge.pmd.PMD;
34  import net.sourceforge.pmd.cpd.CPD;
35  import net.sourceforge.pmd.cpd.CPDConfiguration;
36  import net.sourceforge.pmd.cpd.JavaLanguage;
37  import net.sourceforge.pmd.cpd.Mark;
38  import net.sourceforge.pmd.cpd.Match;
39  import net.sourceforge.pmd.cpd.SourceCode;
40  import net.sourceforge.pmd.cpd.TokenEntry;
41  
42  import org.apache.commons.lang3.StringUtils;
43  import org.codehaus.plexus.util.FileUtils;
44  import org.w3c.dom.Document;
45  
46  /**
47   * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
48   * @version $Id$
49   */
50  public class CpdReportTest
51      extends AbstractPmdReportTest
52  {
53      /**
54       * {@inheritDoc}
55       */
56      @Override
57      protected void setUp()
58          throws Exception
59      {
60          super.setUp();
61          FileUtils.deleteDirectory( new File( getBasedir(), "target/test/unit" ) );
62      }
63  
64      /**
65       * Test CPDReport given the default configuration
66       *
67       * @throws Exception
68       */
69      public void testDefaultConfiguration()
70          throws Exception
71      {
72          File testPom =
73              new File( getBasedir(),
74                        "src/test/resources/unit/default-configuration/cpd-default-configuration-plugin-config.xml" );
75          CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
76          mojo.execute();
77  
78          // check if the CPD files were generated
79          File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
80          assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
81  
82          generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.html" );
83          renderer( mojo, generatedFile );
84          assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
85  
86          // check the contents of cpd.html
87          String str = readFile( new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.html" ) );
88          assertTrue( lowerCaseContains( str, "AppSample.java" ) );
89  
90          str = readFile( new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.html" ) );
91          assertTrue( lowerCaseContains( str, "App.java" ) );
92  
93          str = readFile( new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.html" ) );
94          assertTrue( lowerCaseContains( str, "public String dup( String str )" ) );
95  
96          str = readFile( new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.html" ) );
97          assertTrue( lowerCaseContains( str, "tmp = tmp + str.substring( i, i + 1);" ) );
98      }
99  
100     /**
101      * Test CPDReport using custom configuration
102      *
103      * @throws Exception
104      */
105     public void testCustomConfiguration()
106         throws Exception
107     {
108         File testPom =
109             new File( getBasedir(),
110                       "src/test/resources/unit/custom-configuration/cpd-custom-configuration-plugin-config.xml" );
111         CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
112         mojo.execute();
113 
114         // check if the CPD files were generated
115         File generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/cpd.csv" );
116         assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
117 
118         generatedFile = new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" );
119         renderer( mojo, generatedFile );
120         assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
121 
122         // Contents that should NOT be in the report
123         String str = readFile( new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" ) );
124         assertFalse( lowerCaseContains( str, "/Sample.java" ) );
125 
126         str = readFile( new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" ) );
127         assertFalse( lowerCaseContains( str, "public void duplicateMethod( int i )" ) );
128 
129         // Contents that should be in the report
130         str = readFile( new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" ) );
131         assertTrue( lowerCaseContains( str, "AnotherSample.java" ) );
132 
133         str = readFile( new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" ) );
134         assertTrue( lowerCaseContains( str, "public static void main( String[] args )" ) );
135 
136         str = readFile( new File( getBasedir(), "target/test/unit/custom-configuration/target/site/cpd.html" ) );
137         assertTrue( lowerCaseContains( str, "private String unusedMethod(" ) );
138     }
139 
140     /**
141      * Test CPDReport with invalid format
142      *
143      * @throws Exception
144      */
145     public void testInvalidFormat()
146         throws Exception
147     {
148         try
149         {
150             File testPom =
151                 new File( getBasedir(), "src/test/resources/unit/invalid-format/cpd-invalid-format-plugin-config.xml" );
152             CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
153             setVariableValueToObject( mojo, "compileSourceRoots", mojo.project.getCompileSourceRoots() );
154             mojo.execute();
155 
156             fail( "MavenReportException must be thrown" );
157         }
158         catch ( Exception e )
159         {
160             assertTrue( true );
161         }
162 
163     }
164 
165     /**
166      * Read the contents of the specified file object into a string
167      *
168      * @param file the file to be read
169      * @return a String object that contains the contents of the file
170      * @throws java.io.IOException
171      */
172     private String readFile( File file )
173         throws IOException
174     {
175         String strTmp;
176         StringBuilder str = new StringBuilder( (int) file.length() );
177         try ( BufferedReader in = new BufferedReader( new FileReader( file ) ) )
178         {
179             while ( ( strTmp = in.readLine() ) != null )
180             {
181                 str.append( ' ' );
182                 str.append( strTmp );
183             }
184         }
185 
186         return str.toString();
187     }
188 
189     private CPD prepareMockCpd( String duplicatedCodeFragment )
190     {
191         TokenEntry tFirstEntry = new TokenEntry( "public java", "MyClass.java", 2 );
192         TokenEntry tSecondEntry = new TokenEntry( "public java", "MyClass3.java", 2 );
193         SourceCode sourceCodeFirst = new SourceCode(new SourceCode.StringCodeLoader(
194                 PMD.EOL + duplicatedCodeFragment + PMD.EOL, "MyClass.java"));
195         SourceCode sourceCodeSecond = new SourceCode(new SourceCode.StringCodeLoader(
196                 PMD.EOL + duplicatedCodeFragment + PMD.EOL, "MyClass3.java"));
197 
198         List<Match> tList = new ArrayList<>();
199         Mark tFirstMark = new Mark( tFirstEntry );
200         tFirstMark.setSourceCode(sourceCodeFirst);
201         tFirstMark.setLineCount(1);
202         Mark tSecondMark = new Mark( tSecondEntry );
203         tSecondMark.setSourceCode(sourceCodeSecond);
204         tSecondMark.setLineCount(1);
205         Match tMatch = new Match( 2, tFirstMark, tSecondMark );
206         tList.add( tMatch );
207 
208         CPDConfiguration cpdConfiguration = new CPDConfiguration();
209         cpdConfiguration.setMinimumTileSize( 100 );
210         cpdConfiguration.setLanguage( new JavaLanguage() );
211         cpdConfiguration.setEncoding( "UTF-8" );
212         CPD tCpd = new MockCpd( cpdConfiguration, tList.iterator() );
213 
214         tCpd.go();
215         return tCpd;
216     }
217 
218     public void testWriteNonHtml()
219         throws Exception
220     {
221         File testPom =
222             new File( getBasedir(),
223                       "src/test/resources/unit/default-configuration/cpd-default-configuration-plugin-config.xml" );
224         CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
225         assertNotNull( mojo );
226 
227         String duplicatedCodeFragment = "// ----- duplicated code example -----";
228         CPD tCpd = prepareMockCpd( duplicatedCodeFragment );
229         mojo.writeNonHtml( tCpd );
230 
231         File tReport = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
232 
233         DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
234         Document pmdCpdDocument = builder.parse( tReport );
235         assertNotNull( pmdCpdDocument );
236 
237         String str = readFile( tReport );
238         assertTrue( lowerCaseContains( str, "MyClass.java" ) );
239         assertTrue( lowerCaseContains( str, "MyClass3.java" ) );
240         assertTrue( lowerCaseContains( str, duplicatedCodeFragment ) );
241     }
242 
243     /**
244      * verify the cpd.xml file is included in the site when requested.
245      * @throws Exception
246      */
247     public void testIncludeXmlInSite()
248             throws Exception
249     {
250         File testPom =
251                 new File( getBasedir(),
252                           "src/test/resources/unit/default-configuration/cpd-report-include-xml-in-site-plugin-config.xml" );
253         CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
254         assertNotNull( mojo );
255 
256         String duplicatedCodeFragment = "// ----- duplicated code example -----";
257         CPD tCpd = prepareMockCpd( duplicatedCodeFragment );
258         mojo.writeNonHtml( tCpd );
259 
260         File tReport = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
261         assertTrue( FileUtils.fileExists( tReport.getAbsolutePath() ) );
262 
263         DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
264         Document pmdCpdDocument = builder.parse( tReport );
265         assertNotNull( pmdCpdDocument );
266 
267         String str = readFile( tReport );
268         assertTrue( str.contains( "</pmd-cpd>" ) );
269 
270         File siteReport = new File( getBasedir(), "target/test/unit/default-configuration/target/site/cpd.xml" );
271         assertTrue( FileUtils.fileExists( siteReport.getAbsolutePath() ) );
272         String siteReportContent = readFile( siteReport );
273         assertTrue( siteReportContent.contains( "</pmd-cpd>" ) );
274     }
275 
276 
277     public void testSkipEmptyReportConfiguration()
278         throws Exception
279     {
280         File testPom =
281             new File( getBasedir(), "src/test/resources/unit/empty-report/cpd-skip-empty-report-plugin-config.xml" );
282         CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
283         mojo.execute();
284 
285         // verify the generated files do not exist because PMD was skipped
286         File generatedFile = new File( getBasedir(), "target/test/unit/empty-report/target/site/cpd.html" );
287         assertFalse( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
288     }
289 
290     public void testEmptyReportConfiguration()
291         throws Exception
292     {
293         File testPom =
294             new File( getBasedir(), "src/test/resources/unit/empty-report/cpd-empty-report-plugin-config.xml" );
295         CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
296         mojo.execute();
297 
298         // verify the generated files do exist, even if there are no violations
299         File generatedFile = new File( getBasedir(), "target/test/unit/empty-report/target/site/cpd.html" );
300         assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
301         String str = readFile( new File( getBasedir(), "target/test/unit/empty-report/target/site/cpd.html" ) );
302         assertFalse( lowerCaseContains( str, "Hello.java" ) );
303     }
304 
305     public void testCpdEncodingConfiguration()
306         throws Exception
307     {
308         String originalEncoding = System.getProperty( "file.encoding" );
309         try
310         {
311             System.setProperty( "file.encoding", "UTF-16" );
312 
313             File testPom =
314                 new File( getBasedir(),
315                           "src/test/resources/unit/default-configuration/cpd-default-configuration-plugin-config.xml" );
316             CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
317             mojo.execute();
318 
319             // check if the CPD files were generated
320             File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
321             assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
322             String str = readFile( generatedFile );
323             assertTrue( lowerCaseContains( str, "AppSample.java" ) );
324         }
325         finally
326         {
327             System.setProperty( "file.encoding", originalEncoding );
328         }
329     }
330 
331     public void testCpdJavascriptConfiguration()
332         throws Exception
333     {
334         File testPom =
335                 new File( getBasedir(), "src/test/resources/unit/default-configuration/cpd-javascript-plugin-config.xml" );
336             CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
337             mojo.execute();
338 
339             // verify  the generated file to exist and violations are reported
340             File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
341             assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
342             String str = readFile( generatedFile );
343             assertTrue( lowerCaseContains( str, "Sample.js" ) );
344             assertTrue( lowerCaseContains( str, "SampleDup.js" ) );
345     }
346 
347     public void testCpdJspConfiguration()
348             throws Exception
349     {
350         File testPom =
351                 new File( getBasedir(), "src/test/resources/unit/default-configuration/cpd-jsp-plugin-config.xml" );
352             CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
353             mojo.execute();
354 
355             // verify  the generated file to exist and violations are reported
356             File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
357             assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
358             String str = readFile( generatedFile );
359             assertTrue( lowerCaseContains( str, "sample.jsp" ) );
360             assertTrue( lowerCaseContains( str, "sampleDup.jsp" ) );
361     }
362 
363     public void testExclusionsConfiguration()
364             throws Exception
365     {
366         File testPom =
367             new File( getBasedir(),
368                       "src/test/resources/unit/default-configuration/cpd-report-cpd-exclusions-configuration-plugin-config.xml" );
369         final CpdReport mojo = (CpdReport) lookupMojo( "cpd", testPom );
370         mojo.execute();
371 
372         // verify  the generated file to exist and no duplications are reported
373         File generatedFile = new File( getBasedir(), "target/test/unit/default-configuration/target/cpd.xml" );
374         assertTrue( FileUtils.fileExists( generatedFile.getAbsolutePath() ) );
375         String str = readFile( generatedFile );
376         assertEquals( 0, StringUtils.countMatches( str, "<duplication" ) );
377     }
378 
379     public static class MockCpd
380         extends CPD
381     {
382 
383         private Iterator<Match> matches;
384 
385         public MockCpd( CPDConfiguration configuration, Iterator<Match> tMatch )
386         {
387             super( configuration );
388             matches = tMatch;
389         }
390 
391         @Override
392         public Iterator<Match> getMatches()
393         {
394             return matches;
395         }
396 
397     }
398 
399 }