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.

NewSecurityReviewMeasuresVisitorTest.java 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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.qualitymodel;
  21. import java.util.Arrays;
  22. import java.util.Date;
  23. import javax.annotation.Nullable;
  24. import org.assertj.core.api.Assertions;
  25. import org.assertj.core.data.Offset;
  26. import org.junit.Rule;
  27. import org.junit.Test;
  28. import org.sonar.api.rules.RuleType;
  29. import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
  30. import org.sonar.ce.task.projectanalysis.analysis.Branch;
  31. import org.sonar.ce.task.projectanalysis.component.Component;
  32. import org.sonar.ce.task.projectanalysis.component.FileAttributes;
  33. import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
  34. import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
  35. import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
  36. import org.sonar.ce.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
  37. import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
  38. import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
  39. import org.sonar.ce.task.projectanalysis.period.Period;
  40. import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
  41. import org.sonar.core.issue.DefaultIssue;
  42. import org.sonar.core.util.Uuids;
  43. import org.sonar.db.component.BranchType;
  44. import org.sonar.server.measure.Rating;
  45. import static org.assertj.core.api.Assertions.assertThat;
  46. import static org.mockito.Mockito.mock;
  47. import static org.mockito.Mockito.when;
  48. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  49. import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
  50. import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
  51. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
  52. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_KEY;
  53. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS;
  54. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY;
  55. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
  56. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY;
  57. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING;
  58. import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY;
  59. import static org.sonar.api.rule.Severity.MAJOR;
  60. import static org.sonar.api.rule.Severity.MINOR;
  61. import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
  62. import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
  63. import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
  64. import static org.sonar.ce.task.projectanalysis.measure.MeasureAssert.assertThat;
  65. import static org.sonar.server.measure.Rating.A;
  66. import static org.sonar.server.measure.Rating.B;
  67. import static org.sonar.server.measure.Rating.C;
  68. import static org.sonar.server.measure.Rating.D;
  69. import static org.sonar.server.measure.Rating.E;
  70. public class NewSecurityReviewMeasuresVisitorTest {
  71. private static final Offset<Double> VARIATION_COMPARISON_OFFSET = Offset.offset(0.01);
  72. private static final long LEAK_PERIOD_SNAPSHOT_IN_MILLISEC = 12323L;
  73. private static final Date DEFAULT_CREATION_DATE = new Date(1000L);
  74. private static final Date BEFORE_LEAK_PERIOD_DATE = new Date(LEAK_PERIOD_SNAPSHOT_IN_MILLISEC - 5000L);
  75. private static final Date AFTER_LEAK_PERIOD_DATE = new Date(LEAK_PERIOD_SNAPSHOT_IN_MILLISEC + 5000L);
  76. private static final String LANGUAGE_KEY_1 = "lKey1";
  77. private static final int PROJECT_REF = 1;
  78. private static final int ROOT_DIR_REF = 12;
  79. private static final int DIRECTORY_REF = 123;
  80. private static final int FILE_1_REF = 1231;
  81. private static final int FILE_2_REF = 1232;
  82. private static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
  83. .addChildren(
  84. builder(DIRECTORY, ROOT_DIR_REF).setKey("dir")
  85. .addChildren(
  86. builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
  87. .addChildren(
  88. builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file1").build(),
  89. builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file2").build())
  90. .build())
  91. .build())
  92. .build();
  93. @Rule
  94. public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
  95. @Rule
  96. public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
  97. .add(NEW_SECURITY_REVIEW_RATING)
  98. .add(NEW_SECURITY_HOTSPOTS_REVIEWED)
  99. .add(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS)
  100. .add(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS);
  101. @Rule
  102. public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
  103. @Rule
  104. public PeriodHolderRule periodsHolder = new PeriodHolderRule().setPeriod(new Period("mode", null, LEAK_PERIOD_SNAPSHOT_IN_MILLISEC));
  105. @Rule
  106. public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
  107. @Rule
  108. public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
  109. @Rule
  110. public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
  111. private VisitorsCrawler underTest = new VisitorsCrawler(Arrays.asList(fillComponentIssuesVisitorRule,
  112. new NewSecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, periodsHolder, analysisMetadataHolder, metricRepository)));
  113. @Test
  114. public void compute_measures_when_100_percent_hotspots_reviewed() {
  115. treeRootHolder.setRoot(ROOT_PROJECT);
  116. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  117. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  118. // Should not be taken into account
  119. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  120. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  121. newIssue().setCreationDate(AFTER_LEAK_PERIOD_DATE));
  122. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  123. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  124. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE));
  125. fillComponentIssuesVisitorRule.setIssues(ROOT_DIR_REF,
  126. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE));
  127. underTest.visit(ROOT_PROJECT);
  128. verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
  129. verifyRatingAndReviewedMeasures(FILE_2_REF, A, 100.0);
  130. verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 100.0);
  131. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 100.0);
  132. verifyRatingAndReviewedMeasures(PROJECT_REF, A, 100.0);
  133. }
  134. @Test
  135. public void compute_measures_when_more_than_80_percent_hotspots_reviewed() {
  136. treeRootHolder.setRoot(ROOT_PROJECT);
  137. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  138. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  139. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  140. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  141. // Should not be taken into account
  142. newIssue().setCreationDate(AFTER_LEAK_PERIOD_DATE));
  143. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  144. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  145. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  146. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  147. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  148. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  149. // Should not be taken into account
  150. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  151. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  152. newIssue());
  153. underTest.visit(ROOT_PROJECT);
  154. verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
  155. verifyRatingAndReviewedMeasures(FILE_2_REF, A, 80.0);
  156. verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 87.5);
  157. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 87.5);
  158. verifyRatingAndReviewedMeasures(PROJECT_REF, A, 87.5);
  159. }
  160. @Test
  161. public void compute_measures_when_more_than_70_percent_hotspots_reviewed() {
  162. treeRootHolder.setRoot(ROOT_PROJECT);
  163. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  164. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  165. // Should not be taken into account
  166. newIssue().setCreationDate(AFTER_LEAK_PERIOD_DATE));
  167. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  168. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  169. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  170. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  171. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  172. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  173. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  174. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  175. // Should not be taken into account
  176. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  177. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  178. newIssue());
  179. underTest.visit(ROOT_PROJECT);
  180. verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
  181. verifyRatingAndReviewedMeasures(FILE_2_REF, B, 71.42);
  182. verifyRatingAndReviewedMeasures(DIRECTORY_REF, B, 75.0);
  183. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, B, 75.0);
  184. verifyRatingAndReviewedMeasures(PROJECT_REF, B, 75.0);
  185. }
  186. @Test
  187. public void compute_measures_when_more_than_50_percent_hotspots_reviewed() {
  188. treeRootHolder.setRoot(ROOT_PROJECT);
  189. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  190. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  191. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  192. // Should not be taken into account
  193. newIssue());
  194. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  195. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  196. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  197. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  198. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  199. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  200. // Should not be taken into account
  201. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  202. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  203. newIssue());
  204. underTest.visit(ROOT_PROJECT);
  205. verifyRatingAndReviewedMeasures(FILE_1_REF, C, 50.0);
  206. verifyRatingAndReviewedMeasures(FILE_2_REF, C, 60.0);
  207. verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, 57.14);
  208. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, 57.14);
  209. verifyRatingAndReviewedMeasures(PROJECT_REF, C, 57.14);
  210. }
  211. @Test
  212. public void compute_measures_when_more_30_than_percent_hotspots_reviewed() {
  213. treeRootHolder.setRoot(ROOT_PROJECT);
  214. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  215. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  216. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  217. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  218. // Should not be taken into account
  219. newIssue());
  220. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  221. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  222. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  223. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  224. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  225. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  226. // Should not be taken into account
  227. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  228. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  229. newIssue());
  230. underTest.visit(ROOT_PROJECT);
  231. verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.33);
  232. verifyRatingAndReviewedMeasures(FILE_2_REF, D, 40.0);
  233. verifyRatingAndReviewedMeasures(DIRECTORY_REF, D, 37.5);
  234. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, D, 37.5);
  235. verifyRatingAndReviewedMeasures(PROJECT_REF, D, 37.5);
  236. }
  237. @Test
  238. public void compute_measures_when_less_than_30_percent_hotspots_reviewed() {
  239. treeRootHolder.setRoot(ROOT_PROJECT);
  240. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  241. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  242. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  243. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  244. // Should not be taken into account
  245. newIssue());
  246. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  247. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  248. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  249. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  250. // Should not be taken into account
  251. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  252. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  253. newIssue());
  254. underTest.visit(ROOT_PROJECT);
  255. verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.33);
  256. verifyRatingAndReviewedMeasures(FILE_2_REF, E, 0.0);
  257. verifyRatingAndReviewedMeasures(DIRECTORY_REF, E, 16.66);
  258. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, E, 16.66);
  259. verifyRatingAndReviewedMeasures(PROJECT_REF, E, 16.66);
  260. }
  261. @Test
  262. public void compute_A_rating_and_no_percent_when_no_new_hotspot_on_new_code() {
  263. treeRootHolder.setRoot(ROOT_PROJECT);
  264. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  265. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  266. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  267. newIssue());
  268. underTest.visit(ROOT_PROJECT);
  269. verifyRatingAndReviewedMeasures(PROJECT_REF, A, null);
  270. }
  271. @Test
  272. public void compute_measures_on_pr() {
  273. periodsHolder.setPeriod(null);
  274. Branch b = mock(Branch.class);
  275. when(b.getType()).thenReturn(BranchType.PULL_REQUEST);
  276. analysisMetadataHolder.setBranch(b);
  277. treeRootHolder.setRoot(ROOT_PROJECT);
  278. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  279. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  280. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  281. // Should not be taken into account
  282. newIssue());
  283. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  284. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  285. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  286. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  287. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  288. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  289. // Dates is not taken into account on PR
  290. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(BEFORE_LEAK_PERIOD_DATE),
  291. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(BEFORE_LEAK_PERIOD_DATE));
  292. underTest.visit(ROOT_PROJECT);
  293. verifyRatingAndReviewedMeasures(FILE_1_REF, C, 50.0);
  294. verifyRatingAndReviewedMeasures(FILE_2_REF, C, 57.14);
  295. verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, 55.55);
  296. verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, 55.55);
  297. verifyRatingAndReviewedMeasures(PROJECT_REF, C, 55.55);
  298. }
  299. @Test
  300. public void compute_status_related_measures() {
  301. treeRootHolder.setRoot(ROOT_PROJECT);
  302. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  303. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  304. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  305. // Should not be taken into account
  306. newIssue());
  307. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
  308. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  309. newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  310. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  311. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  312. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
  313. newIssue());
  314. underTest.visit(ROOT_PROJECT);
  315. verifyHotspotStatusMeasures(FILE_1_REF, null, null);
  316. verifyHotspotStatusMeasures(FILE_2_REF, null, null);
  317. verifyHotspotStatusMeasures(DIRECTORY_REF, null, null);
  318. verifyHotspotStatusMeasures(ROOT_DIR_REF, null, null);
  319. verifyHotspotStatusMeasures(PROJECT_REF, 4, 3);
  320. }
  321. @Test
  322. public void compute_0_status_related_measures_when_no_hotspot() {
  323. treeRootHolder.setRoot(ROOT_PROJECT);
  324. underTest.visit(ROOT_PROJECT);
  325. verifyHotspotStatusMeasures(PROJECT_REF, 0, 0);
  326. }
  327. @Test
  328. public void no_measure_if_there_is_no_period() {
  329. periodsHolder.setPeriod(null);
  330. treeRootHolder.setRoot(ROOT_PROJECT);
  331. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
  332. newHotspot(STATUS_TO_REVIEW, null),
  333. newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED));
  334. underTest.visit(ROOT_PROJECT);
  335. assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF).values()).isEmpty();
  336. }
  337. private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, @Nullable Double expectedHotspotsReviewed) {
  338. assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasVariation(expectedReviewRating.getIndex());
  339. if (expectedHotspotsReviewed != null){
  340. assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasVariation(expectedHotspotsReviewed,
  341. VARIATION_COMPARISON_OFFSET);
  342. } else {
  343. assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).isAbsent();
  344. }
  345. }
  346. private void verifyHotspotStatusMeasures(int componentRef, @Nullable Integer hotspotsReviewed, @Nullable Integer hotspotsToReview) {
  347. if (hotspotsReviewed == null) {
  348. Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).isEmpty();
  349. } else {
  350. assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).hasVariation(hotspotsReviewed);
  351. }
  352. if (hotspotsReviewed == null) {
  353. Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).isEmpty();
  354. } else {
  355. assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).hasVariation(hotspotsToReview);
  356. }
  357. }
  358. private static DefaultIssue newHotspot(String status, @Nullable String resolution) {
  359. return new DefaultIssue()
  360. .setKey(Uuids.create())
  361. .setSeverity(MINOR)
  362. .setStatus(status)
  363. .setResolution(resolution)
  364. .setType(RuleType.SECURITY_HOTSPOT)
  365. .setCreationDate(DEFAULT_CREATION_DATE);
  366. }
  367. private static DefaultIssue newIssue() {
  368. return new DefaultIssue()
  369. .setKey(Uuids.create())
  370. .setSeverity(MAJOR)
  371. .setType(RuleType.BUG)
  372. .setCreationDate(DEFAULT_CREATION_DATE);
  373. }
  374. }