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.

ReliabilityAndSecurityRatingMeasuresVisitorTest.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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 org.junit.Rule;
  24. import org.junit.Test;
  25. import org.sonar.api.rules.RuleType;
  26. import org.sonar.api.utils.Duration;
  27. import org.sonar.ce.task.projectanalysis.component.Component;
  28. import org.sonar.ce.task.projectanalysis.component.FileAttributes;
  29. import org.sonar.ce.task.projectanalysis.component.ReportComponent;
  30. import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
  31. import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
  32. import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
  33. import org.sonar.ce.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
  34. import org.sonar.ce.task.projectanalysis.measure.Measure;
  35. import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
  36. import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
  37. import org.sonar.core.issue.DefaultIssue;
  38. import org.sonar.core.util.Uuids;
  39. import org.sonar.server.measure.Rating;
  40. import static org.assertj.core.api.Assertions.assertThat;
  41. import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
  42. import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING;
  43. import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
  44. import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING;
  45. import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
  46. import static org.sonar.api.rule.Severity.BLOCKER;
  47. import static org.sonar.api.rule.Severity.CRITICAL;
  48. import static org.sonar.api.rule.Severity.INFO;
  49. import static org.sonar.api.rule.Severity.MAJOR;
  50. import static org.sonar.api.rule.Severity.MINOR;
  51. import static org.sonar.api.rules.RuleType.BUG;
  52. import static org.sonar.api.rules.RuleType.CODE_SMELL;
  53. import static org.sonar.api.rules.RuleType.VULNERABILITY;
  54. import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
  55. import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
  56. import static org.sonar.ce.task.projectanalysis.component.Component.Type.PROJECT;
  57. import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
  58. import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
  59. import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.entryOf;
  60. import static org.sonar.ce.task.projectanalysis.measure.MeasureRepoEntry.toEntries;
  61. import static org.sonar.server.measure.Rating.A;
  62. import static org.sonar.server.measure.Rating.B;
  63. import static org.sonar.server.measure.Rating.C;
  64. import static org.sonar.server.measure.Rating.D;
  65. import static org.sonar.server.measure.Rating.E;
  66. public class ReliabilityAndSecurityRatingMeasuresVisitorTest {
  67. static final String LANGUAGE_KEY_1 = "lKey1";
  68. static final int PROJECT_REF = 1;
  69. static final int DIRECTORY_REF = 123;
  70. static final int FILE_1_REF = 1231;
  71. static final int FILE_2_REF = 1232;
  72. static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
  73. .addChildren(
  74. builder(DIRECTORY, DIRECTORY_REF).setKey("directory")
  75. .addChildren(
  76. builder(FILE, FILE_1_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file1").build(),
  77. builder(FILE, FILE_2_REF).setFileAttributes(new FileAttributes(false, LANGUAGE_KEY_1, 1)).setKey("file2").build())
  78. .build())
  79. .build();
  80. @Rule
  81. public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
  82. @Rule
  83. public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
  84. .add(RELIABILITY_RATING)
  85. .add(SECURITY_RATING);
  86. @Rule
  87. public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
  88. @Rule
  89. public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
  90. @Rule
  91. public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
  92. VisitorsCrawler underTest = new VisitorsCrawler(
  93. Arrays.asList(fillComponentIssuesVisitorRule, new ReliabilityAndSecurityRatingMeasuresVisitor(metricRepository, measureRepository, componentIssuesRepositoryRule)));
  94. @Test
  95. public void measures_created_for_project_are_all_A_when_they_have_no_FILE_child() {
  96. ReportComponent root = builder(PROJECT, 1).build();
  97. treeRootHolder.setRoot(root);
  98. underTest.visit(root);
  99. assertThat(measureRepository.getRawMeasures(root)
  100. .entrySet().stream().map(e -> entryOf(e.getKey(), e.getValue())))
  101. .containsOnly(
  102. entryOf(RELIABILITY_RATING_KEY, createRatingMeasure(A)),
  103. entryOf(SECURITY_RATING_KEY, createRatingMeasure(A)));
  104. }
  105. @Test
  106. public void compute_reliability_rating() {
  107. treeRootHolder.setRoot(ROOT_PROJECT);
  108. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newBugIssue(1L, MAJOR),
  109. // Should not be taken into account
  110. newVulnerabilityIssue(5L, MINOR));
  111. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newBugIssue(2L, CRITICAL), newBugIssue(3L, MINOR),
  112. // Should not be taken into account
  113. newBugIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
  114. fillComponentIssuesVisitorRule.setIssues(PROJECT_REF, newBugIssue(7L, BLOCKER));
  115. underTest.visit(ROOT_PROJECT);
  116. verifyAddedRawMeasure(FILE_1_REF, RELIABILITY_RATING_KEY, C);
  117. verifyAddedRawMeasure(FILE_2_REF, RELIABILITY_RATING_KEY, D);
  118. verifyAddedRawMeasure(DIRECTORY_REF, RELIABILITY_RATING_KEY, D);
  119. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
  120. }
  121. @Test
  122. public void compute_security_rating() {
  123. treeRootHolder.setRoot(ROOT_PROJECT);
  124. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newVulnerabilityIssue(10L, MAJOR), newVulnerabilityIssue(1L, MAJOR),
  125. // Should not be taken into account
  126. newBugIssue(1L, MAJOR));
  127. fillComponentIssuesVisitorRule.setIssues(FILE_2_REF, newVulnerabilityIssue(2L, CRITICAL), newVulnerabilityIssue(3L, MINOR),
  128. // Should not be taken into account
  129. newVulnerabilityIssue(10L, BLOCKER).setResolution(RESOLUTION_FIXED));
  130. fillComponentIssuesVisitorRule.setIssues(PROJECT_REF, newVulnerabilityIssue(7L, BLOCKER));
  131. underTest.visit(ROOT_PROJECT);
  132. verifyAddedRawMeasure(FILE_1_REF, SECURITY_RATING_KEY, C);
  133. verifyAddedRawMeasure(FILE_2_REF, SECURITY_RATING_KEY, D);
  134. verifyAddedRawMeasure(DIRECTORY_REF, SECURITY_RATING_KEY, D);
  135. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
  136. }
  137. @Test
  138. public void compute_E_reliability_and_security_rating_on_blocker_issue() {
  139. treeRootHolder.setRoot(ROOT_PROJECT);
  140. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, BLOCKER), newVulnerabilityIssue(1L, BLOCKER),
  141. // Should not be taken into account
  142. newBugIssue(1L, MAJOR));
  143. underTest.visit(ROOT_PROJECT);
  144. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, E);
  145. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, E);
  146. }
  147. @Test
  148. public void compute_D_reliability_and_security_rating_on_critical_issue() {
  149. treeRootHolder.setRoot(ROOT_PROJECT);
  150. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, CRITICAL), newVulnerabilityIssue(15L, CRITICAL),
  151. // Should not be taken into account
  152. newCodeSmellIssue(1L, MAJOR));
  153. underTest.visit(ROOT_PROJECT);
  154. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, D);
  155. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, D);
  156. }
  157. @Test
  158. public void compute_C_reliability_and_security_rating_on_major_issue() {
  159. treeRootHolder.setRoot(ROOT_PROJECT);
  160. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MAJOR), newVulnerabilityIssue(15L, MAJOR),
  161. // Should not be taken into account
  162. newCodeSmellIssue(1L, MAJOR));
  163. underTest.visit(ROOT_PROJECT);
  164. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, C);
  165. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, C);
  166. }
  167. @Test
  168. public void compute_B_reliability_and_security_rating_on_minor_issue() {
  169. treeRootHolder.setRoot(ROOT_PROJECT);
  170. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, MINOR), newVulnerabilityIssue(15L, MINOR),
  171. // Should not be taken into account
  172. newCodeSmellIssue(1L, MAJOR));
  173. underTest.visit(ROOT_PROJECT);
  174. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, B);
  175. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, B);
  176. }
  177. @Test
  178. public void compute_A_reliability_and_security_rating_on_info_issue() {
  179. treeRootHolder.setRoot(ROOT_PROJECT);
  180. fillComponentIssuesVisitorRule.setIssues(FILE_1_REF, newBugIssue(10L, INFO), newVulnerabilityIssue(15L, INFO),
  181. // Should not be taken into account
  182. newCodeSmellIssue(1L, MAJOR));
  183. underTest.visit(ROOT_PROJECT);
  184. verifyAddedRawMeasure(PROJECT_REF, RELIABILITY_RATING_KEY, A);
  185. verifyAddedRawMeasure(PROJECT_REF, SECURITY_RATING_KEY, A);
  186. }
  187. private void verifyAddedRawMeasure(int componentRef, String metricKey, Rating rating) {
  188. assertThat(toEntries(measureRepository.getAddedRawMeasures(componentRef))).contains(entryOf(metricKey, newMeasureBuilder().create(rating.getIndex(), rating.name())));
  189. }
  190. private static Measure createRatingMeasure(Rating rating) {
  191. return newMeasureBuilder().create(rating.getIndex(), rating.name());
  192. }
  193. private static DefaultIssue newBugIssue(long effort, String severity) {
  194. return newIssue(effort, severity, BUG);
  195. }
  196. private static DefaultIssue newVulnerabilityIssue(long effort, String severity) {
  197. return newIssue(effort, severity, VULNERABILITY);
  198. }
  199. private static DefaultIssue newCodeSmellIssue(long effort, String severity) {
  200. return newIssue(effort, severity, CODE_SMELL);
  201. }
  202. private static DefaultIssue newIssue(long effort, String severity, RuleType type) {
  203. return newIssue(severity, type)
  204. .setEffort(Duration.create(effort));
  205. }
  206. private static DefaultIssue newIssue(String severity, RuleType type) {
  207. return new DefaultIssue()
  208. .setKey(Uuids.create())
  209. .setSeverity(severity)
  210. .setType(type)
  211. .setCreationDate(new Date(1000L));
  212. }
  213. }