]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-22727 Introduce software quality security review rating metrics
authorDDMili <130993898+dejan-milisavljevic-sonarsource@users.noreply.github.com>
Mon, 12 Aug 2024 11:42:10 +0000 (13:42 +0200)
committersonartech <sonartech@sonarsource.com>
Mon, 26 Aug 2024 20:03:05 +0000 (20:03 +0000)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java
server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java
server/sonar-server-common/src/test/java/org/sonar/server/security/SecurityReviewRatingTest.java

index c5eb63dc341e4b845dc598f35b2fa4282d005a18..1b6c33094274b54d4d2e616971e54ce4c1f82a5d 100644 (file)
@@ -23,11 +23,11 @@ import java.util.Optional;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.PathAwareVisitorAdapter;
 import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepository;
+import org.sonar.ce.task.projectanalysis.issue.NewIssueClassifier;
 import org.sonar.ce.task.projectanalysis.measure.Measure;
 import org.sonar.ce.task.projectanalysis.measure.MeasureRepository;
 import org.sonar.ce.task.projectanalysis.metric.Metric;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
-import org.sonar.ce.task.projectanalysis.issue.NewIssueClassifier;
 
 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_KEY;
 import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY;
@@ -36,6 +36,8 @@ import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY;
 import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT;
 import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
 import static org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit.FILE;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
+import static org.sonar.server.security.SecurityReviewRating.computeAToDRating;
 import static org.sonar.server.security.SecurityReviewRating.computePercent;
 import static org.sonar.server.security.SecurityReviewRating.computeRating;
 
@@ -44,6 +46,7 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
   private final ComponentIssuesRepository componentIssuesRepository;
   private final MeasureRepository measureRepository;
   private final Metric newSecurityReviewRatingMetric;
+  private final Metric newSoftwareQualitySecurityReviewRatingMetric;
   private final Metric newSecurityHotspotsReviewedMetric;
   private final Metric newSecurityHotspotsReviewedStatusMetric;
   private final Metric newSecurityHotspotsToReviewStatusMetric;
@@ -55,6 +58,7 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
     this.componentIssuesRepository = componentIssuesRepository;
     this.measureRepository = measureRepository;
     this.newSecurityReviewRatingMetric = metricRepository.getByKey(NEW_SECURITY_REVIEW_RATING_KEY);
+    this.newSoftwareQualitySecurityReviewRatingMetric = metricRepository.getByKey(NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY);
     this.newSecurityHotspotsReviewedMetric = metricRepository.getByKey(NEW_SECURITY_HOTSPOTS_REVIEWED_KEY);
     this.newSecurityHotspotsReviewedStatusMetric = metricRepository.getByKey(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY);
     this.newSecurityHotspotsToReviewStatusMetric = metricRepository.getByKey(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY);
@@ -92,6 +96,8 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
 
     Optional<Double> percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
     measureRepository.add(component, newSecurityReviewRatingMetric, Measure.newMeasureBuilder().create(computeRating(percent.orElse(null)).getIndex()));
