You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CpdAnalyserTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Sonar, open source software quality management tool.
  3. * Copyright (C) 2008-2011 SonarSource
  4. * mailto:contact AT sonarsource DOT com
  5. *
  6. * Sonar is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * Sonar is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Sonar; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
  19. */
  20. package org.sonar.plugins.cpd;
  21. import static org.mockito.Matchers.anyList;
  22. import static org.mockito.Matchers.anyObject;
  23. import static org.mockito.Matchers.argThat;
  24. import static org.mockito.Matchers.eq;
  25. import static org.mockito.Mockito.atLeastOnce;
  26. import static org.mockito.Mockito.mock;
  27. import static org.mockito.Mockito.verify;
  28. import static org.mockito.Mockito.when;
  29. import java.io.File;
  30. import java.util.Arrays;
  31. import java.util.Collections;
  32. import java.util.LinkedHashSet;
  33. import java.util.Set;
  34. import net.sourceforge.pmd.cpd.TokenEntry;
  35. import org.junit.Test;
  36. import org.sonar.api.batch.CpdMapping;
  37. import org.sonar.api.batch.SensorContext;
  38. import org.sonar.api.measures.CoreMetrics;
  39. import org.sonar.api.resources.JavaFile;
  40. import org.sonar.api.resources.Project;
  41. import org.sonar.api.resources.ProjectFileSystem;
  42. import org.sonar.api.resources.Resource;
  43. import org.sonar.api.test.IsMeasure;
  44. import org.sonar.duplications.cpd.Match;
  45. public class CpdAnalyserTest {
  46. @Test
  47. public void testOneSimpleDuplicationBetweenTwoFiles() throws Exception {
  48. ProjectFileSystem fileSystem = mock(ProjectFileSystem.class);
  49. when(fileSystem.getSourceDirs()).thenReturn(Collections.<File> emptyList());
  50. File file1 = new File("target/tmp/file1.ext");
  51. File file2 = new File("target/tmp/file2.ext");
  52. Project project = new Project("key").setFileSystem(fileSystem);
  53. SensorContext context = mock(SensorContext.class);
  54. CpdMapping cpdMapping = mock(CpdMapping.class);
  55. Resource resource1 = new JavaFile("foo.Foo");
  56. Resource resource2 = new JavaFile("foo.Bar");
  57. when(cpdMapping.createResource((File) anyObject(), anyList())).thenReturn(resource1).thenReturn(resource2).thenReturn(resource2)
  58. .thenReturn(resource1);
  59. when(context.saveResource(resource1)).thenReturn("key1");
  60. when(context.saveResource(resource2)).thenReturn("key2");
  61. Match match1 = new Match(5, new TokenEntry(null, file1.getAbsolutePath(), 5), new TokenEntry(null, file2.getAbsolutePath(), 15));
  62. match1.setLineCount(200);
  63. CpdAnalyser cpdAnalyser = new CpdAnalyser(project, context, cpdMapping);
  64. cpdAnalyser.analyse(Arrays.asList(match1).iterator());
  65. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_FILES, 1d);
  66. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  67. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_LINES, 200d);
  68. verify(context).saveMeasure(
  69. eq(resource1),
  70. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  71. + "<duplication lines=\"200\" start=\"5\" target-start=\"15\" target-resource=\"key2\"/>" + "</duplications>")));
  72. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_FILES, 1d);
  73. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_LINES, 200d);
  74. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  75. verify(context).saveMeasure(
  76. eq(resource2),
  77. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA,
  78. "<duplications><duplication lines=\"200\" start=\"15\" target-start=\"5\" target-resource=\"key1\"/></duplications>")));
  79. verify(context, atLeastOnce()).saveResource(resource1);
  80. verify(context, atLeastOnce()).saveResource(resource2);
  81. }
  82. @Test
  83. public void testClassicalCaseWithTwoDuplicatedBlocsInvolvingThreeFiles() throws Exception {
  84. ProjectFileSystem fileSystem = mock(ProjectFileSystem.class);
  85. when(fileSystem.getSourceDirs()).thenReturn(Collections.<File> emptyList());
  86. File file1 = new File("target/tmp/file1.ext");
  87. File file2 = new File("target/tmp/file2.ext");
  88. File file3 = new File("target/tmp/file3.ext");
  89. Project project = new Project("key").setFileSystem(fileSystem);
  90. SensorContext context = mock(SensorContext.class);
  91. CpdMapping cpdMapping = mock(CpdMapping.class);
  92. Resource resource1 = new JavaFile("foo.Foo");
  93. Resource resource2 = new JavaFile("foo.Bar");
  94. Resource resource3 = new JavaFile("foo.Hotel");
  95. when(cpdMapping.createResource((File) anyObject(), anyList())).thenReturn(resource1).thenReturn(resource2).thenReturn(resource2)
  96. .thenReturn(resource1).thenReturn(resource1).thenReturn(resource3).thenReturn(resource3).thenReturn(resource1);
  97. when(context.saveResource(resource1)).thenReturn("key1");
  98. when(context.saveResource(resource2)).thenReturn("key2");
  99. when(context.saveResource(resource3)).thenReturn("key3");
  100. Match match1 = new Match(5, new TokenEntry(null, file1.getAbsolutePath(), 5), new TokenEntry(null, file2.getAbsolutePath(), 15));
  101. match1.setLineCount(200);
  102. Match match2 = new Match(5, new TokenEntry(null, file1.getAbsolutePath(), 5), new TokenEntry(null, file3.getAbsolutePath(), 15));
  103. match2.setLineCount(100);
  104. CpdAnalyser cpdAnalyser = new CpdAnalyser(project, context, cpdMapping);
  105. cpdAnalyser.analyse(Arrays.asList(match1, match2).iterator());
  106. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_FILES, 1d);
  107. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_BLOCKS, 2d);
  108. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_LINES, 200d);
  109. verify(context).saveMeasure(
  110. eq(resource1),
  111. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  112. + "<duplication lines=\"100\" start=\"5\" target-start=\"15\" target-resource=\"key3\"/>"
  113. + "<duplication lines=\"200\" start=\"5\" target-start=\"15\" target-resource=\"key2\"/>"
  114. + "</duplications>")));
  115. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_FILES, 1d);
  116. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_LINES, 200d);
  117. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  118. verify(context).saveMeasure(
  119. eq(resource2),
  120. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA,
  121. "<duplications><duplication lines=\"200\" start=\"15\" target-start=\"5\" target-resource=\"key1\"/></duplications>")));
  122. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_FILES, 1d);
  123. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_LINES, 100d);
  124. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  125. verify(context).saveMeasure(
  126. eq(resource3),
  127. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA,
  128. "<duplications><duplication lines=\"100\" start=\"15\" target-start=\"5\" target-resource=\"key1\"/></duplications>")));
  129. verify(context, atLeastOnce()).saveResource(resource1);
  130. verify(context, atLeastOnce()).saveResource(resource2);
  131. verify(context, atLeastOnce()).saveResource(resource3);
  132. }
  133. @Test
  134. public void testOneDuplicatedBlocInvolvingMoreThanTwoFiles() throws Exception {
  135. ProjectFileSystem fileSystem = mock(ProjectFileSystem.class);
  136. when(fileSystem.getSourceDirs()).thenReturn(Collections.<File> emptyList());
  137. File file1 = new File("target/tmp/file1.ext");
  138. File file2 = new File("target/tmp/file2.ext");
  139. File file3 = new File("target/tmp/file3.ext");
  140. File file4 = new File("target/tmp/file4.ext");
  141. Project project = new Project("key").setFileSystem(fileSystem);
  142. SensorContext context = mock(SensorContext.class);
  143. CpdMapping cpdMapping = mock(CpdMapping.class);
  144. Resource resource1 = new JavaFile("foo.Foo");
  145. Resource resource2 = new JavaFile("foo.Bar");
  146. Resource resource3 = new JavaFile("foo.Hotel");
  147. Resource resource4 = new JavaFile("foo.Coffee");
  148. when(cpdMapping.createResource((File) anyObject(), anyList())).thenReturn(resource1).thenReturn(resource2).thenReturn(resource3)
  149. .thenReturn(resource4).thenReturn(resource2).thenReturn(resource1).thenReturn(resource3).thenReturn(resource4)
  150. .thenReturn(resource3).thenReturn(resource1).thenReturn(resource2).thenReturn(resource4).thenReturn(resource4)
  151. .thenReturn(resource1).thenReturn(resource2).thenReturn(resource3);
  152. when(context.saveResource(resource1)).thenReturn("key1");
  153. when(context.saveResource(resource2)).thenReturn("key2");
  154. when(context.saveResource(resource3)).thenReturn("key3");
  155. when(context.saveResource(resource4)).thenReturn("key4");
  156. Match match = new Match(5, createTokenEntry(file1.getAbsolutePath(), 5), createTokenEntry(file2.getAbsolutePath(), 15));
  157. match.setLineCount(200);
  158. Set<TokenEntry> tokenEntries = new LinkedHashSet<TokenEntry>();
  159. tokenEntries.add(createTokenEntry(file1.getAbsolutePath(), 5));
  160. tokenEntries.add(createTokenEntry(file2.getAbsolutePath(), 15));
  161. tokenEntries.add(createTokenEntry(file3.getAbsolutePath(), 7));
  162. tokenEntries.add(createTokenEntry(file4.getAbsolutePath(), 10));
  163. match.setMarkSet(tokenEntries);
  164. CpdAnalyser cpdAnalyser = new CpdAnalyser(project, context, cpdMapping);
  165. cpdAnalyser.analyse(Arrays.asList(match).iterator());
  166. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_FILES, 1d);
  167. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  168. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_LINES, 200d);
  169. verify(context).saveMeasure(
  170. eq(resource1),
  171. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  172. + "<duplication lines=\"200\" start=\"5\" target-start=\"15\" target-resource=\"key2\"/>"
  173. + "<duplication lines=\"200\" start=\"5\" target-start=\"7\" target-resource=\"key3\"/>"
  174. + "<duplication lines=\"200\" start=\"5\" target-start=\"10\" target-resource=\"key4\"/>" + "</duplications>")));
  175. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_FILES, 1d);
  176. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_LINES, 200d);
  177. verify(context).saveMeasure(resource3, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  178. verify(context).saveMeasure(
  179. eq(resource2),
  180. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  181. + "<duplication lines=\"200\" start=\"15\" target-start=\"5\" target-resource=\"key1\"/>"
  182. + "<duplication lines=\"200\" start=\"15\" target-start=\"7\" target-resource=\"key3\"/>"
  183. + "<duplication lines=\"200\" start=\"15\" target-start=\"10\" target-resource=\"key4\"/>" + "</duplications>")));
  184. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_FILES, 1d);
  185. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_LINES, 200d);
  186. verify(context).saveMeasure(resource2, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  187. verify(context).saveMeasure(
  188. eq(resource3),
  189. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  190. + "<duplication lines=\"200\" start=\"7\" target-start=\"5\" target-resource=\"key1\"/>"
  191. + "<duplication lines=\"200\" start=\"7\" target-start=\"15\" target-resource=\"key2\"/>"
  192. + "<duplication lines=\"200\" start=\"7\" target-start=\"10\" target-resource=\"key4\"/>" + "</duplications>")));
  193. verify(context).saveMeasure(resource4, CoreMetrics.DUPLICATED_LINES, 200d);
  194. verify(context).saveMeasure(resource4, CoreMetrics.DUPLICATED_FILES, 1d);
  195. verify(context).saveMeasure(resource4, CoreMetrics.DUPLICATED_BLOCKS, 1d);
  196. verify(context).saveMeasure(
  197. eq(resource4),
  198. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  199. + "<duplication lines=\"200\" start=\"10\" target-start=\"5\" target-resource=\"key1\"/>"
  200. + "<duplication lines=\"200\" start=\"10\" target-start=\"15\" target-resource=\"key2\"/>"
  201. + "<duplication lines=\"200\" start=\"10\" target-start=\"7\" target-resource=\"key3\"/>" + "</duplications>")));
  202. verify(context, atLeastOnce()).saveResource(resource1);
  203. verify(context, atLeastOnce()).saveResource(resource2);
  204. verify(context, atLeastOnce()).saveResource(resource3);
  205. verify(context, atLeastOnce()).saveResource(resource4);
  206. }
  207. @Test
  208. public void testDuplicationOnSameFile() throws Exception {
  209. ProjectFileSystem fileSystem = mock(ProjectFileSystem.class);
  210. when(fileSystem.getSourceDirs()).thenReturn(Collections.<File> emptyList());
  211. File file1 = new File("target/tmp/file1.ext");
  212. Project project = new Project("key").setFileSystem(fileSystem);
  213. SensorContext context = mock(SensorContext.class);
  214. CpdMapping cpdMapping = mock(CpdMapping.class);
  215. Resource resource1 = new JavaFile("foo.Foo");
  216. when(cpdMapping.createResource((File) anyObject(), anyList())).thenReturn(resource1).thenReturn(resource1);
  217. when(context.saveResource(resource1)).thenReturn("key1");
  218. Match match1 = new Match(304, new TokenEntry(null, file1.getAbsolutePath(), 5), new TokenEntry(null, file1.getAbsolutePath(), 215));
  219. match1.setLineCount(200);
  220. CpdAnalyser cpdAnalyser = new CpdAnalyser(project, context, cpdMapping);
  221. cpdAnalyser.analyse(Arrays.asList(match1).iterator());
  222. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_FILES, 1d);
  223. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_LINES, 400d);
  224. verify(context).saveMeasure(resource1, CoreMetrics.DUPLICATED_BLOCKS, 2d);
  225. verify(context).saveMeasure(
  226. eq(resource1),
  227. argThat(new IsMeasure(CoreMetrics.DUPLICATIONS_DATA, "<duplications>"
  228. + "<duplication lines=\"200\" start=\"5\" target-start=\"215\" target-resource=\"key1\"/>"
  229. + "<duplication lines=\"200\" start=\"215\" target-start=\"5\" target-resource=\"key1\"/>" + "</duplications>")));
  230. verify(context, atLeastOnce()).saveResource(resource1);
  231. }
  232. private static TokenEntry createTokenEntry(String sourceId, int line) {
  233. TokenEntry entry = new TokenEntry(null, sourceId, line);
  234. entry.setHashCode(sourceId.hashCode() + line);
  235. return entry;
  236. }
  237. }