--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.metric;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import java.util.Optional;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+
+import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY;
+import static org.sonar.api.measures.CoreMetrics.CRITICAL_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
+import static org.sonar.api.measures.CoreMetrics.INFO_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.MAJOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.MINOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_CODE_SMELLS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_INFO_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.NEW_MINOR_VIOLATIONS_KEY;
+import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_HIGH_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_INFO_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_LOW_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_HIGH_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_INFO_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_LOW_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY;
+
+/**
+ * Defines the metrics mapping between the standard mode and the MQR mode.
+ * This list all the metrics that are specific for each mode, and the equivalent metric in the other mode.
+ */
+public class StandardToMQRMetrics {
+ private static final BiMap<String, String> STANDARD_TO_MQR_MODE_METRICS;
+
+ private static final BiMap<String, String> MQR_TO_STANDARD_MODE_METRICS;
+
+ static {
+ STANDARD_TO_MQR_MODE_METRICS = HashBiMap.create();
+ // Severity related metrics
+ STANDARD_TO_MQR_MODE_METRICS.put(BLOCKER_VIOLATIONS_KEY, SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_BLOCKER_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CRITICAL_VIOLATIONS_KEY, SOFTWARE_QUALITY_HIGH_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_CRITICAL_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_HIGH_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(MAJOR_VIOLATIONS_KEY, SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_MAJOR_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(MINOR_VIOLATIONS_KEY, SOFTWARE_QUALITY_LOW_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_MINOR_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_LOW_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(INFO_VIOLATIONS_KEY, SOFTWARE_QUALITY_INFO_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_INFO_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_INFO_ISSUES_KEY);
+
+ // Maintainability related metrics
+ STANDARD_TO_MQR_MODE_METRICS.put(CODE_SMELLS_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(NEW_CODE_SMELLS_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(SQALE_RATING_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.TECHNICAL_DEBT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_TECHNICAL_DEBT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SQALE_DEBT_RATIO_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SQALE_DEBT_RATIO_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
+
+ STANDARD_TO_MQR_MODE_METRICS.put(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY);
+
+ // Security related metrics
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SECURITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SECURITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SECURITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.VULNERABILITIES_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_VULNERABILITIES_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_ISSUES_KEY);
+
+ // Reliability related metrics
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.BUGS_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_ISSUES_KEY);
+ STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_BUGS_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_ISSUES_KEY);
+
+ MQR_TO_STANDARD_MODE_METRICS = STANDARD_TO_MQR_MODE_METRICS.inverse();
+ }
+
+ private StandardToMQRMetrics() {
+ }
+
+ public static boolean isStandardMetric(String metricKey) {
+ return STANDARD_TO_MQR_MODE_METRICS.containsKey(metricKey);
+ }
+
+ public static boolean isMQRMetric(String metricKey) {
+ return MQR_TO_STANDARD_MODE_METRICS.containsKey(metricKey);
+ }
+
+ /**
+ * Retrieves equivalent metric in the other mode. Return empty if metric has no equivalence
+ */
+ public static Optional<String> getEquivalentMetric(String metricKey) {
+ return Optional.ofNullable(STANDARD_TO_MQR_MODE_METRICS.get(metricKey))
+ .or(() -> Optional.ofNullable(MQR_TO_STANDARD_MODE_METRICS.get(metricKey)));
+ }
+}
static EvaluatedCondition evaluate(Condition condition, QualityGateEvaluator.Measures measures) {
Optional<QualityGateEvaluator.Measure> measure = measures.get(condition.getMetricKey());
if (measure.isEmpty()) {
- return new EvaluatedCondition(condition, EvaluationStatus.OK, null);
+ return new EvaluatedCondition(condition, EvaluationStatus.OK, null, true);
}
Optional<Comparable> value = getMeasureValue(condition, measure.get());
return measure.getValue().isPresent() ? getNumericValue(measure.getType(), measure.getValue().getAsDouble()) : null;
}
- checkArgument(ValueType.LEVEL.equals(measure.getType()), "Condition is not allowed for type %s" , measure.getType());
+ checkArgument(ValueType.LEVEL.equals(measure.getType()), "Condition is not allowed for type %s", measure.getType());
return measure.getStringValue().orElse(null);
}
@Immutable
public class EvaluatedCondition {
private final Condition condition;
+ private Condition originalCondition;
private final EvaluationStatus status;
@Nullable
private final String value;
+ private final boolean missingMeasure;
public EvaluatedCondition(Condition condition, EvaluationStatus status, @Nullable String value) {
+ this(condition, status, value, false);
+ }
+
+ public EvaluatedCondition(Condition condition, EvaluationStatus status, @Nullable String value, boolean measureMissing) {
+ this(condition, condition, status, value, measureMissing);
+ }
+
+ public EvaluatedCondition(Condition condition, Condition originalCondition, EvaluationStatus status, @Nullable String value, boolean measureMissing) {
this.condition = requireNonNull(condition, "condition can't be null");
+ this.originalCondition = originalCondition;
this.status = requireNonNull(status, "status can't be null");
this.value = value;
+ this.missingMeasure = measureMissing;
}
public Condition getCondition() {
return condition;
}
+ public Condition getOriginalCondition() {
+ return originalCondition;
+ }
+
+ public EvaluatedCondition setOriginalCondition(Condition originalCondition) {
+ this.originalCondition = originalCondition;
+ return this;
+ }
+
public EvaluationStatus getStatus() {
return status;
}
public String toString() {
return "EvaluatedCondition{" +
"condition=" + condition +
+ ", originalCondition=" + originalCondition +
", status=" + status +
", value=" + (value == null ? null : ('\'' + value + '\'')) +
'}';
}
+ public boolean isMissingMeasure() {
+ return missingMeasure;
+ }
+
/**
* Quality gate condition evaluation status.
*/
/**
* No measure found or measure had no value. The condition has not been evaluated and therefor ignored in
* the computation of the Quality Gate status.
+ * @deprecated since 10.8, the value is never used in the code
*/
+ @Deprecated(since = "10.8")
NO_VALUE,
/**
* Condition evaluated as OK, error thresholds hasn't been reached.
Set<Condition> conditions = qualityGate.getConditions();
Set<Condition> conditionsNotEvaluated = conditions.stream()
- .filter(c -> !evaluatedConditions.containsKey(c))
+ .filter(c -> !evaluatedConditions.containsKey(c) && !hasOriginalCondition(evaluatedConditions.values(), c))
.collect(Collectors.toSet());
checkArgument(conditionsNotEvaluated.isEmpty(), "Evaluation missing for the following conditions: %s", conditionsNotEvaluated);
- Set<Condition> unknownConditions = evaluatedConditions.keySet().stream()
- .filter(c -> !conditions.contains(c))
+ Set<Condition> unknownConditions = evaluatedConditions.entrySet().stream()
+ .filter(c -> !conditions.contains(c.getValue().getCondition()) && !conditions.contains(c.getValue().getOriginalCondition()))
+ .map(Map.Entry::getKey)
.collect(Collectors.toSet());
+
checkArgument(unknownConditions.isEmpty(), "Evaluation provided for unknown conditions: %s", unknownConditions);
}
+
+ private static boolean hasOriginalCondition(Collection<EvaluatedCondition> evaluatedConditions, Condition c) {
+ return evaluatedConditions.stream().anyMatch(ec -> ec.getOriginalCondition().equals(c));
+ }
}
}
CoreMetrics.NEW_DUPLICATED_LINES_KEY,
CoreMetrics.NEW_BLOCKS_DUPLICATED_KEY);
+ private final QualityGateFallbackManager qualityGateFallbackManager;
+
+ public QualityGateEvaluatorImpl(QualityGateFallbackManager qualityGateFallbackManager) {
+ this.qualityGateFallbackManager = qualityGateFallbackManager;
+ }
+
@Override
public EvaluatedQualityGate evaluate(QualityGate gate, Measures measures, Configuration configuration) {
EvaluatedQualityGate.Builder result = EvaluatedQualityGate.newBuilder()
String metricKey = condition.getMetricKey();
EvaluatedCondition evaluation = ConditionEvaluator.evaluate(condition, measures);
+ if (evaluation.isMissingMeasure()) {
+ evaluation = qualityGateFallbackManager.getFallbackCondition(evaluation.getCondition())
+ .map(c -> ConditionEvaluator.evaluate(c, measures).setOriginalCondition(condition))
+ .orElse(evaluation);
+ }
+
if (isSmallChangeset && evaluation.getStatus() != EvaluationStatus.OK && METRICS_TO_IGNORE_ON_SMALL_CHANGESETS.contains(metricKey)) {
- result.addEvaluatedCondition(new EvaluatedCondition(evaluation.getCondition(), EvaluationStatus.OK, evaluation.getValue().orElse(null)));
+ result.addEvaluatedCondition(new EvaluatedCondition(evaluation.getCondition(), evaluation.getOriginalCondition(),
+ EvaluationStatus.OK, evaluation.getValue().orElse(null), evaluation.isMissingMeasure()));
result.setIgnoredConditionsOnSmallChangeset(true);
} else {
result.addEvaluatedCondition(evaluation);
metricKeys.add(CoreMetrics.NEW_LINES_KEY);
for (Condition condition : gate.getConditions()) {
metricKeys.add(condition.getMetricKey());
+ qualityGateFallbackManager.getFallbackCondition(condition)
+ .ifPresent(c -> metricKeys.add(c.getMetricKey()));
}
return metricKeys;
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualitygate;
+
+import java.util.Optional;
+import org.sonar.server.metric.StandardToMQRMetrics;
+
+/**
+ * This class is used to manage the fallback of the quality gate conditions, in case one of the measure has not been computed yet.
+ * This is to ensure continuity of the quality gate evaluation in the scenario of introduction of new measures, but the project has not been reanalyzed yet.
+ * The live quality gate evaluation will fallback to an equivalent metric until the project is reanalyzed
+ */
+public class QualityGateFallbackManager {
+
+ public Optional<Condition> getFallbackCondition(Condition condition) {
+ Optional<String> equivalentMetric = StandardToMQRMetrics.getEquivalentMetric(condition.getMetricKey());
+ if (StandardToMQRMetrics.isMQRMetric(condition.getMetricKey()) && equivalentMetric.isPresent()) {
+ return Optional.of(new Condition(equivalentMetric.get(), condition.getOperator(), condition.getErrorThreshold()));
+ } else {
+ return Optional.empty();
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.metric;
+
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+
+class StandardToMQRMetricsTest {
+ @Test
+ void isStandardMetric_shouldReturnExpectedResult() {
+ Assertions.assertThat(StandardToMQRMetrics.isStandardMetric(CoreMetrics.RELIABILITY_RATING_KEY)).isTrue();
+ Assertions.assertThat(StandardToMQRMetrics.isMQRMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_HIGH_ISSUES_KEY)).isTrue();
+
+ Assertions.assertThat(StandardToMQRMetrics.isMQRMetric(CoreMetrics.SECURITY_RATING_KEY)).isFalse();
+ Assertions.assertThat(StandardToMQRMetrics.isStandardMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY)).isFalse();
+ }
+
+ @Test
+ void getEquivalentMetric_shouldReturnExpectedResult() {
+ Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(CoreMetrics.COMMENT_LINES_DENSITY_KEY)).isEmpty();
+ Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY)).hasValue(CoreMetrics.RELIABILITY_RATING_KEY);
+ Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(CoreMetrics.RELIABILITY_RATING_KEY)).hasValue(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
+ }
+}
@Test
public void override_toString() {
- assertThat(underTest).hasToString("EvaluatedCondition{condition=" +
- "Condition{metricKey='metricKey', operator=GREATER_THAN, errorThreshold='2'}, " +
- "status=ERROR, value='value'}");
+ assertThat(underTest).hasToString("EvaluatedCondition{condition=Condition{metricKey='metricKey', " +
+ "operator=GREATER_THAN, errorThreshold='2'}, " +
+ "originalCondition=Condition{metricKey='metricKey', " +
+ "operator=GREATER_THAN, errorThreshold='2'}, status=ERROR, value='value'}");
}
@Test
public void toString_does_not_quote_null_value() {
EvaluatedCondition underTest = new EvaluatedCondition(CONDITION_1, ERROR, null);
- assertThat(underTest).hasToString("EvaluatedCondition{condition=" +
- "Condition{metricKey='metricKey', operator=GREATER_THAN, errorThreshold='2'}, " +
+ assertThat(underTest).hasToString("EvaluatedCondition{condition=Condition{metricKey='metricKey', " +
+ "operator=GREATER_THAN, errorThreshold='2'}, " +
+ "originalCondition=Condition{metricKey='metricKey', " +
+ "operator=GREATER_THAN, errorThreshold='2'}, " +
"status=ERROR, value=null}");
}
import java.util.HashSet;
import java.util.Random;
import org.apache.commons.lang3.RandomStringUtils;
-import org.junit.Test;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric.Level;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.server.qualitygate.EvaluatedQualityGate.newBuilder;
-public class EvaluatedQualityGateTest {
+class EvaluatedQualityGateTest {
private static final String QUALITY_GATE_ID = "qg_id";
private static final String QUALITY_GATE_NAME = "qg_name";
private static final QualityGate NO_CONDITION_QUALITY_GATE = new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, emptySet());
private EvaluatedQualityGate.Builder builder = newBuilder();
@Test
- public void build_fails_with_NPE_if_status_not_set() {
+ void build_fails_with_NPE_if_status_not_set() {
builder.setQualityGate(NO_CONDITION_QUALITY_GATE);
assertThatThrownBy(() -> builder.build())
}
@Test
- public void addCondition_fails_with_NPE_if_condition_is_null() {
+ void addCondition_fails_with_NPE_if_condition_is_null() {
assertThatThrownBy(() -> builder.addEvaluatedCondition(null, EvaluatedCondition.EvaluationStatus.ERROR, "a_value"))
.isInstanceOf(NullPointerException.class)
.hasMessage("condition can't be null");
}
@Test
- public void addCondition_fails_with_NPE_if_status_is_null() {
+ void addCondition_fails_with_NPE_if_status_is_null() {
assertThatThrownBy(() -> builder.addEvaluatedCondition(new Condition("metric_key", Condition.Operator.LESS_THAN, "2"), null, "a_value"))
.isInstanceOf(NullPointerException.class)
.hasMessage("status can't be null");
}
@Test
- public void addCondition_accepts_null_value() {
+ void addCondition_accepts_null_value() {
builder.addEvaluatedCondition(CONDITION_1, EvaluatedCondition.EvaluationStatus.NO_VALUE, null);
assertThat(builder.getEvaluatedConditions())
}
@Test
- public void getEvaluatedConditions_returns_empty_with_no_condition_added_to_builder() {
+ void getEvaluatedConditions_returns_empty_with_no_condition_added_to_builder() {
assertThat(builder.getEvaluatedConditions()).isEmpty();
}
@Test
- public void build_fails_with_IAE_if_condition_added_and_no_on_QualityGate() {
+ void build_fails_with_IAE_if_condition_added_and_no_on_QualityGate() {
builder.setQualityGate(NO_CONDITION_QUALITY_GATE)
.setStatus(randomStatus)
.addEvaluatedCondition(CONDITION_1, randomEvaluationStatus, randomValue);
}
@Test
- public void build_fails_with_IAE_if_condition_is_missing_for_one_defined_in_QualityGate() {
+ void build_fails_with_IAE_if_condition_is_missing_for_one_defined_in_QualityGate() {
builder.setQualityGate(ONE_CONDITION_QUALITY_GATE)
.setStatus(randomStatus);
}
@Test
- public void getEvaluatedConditions_is_sorted() {
+ void build_whenConditionIsAFallback_shouldNotThrowException() {
+ builder.setQualityGate(ONE_CONDITION_QUALITY_GATE).setStatus(randomStatus)
+ .addEvaluatedCondition(new EvaluatedCondition(CONDITION_2, CONDITION_1, randomEvaluationStatus, randomValue, false));
+
+ Assertions.assertThat(builder.build()
+ .getEvaluatedConditions()).hasSize(1);
+ }
+
+ @Test
+ void getEvaluatedConditions_is_sorted() {
EvaluatedQualityGate underTest = builder
.setQualityGate(ALL_CONDITIONS_QUALITY_GATE)
.setStatus(randomStatus)
}
@Test
- public void verify_getters() {
+ void verify_getters() {
EvaluatedQualityGate underTest = builder
.setQualityGate(ONE_CONDITION_QUALITY_GATE)
.setStatus(randomStatus)
}
@Test
- public void verify_getters_when_no_condition() {
+ void verify_getters_when_no_condition() {
EvaluatedQualityGate underTest = builder
.setQualityGate(NO_CONDITION_QUALITY_GATE)
.setStatus(randomStatus)
}
@Test
- public void verify_getters_when_multiple_conditions() {
+ void verify_getters_when_multiple_conditions() {
QualityGate qualityGate = new QualityGate(QUALITY_GATE_ID, QUALITY_GATE_NAME, ImmutableSet.of(CONDITION_1, CONDITION_2));
EvaluatedQualityGate underTest = builder
.setQualityGate(qualityGate)
}
@Test
- public void equals_is_based_on_all_fields() {
+ void equals_is_based_on_all_fields() {
EvaluatedQualityGate.Builder builder = this.builder
.setQualityGate(ONE_CONDITION_QUALITY_GATE)
.setStatus(Level.ERROR)
}
@Test
- public void hashcode_is_based_on_all_fields() {
+ void hashcode_is_based_on_all_fields() {
EvaluatedQualityGate.Builder builder = this.builder
.setQualityGate(ONE_CONDITION_QUALITY_GATE)
.setStatus(Level.ERROR)
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.ConfigurationBridge;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.tuple;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_LINES_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
-public class QualityGateEvaluatorImplTest {
+class QualityGateEvaluatorImplTest {
private final MapSettings settings = new MapSettings();
private final Configuration configuration = new ConfigurationBridge(settings);
- private final QualityGateEvaluator underTest = new QualityGateEvaluatorImpl();
+ QualityGateFallbackManager qualityGateFallbackManager = mock(QualityGateFallbackManager.class);
+ private final QualityGateEvaluator underTest = new QualityGateEvaluatorImpl(qualityGateFallbackManager);
@Test
- public void getMetricKeys_includes_by_default_new_lines() {
+ void getMetricKeys_includes_by_default_new_lines() {
QualityGate gate = mock(QualityGate.class);
assertThat(underTest.getMetricKeys(gate)).containsExactly(NEW_LINES_KEY);
}
@Test
- public void getMetricKeys_includes_metrics_from_qgate() {
+ void getMetricKeys_includes_metrics_from_qgate() {
Set<String> metricKeys = ImmutableSet.of("foo", "bar", "baz");
Set<Condition> conditions = metricKeys.stream().map(key -> {
Condition condition = mock(Condition.class);
}
@Test
- public void evaluated_conditions_are_sorted() {
+ void getMetricKeys_shouldIncludeFallbackConditionsMetricKeys() {
+ Set<String> metricKeys = ImmutableSet.of("foo", "bar", "baz");
+ when(qualityGateFallbackManager.getFallbackCondition(any())).thenReturn(Optional.of(new Condition("fallback", Condition.Operator.GREATER_THAN, "0")));
+ Set<Condition> conditions = metricKeys.stream().map(key -> {
+ Condition condition = mock(Condition.class);
+ when(condition.getMetricKey()).thenReturn(key);
+ return condition;
+ }).collect(Collectors.toSet());
+
+ QualityGate gate = mock(QualityGate.class);
+ when(gate.getConditions()).thenReturn(conditions);
+ assertThat(underTest.getMetricKeys(gate)).containsAll(metricKeys);
+ assertThat(underTest.getMetricKeys(gate)).contains("fallback");
+ }
+
+ @Test
+ void evaluate_whenConditionHasNoDataAndHasFallBack_shouldEvaluateFallbackInstead() {
+ when(qualityGateFallbackManager.getFallbackCondition(any())).thenReturn(Optional.of(new Condition("fallback", Condition.Operator.GREATER_THAN, "0")));
+ Condition condition = mock(Condition.class);
+ when(condition.getMetricKey()).thenReturn("foo");
+
+ QualityGate gate = mock(QualityGate.class);
+ when(gate.getConditions()).thenReturn(Set.of(condition));
+ QualityGateEvaluator.Measures measures = mock(QualityGateEvaluator.Measures.class);
+ when(measures.get("foo")).thenReturn(Optional.empty());
+ when(measures.get("fallback")).thenReturn(Optional.of(new FakeMeasure(1)));
+
+ assertThat(underTest.evaluate(gate, measures, configuration).getEvaluatedConditions())
+ .extracting(x -> x.getCondition().getMetricKey(), x -> x.getOriginalCondition().getMetricKey())
+ .containsExactly(tuple("fallback", "foo"));
+ }
+
+ @Test
+ void evaluated_conditions_are_sorted() {
Set<String> metricKeys = ImmutableSet.of("foo", "bar", NEW_MAINTAINABILITY_RATING_KEY);
Set<Condition> conditions = metricKeys.stream().map(key -> {
Condition condition = mock(Condition.class);
QualityGateEvaluator.Measures measures = mock(QualityGateEvaluator.Measures.class);
assertThat(underTest.evaluate(gate, measures, configuration).getEvaluatedConditions()).extracting(x -> x.getCondition().getMetricKey())
- .containsExactly(NEW_MAINTAINABILITY_RATING_KEY, "bar", "foo");
+ .containsExactly(NEW_MAINTAINABILITY_RATING_KEY, "bar", "foo");
}
@Test
- public void evaluate_is_OK_for_empty_qgate() {
+ void evaluate_is_OK_for_empty_qgate() {
QualityGate gate = mock(QualityGate.class);
QualityGateEvaluator.Measures measures = mock(QualityGateEvaluator.Measures.class);
EvaluatedQualityGate evaluatedQualityGate = underTest.evaluate(gate, measures, configuration);
}
@Test
- public void evaluate_is_ERROR() {
+ void evaluate_is_ERROR() {
Condition condition = new Condition(NEW_MAINTAINABILITY_RATING_KEY, Condition.Operator.GREATER_THAN, "0");
QualityGate gate = mock(QualityGate.class);
}
@Test
- public void evaluate_for_small_changes() {
+ void evaluate_for_small_changes() {
Condition condition = new Condition(NEW_DUPLICATED_LINES_KEY, Condition.Operator.GREATER_THAN, "0");
Map<String, QualityGateEvaluator.Measure> notSmallChange = new HashMap<>();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.qualitygate;
+
+import java.util.Optional;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+class QualityGateFallbackManagerTest {
+
+ QualityGateFallbackManager underTest = new QualityGateFallbackManager();
+
+ @Test
+ void getFallbackCondition_whenConditionIsSoftwareQualityMetricWithEquivalence_shouldReturnExpectedCondition() {
+ Condition condition = new Condition(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY, Condition.Operator.GREATER_THAN, "3");
+ Optional<Condition> fallbackCondition = underTest.getFallbackCondition(condition);
+ assertThat(fallbackCondition).isPresent()
+ .get()
+ .extracting(Condition::getMetricKey, Condition::getOperator, Condition::getErrorThreshold)
+ .containsExactly(CoreMetrics.SECURITY_RATING_KEY, Condition.Operator.GREATER_THAN, "3");
+ }
+
+ @Test
+ void getFallbackCondition_whenConditionIsStandardMetricWithEquivalence_shouldNotReturnCondition() {
+ Condition condition = new Condition(CoreMetrics.SECURITY_RATING_KEY, Condition.Operator.GREATER_THAN, "3");
+ Optional<Condition> fallbackCondition = underTest.getFallbackCondition(condition);
+ assertThat(fallbackCondition).isEmpty();
+ }
+
+ @Test
+ void getFallbackCondition_whenConditionIsAnyMetricWithoutEquivalence_shouldNotReturnCondition() {
+ Condition condition = new Condition(CoreMetrics.LINES_KEY, Condition.Operator.GREATER_THAN, "3");
+ Optional<Condition> fallbackCondition = underTest.getFallbackCondition(condition);
+ assertThat(fallbackCondition).isEmpty();
+ }
+
+}
import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.measure.Rating;
-import org.sonar.server.qualitygate.ws.StandardToMQRMetrics;
+import org.sonar.server.metric.StandardToMQRMetrics;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.lang.Double.parseDouble;
import java.util.Set;
import java.util.stream.Collectors;
import org.sonar.db.metric.MetricDto;
-import org.sonar.server.qualitygate.ws.StandardToMQRMetrics;
+import org.sonar.server.metric.StandardToMQRMetrics;
public class QualityGateModeChecker {
QualityGateModeChecker.class,
QualityGateConditionsUpdater.class,
QualityGateFinder.class,
- QualityGateEvaluatorImpl.class);
+ QualityGateEvaluatorImpl.class,
+ QualityGateFallbackManager.class);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualitygate.ws;
-
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import java.util.Optional;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.metric.SoftwareQualitiesMetrics;
-
-import static org.sonar.api.measures.CoreMetrics.BLOCKER_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY;
-import static org.sonar.api.measures.CoreMetrics.CRITICAL_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY;
-import static org.sonar.api.measures.CoreMetrics.INFO_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.MAJOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.MINOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_BLOCKER_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_CODE_SMELLS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_CRITICAL_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_INFO_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_MAJOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.NEW_MINOR_VIOLATIONS_KEY;
-import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_HIGH_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_INFO_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_LOW_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_HIGH_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_INFO_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_LOW_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
-import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY;
-
-/**
- * Defines the metrics mapping between the standard mode and the MQR mode.
- * This list all the metrics that are specific for each mode, and the equivalent metric in the other mode.
- */
-public class StandardToMQRMetrics {
- private static final BiMap<String, String> STANDARD_TO_MQR_MODE_METRICS;
-
- private static final BiMap<String, String> MQR_TO_STANDARD_MODE_METRICS;
-
- static {
- STANDARD_TO_MQR_MODE_METRICS = HashBiMap.create();
- // Severity related metrics
- STANDARD_TO_MQR_MODE_METRICS.put(BLOCKER_VIOLATIONS_KEY, SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_BLOCKER_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_BLOCKER_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CRITICAL_VIOLATIONS_KEY, SOFTWARE_QUALITY_HIGH_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_CRITICAL_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_HIGH_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(MAJOR_VIOLATIONS_KEY, SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_MAJOR_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_MEDIUM_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(MINOR_VIOLATIONS_KEY, SOFTWARE_QUALITY_LOW_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_MINOR_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_LOW_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(INFO_VIOLATIONS_KEY, SOFTWARE_QUALITY_INFO_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_INFO_VIOLATIONS_KEY, NEW_SOFTWARE_QUALITY_INFO_ISSUES_KEY);
-
- // Maintainability related metrics
- STANDARD_TO_MQR_MODE_METRICS.put(CODE_SMELLS_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(NEW_CODE_SMELLS_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(SQALE_RATING_KEY, SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.TECHNICAL_DEBT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_TECHNICAL_DEBT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SQALE_DEBT_RATIO_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SQALE_DEBT_RATIO_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_DEBT_RATIO_KEY);
-
- STANDARD_TO_MQR_MODE_METRICS.put(EFFORT_TO_REACH_MAINTAINABILITY_RATING_A_KEY, EFFORT_TO_REACH_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_A_KEY);
-
- // Security related metrics
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SECURITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SECURITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.SECURITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_SECURITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.VULNERABILITIES_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_VULNERABILITIES_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_ISSUES_KEY);
-
- // Reliability related metrics
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.RELIABILITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_RELIABILITY_REMEDIATION_EFFORT_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_REMEDIATION_EFFORT_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.BUGS_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_ISSUES_KEY);
- STANDARD_TO_MQR_MODE_METRICS.put(CoreMetrics.NEW_BUGS_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_ISSUES_KEY);
-
- MQR_TO_STANDARD_MODE_METRICS = STANDARD_TO_MQR_MODE_METRICS.inverse();
- }
-
- private StandardToMQRMetrics() {
- }
-
- public static boolean isStandardMetric(String metricKey) {
- return STANDARD_TO_MQR_MODE_METRICS.containsKey(metricKey);
- }
-
- public static boolean isMQRMetric(String metricKey) {
- return MQR_TO_STANDARD_MODE_METRICS.containsKey(metricKey);
- }
-
- /**
- * Retrieves equivalent metric in the other mode. Return empty if metric has no equivalence
- */
- public static Optional<String> getEquivalentMetric(String metricKey) {
- return Optional.ofNullable(STANDARD_TO_MQR_MODE_METRICS.get(metricKey))
- .or(() -> Optional.ofNullable(MQR_TO_STANDARD_MODE_METRICS.get(metricKey)));
- }
-}
public void verify_count_of_added_components() {
ListContainer container = new ListContainer();
new QualityGateModule().configure(container);
- assertThat(container.getAddedObjects()).hasSize(6);
+ assertThat(container.getAddedObjects()).hasSize(7);
}
}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2024 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.qualitygate.ws;
-
-import org.assertj.core.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.core.metric.SoftwareQualitiesMetrics;
-
-class StandardToMQRMetricsTest {
-
- @Test
- void isStandardMetric_shouldReturnExpectedResult() {
- Assertions.assertThat(StandardToMQRMetrics.isStandardMetric(CoreMetrics.RELIABILITY_RATING_KEY)).isTrue();
- Assertions.assertThat(StandardToMQRMetrics.isMQRMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_HIGH_ISSUES_KEY)).isTrue();
-
- Assertions.assertThat(StandardToMQRMetrics.isMQRMetric(CoreMetrics.SECURITY_RATING_KEY)).isFalse();
- Assertions.assertThat(StandardToMQRMetrics.isStandardMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_ISSUES_KEY)).isFalse();
- }
-
- @Test
- void getEquivalentMetric_shouldReturnExpectedResult() {
- Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(CoreMetrics.COMMENT_LINES_DENSITY_KEY)).isEmpty();
- Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY)).hasValue(CoreMetrics.RELIABILITY_RATING_KEY);
- Assertions.assertThat(StandardToMQRMetrics.getEquivalentMetric(CoreMetrics.RELIABILITY_RATING_KEY)).hasValue(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY);
- }
-
-}