+    measureRepository.add(component, newSoftwareQualitySecurityReviewRatingMetric,
+      Measure.newMeasureBuilder().create(computeAToDRating(percent.orElse(null)).getIndex()));
     percent.ifPresent(p -> measureRepository.add(component, newSecurityHotspotsReviewedMetric, Measure.newMeasureBuilder().create(p)));
 
     if (!path.isRoot()) {
index c8e8ec02fc0a40db5fceb5b58c3b94cf412aca46..34f3949b1e60f16a2cb92972b635381c0f81645f 100644 (file)
@@ -37,6 +37,8 @@ import static org.sonar.api.rules.RuleType.SECURITY_HOTSPOT;
 import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;
 import static org.sonar.ce.task.projectanalysis.component.CrawlerDepthLimit.FILE;
 import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilder;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
+import static org.sonar.server.security.SecurityReviewRating.computeAToDRating;
 import static org.sonar.server.security.SecurityReviewRating.computePercent;
 import static org.sonar.server.security.SecurityReviewRating.computeRating;
 
@@ -45,6 +47,7 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
   private final ComponentIssuesRepository componentIssuesRepository;
   private final MeasureRepository measureRepository;
   private final Metric securityReviewRatingMetric;
+  private final Metric softwareQualitySecurityReviewRatingMetric;
   private final Metric securityHotspotsReviewedMetric;
   private final Metric securityHotspotsReviewedStatusMetric;
   private final Metric securityHotspotsToReviewStatusMetric;
@@ -54,6 +57,7 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
     this.componentIssuesRepository = componentIssuesRepository;
     this.measureRepository = measureRepository;
     this.securityReviewRatingMetric = metricRepository.getByKey(SECURITY_REVIEW_RATING_KEY);
+    this.softwareQualitySecurityReviewRatingMetric = metricRepository.getByKey(SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY);
     this.securityHotspotsReviewedMetric = metricRepository.getByKey(SECURITY_HOTSPOTS_REVIEWED_KEY);
     this.securityHotspotsReviewedStatusMetric = metricRepository.getByKey(SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY);
     this.securityHotspotsToReviewStatusMetric = metricRepository.getByKey(SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY);
@@ -84,6 +88,8 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
     measureRepository.add(component, securityHotspotsToReviewStatusMetric, newMeasureBuilder().create(path.current().getHotspotsToReview()));
     Optional<Double> percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
     measureRepository.add(component, securityReviewRatingMetric, RatingMeasures.get(computeRating(percent.orElse(null))));
+    measureRepository.add(component, softwareQualitySecurityReviewRatingMetric,
+      RatingMeasures.get(computeAToDRating(percent.orElse(null))));
     percent.ifPresent(p -> measureRepository.add(component, securityHotspotsReviewedMetric, newMeasureBuilder().create(p, securityHotspotsReviewedMetric.getDecimalScale())));
 
     if (!path.isRoot()) {
index b00a73f5dc9be4a88e8f6b93775a61dd46cd1c72..e13d1590a9f5a29cfeb5628ed1cc01f9b8fc4ff2 100644 (file)
@@ -23,9 +23,9 @@ import java.util.Arrays;
 import javax.annotation.Nullable;
 import org.assertj.core.api.Assertions;
 import org.assertj.core.data.Offset;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.sonar.api.rules.RuleType;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.FileAttributes;
@@ -33,9 +33,9 @@ import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
 import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
 import org.sonar.ce.task.projectanalysis.issue.ComponentIssuesRepositoryRule;
 import org.sonar.ce.task.projectanalysis.issue.FillComponentIssuesVisitorRule;
+import org.sonar.ce.task.projectanalysis.issue.NewIssueClassifier;
 import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
 import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
-import org.sonar.ce.task.projectanalysis.issue.NewIssueClassifier;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.util.UuidFactoryFast;
 import org.sonar.core.util.Uuids;
@@ -68,8 +68,10 @@ import static org.sonar.server.measure.Rating.B;
 import static org.sonar.server.measure.Rating.C;
 import static org.sonar.server.measure.Rating.D;
 import static org.sonar.server.measure.Rating.E;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
 
-public class NewSecurityReviewMeasuresVisitorTest {
+class NewSecurityReviewMeasuresVisitorTest {
   private static final Offset<Double> VALUE_COMPARISON_OFFSET = Offset.offset(0.01);
   private static final String LANGUAGE_KEY_1 = "lKey1";
 
@@ -91,31 +93,32 @@ public class NewSecurityReviewMeasuresVisitorTest {
         .build())
     .build();
 
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+  @RegisterExtension
+  private final TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+  @RegisterExtension
+  private final MetricRepositoryRule metricRepository = new MetricRepositoryRule()
     .add(NEW_SECURITY_REVIEW_RATING)
+    .add(NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING)
     .add(NEW_SECURITY_HOTSPOTS_REVIEWED)
     .add(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS)
     .add(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS);
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-  @Rule
-  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-  @Rule
-  public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
+  @RegisterExtension
+  private final MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+  private final ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
+  @RegisterExtension
+  private final FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule =
+    new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
   private final NewIssueClassifier newIssueClassifier = mock(NewIssueClassifier.class);
   private final VisitorsCrawler underTest = new VisitorsCrawler(Arrays.asList(fillComponentIssuesVisitorRule,
     new NewSecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, metricRepository, newIssueClassifier)));
 
-  @Before
-  public void setup() {
+  @BeforeEach
+  void setup() {
     when(newIssueClassifier.isEnabled()).thenReturn(true);
   }
 
   @Test
-  public void compute_measures_when_100_percent_hotspots_reviewed() {
+  void compute_measures_when_100_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -131,15 +134,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, A, 100.0);
   }
 
   @Test
-  public void compute_measures_when_more_than_80_percent_hotspots_reviewed() {
+  void compute_measures_when_more_than_80_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -160,15 +163,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, A, 80.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 87.5);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 87.5);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, 87.5);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, A, B, 80.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, B, 87.5);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, B, 87.5);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, B, 87.5);
   }
 
   @Test
