Browse Source

SONAR-11776 Quality Gate failure conditions should be sorted

tags/7.7
Duarte Meneses 5 years ago
parent
commit
4b841d5086

+ 6
- 2
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/measure/qualitygatedetails/QualityGateDetailsData.java View File

@@ -22,11 +22,13 @@ package org.sonar.ce.task.projectanalysis.measure.qualitygatedetails;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import javax.annotation.concurrent.Immutable;
import org.sonar.ce.task.projectanalysis.measure.Measure;
import org.sonar.ce.task.projectanalysis.qualitygate.Condition;
import org.sonar.server.qualitygate.ConditionComparator;

import static com.google.common.collect.FluentIterable.from;
import static java.util.Objects.requireNonNull;

@Immutable
@@ -40,7 +42,9 @@ public class QualityGateDetailsData {

public QualityGateDetailsData(Measure.Level level, Iterable<EvaluatedCondition> conditions, boolean ignoredConditions) {
this.level = requireNonNull(level);
this.conditions = from(conditions).toList();
this.conditions = StreamSupport.stream(conditions.spliterator(), false)
.sorted(new ConditionComparator<>(c -> c.getCondition().getMetric().getKey()))
.collect(Collectors.toList());
this.ignoredConditions = ignoredConditions;
}


+ 62
- 0
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/ConditionComparator.java View File

@@ -0,0 +1,62 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;

/**
* Sorts conditions, first based on an hardcoded list of metric keys, then alphabetically by metric key.
*/
public class ConditionComparator<T> implements Comparator<T> {
private static final List<String> CONDITIONS_ORDER = Arrays.asList(NEW_RELIABILITY_RATING_KEY, RELIABILITY_RATING_KEY,
NEW_SECURITY_RATING_KEY, SECURITY_RATING_KEY, NEW_MAINTAINABILITY_RATING_KEY, SQALE_RATING_KEY,
NEW_COVERAGE_KEY, COVERAGE_KEY,
NEW_DUPLICATED_LINES_DENSITY_KEY, DUPLICATED_LINES_DENSITY_KEY);
private static final Map<String, Integer> CONDITIONS_ORDER_IDX = IntStream.range(0, CONDITIONS_ORDER.size()).boxed()
.collect(Collectors.toMap(CONDITIONS_ORDER::get, x -> x));

private final Function<T, String> metricKeyExtractor;

public ConditionComparator(Function<T, String> metricKeyExtractor) {
this.metricKeyExtractor = metricKeyExtractor;
}

@Override public int compare(T c1, T c2) {
Function<T, Integer> byList = c -> CONDITIONS_ORDER_IDX.getOrDefault(metricKeyExtractor.apply(c), Integer.MAX_VALUE);
return Comparator.comparing(byList).thenComparing(metricKeyExtractor).compare(c1, c2);
}
}

+ 1
- 28
server/sonar-server-common/src/main/java/org/sonar/server/qualitygate/EvaluatedQualityGate.java View File

@@ -21,17 +21,13 @@ package org.sonar.server.qualitygate;

import com.google.common.collect.ImmutableSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import org.sonar.api.measures.Metric;
@@ -39,16 +35,6 @@ import org.sonar.server.qualitygate.EvaluatedCondition.EvaluationStatus;

import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;

@Immutable
public class EvaluatedQualityGate {
@@ -113,19 +99,6 @@ public class EvaluatedQualityGate {
}

public static final class Builder {
private static final List<String> CONDITIONS_ORDER = Arrays.asList(NEW_RELIABILITY_RATING_KEY, RELIABILITY_RATING_KEY,
NEW_SECURITY_RATING_KEY, SECURITY_RATING_KEY, NEW_MAINTAINABILITY_RATING_KEY, SQALE_RATING_KEY,
NEW_COVERAGE_KEY, COVERAGE_KEY,
NEW_DUPLICATED_LINES_DENSITY_KEY, DUPLICATED_LINES_DENSITY_KEY);
private static final Map<String, Integer> CONDITIONS_ORDER_IDX = IntStream.range(0, CONDITIONS_ORDER.size()).boxed()
.collect(Collectors.toMap(CONDITIONS_ORDER::get, x -> x));

private static final Comparator<EvaluatedCondition> CONDITION_COMPARATOR = (c1, c2) -> {
Function<EvaluatedCondition, Integer> byList = c -> CONDITIONS_ORDER_IDX.getOrDefault(c.getCondition().getMetricKey(), Integer.MAX_VALUE);
Function<EvaluatedCondition, String> byMetricKey = c -> c.getCondition().getMetricKey();
return Comparator.comparing(byList).thenComparing(byMetricKey).compare(c1, c2);
};

private QualityGate qualityGate;
private Metric.Level status;
private final Map<Condition, EvaluatedCondition> evaluatedConditions = new LinkedHashMap<>();
@@ -167,7 +140,7 @@ public class EvaluatedQualityGate {
public EvaluatedQualityGate build() {
checkEvaluatedConditions(qualityGate, evaluatedConditions);
List<EvaluatedCondition> sortedEvaluatedConditions = new ArrayList<>(evaluatedConditions.values());
sortedEvaluatedConditions.sort(CONDITION_COMPARATOR);
sortedEvaluatedConditions.sort(new ConditionComparator<>(c -> c.getCondition().getMetricKey()));
return new EvaluatedQualityGate(
this.qualityGate,
this.status,

+ 43
- 0
server/sonar-server-common/src/test/java/org/sonar/server/qualitygate/ConditionComparatorTest.java View File

@@ -0,0 +1,43 @@
/*
* SonarQube
* Copyright (C) 2009-2019 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.Arrays;
import java.util.List;
import org.junit.Test;

import static org.assertj.core.api.Java6Assertions.assertThat;
import static org.sonar.api.measures.CoreMetrics.NEW_COVERAGE_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY;
import static org.sonar.api.measures.CoreMetrics.NEW_SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.RELIABILITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;

public class ConditionComparatorTest {
@Test
public void sort_by_hardcoded_metric_keys_then_alphabetically() {
ConditionComparator<String> comparator = new ConditionComparator<>(x -> x);
List<String> conditions = Arrays.asList(NEW_DUPLICATED_LINES_DENSITY_KEY, RELIABILITY_RATING_KEY, "rule1", SQALE_RATING_KEY, "abc",
NEW_SECURITY_RATING_KEY, "metric", NEW_COVERAGE_KEY);
conditions.sort(comparator);
assertThat(conditions).contains(RELIABILITY_RATING_KEY, NEW_SECURITY_RATING_KEY, SQALE_RATING_KEY,
NEW_COVERAGE_KEY, "abc", "metric", "rule1");
}
}

Loading…
Cancel
Save