aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2020-02-03 14:10:24 +0100
committerSonarTech <sonartech@sonarsource.com>2020-02-11 20:46:12 +0100
commitc51fa2468cfe46d85b86d8121de84cd0a06fed89 (patch)
tree569fd424ab6500ee1f779c14bedf38502f0155c4
parent49a43c2bcafa4b5af52c50b399c772f828d0f534 (diff)
downloadsonarqube-c51fa2468cfe46d85b86d8121de84cd0a06fed89.tar.gz
sonarqube-c51fa2468cfe46d85b86d8121de84cd0a06fed89.zip
SONAR-12962 Compute Security Review measures on Applications
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java16
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewCounter.java8
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java11
-rw-r--r--server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfolios.java (renamed from server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplications.java)13
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java136
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java131
-rw-r--r--server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosTest.java (renamed from server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest.java)24
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImpl.java12
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImplTest.java50
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties6
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java88
12 files changed, 378 insertions, 119 deletions
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java
index 5c48a164805..806915dded5 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitor.java
@@ -30,6 +30,8 @@ import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import org.sonar.ce.task.projectanalysis.period.PeriodHolder;
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;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY;
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;
@@ -45,6 +47,8 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
private final AnalysisMetadataHolder analysisMetadataHolder;
private final Metric newSecurityReviewRatingMetric;
private final Metric newSecurityHotspotsReviewedMetric;
+ private final Metric newSecurityHotspotsReviewedStatusMetric;
+ private final Metric newSecurityHotspotsToReviewStatusMetric;
public NewSecurityReviewMeasuresVisitor(ComponentIssuesRepository componentIssuesRepository, MeasureRepository measureRepository, PeriodHolder periodHolder,
AnalysisMetadataHolder analysisMetadataHolder, MetricRepository metricRepository) {
@@ -55,11 +59,19 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
this.analysisMetadataHolder = analysisMetadataHolder;
this.newSecurityReviewRatingMetric = metricRepository.getByKey(NEW_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);
}
@Override
public void visitProject(Component project, Path<SecurityReviewCounter> path) {
computeMeasure(project, path);
+ if (!periodHolder.hasPeriod() && !analysisMetadataHolder.isPullRequest()) {
+ return;
+ }
+ // The following measures are only computed on projects level as they are required to compute the others measures on applications
+ measureRepository.add(project, newSecurityHotspotsReviewedStatusMetric, Measure.newMeasureBuilder().setVariation(path.current().getHotspotsReviewed()).createNoValue());
+ measureRepository.add(project, newSecurityHotspotsToReviewStatusMetric, Measure.newMeasureBuilder().setVariation(path.current().getHotspotsToReview()).createNoValue());
}
@Override
@@ -79,10 +91,10 @@ public class NewSecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Se
componentIssuesRepository.getIssues(component)
.stream()
.filter(issue -> issue.type().equals(SECURITY_HOTSPOT))
- .filter(issue -> analysisMetadataHolder.isPullRequest() || periodHolder.getPeriod().isOnPeriod(issue.creationDate()) )
+ .filter(issue -> analysisMetadataHolder.isPullRequest() || periodHolder.getPeriod().isOnPeriod(issue.creationDate()))
.forEach(issue -> path.current().processHotspot(issue));
- Double percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
+ double percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
measureRepository.add(component, newSecurityHotspotsReviewedMetric, Measure.newMeasureBuilder().setVariation(percent).createNoValue());
measureRepository.add(component, newSecurityReviewRatingMetric, Measure.newMeasureBuilder().setVariation(computeRating(percent).getIndex()).createNoValue());
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewCounter.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewCounter.java
index 07d35e3a98c..d09f039b98d 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewCounter.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewCounter.java
@@ -25,8 +25,8 @@ import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
final class SecurityReviewCounter {
- private long hotspotsReviewed;
- private long hotspotsToReview;
+ private int hotspotsReviewed;
+ private int hotspotsToReview;
SecurityReviewCounter() {
// prevents instantiation
@@ -45,11 +45,11 @@ final class SecurityReviewCounter {
hotspotsToReview += otherCounter.hotspotsToReview;
}
- public long getHotspotsReviewed() {
+ public int getHotspotsReviewed() {
return hotspotsReviewed;
}
- public long getHotspotsToReview() {
+ public int getHotspotsToReview() {
return hotspotsToReview;
}
}
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java
index 2bb1fdc3d3f..574d53a74e3 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitor.java
@@ -30,6 +30,8 @@ import org.sonar.ce.task.projectanalysis.metric.Metric;
import org.sonar.ce.task.projectanalysis.metric.MetricRepository;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_KEY;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.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;
@@ -43,6 +45,8 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
private final MeasureRepository measureRepository;
private final Metric securityReviewRatingMetric;
private final Metric securityHotspotsReviewedMetric;
+ private final Metric securityHotspotsReviewedStatusMetric;
+ private final Metric securityHotspotsToReviewStatusMetric;
public SecurityReviewMeasuresVisitor(ComponentIssuesRepository componentIssuesRepository, MeasureRepository measureRepository, MetricRepository metricRepository) {
super(FILE, POST_ORDER, SecurityReviewMeasuresVisitor.CounterFactory.INSTANCE);
@@ -50,11 +54,16 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
this.measureRepository = measureRepository;
this.securityReviewRatingMetric = metricRepository.getByKey(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);
}
@Override
public void visitProject(Component project, Path<SecurityReviewCounter> path) {
computeMeasure(project, path);
+ // The following measures are only computed on projects level as they are required to compute the others measures on applications
+ measureRepository.add(project, securityHotspotsReviewedStatusMetric, Measure.newMeasureBuilder().create(path.current().getHotspotsReviewed()));
+ measureRepository.add(project, securityHotspotsToReviewStatusMetric, Measure.newMeasureBuilder().create(path.current().getHotspotsToReview()));
}
@Override
@@ -73,7 +82,7 @@ public class SecurityReviewMeasuresVisitor extends PathAwareVisitorAdapter<Secur
.filter(issue -> issue.type().equals(SECURITY_HOTSPOT))
.forEach(issue -> path.current().processHotspot(issue));
- Double percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
+ double percent = computePercent(path.current().getHotspotsToReview(), path.current().getHotspotsReviewed());
measureRepository.add(component, securityHotspotsReviewedMetric, Measure.newMeasureBuilder().create(percent, securityHotspotsReviewedMetric.getDecimalScale()));
measureRepository.add(component, securityReviewRatingMetric, RatingMeasures.get(computeRating(percent)));
diff --git a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplications.java b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfolios.java
index 382606a81e6..a88e3d07c43 100644
--- a/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplications.java
+++ b/server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfolios.java
@@ -34,15 +34,16 @@ import org.sonar.server.security.SecurityReviewRating;
import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING_KEY;
+import static org.sonar.ce.task.projectanalysis.component.ViewAttributes.Type.APPLICATION;
-public class SecurityReviewRatingVisitorForPortfoliosAndApplications extends TypeAwareVisitorAdapter {
+public class SecurityReviewRatingVisitorForPortfolios extends TypeAwareVisitorAdapter {
private final MeasureRepository measureRepository;
private final Metric nclocMetric;
private final Metric securityHostspotsMetric;
private final Metric securityReviewRatingMetric;
- public SecurityReviewRatingVisitorForPortfoliosAndApplications(MeasureRepository measureRepository, MetricRepository metricRepository) {
+ public SecurityReviewRatingVisitorForPortfolios(MeasureRepository measureRepository, MetricRepository metricRepository) {
super(CrawlerDepthLimit.SUBVIEW, Order.POST_ORDER);
this.measureRepository = measureRepository;
this.nclocMetric = metricRepository.getByKey(NCLOC_KEY);
@@ -51,12 +52,10 @@ public class SecurityReviewRatingVisitorForPortfoliosAndApplications extends Typ
}
@Override
- public void visitProject(Component project) {
- // Do nothing
- }
-
- @Override
public void visitView(Component view) {
+ if (view.getViewAttributes().getType().equals(APPLICATION)) {
+ return;
+ }
computeMeasure(view);
}
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java
index 08b85755a8d..c39752eb775 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/NewSecurityReviewMeasuresVisitorTest.java
@@ -22,6 +22,7 @@ package org.sonar.ce.task.projectanalysis.qualitymodel;
import java.util.Arrays;
import java.util.Date;
import javax.annotation.Nullable;
+import org.assertj.core.api.Assertions;
import org.assertj.core.data.Offset;
import org.junit.Rule;
import org.junit.Test;
@@ -34,7 +35,6 @@ 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.measure.MeasureAssert;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
import org.sonar.ce.task.projectanalysis.period.Period;
@@ -52,6 +52,10 @@ import static org.sonar.api.issue.Issue.STATUS_REVIEWED;
import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
+import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY;
import static org.sonar.api.rule.Severity.MAJOR;
@@ -59,6 +63,7 @@ import static org.sonar.api.rule.Severity.MINOR;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.DIRECTORY;
import static org.sonar.ce.task.projectanalysis.component.Component.Type.FILE;
import static org.sonar.ce.task.projectanalysis.component.ReportComponent.builder;
+import static org.sonar.ce.task.projectanalysis.measure.MeasureAssert.assertThat;
import static org.sonar.server.measure.Rating.A;
import static org.sonar.server.measure.Rating.B;
import static org.sonar.server.measure.Rating.C;
@@ -99,7 +104,9 @@ public class NewSecurityReviewMeasuresVisitorTest {
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(NEW_SECURITY_REVIEW_RATING)
- .add(NEW_SECURITY_HOTSPOTS_REVIEWED);
+ .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
@@ -131,11 +138,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, A, 100.0);
- verifyMeasures(DIRECTORY_REF, A, 100.0);
- verifyMeasures(ROOT_DIR_REF, A, 100.0);
- verifyMeasures(PROJECT_REF, A, 100.0);
+ 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);
}
@Test
@@ -160,11 +167,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, A, 80.0);
- verifyMeasures(DIRECTORY_REF, A, 87.5);
- verifyMeasures(ROOT_DIR_REF, A, 87.5);
- verifyMeasures(PROJECT_REF, A, 87.5);
+ 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);
}
@Test
@@ -189,11 +196,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, B, 71.42);
- verifyMeasures(DIRECTORY_REF, B, 75.0);
- verifyMeasures(ROOT_DIR_REF, B, 75.0);
- verifyMeasures(PROJECT_REF, B, 75.0);
+ 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);
}
@Test
@@ -217,11 +224,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, C, 50.0);
- verifyMeasures(FILE_2_REF, C, 60.0);
- verifyMeasures(DIRECTORY_REF, C, 57.14);
- verifyMeasures(ROOT_DIR_REF, C, 57.14);
- verifyMeasures(PROJECT_REF, C, 57.14);
+ 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);
}
@Test
@@ -246,11 +253,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, D, 33.33);
- verifyMeasures(FILE_2_REF, D, 40.0);
- verifyMeasures(DIRECTORY_REF, D, 37.5);
- verifyMeasures(ROOT_DIR_REF, D, 37.5);
- verifyMeasures(PROJECT_REF, D, 37.5);
+ 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);
}
@Test
@@ -273,11 +280,11 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, D, 33.33);
- verifyMeasures(FILE_2_REF, E, 0.0);
- verifyMeasures(DIRECTORY_REF, E, 16.66);
- verifyMeasures(ROOT_DIR_REF, E, 16.66);
- verifyMeasures(PROJECT_REF, E, 16.66);
+ 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);
}
@Test
@@ -290,7 +297,7 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(PROJECT_REF, A, 100.0);
+ verifyRatingAndReviewedMeasures(PROJECT_REF, A, 100.0);
}
@Test
@@ -317,11 +324,45 @@ public class NewSecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, C, 50.0);
- verifyMeasures(FILE_2_REF, C, 57.14);
- verifyMeasures(DIRECTORY_REF, C, 55.55);
- verifyMeasures(ROOT_DIR_REF, C, 55.55);
- verifyMeasures(PROJECT_REF, C, 55.55);
+ verifyRatingAndReviewedMeasures(FILE_1_REF, C, 50.0);
+ verifyRatingAndReviewedMeasures(FILE_2_REF, C, 57.14);
+ verifyRatingAndReviewedMeasures(DIRECTORY_REF, C, 55.55);
+ verifyRatingAndReviewedMeasures(ROOT_DIR_REF, C, 55.55);
+ verifyRatingAndReviewedMeasures(PROJECT_REF, C, 55.55);
+ }
+
+ @Test
+ public void compute_status_related_measures() {
+ treeRootHolder.setRoot(ROOT_PROJECT);
+ fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
+ newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ // Should not be taken into account
+ newIssue());
+ fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
+ newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newHotspot(STATUS_TO_REVIEW, null).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED).setCreationDate(AFTER_LEAK_PERIOD_DATE),
+ newIssue());
+
+ underTest.visit(ROOT_PROJECT);
+
+ verifyHotspotStatusMeasures(FILE_1_REF, null, null);
+ verifyHotspotStatusMeasures(FILE_2_REF, null, null);
+ verifyHotspotStatusMeasures(DIRECTORY_REF, null, null);
+ verifyHotspotStatusMeasures(ROOT_DIR_REF, null, null);
+ verifyHotspotStatusMeasures(PROJECT_REF, 4, 3);
+ }
+
+ @Test
+ public void compute_0_status_related_measures_when_no_hotspot() {
+ treeRootHolder.setRoot(ROOT_PROJECT);
+
+ underTest.visit(ROOT_PROJECT);
+
+ verifyHotspotStatusMeasures(PROJECT_REF, 0, 0);
}
@Test
@@ -337,12 +378,25 @@ public class NewSecurityReviewMeasuresVisitorTest {
assertThat(measureRepository.getAddedRawMeasures(PROJECT_REF).values()).isEmpty();
}
- private void verifyMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
- MeasureAssert.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasVariation(expectedReviewRating.getIndex());
- MeasureAssert.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasVariation(expectedHotspotsReviewed,
+ private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_REVIEW_RATING_KEY)).hasVariation(expectedReviewRating.getIndex());
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_KEY)).hasVariation(expectedHotspotsReviewed,
VARIATION_COMPARISON_OFFSET);
}
+ private void verifyHotspotStatusMeasures(int componentRef, @Nullable Integer hotspotsReviewed, @Nullable Integer hotspotsToReview) {
+ if (hotspotsReviewed == null) {
+ Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).isEmpty();
+ } else {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).hasVariation(hotspotsReviewed);
+ }
+ if (hotspotsReviewed == null) {
+ Assertions.assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).isEmpty();
+ } else {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).hasVariation(hotspotsToReview);
+ }
+ }
+
private static DefaultIssue newHotspot(String status, @Nullable String resolution) {
return new DefaultIssue()
.setKey(Uuids.create())
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java
index 7e259ea5998..9780f4e72f3 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewMeasuresVisitorTest.java
@@ -41,6 +41,10 @@ import static org.sonar.api.issue.Issue.RESOLUTION_FIXED;
import static org.sonar.api.issue.Issue.RESOLUTION_SAFE;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_KEY;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS;
+import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING_KEY;
import static org.sonar.api.rule.Severity.MAJOR;
@@ -81,7 +85,9 @@ public class SecurityReviewMeasuresVisitorTest {
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(SECURITY_REVIEW_RATING)
- .add(SECURITY_HOTSPOTS_REVIEWED);
+ .add(SECURITY_HOTSPOTS_REVIEWED)
+ .add(SECURITY_HOTSPOTS_REVIEWED_STATUS)
+ .add(SECURITY_HOTSPOTS_TO_REVIEW_STATUS);
@Rule
public ComponentIssuesRepositoryRule componentIssuesRepositoryRule = new ComponentIssuesRepositoryRule(treeRootHolder);
@Rule
@@ -93,7 +99,7 @@ public class SecurityReviewMeasuresVisitorTest {
new SecurityReviewMeasuresVisitor(componentIssuesRepositoryRule, measureRepository, metricRepository)));
@Test
- public void compute_measures_when_100_percent_hotspots_reviewed() {
+ public 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),
@@ -106,15 +112,15 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, A, 100.0);
- verifyMeasures(DIRECTORY_REF, A, 100.0);
- verifyMeasures(ROOT_DIR_REF, A, 100.0);
- verifyMeasures(PROJECT_REF, A, 100.0);
+ 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);
}
@Test
- public void compute_measures_when_more_than_80_percent_hotspots_reviewed() {
+ public 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),
@@ -132,15 +138,15 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, A, 80.0);
- verifyMeasures(DIRECTORY_REF, A, 87.5);
- verifyMeasures(ROOT_DIR_REF, A, 87.5);
- verifyMeasures(PROJECT_REF, A, 87.5);
+ 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);
}
@Test
- public void compute_measures_when_more_than_70_percent_hotspots_reviewed() {
+ public 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),
@@ -158,15 +164,15 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, A, 100.0);
- verifyMeasures(FILE_2_REF, B, 71.4);
- verifyMeasures(DIRECTORY_REF, B, 75.0);
- verifyMeasures(ROOT_DIR_REF, B, 75.0);
- verifyMeasures(PROJECT_REF, B, 75.0);
+ 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);
}
@Test
- public void compute_measures_when_more_than_50_percent_hotspots_reviewed() {
+ public 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),
@@ -183,15 +189,15 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, C, 50.0);
- verifyMeasures(FILE_2_REF, C, 60.0);
- verifyMeasures(DIRECTORY_REF, C, 57.1);
- verifyMeasures(ROOT_DIR_REF, C, 57.1);
- verifyMeasures(PROJECT_REF, C, 57.1);
+ 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);
}
@Test
- public void compute_measures_when_more_30_than_percent_hotspots_reviewed() {
+ public 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),
@@ -209,15 +215,15 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, D, 33.3);
- verifyMeasures(FILE_2_REF, D, 40.0);
- verifyMeasures(DIRECTORY_REF, D, 37.5);
- verifyMeasures(ROOT_DIR_REF, D, 37.5);
- verifyMeasures(PROJECT_REF, D, 37.5);
+ 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);
}
@Test
- public void compute_measures_when_less_than_30_percent_hotspots_reviewed() {
+ public 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),
@@ -233,11 +239,11 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(FILE_1_REF, D, 33.3);
- verifyMeasures(FILE_2_REF, E, 0.0);
- verifyMeasures(DIRECTORY_REF, E, 16.7);
- verifyMeasures(ROOT_DIR_REF, E, 16.7);
- verifyMeasures(PROJECT_REF, E, 16.7);
+ 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);
}
@Test
@@ -246,10 +252,44 @@ public class SecurityReviewMeasuresVisitorTest {
underTest.visit(ROOT_PROJECT);
- verifyMeasures(PROJECT_REF, A, 100.0);
+ verifyRatingAndReviewedMeasures(PROJECT_REF, A, 100.0);
}
- private void verifyMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
+ @Test
+ public void compute_status_related_measures() {
+ treeRootHolder.setRoot(ROOT_PROJECT);
+ fillComponentIssuesVisitorRule.setIssues(FILE_1_REF,
+ newHotspot(STATUS_TO_REVIEW, null),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
+ // Should not be taken into account
+ newIssue());
+ fillComponentIssuesVisitorRule.setIssues(FILE_2_REF,
+ newHotspot(STATUS_TO_REVIEW, null),
+ newHotspot(STATUS_TO_REVIEW, null),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
+ newHotspot(STATUS_REVIEWED, RESOLUTION_FIXED),
+ newIssue());
+
+ underTest.visit(ROOT_PROJECT);
+
+ verifyHotspotStatusMeasures(FILE_1_REF, null, null);
+ verifyHotspotStatusMeasures(FILE_2_REF, null, null);
+ verifyHotspotStatusMeasures(DIRECTORY_REF, null, null);
+ verifyHotspotStatusMeasures(ROOT_DIR_REF, null, null);
+ verifyHotspotStatusMeasures(PROJECT_REF, 4, 3);
+ }
+
+ @Test
+ public void compute_0_status_related_measures_when_no_hotspot() {
+ treeRootHolder.setRoot(ROOT_PROJECT);
+
+ underTest.visit(ROOT_PROJECT);
+
+ verifyHotspotStatusMeasures(PROJECT_REF, 0, 0);
+ }
+
+ private void verifyRatingAndReviewedMeasures(int componentRef, Rating expectedReviewRating, double expectedHotspotsReviewed) {
verifySecurityReviewRating(componentRef, expectedReviewRating);
verifySecurityHotspotsReviewed(componentRef, expectedHotspotsReviewed);
}
@@ -264,6 +304,19 @@ public class SecurityReviewMeasuresVisitorTest {
assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_REVIEWED_KEY).get().getDoubleValue()).isEqualTo(percent);
}
+ private void verifyHotspotStatusMeasures(int componentRef, @Nullable Integer hotspotsReviewed, @Nullable Integer hotspotsToReview) {
+ if (hotspotsReviewed == null){
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY)).isEmpty();
+ } else {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY).get().getIntValue()).isEqualTo(hotspotsReviewed);
+ }
+ if (hotspotsReviewed == null){
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY)).isEmpty();
+ } else {
+ assertThat(measureRepository.getAddedRawMeasure(componentRef, SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY).get().getIntValue()).isEqualTo(hotspotsToReview);
+ }
+ }
+
private static DefaultIssue newHotspot(String status, @Nullable String resolution) {
return new DefaultIssue()
.setKey(Uuids.create())
diff --git a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest.java b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosTest.java
index a55e2db19be..099113d525e 100644
--- a/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest.java
+++ b/server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/qualitymodel/SecurityReviewRatingVisitorForPortfoliosTest.java
@@ -26,7 +26,6 @@ import org.sonar.ce.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.ce.task.projectanalysis.component.ViewAttributes;
import org.sonar.ce.task.projectanalysis.component.ViewsComponent;
import org.sonar.ce.task.projectanalysis.component.VisitorsCrawler;
-import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.measure.MeasureRepositoryRule;
import org.sonar.ce.task.projectanalysis.metric.MetricRepositoryRule;
@@ -42,22 +41,18 @@ import static org.sonar.ce.task.projectanalysis.measure.Measure.newMeasureBuilde
import static org.sonar.server.measure.Rating.B;
import static org.sonar.server.measure.Rating.C;
-public class SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest {
+public class SecurityReviewRatingVisitorForPortfoliosTest {
private static final int PORTFOLIO_REF = 10;
private static final int SUB_PORTFOLIO_1_REF = 11;
private static final int SUB_PORTFOLIO_2_REF = 12;
private static final Component PORTFOLIO = ViewsComponent.builder(Component.Type.VIEW, Integer.toString(PORTFOLIO_REF))
+ .setViewAttributes(new ViewAttributes(ViewAttributes.Type.PORTFOLIO))
.addChildren(
ViewsComponent.builder(Component.Type.SUBVIEW, Integer.toString(SUB_PORTFOLIO_1_REF)).build(),
ViewsComponent.builder(Component.Type.SUBVIEW, Integer.toString(SUB_PORTFOLIO_2_REF)).build())
.build();
- private static final int APPLICATION_REF = 20;
- private static final Component APPLICATION = ViewsComponent.builder(Component.Type.VIEW, Integer.toString(APPLICATION_REF))
- .setViewAttributes(new ViewAttributes(ViewAttributes.Type.APPLICATION))
- .build();
-
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@@ -70,7 +65,7 @@ public class SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest {
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- private VisitorsCrawler underTest = new VisitorsCrawler(singletonList(new SecurityReviewRatingVisitorForPortfoliosAndApplications(measureRepository, metricRepository)));
+ private VisitorsCrawler underTest = new VisitorsCrawler(singletonList(new SecurityReviewRatingVisitorForPortfolios(measureRepository, metricRepository)));
@Test
public void compute_security_review_rating_on_portfolio() {
@@ -90,19 +85,6 @@ public class SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest {
}
@Test
- public void compute_security_review_rating_on_application() {
- treeRootHolder.setRoot(APPLICATION);
- measureRepository.addRawMeasure(APPLICATION_REF, NCLOC_KEY, newMeasureBuilder().create(1000));
- measureRepository.addRawMeasure(APPLICATION_REF, SECURITY_HOTSPOTS_KEY, newMeasureBuilder().create(12));
-
- underTest.visit(APPLICATION);
-
- Measure measure = measureRepository.getAddedRawMeasure(APPLICATION_REF, SECURITY_REVIEW_RATING_KEY).get();
- assertThat(measure.getIntValue()).isEqualTo(C.getIndex());
- assertThat(measure.getData()).isEqualTo(C.name());
- }
-
- @Test
public void compute_nothing_when_no_ncloc() {
treeRootHolder.setRoot(PORTFOLIO);
measureRepository.addRawMeasure(PORTFOLIO_REF, SECURITY_HOTSPOTS_KEY, newMeasureBuilder().create(2));
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java
index 6a5d2673eb3..f96839250fc 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/security/SecurityReviewRating.java
@@ -55,7 +55,7 @@ public class SecurityReviewRating {
}
}
- public static Double computePercent(long hotspotsToReview, long hotspotsReviewed) {
+ public static double computePercent(long hotspotsToReview, long hotspotsReviewed) {
long total = hotspotsToReview + hotspotsReviewed;
if (total == 0) {
return 100.0;
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImpl.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImpl.java
index f65b6bad7f0..d4a63507f33 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImpl.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImpl.java
@@ -117,6 +117,12 @@ public class IssueMetricFormulaFactoryImpl implements IssueMetricFormulaFactory
(context, issues) -> context
.setValue(computePercent(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, false), issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, false)))),
+ new IssueMetricFormula(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, false,
+ (context, issues) -> context.setValue(issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, false))),
+
+ new IssueMetricFormula(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, false,
+ (context, issues) -> context.setValue(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, false))),
+
new IssueMetricFormula(CoreMetrics.NEW_CODE_SMELLS, true,
(context, issues) -> context.setLeakValue(issues.countUnresolvedByType(RuleType.CODE_SMELL, true))),
@@ -180,6 +186,12 @@ public class IssueMetricFormulaFactoryImpl implements IssueMetricFormulaFactory
context.setLeakValue(percent);
}),
+ new IssueMetricFormula(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, true,
+ (context, issues) -> context.setLeakValue(issues.countHotspotsByStatus(Issue.STATUS_REVIEWED, true))),
+
+ new IssueMetricFormula(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, true,
+ (context, issues) -> context.setLeakValue(issues.countHotspotsByStatus(Issue.STATUS_TO_REVIEW, true))),
+
new IssueMetricFormula(CoreMetrics.NEW_SQALE_DEBT_RATIO, true,
(context, issues) -> context.setLeakValue(100.0 * newDebtDensity(context)),
asList(CoreMetrics.NEW_TECHNICAL_DEBT, CoreMetrics.NEW_DEVELOPMENT_COST)),
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImplTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImplTest.java
index f23aa1c8cc1..7f92edb76e0 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImplTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/measure/live/IssueMetricFormulaFactoryImplTest.java
@@ -139,13 +139,35 @@ public class IssueMetricFormulaFactoryImplTest {
with(
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
- .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED, 75.0);
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED, 75.0);
withNoIssues()
.assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED, 100.0);
}
@Test
+ public void test_security_hotspots_reviewed_status() {
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
+
+ withNoIssues()
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
+ }
+
+ @Test
+ public void test_security_hotspots_to_review_status() {
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1))
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
+
+ withNoIssues()
+ .assertThatValueIs(CoreMetrics.SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
+ }
+
+ @Test
public void count_unresolved_by_severity() {
withNoIssues()
.assertThatValueIs(CoreMetrics.BLOCKER_VIOLATIONS, 0)
@@ -679,6 +701,32 @@ public class IssueMetricFormulaFactoryImplTest {
}
@Test
+ public void test_new_security_hotspots_reviewed_status() {
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
+ // not in leak
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 3.0);
+
+ withNoIssues()
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS, 0.0);
+ }
+
+ @Test
+ public void test_new_security_hotspots_to_review_status() {
+ with(
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_REVIEWED).setCount(3).setInLeak(true),
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(1).setInLeak(true),
+ // not in leak
+ newGroup(RuleType.SECURITY_HOTSPOT).setStatus(Issue.STATUS_TO_REVIEW).setCount(5).setInLeak(false))
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 1.0);
+
+ withNoIssues()
+ .assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS, 0.0);
+ }
+
+ @Test
public void test_new_sqale_debt_ratio_and_new_maintainability_rating() {
withNoIssues()
.assertThatLeakValueIs(CoreMetrics.NEW_SQALE_DEBT_RATIO, 0)
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 45e6844cc53..a45aafd6321 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2115,11 +2115,13 @@ metric.new_security_hotspots.short_name=Security Hotspots
metric.new_security_hotspots_reviewed.description=Percentage of Security Hotspots Reviewed on New Code
metric.new_security_hotspots_reviewed.name=Security Hotspots Reviewed on New Code
metric.new_security_hotspots_reviewed.short_name=Security Hotspots Reviewed
+metric.new_security_hotspots_reviewed_status.description=Security Review Reviewed Status on New Code
+metric.new_security_hotspots_reviewed_status.name=Security Review Reviewed Status on New Code
+metric.new_security_hotspots_to_review_status.description=Security Review To Review Status on New Code
+metric.new_security_hotspots_to_review_status.name=Security Review To Review Status on New Code
metric.new_security_rating.description=Security rating on new code
metric.new_security_rating.name=Security Rating on New Code
metric.new_security_rating.extra_short_name=Rating
-metric.new_security_review_rating.description=Security Review rating on new code
-metric.new_security_review_rating.name=Security Review Rating on New Code
metric.new_security_remediation_effort.description=Security remediation effort on new code
metric.new_security_remediation_effort.name=Security Remediation Effort on New Code
metric.new_security_remediation_effort.extra_short_name=Remediation Effort
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
index 2f2e58de4c3..4921e34a853 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java
@@ -1590,6 +1590,94 @@ public final class CoreMetrics {
.setBestValue(100.0)
.create();
+ /**
+ * @since 8.2
+ */
+ public static final String SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY = "security_hotspots_reviewed_status";
+
+ /**
+ * @since 8.2
+ *
+ * This hidden metric is only needed to compute 'security_review_rating' and 'security_hotspots_reviewed' on Applications.
+ */
+ public static final Metric<Integer> SECURITY_HOTSPOTS_REVIEWED_STATUS = new Metric.Builder(SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY, "Security Review Reviewed Status",
+ Metric.ValueType.INT)
+ .setDescription("Security Review Reviewed Status")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setQualitative(false)
+ .setDomain(DOMAIN_SECURITY_REVIEW)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .setDeleteHistoricalData(true)
+ .setHidden(true)
+ .create();
+
+ /**
+ * @since 8.2
+ */
+ public static final String SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY = "security_hotspots_to_review_status";
+
+ /**
+ * @since 8.2
+ *
+ * This hidden metric is only needed to compute 'security_review_rating' and 'security_hotspots_reviewed' on Applications.
+ */
+ public static final Metric<Integer> SECURITY_HOTSPOTS_TO_REVIEW_STATUS = new Metric.Builder(SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY, "Security Review To Review Status",
+ Metric.ValueType.INT)
+ .setDescription("Security Review To Review Status")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setQualitative(false)
+ .setDomain(DOMAIN_SECURITY_REVIEW)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .setDeleteHistoricalData(true)
+ .setHidden(true)
+ .create();
+
+ /**
+ * @since 8.2
+ */
+ public static final String NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY = "new_security_hotspots_reviewed_status";
+
+ /**
+ * @since 8.2
+ *
+ * This hidden metric is only needed to compute 'new_security_review_rating' and 'new_security_hotspots_reviewed' on Applications.
+ */
+ public static final Metric<Integer> NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS = new Metric.Builder(NEW_SECURITY_HOTSPOTS_REVIEWED_STATUS_KEY,
+ "Security Review Reviewed Status on New Code", Metric.ValueType.INT)
+ .setDescription("Security Review Reviewed Status on New Code")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setQualitative(false)
+ .setDomain(DOMAIN_SECURITY_REVIEW)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .setDeleteHistoricalData(true)
+ .setHidden(true)
+ .create();
+
+ /**
+ * @since 8.2
+ */
+ public static final String NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY = "new_security_hotspots_to_review_status";
+
+ /**
+ * @since 8.2
+ *
+ * This hidden metric is only needed to compute 'new_security_review_rating' and 'new_security_hotspots_reviewed' on Applications.
+ */
+ public static final Metric<Integer> NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS = new Metric.Builder(NEW_SECURITY_HOTSPOTS_TO_REVIEW_STATUS_KEY,
+ "Security Review To Review Status on New Code", Metric.ValueType.INT)
+ .setDescription("Security Review To Review Status on New Code")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setQualitative(false)
+ .setDomain(DOMAIN_SECURITY_REVIEW)
+ .setBestValue(0.0)
+ .setOptimizedBestValue(true)
+ .setDeleteHistoricalData(true)
+ .setHidden(true)
+ .create();
+
// --------------------------------------------------------------------------------------------------------------------
//
// FILE DATA