-  public void compute_measures_when_more_than_70_percent_hotspots_reviewed() {
+  void compute_measures_when_more_than_70_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -189,15 +192,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, B, 71.42);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, B, 75.0);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, B, 75.0);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, B, 75.0);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, B, B, 71.42);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, B, B, 75.0);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, B, B, 75.0);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, B, B, 75.0);
   }
 
   @Test
-  public void compute_measures_when_more_than_50_percent_hotspots_reviewed() {
+  void compute_measures_when_more_than_50_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -217,15 +220,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, C, 50.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, C, 60.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, 57.14);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, 57.14);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, C, 57.14);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, C, C, 50.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, C, C, 60.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, C, 57.14);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, C, 57.14);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, C, C, 57.14);
   }
 
   @Test
-  public void compute_measures_when_more_30_than_percent_hotspots_reviewed() {
+  void compute_measures_when_more_30_than_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -246,15 +249,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.33);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, D, 40.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, D, 37.5);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, D, 37.5);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, D, 37.5);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, D, D, 33.33);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, D, D, 40.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, D, D, 37.5);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, D, D, 37.5);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, D, D, 37.5);
   }
 
   @Test
-  public void compute_measures_when_less_than_30_percent_hotspots_reviewed() {
+  void compute_measures_when_less_than_30_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -273,15 +276,15 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.33);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, E, 0.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, E, 16.66);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, E, 16.66);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, E, 16.66);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, D, D, 33.33);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, E, D, 0.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, E, D, 16.66);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, E, D, 16.66);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, E, D, 16.66);
   }
 
   @Test
-  public void compute_A_rating_and_no_percent_when_no_new_hotspot_on_new_code() {
+  void compute_A_rating_and_no_percent_when_no_new_hotspot_on_new_code() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       oldHotspot(STATUS_TO_REVIEW, null),
@@ -290,11 +293,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, null);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, A, null);
   }
 
   @Test
