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.

LastCommitVisitorTest.java 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program 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. * This program 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 License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.ce.task.projectanalysis.source;
  21. import com.google.common.collect.Lists;
  22. import java.util.Optional;
  23. import org.junit.Rule;
  24. import org.junit.Test;
  25. import org.sonar.api.measures.CoreMetrics;
  26. import org.sonar.ce.task.projectanalysis.component.Component;
  27. import org.sonar.ce.task.projectanalysis.component.FileAttributes;
  28. import org.sonar.ce.task.projectanalysis.component.ReportComponent;
  29. import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
  30. import org.sonar.ce.task.projectanalysis.component.ViewsComponent;
  31. import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
  32. import org.sonar.ce.task.projectanalysis.measure.Measure;
  33. import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
  34. import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
  35. import org.sonar.ce.task.projectanalysis.scm.Changeset;
  36. import org.sonar.ce.task.projectanalysis.scm.ScmInfoRepositoryRule;
  37. import static org.assertj.core.api.Assertions.assertThat;
  38. import static org.sonar.api.measures.CoreMetrics.LAST_COMMIT_DATE_KEY;
  39. import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
  40. import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
  41. import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
  42. import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT_VIEW;
  43. import static org.sonar.ce.task.projectanalysis.component.Component.Type.SUBVIEW;
  44. import static org.sonar.ce.task.projectanalysis.component.Component.Type.VIEW;
  45. import static org.sonar.ce.task.projectanalysis.component.ViewsComponent.builder;
  46. import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
  47. public class LastCommitVisitorTest {
  48. private static final int PROJECT_REF = 1;
  49. private static final int DIR_REF = 2;
  50. private static final int FILE_1_REF = 1_111;
  51. private static final int FILE_2_REF = 1_112;
  52. private static final int FILE_3_REF = 1_121;
  53. private static final int DIR_1_REF = 3;
  54. private static final int DIR_2_REF = 4;
  55. @Rule
  56. public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
  57. @Rule
  58. public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
  59. .add(CoreMetrics.LAST_COMMIT_DATE);
  60. @Rule
  61. public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
  62. @Rule
  63. public ScmInfoRepositoryRule scmInfoRepository = new ScmInfoRepositoryRule();
  64. @Test
  65. public void aggregate_date_of_last_commit_to_directories_and_project() {
  66. final long FILE_1_DATE = 1_100_000_000_000L;
  67. // FILE_2 is the most recent file in DIR_1
  68. final long FILE_2_DATE = 1_200_000_000_000L;
  69. // FILE_3 is the most recent file in the project
  70. final long FILE_3_DATE = 1_300_000_000_000L;
  71. // simulate the output of visitFile()
  72. LastCommitVisitor visitor = new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository) {
  73. @Override
  74. public void visitFile(Component file, Path<LastCommit> path) {
  75. long fileDate;
  76. switch (file.getReportAttributes().getRef()) {
  77. case FILE_1_REF:
  78. fileDate = FILE_1_DATE;
  79. break;
  80. case FILE_2_REF:
  81. fileDate = FILE_2_DATE;
  82. break;
  83. case FILE_3_REF:
  84. fileDate = FILE_3_DATE;
  85. break;
  86. default:
  87. throw new IllegalArgumentException();
  88. }
  89. path.parent().addDate(fileDate);
  90. }
  91. };
  92. // project with 1 module, 2 directories and 3 files
  93. ReportComponent project = ReportComponent.builder(PROJECT, PROJECT_REF)
  94. .addChildren(
  95. ReportComponent.builder(DIRECTORY, DIR_REF)
  96. .addChildren(
  97. ReportComponent.builder(DIRECTORY, DIR_1_REF)
  98. .addChildren(
  99. createFileComponent(FILE_1_REF),
  100. createFileComponent(FILE_2_REF))
  101. .build(),
  102. ReportComponent.builder(DIRECTORY, DIR_2_REF)
  103. .addChildren(
  104. createFileComponent(FILE_3_REF))
  105. .build())
  106. .build())
  107. .build();
  108. treeRootHolder.setRoot(project);
  109. VisitorsCrawler underTest = new VisitorsCrawler(Lists.newArrayList(visitor));
  110. underTest.visit(project);
  111. assertDate(DIR_1_REF, FILE_2_DATE);
  112. assertDate(DIR_2_REF, FILE_3_DATE);
  113. assertDate(DIR_REF, FILE_3_DATE);
  114. // project
  115. assertDate(PROJECT_REF, FILE_3_DATE);
  116. }
  117. @Test
  118. public void aggregate_date_of_last_commit_to_views() {
  119. final int VIEW_REF = 1;
  120. final int SUBVIEW_1_REF = 2;
  121. final int SUBVIEW_2_REF = 3;
  122. final int SUBVIEW_3_REF = 4;
  123. final int PROJECT_1_REF = 5;
  124. final int PROJECT_2_REF = 6;
  125. final int PROJECT_3_REF = 7;
  126. final long PROJECT_1_DATE = 1_500_000_000_000L;
  127. // the second project has the most recent commit date
  128. final long PROJECT_2_DATE = 1_700_000_000_000L;
  129. final long PROJECT_3_DATE = 1_600_000_000_000L;
  130. // view with 3 nested sub-views and 3 projects
  131. ViewsComponent view = ViewsComponent.builder(VIEW, VIEW_REF)
  132. .addChildren(
  133. builder(SUBVIEW, SUBVIEW_1_REF)
  134. .addChildren(
  135. builder(SUBVIEW, SUBVIEW_2_REF)
  136. .addChildren(
  137. builder(PROJECT_VIEW, PROJECT_1_REF).build(),
  138. builder(PROJECT_VIEW, PROJECT_2_REF).build())
  139. .build(),
  140. builder(SUBVIEW, SUBVIEW_3_REF)
  141. .addChildren(
  142. builder(PROJECT_VIEW, PROJECT_3_REF).build())
  143. .build())
  144. .build())
  145. .build();
  146. treeRootHolder.setRoot(view);
  147. measureRepository.addRawMeasure(PROJECT_1_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_1_DATE));
  148. measureRepository.addRawMeasure(PROJECT_2_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_2_DATE));
  149. measureRepository.addRawMeasure(PROJECT_3_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_3_DATE));
  150. VisitorsCrawler underTest = new VisitorsCrawler(Lists.newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));
  151. underTest.visit(view);
  152. // second level of sub-views
  153. assertDate(SUBVIEW_2_REF, PROJECT_2_DATE);
  154. assertDate(SUBVIEW_3_REF, PROJECT_3_DATE);
  155. // first level of sub-views
  156. assertDate(SUBVIEW_1_REF, PROJECT_2_DATE);
  157. // view
  158. assertDate(VIEW_REF, PROJECT_2_DATE);
  159. }
  160. @Test
  161. public void compute_date_of_file_from_scm_repo() {
  162. VisitorsCrawler underTest = new VisitorsCrawler(Lists.newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));
  163. scmInfoRepository.setScmInfo(FILE_1_REF,
  164. Changeset.newChangesetBuilder()
  165. .setAuthor("john")
  166. .setDate(1_500_000_000_000L)
  167. .setRevision("rev-1")
  168. .build(),
  169. Changeset.newChangesetBuilder()
  170. .setAuthor("tom")
  171. // this is the most recent change
  172. .setDate(1_600_000_000_000L)
  173. .setRevision("rev-2")
  174. .build(),
  175. Changeset.newChangesetBuilder()
  176. .setAuthor("john")
  177. .setDate(1_500_000_000_000L)
  178. .setRevision("rev-1")
  179. .build());
  180. ReportComponent file = createFileComponent(FILE_1_REF);
  181. treeRootHolder.setRoot(file);
  182. underTest.visit(file);
  183. assertDate(FILE_1_REF, 1_600_000_000_000L);
  184. }
  185. @Test
  186. public void date_is_not_computed_on_file_if_blame_is_not_in_scm_repo() {
  187. VisitorsCrawler underTest = new VisitorsCrawler(Lists.newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));
  188. ReportComponent file = createFileComponent(FILE_1_REF);
  189. treeRootHolder.setRoot(file);
  190. underTest.visit(file);
  191. Optional<Measure> measure = measureRepository.getAddedRawMeasure(FILE_1_REF, LAST_COMMIT_DATE_KEY);
  192. assertThat(measure).isEmpty();
  193. }
  194. private void assertDate(int componentRef, long expectedDate) {
  195. Optional<Measure> measure = measureRepository.getAddedRawMeasure(componentRef, LAST_COMMIT_DATE_KEY);
  196. assertThat(measure).isPresent();
  197. assertThat(measure.get().getLongValue()).isEqualTo(expectedDate);
  198. }
  199. private ReportComponent createFileComponent(int fileRef) {
  200. return ReportComponent.builder(FILE, fileRef).setFileAttributes(new FileAttributes(false, "js", 1)).build();
  201. }
  202. }