aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorDejan Milisavljevic <130993898+dejan-milisavljevic-sonarsource@users.noreply.github.com>2024-08-14 12:03:22 +0200
committersonartech <sonartech@sonarsource.com>2024-08-26 20:03:06 +0000
commitfc0739fd4eaf7a467de77773be76ddbb5f8040ef (patch)
tree466d0bc4725038ae206318d8e89ff4fb4bcb8b2d /server
parent9324868e5ad6264744afd9f5a5ea7555ab2de65b (diff)
downloadsonarqube-fc0739fd4eaf7a467de77773be76ddbb5f8040ef.tar.gz
sonarqube-fc0739fd4eaf7a467de77773be76ddbb5f8040ef.zip
SONAR-22727 index software qualitiy measure to project measures
Co-authored-by: Léo Geoffroy <leo.geoffroy@sonarsource.com>
Diffstat (limited to 'server')
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java14
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/es/IndexDefinitionHash.java3
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/BuiltIndex.java6
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/NewIndex.java13
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java5
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java2
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializer.java65
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java24
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java11
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializerTest.java101
-rw-r--r--server/sonar-webserver-es/build.gradle1
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java49
-rw-r--r--server/sonar-webserver-es/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java397
-rw-r--r--server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java109
14 files changed, 626 insertions, 174 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
index 95c0eb350dc..f7d898745b0 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/measure/ProjectMeasuresIndexerIterator.java
@@ -40,6 +40,7 @@ import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
import org.sonar.core.util.CloseableIterator;
import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
@@ -70,7 +71,18 @@ public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMea
CoreMetrics.NEW_COVERAGE_KEY,
CoreMetrics.NEW_DUPLICATED_LINES_DENSITY_KEY,
CoreMetrics.NEW_LINES_KEY,
- CoreMetrics.NEW_RELIABILITY_RATING_KEY);
+ CoreMetrics.NEW_RELIABILITY_RATING_KEY,
+
+ //Ratings based on software quality
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+ SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY
+ );
private static final String SQL_PROJECTS = "SELECT p.uuid, p.kee, p.name, p.created_at, s.created_at, p.tags, p.qualifier " +
"FROM projects p " +
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/es/IndexDefinitionHash.java b/server/sonar-server-common/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
index e36f8a1acb1..42783e5404f 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/es/IndexDefinitionHash.java
@@ -45,7 +45,8 @@ class IndexDefinitionHash {
index.getSettings().toString(),
Map.of(mainType.getIndex(), mainType),
index.getRelationTypes().stream().collect(Collectors.toMap(IndexType.IndexRelationType::getName, Function.identity())),
- index.getAttributes());
+ index.getAttributes(),
+ index.getCustomHashMetadata());
}
private static String of(String str, Map<?, ?>... maps) {
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/BuiltIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/BuiltIndex.java
index 1e2c0b74208..62763890bd2 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/BuiltIndex.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/BuiltIndex.java
@@ -44,12 +44,14 @@ public final class BuiltIndex<T extends NewIndex<T>> {
private final Set<IndexRelationType> relationTypes;
private final Settings settings;
private final Map<String, Object> attributes;
+ private final Map<String, String> customHashMetadata;
BuiltIndex(T newIndex) {
this.mainType = newIndex.getMainType();
this.settings = newIndex.getSettings().build();
this.relationTypes = newIndex.getRelationsStream().collect(Collectors.toSet());
this.attributes = buildAttributes(newIndex);
+ this.customHashMetadata = newIndex.getCustomHashMetadata();
}
private static Map<String, Object> buildAttributes(NewIndex<?> newIndex) {
@@ -121,4 +123,8 @@ public final class BuiltIndex<T extends NewIndex<T>> {
public Map<String, Object> getAttributes() {
return attributes;
}
+
+ public Map<String, String> getCustomHashMetadata() {
+ return customHashMetadata;
+ }
}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/NewIndex.java b/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/NewIndex.java
index dc719bd4d64..1a5c6fff264 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/NewIndex.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/es/newindex/NewIndex.java
@@ -47,6 +47,7 @@ public abstract class NewIndex<T extends NewIndex<T>> {
private final Settings.Builder settings = DefaultIndexSettings.defaults();
private final Map<String, Object> attributes = new TreeMap<>();
private final Map<String, Object> properties = new TreeMap<>();
+ private final Map<String, String> customHashMetadata = new TreeMap<>();
public NewIndex(Index index, SettingsConfiguration settingsConfiguration) {
this.index = index;
@@ -158,4 +159,16 @@ public abstract class NewIndex<T extends NewIndex<T>> {
public abstract BuiltIndex<T> build();
+ /**
+ * Set additional information to be used to compute the hash of the index.
+ * If hash metadata changes, the hash of index will also change.
+ */
+ public T addCustomHashMetadata(String key, String value) {
+ this.customHashMetadata.put(key, value);
+ return castThis();
+ }
+
+ public Map<String, String> getCustomHashMetadata() {
+ return customHashMetadata;
+ }
}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java
index 3172c6f3bd0..5766293f352 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexDefinition.java
@@ -22,6 +22,7 @@ package org.sonar.server.measure.index;
import javax.inject.Inject;
import org.sonar.api.config.Configuration;
import org.sonar.api.config.internal.MapSettings;
+import org.sonar.db.measure.ProjectMeasuresIndexerIterator;
import org.sonar.server.es.Index;
import org.sonar.server.es.IndexDefinition;
import org.sonar.server.es.IndexType;
@@ -65,6 +66,7 @@ public class ProjectMeasuresIndexDefinition implements IndexDefinition {
public static final String FIELD_NCLOC_DISTRIBUTION_LANGUAGE = FIELD_NCLOC_DISTRIBUTION + "." + SUB_FIELD_DISTRIB_LANGUAGE;
public static final String FIELD_NCLOC_DISTRIBUTION_NCLOC = FIELD_NCLOC_DISTRIBUTION + "." + SUB_FIELD_DISTRIB_NCLOC;
+ private static final String METRICS_CUSTOM_METADATA_KEY = "metrics";
private final Configuration config;
private final boolean enableSource;
@@ -94,7 +96,8 @@ public class ProjectMeasuresIndexDefinition implements IndexDefinition {
.setRefreshInterval(MANUAL_REFRESH_INTERVAL)
.setDefaultNbOfShards(5)
.build())
- .setEnableSource(enableSource);
+ .setEnableSource(enableSource)
+ .addCustomHashMetadata(METRICS_CUSTOM_METADATA_KEY, String.join(",", ProjectMeasuresIndexerIterator.METRIC_KEYS));
TypeMapping mapping = index.createTypeMapping(TYPE_PROJECT_MEASURES);
mapping.keywordFieldBuilder(FIELD_UUID).disableNorms().build();
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java
index d698e08a619..6f5898c73c6 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndexer.java
@@ -211,7 +211,7 @@ public class ProjectMeasuresIndexer implements EventIndexer, AnalysisIndexer, Ne
.setTags(project.getTags())
.setAnalysedAt(analysisDate == null ? null : new Date(analysisDate))
.setCreatedAt(new Date(project.getCreationDate()))
- .setMeasuresFromMap(projectMeasures.getMeasures().getNumericMeasures())
+ .setMeasuresFromMap(ProjectMeasuresSoftwareQualityRatingsInitializer.initializeSoftwareQualityRatings(projectMeasures.getMeasures().getNumericMeasures()))
.setLanguages(new ArrayList<>(projectMeasures.getMeasures().getNclocByLanguages().keySet()))
.setNclocLanguageDistributionFromMap(projectMeasures.getMeasures().getNclocByLanguages());
}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializer.java b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializer.java
new file mode 100644
index 00000000000..fecce77fcd4
--- /dev/null
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializer.java
@@ -0,0 +1,65 @@
+/*
+ * 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.measure.index;
+
+import java.util.Map;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+import org.sonar.server.measure.Rating;
+
+/**
+ * This class defines "default" measures values for the "Software Quality Rating Metrics" when they do not exist.
+ * The "default" value is the same as the equivalent "Rule Type Rating Metric", except for E Rating that is converted to D Rating
+ * If the "Software Quality Rating Metrics" exists, then no changes are made
+ */
+public class ProjectMeasuresSoftwareQualityRatingsInitializer {
+
+ private static final Map<String, String> RATING_KEY_TO_SOFTWARE_QUALITY_RATING_KEY = Map.of(
+ CoreMetrics.SQALE_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ CoreMetrics.RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+ CoreMetrics.SECURITY_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+ CoreMetrics.SECURITY_REVIEW_RATING_KEY, SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+ CoreMetrics.NEW_SECURITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+ CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY,
+ CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ CoreMetrics.NEW_RELIABILITY_RATING_KEY, SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY
+ );
+
+ private ProjectMeasuresSoftwareQualityRatingsInitializer() {
+ }
+
+ public static Map<String, Double> initializeSoftwareQualityRatings(Map<String, Double> measures) {
+
+ RATING_KEY_TO_SOFTWARE_QUALITY_RATING_KEY.forEach((k, v) -> initializeSoftwareQualityRatingMeasure(measures, k, v));
+ return measures;
+ }
+
+ private static void initializeSoftwareQualityRatingMeasure(Map<String, Double> measures, String ruleTypeMetric,
+ String softwareQualityMetric) {
+ if (measures.containsKey(softwareQualityMetric)) {
+ return;
+ }
+
+ Double value = measures.get(ruleTypeMetric);
+ if (value != null) {
+ measures.put(softwareQualityMetric, value > Rating.D.getIndex() ? Double.valueOf(Rating.D.getIndex()) : value);
+ }
+ }
+}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
index 9c8047bcf41..4403aec2ae1 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/es/IndexDefinitionHashTest.java
@@ -414,6 +414,30 @@ public class IndexDefinitionHashTest {
.isNotEqualTo(hashOf(new TestNewIndex(mainType, someRefreshInterval)));
}
+ @Test
+ public void hash_changes_if_customHashMetadata_changes() {
+ Index index = Index.simple("foo");
+ Configuration emptySettings = new MapSettings().asConfig();
+ SettingsConfiguration emptyConfiguration = SettingsConfiguration.newBuilder(emptySettings)
+ .build();
+ IndexMainType mainType = IndexMainType.main(index, "bar");
+ assertThat(hashOf(new TestNewIndex(mainType, emptyConfiguration)))
+ .isNotEqualTo(hashOf(new TestNewIndex(mainType, emptyConfiguration)
+ .addCustomHashMetadata("foo", "bar")));
+
+ assertThat(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar")))
+ .isNotEqualTo(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo2", "bar")));
+
+ assertThat(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar")))
+ .isNotEqualTo(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar,bar2")));
+
+ assertThat(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar")))
+ .isEqualTo(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar")));
+
+ assertThat(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo", "bar").addCustomHashMetadata("foo2", "bar2")))
+ .isEqualTo(hashOf(new TestNewIndex(mainType, emptyConfiguration).addCustomHashMetadata("foo2", "bar2").addCustomHashMetadata("foo", "bar")));
+ }
+
private static SettingsConfiguration settingsConfigurationOf(MapSettings settings) {
return SettingsConfiguration.newBuilder(settings.asConfig()).build();
}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java
index eab6b8f9d11..6824d572e02 100644
--- a/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/es/newindex/NewIndexTest.java
@@ -341,6 +341,17 @@ public class NewIndexTest {
}
@Test
+ @UseDataProvider("indexWithAndWithoutRelations")
+ public void index_withHashMetadata(Index index) {
+ NewIndex newIndex = new SimplestNewIndex(IndexType.main(index, "foo"), defaultSettingsConfiguration).addCustomHashMetadata("custom", "hash");
+
+ assertThat(newIndex.getCustomHashMetadata()).containsExactly(entry("custom", "hash"));
+
+ BuiltIndex build = newIndex.build();
+ assertThat(build.getCustomHashMetadata()).containsExactly(entry("custom", "hash"));
+ }
+
+ @Test
public void createTypeMapping_with_IndexRelationType_fails_with_ISE_if_index_does_not_allow_relations() {
IndexType.IndexRelationType indexRelationType = IndexType.relation(IndexType.main(Index.withRelations(someIndexName), "bar"), "bar");
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializerTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializerTest.java
new file mode 100644
index 00000000000..ed9119174ec
--- /dev/null
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/measure/index/ProjectMeasuresSoftwareQualityRatingsInitializerTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.measure.index;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.jupiter.api.Test;
+import org.sonar.api.measures.CoreMetrics;
+import org.sonar.core.metric.SoftwareQualitiesMetrics;
+import org.sonar.server.measure.Rating;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ProjectMeasuresSoftwareQualityRatingsInitializerTest {
+
+ @Test
+ void initializeSoftwareQualityRatings_whenNoRating_thenNoSoftwareQualityRatingMetric() {
+ Map<String, Double> initialMeasures = new HashMap<>();
+ initialMeasures.put(CoreMetrics.BRANCH_COVERAGE_KEY, null);
+ initialMeasures.put(CoreMetrics.ACCEPTED_ISSUES_KEY, 12.0);
+ initialMeasures.put(CoreMetrics.SQALE_RATING_KEY, null);
+
+ Map<String, Double> measures = new HashMap<>(initialMeasures);
+ ProjectMeasuresSoftwareQualityRatingsInitializer.initializeSoftwareQualityRatings(measures);
+
+ assertThat(measures).containsExactlyInAnyOrderEntriesOf(initialMeasures);
+ }
+
+ @Test
+ void initializeSoftwareQualityRatings_whenRatingAndNoSoftwareQualityRating_thenSoftwareQualityRatingMetricAreCreated() {
+ Map<String, Double> initialMeasures = new HashMap<>();
+ initialMeasures.put(CoreMetrics.SQALE_RATING_KEY, 1.0);
+ initialMeasures.put(CoreMetrics.RELIABILITY_RATING_KEY, 2.0);
+ initialMeasures.put(CoreMetrics.SECURITY_RATING_KEY, 3.0);
+ initialMeasures.put(CoreMetrics.SECURITY_REVIEW_RATING_KEY, 4.0);
+ initialMeasures.put(CoreMetrics.NEW_SECURITY_RATING_KEY, 4.0);
+ initialMeasures.put(CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY, 3.0);
+ initialMeasures.put(CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY, 2.0);
+ initialMeasures.put(CoreMetrics.NEW_RELIABILITY_RATING_KEY, 1.0);
+
+ Map<String, Double> measures = new HashMap<>(initialMeasures);
+
+ ProjectMeasuresSoftwareQualityRatingsInitializer.initializeSoftwareQualityRatings(measures);
+
+ assertThat(measures).hasSize(initialMeasures.size() * 2)
+ .containsAllEntriesOf(initialMeasures)
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, 1.0)
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, 2.0)
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY, 3.0)
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, 4.0)
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY, 4.0)
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, 3.0)
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, 2.0)
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, 1.0);
+ }
+
+ @Test
+ void initializeSoftwareQualityRatings_whenERating_thenSoftwareQualityRatingCreatedWithD() {
+ Map<String, Double> initialMeasures = new HashMap<>();
+ initialMeasures.put(CoreMetrics.SQALE_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.RELIABILITY_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.SECURITY_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.SECURITY_REVIEW_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.NEW_SECURITY_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.NEW_SECURITY_REVIEW_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.NEW_MAINTAINABILITY_RATING_KEY, (double) Rating.E.getIndex());
+ initialMeasures.put(CoreMetrics.NEW_RELIABILITY_RATING_KEY, (double) Rating.E.getIndex());
+
+ Map<String, Double> measures = new HashMap<>(initialMeasures);
+
+ ProjectMeasuresSoftwareQualityRatingsInitializer.initializeSoftwareQualityRatings(measures);
+
+ assertThat(measures).hasSize(initialMeasures.size() * 2)
+ .containsAllEntriesOf(initialMeasures)
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, (double) Rating.D.getIndex())
+ .containsEntry(SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, (double) Rating.D.getIndex());
+ }
+}
diff --git a/server/sonar-webserver-es/build.gradle b/server/sonar-webserver-es/build.gradle
index d59d52be520..d51c2b4f16b 100644
--- a/server/sonar-webserver-es/build.gradle
+++ b/server/sonar-webserver-es/build.gradle
@@ -21,6 +21,7 @@ dependencies {
testImplementation 'com.github.spotbugs:spotbugs-annotations'
testImplementation 'com.tngtech.java:junit-dataprovider'
testImplementation 'org.junit.jupiter:junit-jupiter-api'
+ testImplementation 'org.junit.jupiter:junit-jupiter-params'
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.sonarsource.api.plugin:sonar-plugin-api-test-fixtures'
testImplementation testFixtures(project(':server:sonar-webserver-auth'))
diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
index 5e33203b4bd..9d6344f96e2 100644
--- a/server/sonar-webserver-es/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
+++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java
@@ -21,6 +21,7 @@ package org.sonar.server.measure.index;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -103,6 +104,14 @@ import static org.sonar.api.measures.CoreMetrics.SECURITY_HOTSPOTS_REVIEWED_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SECURITY_REVIEW_RATING_KEY;
import static org.sonar.api.measures.CoreMetrics.SQALE_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars;
import static org.sonar.server.es.EsUtils.termsToMap;
import static org.sonar.server.es.IndexType.FIELD_INDEX_TYPE;
@@ -154,6 +163,8 @@ public class ProjectMeasuresIndex {
NEW_DUPLICATED_LINES_DENSITY(new RangeWithNoDataMeasureFacet(NEW_DUPLICATED_LINES_DENSITY_KEY, DUPLICATIONS_THRESHOLDS)),
COVERAGE(new RangeWithNoDataMeasureFacet(COVERAGE_KEY, COVERAGE_THRESHOLDS)),
NEW_COVERAGE(new RangeWithNoDataMeasureFacet(NEW_COVERAGE_KEY, COVERAGE_THRESHOLDS)),
+
+ //RuleType ratings
SQALE_RATING(new RatingMeasureFacet(SQALE_RATING_KEY)),
NEW_MAINTAINABILITY_RATING(new RatingMeasureFacet(NEW_MAINTAINABILITY_RATING_KEY)),
RELIABILITY_RATING(new RatingMeasureFacet(RELIABILITY_RATING_KEY)),
@@ -162,6 +173,17 @@ public class ProjectMeasuresIndex {
NEW_SECURITY_RATING(new RatingMeasureFacet(NEW_SECURITY_RATING_KEY)),
SECURITY_REVIEW_RATING(new RatingMeasureFacet(SECURITY_REVIEW_RATING_KEY)),
NEW_SECURITY_REVIEW_RATING(new RatingMeasureFacet(NEW_SECURITY_REVIEW_RATING_KEY)),
+
+ //Software quality ratings
+ SOFTWARE_QUALITY_MAINTAINABILITY_RATING(new RatingMeasureFacet(SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, 4)),
+ NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING(new RatingMeasureFacet(NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, 4)),
+ SOFTWARE_QUALITY_RELIABILITY_RATING(new RatingMeasureFacet(SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, 4)),
+ NEW_SOFTWARE_QUALITY_RELIABILITY_RATING(new RatingMeasureFacet(NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, 4)),
+ SOFTWARE_QUALITY_SECURITY_RATING(new RatingMeasureFacet(SOFTWARE_QUALITY_SECURITY_RATING_KEY, 4)),
+ NEW_SOFTWARE_QUALITY_SECURITY_RATING(new RatingMeasureFacet(NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY, 4)),
+ SOFTWARE_QUALITY_SECURITY_REVIEW_RATING(new RatingMeasureFacet(SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, 4)),
+ NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING(new RatingMeasureFacet(NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, 4)),
+
SECURITY_HOTSPOTS_REVIEWED(new RangeMeasureFacet(SECURITY_HOTSPOTS_REVIEWED_KEY, SECURITY_REVIEW_RATING_THRESHOLDS)),
NEW_SECURITY_HOTSPOTS_REVIEWED(new RangeMeasureFacet(NEW_SECURITY_HOTSPOTS_REVIEWED_KEY, SECURITY_REVIEW_RATING_THRESHOLDS)),
ALERT_STATUS(new MeasureFacet(ALERT_STATUS_KEY, ProjectMeasuresIndex::buildAlertStatusFacet)),
@@ -566,14 +588,20 @@ public class ProjectMeasuresIndex {
private static class RatingMeasureFacet extends MeasureFacet {
private RatingMeasureFacet(String metricKey) {
- super(metricKey, new MetricRatingFacetBuilder(metricKey));
+ super(metricKey, new MetricRatingFacetBuilder(metricKey, 5));
+ }
+
+ private RatingMeasureFacet(String metricKey, int maxRating) {
+ super(metricKey, new MetricRatingFacetBuilder(metricKey, maxRating));
}
private static class MetricRatingFacetBuilder implements FacetBuilder {
private final String metricKey;
+ private final int maxRating;
- private MetricRatingFacetBuilder(String metricKey) {
+ private MetricRatingFacetBuilder(String metricKey, int maxRating) {
this.metricKey = metricKey;
+ this.maxRating = maxRating;
}
@Override
@@ -581,19 +609,20 @@ public class ProjectMeasuresIndex {
return topAggregationHelper.buildTopAggregation(
facet.getName(), facet.getTopAggregationDef(),
NO_EXTRA_FILTER,
- t -> t.subAggregation(createMeasureRatingFacet(metricKey)));
+ t -> t.subAggregation(createMeasureRatingFacet(metricKey, maxRating)));
}
- private static AbstractAggregationBuilder<?> createMeasureRatingFacet(String metricKey) {
+ private static AbstractAggregationBuilder<?> createMeasureRatingFacet(String metricKey, int maxRating) {
+ List<KeyedFilter> filter = new ArrayList<>();
+ for (int i = 1; i <= maxRating; i++) {
+ filter.add(new KeyedFilter(String.valueOf(i), termQuery(FIELD_MEASURES_MEASURE_VALUE, Double.valueOf(i))));
+ }
+
return AggregationBuilders.nested("nested_" + metricKey, FIELD_MEASURES)
.subAggregation(
AggregationBuilders.filter("filter_" + metricKey, termsQuery(FIELD_MEASURES_MEASURE_KEY, metricKey))
- .subAggregation(filters(metricKey,
- new KeyedFilter("1", termQuery(FIELD_MEASURES_MEASURE_VALUE, 1D)),
- new KeyedFilter("2", termQuery(FIELD_MEASURES_MEASURE_VALUE, 2D)),
- new KeyedFilter("3", termQuery(FIELD_MEASURES_MEASURE_VALUE, 3D)),
- new KeyedFilter("4", termQuery(FIELD_MEASURES_MEASURE_VALUE, 4D)),
- new KeyedFilter("5", termQuery(FIELD_MEASURES_MEASURE_VALUE, 5D)))));
+ .subAggregation(filters(metricKey, filter.toArray(new KeyedFilter[0])
+ )));
}
}
}
diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
index 6e2961e4c4d..8b21640cbb5 100644
--- a/server/sonar-webserver-es/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
+++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java
@@ -19,22 +19,17 @@
*/
package org.sonar.server.measure.index;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
-import com.tngtech.java.junit.dataprovider.DataProvider;
-import com.tngtech.java.junit.dataprovider.DataProviderRunner;
-import com.tngtech.java.junit.dataprovider.UseDataProvider;
-import java.time.Instant;
import java.util.Arrays;
-import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.stream.IntStream;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import org.sonar.api.utils.System2;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTesting;
@@ -55,7 +50,6 @@ import static com.google.common.collect.Sets.newHashSet;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Collections.singletonList;
-import static java.util.stream.Collectors.toList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.entry;
@@ -73,8 +67,7 @@ import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE
import static org.sonar.server.measure.index.ProjectMeasuresQuery.Operator;
import static org.sonarqube.ws.client.project.ProjectsWsParameters.FILTER_QUALIFIER;
-@RunWith(DataProviderRunner.class)
-public class ProjectMeasuresIndexTest {
+class ProjectMeasuresIndexTest {
private static final String MAINTAINABILITY_RATING = "sqale_rating";
private static final String NEW_MAINTAINABILITY_RATING_KEY = "new_maintainability_rating";
@@ -84,6 +77,17 @@ public class ProjectMeasuresIndexTest {
private static final String NEW_SECURITY_RATING = "new_security_rating";
private static final String SECURITY_REVIEW_RATING = "security_review_rating";
private static final String NEW_SECURITY_REVIEW_RATING = "new_security_review_rating";
+
+ //Software quality ratings
+ private static final String SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY = "software_quality_maintainability_rating";
+ private static final String NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY = "new_software_quality_maintainability_rating";
+ private static final String SOFTWARE_QUALITY_RELIABILITY_RATING_KEY = "software_quality_reliability_rating";
+ private static final String NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY = "new_software_quality_reliability_rating";
+ private static final String SOFTWARE_QUALITY_SECURITY_RATING_KEY = "software_quality_security_rating";
+ private static final String NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY = "new_software_quality_security_rating";
+ private static final String SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY = "software_quality_security_review_rating";
+ private static final String NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY = "new_software_quality_security_review_rating";
+
private static final String SECURITY_HOTSPOTS_REVIEWED = "security_hotspots_reviewed";
private static final String NEW_SECURITY_HOTSPOTS_REVIEWED = "new_security_hotspots_reviewed";
private static final String COVERAGE = "coverage";
@@ -105,28 +109,41 @@ public class ProjectMeasuresIndexTest {
private static final GroupDto GROUP1 = newGroupDto();
private static final GroupDto GROUP2 = newGroupDto();
- @Rule
- public EsTester es = EsTester.create();
- @Rule
- public UserSessionRule userSession = UserSessionRule.standalone();
+ @RegisterExtension
+ private final EsTester es = EsTester.create();
+ @RegisterExtension
+ private final UserSessionRule userSession = UserSessionRule.standalone();
+
+ private static String[] rating_metric_keys() {
+ return new String[]{
+ MAINTAINABILITY_RATING, NEW_MAINTAINABILITY_RATING_KEY,
+ RELIABILITY_RATING, NEW_RELIABILITY_RATING,
+ SECURITY_RATING, NEW_SECURITY_RATING,
+ SECURITY_REVIEW_RATING, NEW_SECURITY_REVIEW_RATING
+ };
+ }
- @DataProvider
- public static Object[][] rating_metric_keys() {
- return new Object[][] {{MAINTAINABILITY_RATING}, {NEW_MAINTAINABILITY_RATING_KEY}, {RELIABILITY_RATING}, {NEW_RELIABILITY_RATING}, {SECURITY_RATING}, {NEW_SECURITY_RATING},
- {SECURITY_REVIEW_RATING}, {NEW_SECURITY_REVIEW_RATING}};
+ private static String[] software_quality_rating_metric_keys() {
+ return new String[]{
+ SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY, NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY,
+ SOFTWARE_QUALITY_RELIABILITY_RATING_KEY, NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY,
+ SOFTWARE_QUALITY_SECURITY_RATING_KEY, NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY,
+ SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY, NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY
+ };
}
- private ProjectMeasuresIndexer projectMeasureIndexer = new ProjectMeasuresIndexer(null, es.client());
- private PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, projectMeasureIndexer);
- private ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client(), new WebAuthorizationTypeSupport(userSession), System2.INSTANCE);
+ private final ProjectMeasuresIndexer projectMeasureIndexer = new ProjectMeasuresIndexer(null, es.client());
+ private final PermissionIndexerTester authorizationIndexer = new PermissionIndexerTester(es, projectMeasureIndexer);
+ private final ProjectMeasuresIndex underTest = new ProjectMeasuresIndex(es.client(), new WebAuthorizationTypeSupport(userSession),
+ System2.INSTANCE);
@Test
- public void return_empty_if_no_projects() {
+ void return_empty_if_no_projects() {
assertNoResults(new ProjectMeasuresQuery());
}
@Test
- public void default_sort_is_by_ascending_case_insensitive_name_then_by_key() {
+ void default_sort_is_by_ascending_case_insensitive_name_then_by_key() {
ComponentDto windows = ComponentTesting.newPrivateProjectDto().setUuid("windows").setName("Windows").setKey("project1");
ComponentDto apachee = ComponentTesting.newPrivateProjectDto().setUuid("apachee").setName("apachee").setKey("project2");
ComponentDto apache1 = ComponentTesting.newPrivateProjectDto().setUuid("apache-1").setName("Apache").setKey("project3");
@@ -137,7 +154,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void sort_by_insensitive_name() {
+ void sort_by_insensitive_name() {
ComponentDto windows = ComponentTesting.newPrivateProjectDto().setUuid("windows").setName("Windows");
ComponentDto apachee = ComponentTesting.newPrivateProjectDto().setUuid("apachee").setName("apachee");
ComponentDto apache = ComponentTesting.newPrivateProjectDto().setUuid("apache").setName("Apache");
@@ -148,7 +165,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void sort_by_ncloc() {
+ void sort_by_ncloc() {
index(
newDoc(PROJECT1, NCLOC, 15_000d),
newDoc(PROJECT2, NCLOC, 30_000d),
@@ -159,7 +176,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void sort_by_a_metric_then_by_name_then_by_key() {
+ void sort_by_a_metric_then_by_name_then_by_key() {
ComponentDto windows = ComponentTesting.newPrivateProjectDto().setUuid("windows").setName("Windows").setKey("project1");
ComponentDto apachee = ComponentTesting.newPrivateProjectDto().setUuid("apachee").setName("apachee").setKey("project2");
ComponentDto apache1 = ComponentTesting.newPrivateProjectDto().setUuid("apache-1").setName("Apache").setKey("project3");
@@ -175,7 +192,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void sort_by_quality_gate_status() {
+ void sort_by_quality_gate_status() {
ComponentDto project4 = ComponentTesting.newPrivateProjectDto().setUuid("Project-4").setName("Project 4").setKey("key-4");
index(
newDoc(PROJECT1).setQualityGateStatus(OK.name()),
@@ -186,40 +203,8 @@ public class ProjectMeasuresIndexTest {
assertResults(new ProjectMeasuresQuery().setSort("alert_status").setAsc(false), PROJECT2, PROJECT1, project4);
}
- public void sort_by_creation_date() {
- Instant now = Instant.ofEpochMilli(1000L);
- Date nowMinus10 = Date.from(now.minusSeconds(10));
- Date nowMinus20 = Date.from(now.minusSeconds(20));
- Date nowMinus30 = Date.from(now.minusSeconds(30));
-
- ComponentDto project4 = ComponentTesting.newPrivateProjectDto().setUuid("Project-4").setName("Project 4").setKey("key-4");
- index(
- newDoc(PROJECT1).setCreatedAt(nowMinus10),
- newDoc(PROJECT2).setCreatedAt(nowMinus30),
- newDoc(project4).setCreatedAt(nowMinus20));
-
- assertResults(new ProjectMeasuresQuery().setSort("creation_date").setAsc(true), PROJECT1, project4, PROJECT2);
- assertResults(new ProjectMeasuresQuery().setSort("creation_date").setAsc(false), PROJECT2, PROJECT1, project4);
- }
-
- public void sort_by_analysis_date() {
- Instant now = Instant.ofEpochMilli(1000L);
- Date nowMinus10 = Date.from(now.minusSeconds(10));
- Date nowMinus20 = Date.from(now.minusSeconds(20));
- Date nowMinus30 = Date.from(now.minusSeconds(30));
-
- ComponentDto project4 = ComponentTesting.newPrivateProjectDto().setUuid("Project-4").setName("Project 4").setKey("key-4");
- index(
- newDoc(PROJECT1).setAnalysedAt(nowMinus10),
- newDoc(PROJECT2).setAnalysedAt(nowMinus30),
- newDoc(project4).setAnalysedAt(nowMinus20));
-
- assertResults(new ProjectMeasuresQuery().setSort("analysis_date").setAsc(true), PROJECT1, project4, PROJECT2);
- assertResults(new ProjectMeasuresQuery().setSort("analysis_date").setAsc(false), PROJECT2, PROJECT1, project4);
- }
-
@Test
- public void sort_by_quality_gate_status_then_by_name_then_by_key() {
+ void sort_by_quality_gate_status_then_by_name_then_by_key() {
ComponentDto windows = ComponentTesting.newPrivateProjectDto().setUuid("windows").setName("Windows").setKey("project1");
ComponentDto apachee = ComponentTesting.newPrivateProjectDto().setUuid("apachee").setName("apachee").setKey("project2");
ComponentDto apache1 = ComponentTesting.newPrivateProjectDto().setUuid("apache-1").setName("Apache").setKey("project3");
@@ -235,7 +220,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void paginate_results() {
+ void paginate_results() {
IntStream.rangeClosed(1, 9)
.forEach(i -> index(newDoc(newPrivateProjectDto("P" + i))));
@@ -246,7 +231,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_with_lower_than() {
+ void filter_with_lower_than() {
index(
newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d),
@@ -259,7 +244,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_with_lower_than_or_equals() {
+ void filter_with_lower_than_or_equals() {
index(
newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d),
@@ -272,7 +257,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_with_greater_than() {
+ void filter_with_greater_than() {
index(
newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d),
@@ -286,7 +271,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_with_greater_than_or_equals() {
+ void filter_with_greater_than_or_equals() {
index(
newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d),
@@ -300,7 +285,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_with_equals() {
+ void filter_with_equals() {
index(
newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d),
@@ -313,7 +298,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_no_data_with_several_projects() {
+ void filter_on_no_data_with_several_projects() {
index(
newDoc(PROJECT1, NCLOC, 1d),
newDoc(PROJECT2, DUPLICATION, 80d));
@@ -325,7 +310,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_no_data_should_not_return_projects_with_data_and_other_measures() {
+ void filter_on_no_data_should_not_return_projects_with_data_and_other_measures() {
ComponentDto project = ComponentTesting.newPrivateProjectDto();
index(newDoc(project, DUPLICATION, 80d, NCLOC, 1d));
@@ -335,7 +320,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_no_data_should_not_return_projects_with_data() {
+ void filter_on_no_data_should_not_return_projects_with_data() {
ComponentDto project = ComponentTesting.newPrivateProjectDto();
index(newDoc(project, DUPLICATION, 80d));
@@ -345,7 +330,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_no_data_should_return_projects_with_no_data() {
+ void filter_on_no_data_should_return_projects_with_no_data() {
ComponentDto project = ComponentTesting.newPrivateProjectDto();
index(newDoc(project, NCLOC, 1d));
@@ -355,7 +340,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_several_metrics() {
+ void filter_on_several_metrics() {
index(
newDoc(PROJECT1, COVERAGE, 81d, NCLOC, 10_001d),
newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_001d),
@@ -369,7 +354,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_security_hotspots_reviewed() {
+ void facet_security_hotspots_reviewed() {
index(
// 2 docs with no measure
newDocWithNoMeasure(),
@@ -406,7 +391,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_new_security_hotspots_reviewed() {
+ void facet_new_security_hotspots_reviewed() {
index(
// 2 docs with no measure
newDocWithNoMeasure(),
@@ -443,7 +428,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_quality_gate_status() {
+ void filter_on_quality_gate_status() {
index(
newDoc(PROJECT1).setQualityGateStatus(OK.name()),
newDoc(PROJECT2).setQualityGateStatus(OK.name()),
@@ -454,7 +439,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_languages() {
+ void filter_on_languages() {
ComponentDto project4 = ComponentTesting.newPrivateProjectDto().setUuid("Project-4").setName("Project 4").setKey("key-4");
index(
newDoc(PROJECT1).setLanguages(singletonList("java")),
@@ -468,7 +453,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_query_text() {
+ void filter_on_query_text() {
ComponentDto windows = ComponentTesting.newPrivateProjectDto().setUuid("windows").setName("Windows").setKey("project1");
ComponentDto apachee = ComponentTesting.newPrivateProjectDto().setUuid("apachee").setName("apachee").setKey("project2");
ComponentDto apache1 = ComponentTesting.newPrivateProjectDto().setUuid("apache-1").setName("Apache").setKey("project3");
@@ -481,7 +466,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_ids() {
+ void filter_on_ids() {
index(
newDoc(PROJECT1),
newDoc(PROJECT2),
@@ -492,7 +477,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_tags() {
+ void filter_on_tags() {
index(
newDoc(PROJECT1).setTags(newArrayList("finance", "platform")),
newDoc(PROJECT2).setTags(newArrayList("marketing", "platform")),
@@ -506,7 +491,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void filter_on_qualifier() {
+ void filter_on_qualifier() {
index(newDoc(PROJECT1), newDoc(PROJECT2), newDoc(PROJECT3),
newDoc(APP1), newDoc(APP2), newDoc(APP3));
@@ -524,7 +509,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void return_correct_number_of_total_if_exceeds_index_max_results() {
+ void return_correct_number_of_total_if_exceeds_index_max_results() {
index(IntStream.range(0, 12_000)
.mapToObj(operand -> newDoc(ComponentTesting.newPrivateProjectDto()))
.toArray(ProjectMeasuresDoc[]::new));
@@ -535,7 +520,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void return_only_projects_and_applications_authorized_for_user() {
+ void return_only_projects_and_applications_authorized_for_user() {
indexForUser(USER1, newDoc(PROJECT1), newDoc(PROJECT2),
newDoc(APP1), newDoc(APP2));
indexForUser(USER2, newDoc(PROJECT3), newDoc(APP3));
@@ -545,7 +530,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void return_only_projects_and_applications_authorized_for_user_groups() {
+ void return_only_projects_and_applications_authorized_for_user_groups() {
indexForGroup(GROUP1, newDoc(PROJECT1), newDoc(PROJECT2),
newDoc(APP1), newDoc(APP2));
indexForGroup(GROUP2, newDoc(PROJECT3));
@@ -555,7 +540,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void return_only_projects_and_applications_authorized_for_user_and_groups() {
+ void return_only_projects_and_applications_authorized_for_user_and_groups() {
indexForUser(USER1, newDoc(PROJECT1), newDoc(PROJECT2),
newDoc(APP1), newDoc(APP2));
indexForGroup(GROUP1, newDoc(PROJECT3));
@@ -565,7 +550,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void anonymous_user_can_only_access_projects_and_applications_authorized_for_anyone() {
+ void anonymous_user_can_only_access_projects_and_applications_authorized_for_anyone() {
index(newDoc(PROJECT1), newDoc(APP1));
indexForUser(USER1, newDoc(PROJECT2), newDoc(APP2));
@@ -574,7 +559,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void return_all_projects_and_applications_when_setIgnoreAuthorization_is_true() {
+ void return_all_projects_and_applications_when_setIgnoreAuthorization_is_true() {
indexForUser(USER1, newDoc(PROJECT1), newDoc(PROJECT2), newDoc(APP1), newDoc(APP2));
indexForUser(USER2, newDoc(PROJECT3), newDoc(APP3));
userSession.logIn(USER1);
@@ -584,7 +569,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void does_not_return_facet_when_no_facets_in_options() {
+ void does_not_return_facet_when_no_facets_in_options() {
index(
newDoc(PROJECT1, NCLOC, 10d, COVERAGE_KEY, 30d, MAINTAINABILITY_RATING, 3d)
.setQualityGateStatus(OK.name()));
@@ -595,7 +580,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_ncloc() {
+ void facet_ncloc() {
index(
// 3 docs with ncloc<1K
newDoc(NCLOC, 0d),
@@ -630,7 +615,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_ncloc_is_sticky() {
+ void facet_ncloc_is_sticky() {
index(
// 1 docs with ncloc<1K
newDoc(NCLOC, 999d, COVERAGE, 0d, DUPLICATION, 0d),
@@ -670,7 +655,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_ncloc_contains_only_projects_authorized_for_user() {
+ void facet_ncloc_contains_only_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
// docs with ncloc<1K
@@ -702,7 +687,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_new_lines() {
+ void facet_new_lines() {
index(
// 3 docs with ncloc<1K
newDoc(NEW_LINES, 0d),
@@ -737,7 +722,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_coverage() {
+ void facet_coverage() {
index(
// 1 doc with no coverage
newDocWithNoMeasure(),
@@ -775,7 +760,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_coverage_is_sticky() {
+ void facet_coverage_is_sticky() {
index(
// docs with no coverage
newDoc(NCLOC, 999d, DUPLICATION, 0d),
@@ -819,7 +804,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_coverage_contains_only_projects_authorized_for_user() {
+ void facet_coverage_contains_only_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
// 1 doc with no coverage
@@ -857,7 +842,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_new_coverage() {
+ void facet_new_coverage() {
index(
// 1 doc with no coverage
newDocWithNoMeasure(),
@@ -895,7 +880,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_duplicated_lines_density() {
+ void facet_duplicated_lines_density() {
index(
// 1 doc with no duplication
newDocWithNoMeasure(),
@@ -933,7 +918,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_duplicated_lines_density_is_sticky() {
+ void facet_duplicated_lines_density_is_sticky() {
index(
// docs with no duplication
newDoc(NCLOC, 50_001d, COVERAGE, 29d),
@@ -973,7 +958,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_duplicated_lines_density_contains_only_projects_authorized_for_user() {
+ void facet_duplicated_lines_density_contains_only_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
// docs with no duplication
@@ -1011,7 +996,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_new_duplicated_lines_density() {
+ void facet_new_duplicated_lines_density() {
index(
// 2 docs with no measure
newDocWithNoMeasure(),
@@ -1049,9 +1034,9 @@ public class ProjectMeasuresIndexTest {
entry("20.0-*", 5L));
}
- @Test
- @UseDataProvider("rating_metric_keys")
- public void facet_on_rating(String metricKey) {
+ @ParameterizedTest
+ @MethodSource("rating_metric_keys")
+ void facet_on_rating(String metricKey) {
index(
// 3 docs with rating A
newDoc(metricKey, 1d),
@@ -1085,9 +1070,38 @@ public class ProjectMeasuresIndexTest {
entry("5", 5L));
}
- @Test
- @UseDataProvider("rating_metric_keys")
- public void facet_on_rating_is_sticky(String metricKey) {
+ @ParameterizedTest
+ @MethodSource("software_quality_rating_metric_keys")
+ void facet_on_software_quality_rating(String metricKey) {
+ index(
+ // 3 docs with rating A
+ newDoc(metricKey, 1d),
+ newDoc(metricKey, 1d),
+ newDoc(metricKey, 1d),
+ // 2 docs with rating B
+ newDoc(metricKey, 2d),
+ newDoc(metricKey, 2d),
+ // 4 docs with rating C
+ newDoc(metricKey, 3d),
+ newDoc(metricKey, 3d),
+ newDoc(metricKey, 3d),
+ newDoc(metricKey, 3d),
+ // 2 docs with rating D
+ newDoc(metricKey, 4d),
+ newDoc(metricKey, 4d));
+
+ Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(metricKey)).getFacets();
+
+ assertThat(facets.get(metricKey)).containsExactly(
+ entry("1", 3L),
+ entry("2", 2L),
+ entry("3", 4L),
+ entry("4", 2L));
+ }
+
+ @ParameterizedTest
+ @MethodSource("rating_metric_keys")
+ void facet_on_rating_is_sticky(String metricKey) {
index(
// docs with rating A
newDoc(metricKey, 1d, NCLOC, 100d, COVERAGE, 0d),
@@ -1129,9 +1143,48 @@ public class ProjectMeasuresIndexTest {
entry("500000.0-*", 0L));
}
- @Test
- @UseDataProvider("rating_metric_keys")
- public void facet_on_rating_contains_only_projects_authorized_for_user(String metricKey) {
+ @ParameterizedTest
+ @MethodSource("software_quality_rating_metric_keys")
+ void facet_on_software_quality_rating_is_sticky(String metricKey) {
+ index(
+ // docs with rating A
+ newDoc(metricKey, 1d, NCLOC, 100d, COVERAGE, 0d),
+ newDoc(metricKey, 1d, NCLOC, 200d, COVERAGE, 0d),
+ newDoc(metricKey, 1d, NCLOC, 999d, COVERAGE, 0d),
+ // docs with rating B
+ newDoc(metricKey, 2d, NCLOC, 2000d, COVERAGE, 0d),
+ newDoc(metricKey, 2d, NCLOC, 5000d, COVERAGE, 0d),
+ // docs with rating C
+ newDoc(metricKey, 3d, NCLOC, 20000d, COVERAGE, 0d),
+ newDoc(metricKey, 3d, NCLOC, 30000d, COVERAGE, 0d),
+ newDoc(metricKey, 3d, NCLOC, 40000d, COVERAGE, 0d),
+ newDoc(metricKey, 3d, NCLOC, 50000d, COVERAGE, 0d),
+ // docs with rating D
+ newDoc(metricKey, 4d, NCLOC, 120000d, COVERAGE, 0d));
+
+ Facets facets = underTest.search(new ProjectMeasuresQuery()
+ .addMetricCriterion(MetricCriterion.create(metricKey, Operator.LT, 3d))
+ .addMetricCriterion(MetricCriterion.create(COVERAGE, Operator.LT, 30d)),
+ new SearchOptions().addFacets(metricKey, NCLOC)).getFacets();
+
+ // Sticky facet on maintainability rating does not take into account maintainability rating filter
+ assertThat(facets.get(metricKey)).containsExactly(
+ entry("1", 3L),
+ entry("2", 2L),
+ entry("3", 4L),
+ entry("4", 1L));
+ // But facet on ncloc does well take into into filters
+ assertThat(facets.get(NCLOC)).containsExactly(
+ entry("*-1000.0", 3L),
+ entry("1000.0-10000.0", 2L),
+ entry("10000.0-100000.0", 0L),
+ entry("100000.0-500000.0", 0L),
+ entry("500000.0-*", 0L));
+ }
+
+ @ParameterizedTest
+ @MethodSource("rating_metric_keys")
+ void facet_on_rating_contains_only_projects_authorized_for_user(String metricKey) {
// User can see these projects
indexForUser(USER1,
// 3 docs with rating A
@@ -1162,8 +1215,38 @@ public class ProjectMeasuresIndexTest {
entry("5", 0L));
}
+ @ParameterizedTest
+ @MethodSource("software_quality_rating_metric_keys")
+ void facet_on_software_quality_rating_contains_only_projects_authorized_for_user(String metricKey) {
+ // User can see these projects
+ indexForUser(USER1,
+ // 3 docs with rating A
+ newDoc(metricKey, 1d),
+ newDoc(metricKey, 1d),
+ newDoc(metricKey, 1d),
+ // 2 docs with rating B
+ newDoc(metricKey, 2d),
+ newDoc(metricKey, 2d));
+
+ // User cannot see these projects
+ indexForUser(USER2,
+ // docs with rating C
+ newDoc(metricKey, 3d),
+ // docs with rating D
+ newDoc(metricKey, 4d));
+
+ userSession.logIn(USER1);
+ Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(metricKey)).getFacets();
+
+ assertThat(facets.get(metricKey)).containsExactly(
+ entry("1", 3L),
+ entry("2", 2L),
+ entry("3", 0L),
+ entry("4", 0L));
+ }
+
@Test
- public void facet_quality_gate() {
+ void facet_quality_gate() {
index(
// 2 docs with QG OK
newDoc().setQualityGateStatus(OK.name()),
@@ -1182,7 +1265,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_quality_gate_is_sticky() {
+ void facet_quality_gate_is_sticky() {
index(
// 2 docs with QG OK
newDoc(NCLOC, 10d, COVERAGE, 0d).setQualityGateStatus(OK.name()),
@@ -1212,7 +1295,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_quality_gate_contains_only_projects_authorized_for_user() {
+ void facet_quality_gate_contains_only_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
// 2 docs with QG OK
@@ -1236,7 +1319,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_languages() {
+ void facet_languages() {
index(
newDoc().setLanguages(singletonList("java")),
newDoc().setLanguages(singletonList("java")),
@@ -1255,7 +1338,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_languages_is_limited_to_10_languages() {
+ void facet_languages_is_limited_to_10_languages() {
index(
newDoc().setLanguages(asList("<null>", "java", "xoo", "css", "cpp")),
newDoc().setLanguages(asList("xml", "php", "python", "perl", "ruby")),
@@ -1267,7 +1350,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_languages_is_sticky() {
+ void facet_languages_is_sticky() {
index(
newDoc(NCLOC, 10d).setLanguages(singletonList("java")),
newDoc(NCLOC, 10d).setLanguages(singletonList("java")),
@@ -1277,7 +1360,7 @@ public class ProjectMeasuresIndexTest {
newDoc(NCLOC, 5000d).setLanguages(asList("<null>", "java", "xoo")));
Facets facets = underTest.search(
- new ProjectMeasuresQuery().setLanguages(ImmutableSet.of("java")),
+ new ProjectMeasuresQuery().setLanguages(Set.of("java")),
new SearchOptions().addFacets(LANGUAGES, NCLOC)).getFacets();
// Sticky facet on language does not take into account language filter
@@ -1296,13 +1379,14 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_languages_returns_more_than_10_languages_when_languages_filter_contains_value_not_in_top_10() {
+ void facet_languages_returns_more_than_10_languages_when_languages_filter_contains_value_not_in_top_10() {
index(
newDoc().setLanguages(asList("<null>", "java", "xoo", "css", "cpp")),
newDoc().setLanguages(asList("xml", "php", "python", "perl", "ruby")),
newDoc().setLanguages(asList("js", "scala")));
- Facets facets = underTest.search(new ProjectMeasuresQuery().setLanguages(ImmutableSet.of("xoo", "xml")), new SearchOptions().addFacets(LANGUAGES)).getFacets();
+ Facets facets = underTest.search(new ProjectMeasuresQuery().setLanguages(Set.of("xoo", "xml")),
+ new SearchOptions().addFacets(LANGUAGES)).getFacets();
assertThat(facets.get(LANGUAGES)).containsOnly(
entry("<null>", 1L),
@@ -1320,7 +1404,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_languages_contains_only_projects_authorized_for_user() {
+ void facet_languages_contains_only_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
newDoc().setLanguages(singletonList("java")),
@@ -1340,7 +1424,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_qualifier() {
+ void facet_qualifier() {
index(
// 2 docs with qualifier APP
newDoc().setQualifier(APP),
@@ -1359,7 +1443,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_qualifier_is_sticky() {
+ void facet_qualifier_is_sticky() {
index(
// 2 docs with qualifier APP
newDoc(NCLOC, 10d, COVERAGE, 0d).setQualifier(APP),
@@ -1389,7 +1473,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_qualifier_contains_only_app_and_projects_authorized_for_user() {
+ void facet_qualifier_contains_only_app_and_projects_authorized_for_user() {
// User can see these projects
indexForUser(USER1,
// 3 docs with qualifier APP, PROJECT
@@ -1414,7 +1498,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_tags() {
+ void facet_tags() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("finance", "javascript")),
@@ -1434,7 +1518,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_tags_is_sticky() {
+ void facet_tags_is_sticky() {
index(
newDoc().setTags(newArrayList("finance")).setQualityGateStatus(OK.name()),
newDoc().setTags(newArrayList("finance")).setQualityGateStatus(ERROR.name()),
@@ -1454,7 +1538,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_tags_returns_10_elements_by_default() {
+ void facet_tags_returns_10_elements_by_default() {
index(
newDoc().setTags(newArrayList("finance1", "finance2", "finance3", "finance4", "finance5", "finance6", "finance7", "finance8", "finance9", "finance10")),
newDoc().setTags(newArrayList("finance1", "finance2", "finance3", "finance4", "finance5", "finance6", "finance7", "finance8", "finance9", "finance10")),
@@ -1466,13 +1550,14 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void facet_tags_returns_more_than_10_tags_when_tags_filter_contains_value_not_in_top_10() {
+ void facet_tags_returns_more_than_10_tags_when_tags_filter_contains_value_not_in_top_10() {
index(
newDoc().setTags(newArrayList("finance1", "finance2", "finance3", "finance4", "finance5", "finance6", "finance7", "finance8", "finance9", "finance10")),
newDoc().setTags(newArrayList("finance1", "finance2", "finance3", "finance4", "finance5", "finance6", "finance7", "finance8", "finance9", "finance10")),
newDoc().setTags(newArrayList("solo", "solo2")));
- Map<String, Long> result = underTest.search(new ProjectMeasuresQuery().setTags(ImmutableSet.of("solo", "solo2")), new SearchOptions().addFacets(FIELD_TAGS)).getFacets()
+ Map<String, Long> result = underTest.search(new ProjectMeasuresQuery().setTags(Set.of("solo", "solo2")),
+ new SearchOptions().addFacets(FIELD_TAGS)).getFacets()
.get(FIELD_TAGS);
assertThat(result).hasSize(12).containsOnlyKeys("finance1", "finance2", "finance3", "finance4", "finance5", "finance6", "finance7", "finance8", "finance9", "finance10", "solo",
@@ -1480,7 +1565,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags() {
+ void search_tags() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("official", "javascript")),
@@ -1495,7 +1580,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_return_all_tags() {
+ void search_tags_return_all_tags() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("official", "javascript")),
@@ -1510,7 +1595,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_in_lexical_order() {
+ void search_tags_in_lexical_order() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("official", "javascript")),
@@ -1525,7 +1610,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_follows_paging() {
+ void search_tags_follows_paging() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("official", "javascript")),
@@ -1548,7 +1633,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_returns_nothing_if_page_too_large() {
+ void search_tags_returns_nothing_if_page_too_large() {
index(
newDoc().setTags(newArrayList("finance", "offshore", "java")),
newDoc().setTags(newArrayList("official", "javascript")),
@@ -1563,7 +1648,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_only_of_authorized_projects() {
+ void search_tags_only_of_authorized_projects() {
indexForUser(USER1,
newDoc(PROJECT1).setTags(singletonList("finance")),
newDoc(PROJECT2).setTags(singletonList("marketing")));
@@ -1578,14 +1663,14 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_tags_with_no_tags() {
+ void search_tags_with_no_tags() {
List<String> result = underTest.searchTags("whatever", 1, 10);
assertThat(result).isEmpty();
}
@Test
- public void search_tags_with_page_size_at_0() {
+ void search_tags_with_page_size_at_0() {
index(newDoc().setTags(newArrayList("offshore")));
List<String> result = underTest.searchTags(null, 1, 0);
@@ -1594,14 +1679,14 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_statistics() {
+ void search_statistics() {
es.putDocuments(TYPE_PROJECT_MEASURES,
newDoc("lines", 10, "coverage", 80)
.setLanguages(Arrays.asList("java", "cs", "js"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 200, "cs", 250, "js", 50)),
+ .setNclocLanguageDistributionFromMap(Map.of("java", 200, "cs", 250, "js", 50)),
newDoc("lines", 20, "coverage", 80)
.setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)));
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)));
ProjectMeasuresStatistics result = underTest.searchSupportStatistics();
@@ -1613,7 +1698,7 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_statistics_for_large_instances() {
+ void search_statistics_for_large_instances() {
int nbProjects = 25000;
int javaLocByProjects = 100;
int jsLocByProjects = 900;
@@ -1621,7 +1706,7 @@ public class ProjectMeasuresIndexTest {
ProjectMeasuresDoc[] documents = IntStream.range(0, nbProjects).mapToObj(i -> newDoc("lines", 10, "coverage", 80)
.setLanguages(asList("java", "cs", "js"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", javaLocByProjects, "cs", csLocByProjects, "js", jsLocByProjects))).toArray(ProjectMeasuresDoc[]::new);
+ .setNclocLanguageDistributionFromMap(Map.of("java", javaLocByProjects, "cs", csLocByProjects, "js", jsLocByProjects))).toArray(ProjectMeasuresDoc[]::new);
es.putDocuments(TYPE_PROJECT_MEASURES, documents);
@@ -1642,23 +1727,23 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_statistics_should_ignore_applications() {
+ void search_statistics_should_ignore_applications() {
es.putDocuments(TYPE_PROJECT_MEASURES,
// insert projects
newDoc(ComponentTesting.newPrivateProjectDto(), "lines", 10, "coverage", 80)
.setLanguages(Arrays.asList("java", "cs", "js"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 200, "cs", 250, "js", 50)),
+ .setNclocLanguageDistributionFromMap(Map.of("java", 200, "cs", 250, "js", 50)),
newDoc(ComponentTesting.newPrivateProjectDto(), "lines", 20, "coverage", 80)
.setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)),
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)),
// insert applications
newDoc(ComponentTesting.newApplication(), "lines", 1000, "coverage", 70)
.setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)),
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)),
newDoc(ComponentTesting.newApplication(), "lines", 20, "coverage", 80)
.setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)));
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)));
ProjectMeasuresStatistics result = underTest.searchSupportStatistics();
@@ -1670,15 +1755,15 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void search_statistics_should_count_0_if_no_projects() {
+ void search_statistics_should_count_0_if_no_projects() {
es.putDocuments(TYPE_PROJECT_MEASURES,
// insert applications
newDoc(ComponentTesting.newApplication(), "lines", 1000, "coverage", 70)
- .setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)),
+ .setLanguages(Arrays.asList("java", "Map", "kotlin"))
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)),
newDoc(ComponentTesting.newApplication(), "lines", 20, "coverage", 80)
.setLanguages(Arrays.asList("java", "python", "kotlin"))
- .setNclocLanguageDistributionFromMap(ImmutableMap.of("java", 300, "python", 100, "kotlin", 404)));
+ .setNclocLanguageDistributionFromMap(Map.of("java", 300, "python", 100, "kotlin", 404)));
ProjectMeasuresStatistics result = underTest.searchSupportStatistics();
@@ -1687,14 +1772,14 @@ public class ProjectMeasuresIndexTest {
}
@Test
- public void fail_if_page_size_greater_than_100() {
+ void fail_if_page_size_greater_than_100() {
assertThatThrownBy(() -> underTest.searchTags("whatever", 1, 101))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Page size must be lower than or equals to 100");
}
@Test
- public void fail_if_page_greater_than_20() {
+ void fail_if_page_greater_than_20() {
assertThatThrownBy(() -> underTest.searchTags("whatever", 21, 100))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Page must be between 0 and 20");
@@ -1702,17 +1787,17 @@ public class ProjectMeasuresIndexTest {
private void index(ProjectMeasuresDoc... docs) {
es.putDocuments(TYPE_PROJECT_MEASURES, docs);
- authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).allowAnyone()).collect(toList()));
+ authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).allowAnyone()).toList());
}
private void indexForUser(UserDto user, ProjectMeasuresDoc... docs) {
es.putDocuments(TYPE_PROJECT_MEASURES, docs);
- authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).addUserUuid(user.getUuid())).collect(toList()));
+ authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).addUserUuid(user.getUuid())).toList());
}
private void indexForGroup(GroupDto group, ProjectMeasuresDoc... docs) {
es.putDocuments(TYPE_PROJECT_MEASURES, docs);
- authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).addGroupUuid(group.getUuid())).collect(toList()));
+ authorizationIndexer.allow(stream(docs).map(doc -> new IndexPermissions(doc.getId(), PROJECT).addGroupUuid(group.getUuid())).toList());
}
private static ProjectMeasuresDoc newDoc(ComponentDto project) {
@@ -1740,7 +1825,7 @@ public class ProjectMeasuresIndexTest {
}
private static Map<String, Object> newMeasure(String key, Object value) {
- return ImmutableMap.of("key", key, "value", value);
+ return Map.of("key", key, "value", value);
}
private static ProjectMeasuresDoc newDocWithNoMeasure() {
diff --git a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
index eda28adb2fe..3269fa61cce 100644
--- a/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
+++ b/server/sonar-webserver-webapi/src/it/java/org/sonar/server/component/ws/SearchProjectsActionIT.java
@@ -23,6 +23,7 @@ import com.google.common.base.Joiner;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
import com.tngtech.java.junit.dataprovider.UseDataProvider;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -95,6 +96,14 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonar.api.server.ws.WebService.Param.SORT;
import static org.sonar.api.utils.DateUtils.formatDateTime;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_RELIABILITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_RATING_KEY;
+import static org.sonar.core.metric.SoftwareQualitiesMetrics.SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_002;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_003;
@@ -127,11 +136,39 @@ public class SearchProjectsActionIT {
}
@DataProvider
+ public static Object[][] software_quality_rating_metric_keys() {
+ return new Object[][]{{SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
+ {SOFTWARE_QUALITY_SECURITY_RATING_KEY}, {SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY}};
+ }
+
+ @DataProvider
+ public static Object[][] all_rating_metric_keys() {
+ List<Object[]> result = new ArrayList<>();
+ result.addAll(Arrays.asList(rating_metric_keys()));
+ result.addAll(Arrays.asList(software_quality_rating_metric_keys()));
+ return result.toArray(new Object[result.size()][]);
+ }
+
+ @DataProvider
public static Object[][] new_rating_metric_keys() {
return new Object[][]{{NEW_MAINTAINABILITY_RATING_KEY}, {NEW_RELIABILITY_RATING_KEY}, {NEW_SECURITY_RATING_KEY}};
}
@DataProvider
+ public static Object[][] new_software_quality_rating_metric_keys() {
+ return new Object[][]{{NEW_SOFTWARE_QUALITY_MAINTAINABILITY_RATING_KEY}, {NEW_SOFTWARE_QUALITY_RELIABILITY_RATING_KEY},
+ {NEW_SOFTWARE_QUALITY_SECURITY_RATING_KEY}, {NEW_SOFTWARE_QUALITY_SECURITY_REVIEW_RATING_KEY}};
+ }
+
+ @DataProvider
+ public static Object[][] all_new_rating_metric_keys() {
+ List<Object[]> result = new ArrayList<>();
+ result.addAll(Arrays.asList(new_rating_metric_keys()));
+ result.addAll(Arrays.asList(new_software_quality_rating_metric_keys()));
+ return result.toArray(new Object[result.size()][]);
+ }
+
+ @DataProvider
public static Object[][] component_qualifiers_for_valid_editions() {
return new Object[][]{
{new String[]{Qualifiers.PROJECT}, Edition.COMMUNITY},
@@ -207,7 +244,15 @@ public class SearchProjectsActionIT {
"new_maintainability_rating",
"name",
"analysisDate",
- "creationDate");
+ "creationDate",
+ "new_software_quality_maintainability_rating",
+ "new_software_quality_reliability_rating",
+ "new_software_quality_security_rating",
+ "new_software_quality_security_review_rating",
+ "software_quality_maintainability_rating",
+ "software_quality_reliability_rating",
+ "software_quality_security_rating",
+ "software_quality_security_review_rating");
Param asc = def.param("asc");
assertThat(asc.defaultValue()).isEqualTo("true");
@@ -223,7 +268,15 @@ public class SearchProjectsActionIT {
, "security_rating", "alert_status",
"languages", "tags", "qualifier", "new_reliability_rating", "new_security_rating", "new_maintainability_rating", "new_coverage",
"new_duplicated_lines_density", "new_lines",
- "security_review_rating", "security_hotspots_reviewed", "new_security_hotspots_reviewed", "new_security_review_rating");
+ "security_review_rating", "security_hotspots_reviewed", "new_security_hotspots_reviewed", "new_security_review_rating",
+ "new_software_quality_maintainability_rating",
+ "new_software_quality_reliability_rating",
+ "new_software_quality_security_rating",
+ "new_software_quality_security_review_rating",
+ "software_quality_maintainability_rating",
+ "software_quality_reliability_rating",
+ "software_quality_security_rating",
+ "software_quality_security_review_rating");
}
@Test
@@ -366,7 +419,7 @@ public class SearchProjectsActionIT {
}
@Test
- @UseDataProvider("rating_metric_keys")
+ @UseDataProvider("all_rating_metric_keys")
public void filter_projects_by_rating(String metricKey) {
userSession.logIn();
MetricDto ratingMetric = db.measures().insertMetric(c -> c.setKey(metricKey).setValueType(INT.name()));
@@ -381,7 +434,7 @@ public class SearchProjectsActionIT {
}
@Test
- @UseDataProvider("new_rating_metric_keys")
+ @UseDataProvider("all_new_rating_metric_keys")
public void filter_projects_by_new_rating(String newMetricKey) {
userSession.logIn();
MetricDto ratingMetric = db.measures().insertMetric(c -> c.setKey(newMetricKey).setValueType(INT.name()));
@@ -945,6 +998,30 @@ public class SearchProjectsActionIT {
}
@Test
+ @UseDataProvider("software_quality_rating_metric_keys")
+ public void return_software_quality_rating_facet(String ratingMetricKey) {
+ userSession.logIn();
+ MetricDto ratingMetric = db.measures().insertMetric(c -> c.setKey(ratingMetricKey).setValueType("RATING"));
+ insertProject(new Measure(ratingMetric, c -> c.setValue(1d)));
+ insertProject(new Measure(ratingMetric, c -> c.setValue(1d)));
+ insertProject(new Measure(ratingMetric, c -> c.setValue(3d)));
+ index();
+
+ SearchProjectsWsResponse result = call(request.setFacets(singletonList(ratingMetricKey)));
+
+ Common.Facet facet = result.getFacets().getFacetsList().stream()
+ .filter(oneFacet -> ratingMetricKey.equals(oneFacet.getProperty()))
+ .findFirst().orElseThrow(IllegalStateException::new);
+ assertThat(facet.getValuesList())
+ .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
+ .containsExactly(
+ tuple("1", 2L),
+ tuple("2", 0L),
+ tuple("3", 1L),
+ tuple("4", 0L));
+ }
+
+ @Test
@UseDataProvider("new_rating_metric_keys")
public void return_new_rating_facet(String newRatingMetricKey) {
userSession.logIn();
@@ -971,6 +1048,30 @@ public class SearchProjectsActionIT {
}
@Test
+ @UseDataProvider("new_software_quality_rating_metric_keys")
+ public void return_new_software_quality_rating_facet(String newRatingMetricKey) {
+ userSession.logIn();
+ MetricDto newRatingMetric = db.measures().insertMetric(c -> c.setKey(newRatingMetricKey).setValueType("RATING"));
+ insertProject(new Measure(newRatingMetric, c -> c.setValue(1d)));
+ insertProject(new Measure(newRatingMetric, c -> c.setValue(1d)));
+ insertProject(new Measure(newRatingMetric, c -> c.setValue(3d)));
+ index();
+
+ SearchProjectsWsResponse result = call(request.setFacets(singletonList(newRatingMetricKey)));
+
+ Common.Facet facet = result.getFacets().getFacetsList().stream()
+ .filter(oneFacet -> newRatingMetricKey.equals(oneFacet.getProperty()))
+ .findFirst().orElseThrow(IllegalStateException::new);
+ assertThat(facet.getValuesList())
+ .extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
+ .containsExactly(
+ tuple("1", 2L),
+ tuple("2", 0L),
+ tuple("3", 1L),
+ tuple("4", 0L));
+ }
+
+ @Test
public void return_coverage_facet() {
userSession.logIn();
MetricDto coverage = db.measures().insertMetric(c -> c.setKey(COVERAGE).setValueType("PERCENT"));