-  public void compute_status_related_measures() {
+  void compute_status_related_measures() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -319,7 +322,7 @@ public class NewSecurityReviewMeasuresVisitorTest {
   }
 
   @Test
-  public void compute_0_status_related_measures_when_no_hotspot() {
+  void compute_0_status_related_measures_when_no_hotspot() {
     treeRootHolder.setRoot(ROOT_PROJECT);
 
     underTest.visit(ROOT_PROJECT);
@@ -328,7 +331,7 @@ public class NewSecurityReviewMeasuresVisitorTest {
   }
 
   @Test
-  public void no_measure_if_there_is_no_period() {
+  void no_measure_if_there_is_no_period() {
     when(newIssueClassifier.isEnabled()).thenReturn(false);
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
@@ -340,8 +343,10 @@ public class NewSecurityReviewMeasuresVisitorTest {
     assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF).values()).isEmpty();
   }
 
-  private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, @Nullable Double expectedHotspotsReviewed) {
+  private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating,
+    Rating expectedSoftwareQualitySecurityReviewRating, @Nullable Double expectedHotspotsReviewed) {
     assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasValue(expectedReviewRating.getIndex());
+    assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY)).hasValue(expectedSoftwareQualitySecurityReviewRating.getIndex());
     if (expectedHotspotsReviewed != null) {
       assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasValue(expectedHotspotsReviewed,
         VALUE_COMPARISON_OFFSET);
index 7d6d267f752fd229377be44b7078d1a231952b87..eb931585aa9f44fc1e23b6b7553ccf420cec75c4 100644 (file)
@@ -20,8 +20,8 @@
 package org.sonar.ce.task.projectanalysis.qualitymodel;
 
 import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 import org.sonar.api.rules.RuleType;
 import org.sonar.ce.task.projectanalysis.component.Component;
 import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
@@ -59,8 +59,10 @@ import static org.sonar.server.measure.Rating.B;
 import static org.sonar.server.measure.Rating.C;
 import static org.sonar.server.measure.Rating.D;
 import static org.sonar.server.measure.Rating.E;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING;
+import static org.sonar.server.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
 
-public class SecurityReviewMeasuresVisitorTest {
+class SecurityReviewMeasuresVisitorTest {
 
   private static final int PROJECT_REF = 1;
   private static final int ROOT_DIR_REF = 12;
@@ -68,7 +70,7 @@ public class SecurityReviewMeasuresVisitorTest {
   private static final int FILE_1_REF = 1231;
   private static final int FILE_2_REF = 1232;
 
-  static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
+  private static final Component ROOT_PROJECT = builder(Component.Type.PROJECT, PROJECT_REF).setKey("project")
     .addChildren(
       builder(DIRECTORY, ROOT_DIR_REF).setKey("dir")
         .addChildren(
@@ -80,26 +82,27 @@ public class SecurityReviewMeasuresVisitorTest {
         .build())
     .build();
 
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
-  @Rule
-  public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
+  @RegisterExtension
+  private final TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+  @RegisterExtension
+  private final MetricRepositoryRule metricRepository = new MetricRepositoryRule()
     .add(SECURITY_REVIEW_RATING)
+    .add(SOFTWARE_QUALITY_SECURITY_REVIEW_RATING)
     .add(SECURITY_HOTSPOTS_REVIEWED)
     .add(SECURITY_HOTSPOTS_REVIEWED_STATUS)
     .add(SECURITY_HOTSPOTS_TO_REVIEW_STATUS);
-  @Rule
-  public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
-  @Rule
-  public FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule = new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
-  @Rule
-  public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
-
-  private VisitorsCrawler underTest = new VisitorsCrawler(asList(fillComponentIssuesVisitorRule,
+  private final ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
+  @RegisterExtension
+  private final FillComponentIssuesVisitorRule fillComponentIssuesVisitorRule =
+    new FillComponentIssuesVisitorRule(componentIssuesRepositoryRule, treeRootHolder);
+  @RegisterExtension
+  private final MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
+
+  private final VisitorsCrawler underTest = new VisitorsCrawler(asList(fillComponentIssuesVisitorRule,
     new SecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, metricRepository)));
 
   @Test
-  public void compute_rating_and_reviewed_measures_when_100_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed_measures_when_100_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -112,15 +115,15 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, A, 100.0);
   }
 
   @Test
-  public void compute_rating_and_reviewed__measures_when_more_than_80_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed__measures_when_more_than_80_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -138,15 +141,15 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, A, 80.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, 87.5);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, 87.5);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, 87.5);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, A, B, 80.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, A, B, 87.5);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, A, B, 87.5);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, B, 87.5);
   }
 
   @Test
-  public void compute_rating_and_reviewed__measures_when_more_than_70_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed__measures_when_more_than_70_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
@@ -164,15 +167,15 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, A, 100.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, B, 71.4);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, B, 75.0);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, B, 75.0);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, B, 75.0);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, A, A, 100.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, B, B, 71.4);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, B, B, 75.0);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, B, B, 75.0);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, B, B, 75.0);
   }
 
   @Test
-  public void compute_rating_and_reviewed__measures_when_more_than_50_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed__measures_when_more_than_50_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -189,15 +192,15 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, C, 50.0);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, C, 60.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, 57.1);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, 57.1);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, C, 57.1);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, C, C,50.0);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, C, C,60.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, C,C, 57.1);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, C,57.1);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, C, C,57.1);
   }
 
   @Test
