@@ -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()); | |||
@@ -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; | |||
} | |||
} |
@@ -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))); | |||
@@ -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); | |||
@@ -50,13 +51,11 @@ public class SecurityReviewRatingVisitorForPortfoliosAndApplications extends Typ | |||
this.securityReviewRatingMetric = metricRepository.getByKey(SECURITY_REVIEW_RATING_KEY); | |||
} | |||
@Override | |||
public void visitProject(Component project) { | |||
// Do nothing | |||
} | |||
@Override | |||
public void visitView(Component view) { | |||
if (view.getViewAttributes().getType().equals(APPLICATION)) { | |||
return; | |||
} | |||
computeMeasure(view); | |||
} | |||
@@ -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()) |
@@ -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()) |
@@ -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() { | |||
@@ -89,19 +84,6 @@ public class SecurityReviewRatingVisitorForPortfoliosAndApplicationsTest { | |||
assertThat(measureRepository.getAddedRawMeasure(PORTFOLIO_REF, SECURITY_REVIEW_RATING_KEY).get().getIntValue()).isEqualTo(B.getIndex()); | |||
} | |||
@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); |
@@ -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; |
@@ -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)), |
@@ -139,12 +139,34 @@ 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() | |||
@@ -678,6 +700,32 @@ public class IssueMetricFormulaFactoryImplTest { | |||
.assertThatLeakValueIs(CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED, 100.0); | |||
} | |||
@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() |
@@ -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 |
@@ -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 |