Selaa lähdekoodia

SONAR-20607 CaYC compliancy check should support legacy cayc conditions

tags/10.3.0.82913
Zipeng WU 6 kuukautta sitten
vanhempi
commit
f04dad11a2

+ 36
- 7
server/sonar-webserver-webapi/src/it/java/org/sonar/server/qualitygate/QualityGateCaycCheckerIT.java Näytä tiedosto

@@ -19,9 +19,15 @@
*/
package org.sonar.server.qualitygate;

import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.sonar.api.measures.Metric;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbTester;
@@ -41,10 +47,13 @@ import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.NEW_VIOLATIONS;
import static org.sonar.server.qualitygate.QualityGateCaycChecker.BEST_VALUE_REQUIREMENTS;
import static org.sonar.server.qualitygate.QualityGateCaycChecker.CAYC_METRICS;
import static org.sonar.server.qualitygate.QualityGateCaycChecker.LEGACY_BEST_VALUE_REQUIREMENTS;
import static org.sonar.server.qualitygate.QualityGateCaycChecker.LEGACY_CAYC_METRICS;
import static org.sonar.server.qualitygate.QualityGateCaycStatus.COMPLIANT;
import static org.sonar.server.qualitygate.QualityGateCaycStatus.NON_COMPLIANT;
import static org.sonar.server.qualitygate.QualityGateCaycStatus.OVER_COMPLIANT;