-  public void compute_rating_and_reviewed__measures_when_more_30_than_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed__measures_when_more_30_than_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -215,15 +218,15 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.3);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, D, 40.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, D, 37.5);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, D, 37.5);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, D, 37.5);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, D, D,33.3);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, D, D,40.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, D,D, 37.5);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, D, D,37.5);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, D, D,37.5);
   }
 
   @Test
-  public void compute_rating_and_reviewed__measures_when_less_than_30_percent_hotspots_reviewed() {
+  void compute_rating_and_reviewed__measures_when_less_than_30_percent_hotspots_reviewed() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -239,24 +242,24 @@ public class SecurityReviewMeasuresVisitorTest {
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(FILE_1_REF, D, 33.3);
-    verifyRatingAndReviewedMeasures(FILE_2_REF, E, 0.0);
-    verifyRatingAndReviewedMeasures(DIRECTORY_REF, E, 16.7);
-    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, E, 16.7);
-    verifyRatingAndReviewedMeasures(PROJECT_REF, E, 16.7);
+    verifyRatingAndReviewedMeasures(FILE_1_REF, D, D,33.3);
+    verifyRatingAndReviewedMeasures(FILE_2_REF, E, D,0.0);
+    verifyRatingAndReviewedMeasures(DIRECTORY_REF, E,D, 16.7);
+    verifyRatingAndReviewedMeasures(ROOT_DIR_REF, E, D,16.7);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, E, D,16.7);
   }
 
   @Test
