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