@RunWith(DataProviderRunner.class)
public class QualityGateCaycCheckerIT {

@Rule
@@ -52,16 +61,18 @@ public class QualityGateCaycCheckerIT {
QualityGateCaycChecker underTest = new QualityGateCaycChecker(db.getDbClient());

@Test
public void checkCaycCompliant_when_contains_all_and_only_complicant_conditions_should_return_compliant() {
@UseDataProvider("caycMetrics")
public void checkCaycCompliant_when_contains_all_and_only_compliant_conditions_should_return_compliant(Set<Metric> caycMetrics) {
String qualityGateUuid = "abcd";
CAYC_METRICS.forEach(metric -> insertCondition(insertMetric(metric), qualityGateUuid, metric.getBestValue()));
caycMetrics.forEach(metric -> insertCondition(insertMetric(metric), qualityGateUuid, metric.getBestValue()));
assertEquals(COMPLIANT, underTest.checkCaycCompliant(db.getSession(), qualityGateUuid));
}

@Test
public void checkCaycCompliant_when_extra_conditions_should_return_over_compliant() {
@UseDataProvider("caycMetrics")
public void checkCaycCompliant_when_extra_conditions_should_return_over_compliant(Set<Metric> caycMetrics) {
String qualityGateUuid = "abcd";
CAYC_METRICS.forEach(metric -> insertCondition(insertMetric(metric), qualityGateUuid, metric.getBestValue()));
caycMetrics.forEach(metric -> insertCondition(insertMetric(metric), qualityGateUuid, metric.getBestValue()));

// extra conditions outside of CAYC requirements
List.of(LINE_COVERAGE, DUPLICATED_LINES).forEach(metric -> insertCondition(insertMetric(metric), qualityGateUuid,
@@ -71,12 +82,13 @@ public class QualityGateCaycCheckerIT {
}

@Test
public void checkCaycCompliant_when_conditions_have_lesser_threshold_value_should_return_non_compliant() {
var metrics = CAYC_METRICS.stream().map(this::insertMetric).toList();
@UseDataProvider("caycMetricsAndBestValueRequirements")
public void checkCaycCompliant_when_conditions_have_lesser_threshold_value_should_return_non_compliant(Set<Metric> caycMetrics, Map<String, Double> bestValueRequirements) {
var metrics = caycMetrics.stream().map(this::insertMetric).toList();

String qualityGateUuid = "abcd";
for (var metric : metrics) {
if (BEST_VALUE_REQUIREMENTS.keySet().contains(metric.getKey())) {
if (bestValueRequirements.keySet().contains(metric.getKey())) {
insertCondition(metric, qualityGateUuid, metric.getBestValue() - 1);
} else {
insertCondition(metric, qualityGateUuid, metric.getBestValue());
@@ -89,6 +101,8 @@ public class QualityGateCaycCheckerIT {
public void isCaycCondition_when_check_compliant_condition_should_return_true() {
CAYC_METRICS.stream().map(this::toMetricDto)
.forEach(metricDto -> assertTrue(underTest.isCaycCondition(metricDto)));
LEGACY_CAYC_METRICS.stream().map(this::toMetricDto)
.forEach(metricDto -> assertTrue(underTest.isCaycCondition(metricDto)));
}

@Test
@@ -117,6 +131,21 @@ public class QualityGateCaycCheckerIT {
assertEquals(COMPLIANT, underTest.checkCaycCompliant(db.getSession(), qualityGateUuid));
}

@DataProvider
public static Object[][] caycMetrics() {
return new Object[][]{
{CAYC_METRICS}, {LEGACY_CAYC_METRICS}
};
}

@DataProvider
public static Object[][] caycMetricsAndBestValueRequirements() {
return new Object[][]{
{CAYC_METRICS, BEST_VALUE_REQUIREMENTS},
{LEGACY_CAYC_METRICS, LEGACY_BEST_VALUE_REQUIREMENTS}
};
}

private void insertCondition(MetricDto metricDto, String qualityGateUuid, Double threshold) {
QualityGateConditionDto newCondition = new QualityGateConditionDto().setQualityGateUuid(qualityGateUuid)
.setUuid(Uuids.create())

+ 40
- 9
server/sonar-webserver-webapi/src/main/java/org/sonar/server/qualitygate/QualityGateCaycChecker.java Näytä tiedosto

@@ -20,6 +20,7 @@
package org.sonar.server.qualitygate;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -37,7 +38,10 @@ import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE;
import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_HOTSPOTS_REVIEWED;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING;
import static org.sonar.api.measures.CoreMetrics.NEW_VIOLATIONS;
import static org.sonar.server.qualitygate.QualityGateCaycStatus.COMPLIANT;
import static org.sonar.server.qualitygate.QualityGateCaycStatus.NON_COMPLIANT;
@@ -49,6 +53,7 @@ public class QualityGateCaycChecker {
NEW_VIOLATIONS,
NEW_SECURITY_HOTSPOTS_REVIEWED
).collect(toMap(Metric::getKey, Metric::getBestValue));

static final Set<String> EXISTENCY_REQUIREMENTS = Set.of(
NEW_DUPLICATED_LINES_DENSITY_KEY,
NEW_COVERAGE_KEY
@@ -60,6 +65,22 @@ public class QualityGateCaycChecker {
NEW_COVERAGE
);

// To be removed after transition
static final Map<String, Double> LEGACY_BEST_VALUE_REQUIREMENTS = Stream.of(
NEW_MAINTAINABILITY_RATING,
NEW_RELIABILITY_RATING,
NEW_SECURITY_HOTSPOTS_REVIEWED,
NEW_SECURITY_RATING
).collect(toMap(Metric::getKey, Metric::getBestValue));
static final Set<Metric<? extends Serializable>> LEGACY_CAYC_METRICS = Set.of(
NEW_MAINTAINABILITY_RATING,
NEW_RELIABILITY_RATING,
NEW_SECURITY_HOTSPOTS_REVIEWED,
NEW_SECURITY_RATING,
NEW_DUPLICATED_LINES_DENSITY,
NEW_COVERAGE
);

private final DbClient dbClient;

public QualityGateCaycChecker(DbClient dbClient) {
@@ -80,16 +101,24 @@ public class QualityGateCaycChecker {
.filter(MetricDto::isEnabled)
.toList();

var caycStatus = checkCaycConditions(metrics, conditionsByMetricId, false);
if (caycStatus == NON_COMPLIANT) {
caycStatus = checkCaycConditions(metrics, conditionsByMetricId, true);
}
return caycStatus;
}

private QualityGateCaycStatus checkCaycConditions(List<MetricDto> metrics, Map<String, QualityGateConditionDto> conditionsByMetricId, boolean legacy) {
var caycMetrics = legacy ? LEGACY_CAYC_METRICS : CAYC_METRICS;

long count = metrics.stream()
.filter(metric -> checkMetricCaycCompliant(conditionsByMetricId.get(metric.getUuid()), metric))
.filter(metric -> checkMetricCaycCompliant(conditionsByMetricId.get(metric.getUuid()), metric, legacy))
.count();

if (metrics.size() == count && count == CAYC_METRICS.size()) {
if (metrics.size() == count && count == caycMetrics.size()) {
return COMPLIANT;
} else if (metrics.size() > count && count == CAYC_METRICS.size()) {
} else if (metrics.size() > count && count == caycMetrics.size()) {
return OVER_COMPLIANT;
}

return NON_COMPLIANT;
}

@@ -101,15 +130,17 @@ public class QualityGateCaycChecker {
}

public boolean isCaycCondition(MetricDto metric) {
return CAYC_METRICS.stream().map(Metric::getKey).anyMatch(metric.getKey()::equals);
return Stream.concat(CAYC_METRICS.stream(), LEGACY_CAYC_METRICS.stream())
.map(Metric::getKey).anyMatch(metric.getKey()::equals);
}

private static boolean checkMetricCaycCompliant(QualityGateConditionDto condition, MetricDto metric) {
private static boolean checkMetricCaycCompliant(QualityGateConditionDto condition, MetricDto metric, boolean legacy) {
var bestValueRequirements = legacy ? LEGACY_BEST_VALUE_REQUIREMENTS : BEST_VALUE_REQUIREMENTS;
if (EXISTENCY_REQUIREMENTS.contains(metric.getKey())) {
return true;
} else if (BEST_VALUE_REQUIREMENTS.containsKey(metric.getKey())) {
} else if (bestValueRequirements.containsKey(metric.getKey())) {
Double errorThreshold = Double.valueOf(condition.getErrorThreshold());
Double caycRequiredThreshold = BEST_VALUE_REQUIREMENTS.get(metric.getKey());
Double caycRequiredThreshold = bestValueRequirements.get(metric.getKey());
return caycRequiredThreshold.compareTo(errorThreshold) == 0;
} else {
return false;

Loading…
Peruuta
Tallenna