-  public void compute_A_rating_and_no_reviewed_when_no_hotspot() {
+  void compute_A_rating_and_no_reviewed_when_no_hotspot() {
     treeRootHolder.setRoot(ROOT_PROJECT);
 
     underTest.visit(ROOT_PROJECT);
 
-    verifyRatingAndReviewedMeasures(PROJECT_REF, A, null);
+    verifyRatingAndReviewedMeasures(PROJECT_REF, A, A,null);
   }
 
   @Test
-  public void compute_status_related_measures() {
+  void compute_status_related_measures() {
     treeRootHolder.setRoot(ROOT_PROJECT);
     fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
       newHotspot(STATUS_TO_REVIEW, null),
@@ -281,7 +284,7 @@ public class SecurityReviewMeasuresVisitorTest {
   }
 
   @Test
-  public void compute_0_status_related_measures_when_no_hotspot() {
+  void compute_0_status_related_measures_when_no_hotspot() {
     treeRootHolder.setRoot(ROOT_PROJECT);
 
     underTest.visit(ROOT_PROJECT);
@@ -289,8 +292,9 @@ public class SecurityReviewMeasuresVisitorTest {
     verifyHotspotStatusMeasures(PROJECT_REF, 0, 0);
   }
 
-  private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, @Nullable Double expectedHotspotsReviewed) {
-    verifySecurityReviewRating(componentRef, expectedReviewRating);
+  private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, Rating expectedSoftwareQualityReviewRating,
+    @Nullable Double expectedHotspotsReviewed) {
+    verifySecurityReviewRating(componentRef, expectedReviewRating, expectedSoftwareQualityReviewRating);
     if (expectedHotspotsReviewed != null) {
       verifySecurityHotspotsReviewed(componentRef, expectedHotspotsReviewed);
     } else {
@@ -298,10 +302,13 @@ public class SecurityReviewMeasuresVisitorTest {
     }
   }
 
-  private void verifySecurityReviewRating(int componentRef, Rating rating) {
+  private void verifySecurityReviewRating(int componentRef, Rating rating, Rating softwareQualityRating) {
     Measure measure = measureRepository.getAddedRawMeasure(componentRef, SECURITY_REVIEW_RATING_KEY).get();
+    Measure softwareQualityMeasure = measureRepository.getAddedRawMeasure(componentRef, SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY).get();
     assertThat(measure.getIntValue()).isEqualTo(rating.getIndex());
     assertThat(measure.getData()).isEqualTo(rating.name());
+    assertThat(softwareQualityMeasure.getIntValue()).isEqualTo(softwareQualityRating.getIndex());
+    assertThat(softwareQualityMeasure.getData()).isEqualTo(softwareQualityRating.name());
   }
 
   private void verifySecurityHotspotsReviewed(int componentRef, double percent) {
index 03e5c44b6cdb3ed282ec0fc8f7482b019423a9c7..69791800a7b9e2d5a6423b60f5c4b0c8182acb4a 100644 (file)
@@ -55,4 +55,15 @@ public class SecurityReviewRating {
     }
     return E;
   }
+
+  public static Rating computeAToDRating(@Nullable Double percent) {
+    if (percent == null || Math.abs(percent - 100.0D) < 10e-6) {
+      return A;
+    } else if (percent >= 70.0D) {
+      return B;
+    } else if (percent >= 50.0D) {
+      return C;
+    }
+    return D;
+  }
 }
index b21b41daf50a77c825f7c6f9e2f81174a3db6f6f..1d586900a1b81abf357c525345c52c81e65fad9f 100644 (file)
  */
 package org.sonar.server.security;
 
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
 import java.util.ArrayList;
 import java.util.List;
 import org.assertj.core.data.Offset;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
 import org.sonar.server.measure.Rating;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -35,16 +33,15 @@ import static org.sonar.server.measure.Rating.B;
 import static org.sonar.server.measure.Rating.C;
 import static org.sonar.server.measure.Rating.D;
 import static org.sonar.server.measure.Rating.E;
+import static org.sonar.server.security.SecurityReviewRating.computeAToDRating;
 import static org.sonar.server.security.SecurityReviewRating.computePercent;
 import static org.sonar.server.security.SecurityReviewRating.computeRating;
 
-@RunWith(DataProviderRunner.class)
-public class SecurityReviewRatingTest {
+class SecurityReviewRatingTest {
 
   private static final Offset<Double> DOUBLE_OFFSET = Offset.offset(0.01d);
 
-  @DataProvider
-  public static Object[][] values() {
+  private static Object[][] values() {
     List<Object[]> res = new ArrayList<>();
     res.add(new Object[] {100.0, A});
     res.add(new Object[] {90.0, A});
@@ -59,14 +56,38 @@ public class SecurityReviewRatingTest {
     return res.toArray(new Object[res.size()][2]);
   }
 
-  @Test
-  @UseDataProvider("values")
-  public void compute_rating(double percent, Rating expectedRating) {
+  private static Object[][] valuesForSoftwareQualityRatings() {
+    List<Object[]> res = new ArrayList<>();
+    res.add(new Object[] {100.0, A});
+    res.add(new Object[] {99.999999, A});
+    res.add(new Object[] {99.99999, B});
+    res.add(new Object[] {99.9, B});
+    res.add(new Object[] {90.0, B});
+    res.add(new Object[] {80.0, B});
+    res.add(new Object[] {75.0, B});
+    res.add(new Object[] {70.0, B});
+    res.add(new Object[] {60, C});
+    res.add(new Object[] {50.0, C});
+    res.add(new Object[] {40.0, D});
+    res.add(new Object[] {30.0, D});
+    res.add(new Object[] {29.9, D});
+    return res.toArray(new Object[res.size()][2]);
+  }
+
+  @ParameterizedTest
+  @MethodSource("values")
+  void compute_rating(double percent, Rating expectedRating) {
     assertThat(computeRating(percent)).isEqualTo(expectedRating);
   }
 
+  @ParameterizedTest
+  @MethodSource("valuesForSoftwareQualityRatings")
+  void compute_ratingForSoftwareQuality(double percent, Rating expectedRating) {
+    assertThat(computeAToDRating(percent)).isEqualTo(expectedRating);
+  }
+
   @Test
-  public void compute_percent() {
+  void compute_percent() {
     assertThat(computePercent(0, 0)).isEmpty();
     assertThat(computePercent(0, 10)).contains(100.0);
     assertThat(computePercent(1, 3)).contains(75.0);