View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cpd;
5   
6   import java.io.File;
7   
8   import org.apache.commons.lang3.SystemUtils;
9   import org.junit.Assert;
10  import org.junit.Before;
11  import org.junit.Test;
12  
13  /**
14   * Unit test for {@link CPD}
15   */
16  public class CPDTest {
17  
18      private static final String BASE_TEST_RESOURCE_PATH = "target/test-classes/net/sourceforge/pmd/cpd/files/";
19      private CPD cpd;
20  
21      private boolean canTestSymLinks = false;
22  
23      @Before
24      public void setup() throws Exception {
25          CPDConfiguration theConfiguration = new CPDConfiguration(new String[] {"--language", "java",
26                  "--minimum-tokens", "10"});
27          cpd = new CPD(theConfiguration);
28  
29          // Symlinks are not well supported under Windows - so the tests are simply not executed here.
30          canTestSymLinks = SystemUtils.IS_OS_UNIX;
31          prepareSymLinks();
32  
33          if (!canTestSymLinks) {
34              System.err.println("*** Skipping unit tests with symlinks.");
35          }
36      }
37  
38      /**
39       * As java doesn't support symlinks in zip files, maven does not, too.
40       * So, we are creating the symlinks manually here before the test.
41       * @throws Exception any error
42       */
43      private void prepareSymLinks() throws Exception {
44          if (canTestSymLinks) {
45              Runtime runtime = Runtime.getRuntime();
46              if (!new File(BASE_TEST_RESOURCE_PATH, "symlink-for-real-file.txt").exists()) {
47                  runtime.exec(new String[] {"ln", "-s", "real-file.txt",
48                          BASE_TEST_RESOURCE_PATH + "symlink-for-real-file.txt"}).waitFor();
49              }
50              if (!new File(BASE_TEST_RESOURCE_PATH, "this-is-a-broken-sym-link-for-test").exists()) {
51                  runtime.exec(new String[] {"ln", "-s", "broken-sym-link",
52                          BASE_TEST_RESOURCE_PATH + "this-is-a-broken-sym-link-for-test"}).waitFor();
53              }
54          }
55      }
56  
57      /**
58       * A broken symlink (which is basically a not existing file), should be skipped.
59       * @throws Exception any error
60       */
61      @Test
62      public void testFileSectionWithBrokenSymlinks() throws Exception {
63          if (canTestSymLinks) {
64              NoFileAssertListener listener = new NoFileAssertListener(0);
65              cpd.setCpdListener(listener);
66  
67              cpd.add(new File(BASE_TEST_RESOURCE_PATH, "this-is-a-broken-sym-link-for-test"));
68              listener.verify();
69          }
70      }
71  
72      /**
73       * A file should be added only once - even if it was found twice, because of a sym link.
74       * @throws Exception any error
75       */
76      @Test
77      public void testFileAddedAsSymlinkAndReal() throws Exception {
78          if (canTestSymLinks) {
79              NoFileAssertListener listener = new NoFileAssertListener(1);
80              cpd.setCpdListener(listener);
81  
82              cpd.add(new File(BASE_TEST_RESOURCE_PATH, "real-file.txt"));
83              cpd.add(new File(BASE_TEST_RESOURCE_PATH, "symlink-for-real-file.txt"));
84              listener.verify();
85          }
86      }
87  
88      /**
89       * Add a file with a relative path - should still be added and not be detected as a sym link.
90       * @throws Exception any error
91       */
92      @Test
93      public void testFileAddedWithRelativePath() throws Exception {
94          NoFileAssertListener listener = new NoFileAssertListener(1);
95          cpd.setCpdListener(listener);
96  
97          cpd.add(new File("./" + BASE_TEST_RESOURCE_PATH, "real-file.txt"));
98          listener.verify();
99      }
100 
101     /**
102      * Simple listener that fails, if to many files were added and not skipped.
103      */
104     private static class NoFileAssertListener implements CPDListener {
105         private int expectedFilesCount;
106         private int files;
107         public NoFileAssertListener(int expectedFilesCount) {
108             this.expectedFilesCount = expectedFilesCount;
109             this.files = 0;
110         }
111         public void addedFile(int fileCount, File file) {
112             files++;
113             if (files > expectedFilesCount) {
114                 Assert.fail("File was added! - " + file);
115             }
116         }
117         public void phaseUpdate(int phase) {
118             // not needed for this test
119         }
120         public void verify() {
121             Assert.assertEquals("Expected " + expectedFilesCount + " files, but " + files + " have been added.",
122                     expectedFilesCount, files);
123         }
124     }
125 }