*/
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;
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
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,
}
@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());
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
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())
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;
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;
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
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) {
.filter(MetricDto::isEnabled)
.toList();
+ var caycStatus = checkCaycConditions(metrics, conditionsByMetricId, false);
+ if (caycStatus == NON_COMPLIANT) {
+ caycStatus = checkCaycConditions(metrics, conditionsByMetricId, true);
+ }
+ return caycStatus;
+ }
+
+ private static 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;
}
}
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;