diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-02-16 11:12:36 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2017-02-17 12:33:20 +0100 |
commit | 0d3be9943570cf5bfb7fbb72fdfe5a6fcb2798c0 (patch) | |
tree | 7daef363e47a7efeddb2ad1c219758390ae966f1 /server/sonar-server | |
parent | 3d8248cb69680296d02a4c3141beccc2517fac87 (diff) | |
download | sonarqube-0d3be9943570cf5bfb7fbb72fdfe5a6fcb2798c0.tar.gz sonarqube-0d3be9943570cf5bfb7fbb72fdfe5a6fcb2798c0.zip |
SONAR-8224 SONAR-8225 Sort by name and metric
Diffstat (limited to 'server/sonar-server')
7 files changed, 689 insertions, 513 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidator.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidator.java index a0fa062ec0d..51118a13380 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidator.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidator.java @@ -23,13 +23,16 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; -import org.sonar.core.util.stream.Collectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.metric.MetricDto; import org.sonar.server.measure.index.ProjectMeasuresQuery; +import static com.google.common.base.Preconditions.checkArgument; +import static org.sonar.core.util.stream.Collectors.toHashSet; +import static org.sonar.core.util.stream.Collectors.toSet; import static org.sonar.server.measure.index.ProjectMeasuresQuery.MetricCriterion; +import static org.sonar.server.measure.index.ProjectMeasuresQuery.SORT_BY_NAME; public class ProjectMeasuresQueryValidator { @@ -40,7 +43,7 @@ public class ProjectMeasuresQueryValidator { } public void validate(DbSession dbSession, ProjectMeasuresQuery query) { - Set<String> metricKeys = query.getMetricCriteria().stream().map(MetricCriterion::getMetricKey).collect(Collectors.toSet()); + Set<String> metricKeys = getMetrics(query); if (metricKeys.isEmpty()) { return; } @@ -50,32 +53,34 @@ public class ProjectMeasuresQueryValidator { checkMetricsAreNumerics(dbMetrics); } - private static void checkMetricKeysExists(List<MetricDto> dbMetrics, Set<String> inputMetricKeys) { - Set<String> dbMetricsKeys = dbMetrics.stream().map(MetricDto::getKey).collect(Collectors.toSet()); - Set<String> unknownKeys = inputMetricKeys.stream().filter(metricKey -> !dbMetricsKeys.contains(metricKey)).collect(Collectors.toSet()); - if (!unknownKeys.isEmpty()) { - throw new IllegalArgumentException(String.format("Unknown metric(s) %s", new TreeSet<>(unknownKeys))); + private static Set<String> getMetrics(ProjectMeasuresQuery query) { + Set<String> metricKeys = query.getMetricCriteria().stream().map(MetricCriterion::getMetricKey).collect(toHashSet()); + if (query.getSort() != null && !SORT_BY_NAME.equals(query.getSort())) { + metricKeys.add(query.getSort()); } + return metricKeys; + } + + private static void checkMetricKeysExists(List<MetricDto> dbMetrics, Set<String> inputMetricKeys) { + Set<String> dbMetricsKeys = dbMetrics.stream().map(MetricDto::getKey).collect(toSet()); + Set<String> unknownKeys = inputMetricKeys.stream().filter(metricKey -> !dbMetricsKeys.contains(metricKey)).collect(toSet()); + checkArgument(unknownKeys.isEmpty(), "Unknown metric(s) %s", new TreeSet<>(unknownKeys)); } private static void checkMetricsAreEnabled(List<MetricDto> dbMetrics) { Set<String> invalidKeys = dbMetrics.stream() .filter(metricDto -> !metricDto.isEnabled()) .map(MetricDto::getKey) - .collect(Collectors.toSet()); - if (!invalidKeys.isEmpty()) { - throw new IllegalArgumentException(String.format("Following metrics are disabled : %s", new TreeSet<>(invalidKeys))); - } + .collect(toSet()); + checkArgument(invalidKeys.isEmpty(), "Following metrics are disabled : %s", new TreeSet<>(invalidKeys)); } private static void checkMetricsAreNumerics(List<MetricDto> dbMetrics) { Set<String> invalidKeys = dbMetrics.stream() .filter(MetricDto::isDataType) .map(MetricDto::getKey) - .collect(Collectors.toSet()); - if (!invalidKeys.isEmpty()) { - throw new IllegalArgumentException(String.format("Following metrics are not numeric : %s", new TreeSet<>(invalidKeys))); - } + .collect(toSet()); + checkArgument(invalidKeys.isEmpty(), "Following metrics are not numeric : %s", new TreeSet<>(invalidKeys)); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java index ab18e47eca5..15300acf08c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchProjectsAction.java @@ -59,11 +59,13 @@ import org.sonarqube.ws.client.component.SearchProjectsRequest; import static com.google.common.base.MoreObjects.firstNonNull; import static java.lang.String.format; +import static org.sonar.api.measures.CoreMetrics.NCLOC_KEY; import static org.sonar.core.util.stream.Collectors.toSet; import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.hasIsFavoriteCriterion; import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.newProjectMeasuresQuery; import static org.sonar.server.component.ws.ProjectMeasuresQueryFactory.toCriteria; import static org.sonar.server.measure.index.ProjectMeasuresIndex.SUPPORTED_FACETS; +import static org.sonar.server.measure.index.ProjectMeasuresQuery.SORT_BY_NAME; import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; import static org.sonar.server.ws.WsUtils.writeProtobuf; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_FILTER; @@ -72,6 +74,7 @@ import static org.sonarqube.ws.client.component.SearchProjectsRequest.DEFAULT_PA import static org.sonarqube.ws.client.component.SearchProjectsRequest.MAX_PAGE_SIZE; public class SearchProjectsAction implements ComponentsWsAction { + private final DbClient dbClient; private final ProjectMeasuresIndex index; private final ProjectMeasuresQueryValidator queryValidator; @@ -131,6 +134,16 @@ public class SearchProjectsAction implements ComponentsWsAction { " <li>'WARN' for Warning</li>" + " <li>'ERROR' for Failed</li>" + "</ul>"); + + action.createParam(Param.SORT) + .setDescription("Sort projects by numeric metric key or by name.<br/>" + + "See '%s' parameter description for the possible metric values", PARAM_FILTER) + .setDefaultValue(SORT_BY_NAME) + .setExampleValue(NCLOC_KEY); + action.createParam(Param.ASCENDING) + .setDescription("Ascending sort") + .setBooleanPossibleValues() + .setDefaultValue(true); } @Override @@ -169,12 +182,14 @@ public class SearchProjectsAction implements ComponentsWsAction { } private SearchResults searchData(DbSession dbSession, SearchProjectsRequest request, @Nullable OrganizationDto organization) { - List<String> criteria = toCriteria(firstNonNull(request.getFilter(), "")); - Set<String> favoriteProjectUuids = loadFavoriteProjectUuids(dbSession); + + List<String> criteria = toCriteria(firstNonNull(request.getFilter(), "")); Set<String> projectUuids = buildFilterOnFavoriteProjectUuids(criteria, favoriteProjectUuids); - ProjectMeasuresQuery query = newProjectMeasuresQuery(criteria, projectUuids); + ProjectMeasuresQuery query = newProjectMeasuresQuery(criteria, projectUuids) + .setSort(request.getSort()) + .setAsc(request.getAsc()); Optional.ofNullable(organization) .map(OrganizationDto::getUuid) .ifPresent(query::setOrganizationUuid); @@ -226,6 +241,8 @@ public class SearchProjectsAction implements ComponentsWsAction { SearchProjectsRequest.Builder request = SearchProjectsRequest.builder() .setOrganization(httpRequest.param(PARAM_ORGANIZATION)) .setFilter(httpRequest.param(PARAM_FILTER)) + .setSort(httpRequest.mandatoryParam(Param.SORT)) + .setAsc(httpRequest.mandatoryParamAsBoolean(Param.ASCENDING)) .setPage(httpRequest.mandatoryParamAsInt(Param.PAGE)) .setPageSize(httpRequest.mandatoryParamAsInt(Param.PAGE_SIZE)); if (httpRequest.hasParam(Param.FACETS)) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java index dd481748d95..7a2abab4db0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresIndex.java @@ -32,7 +32,7 @@ import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.search.aggregations.AbstractAggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.range.RangeBuilder; -import org.elasticsearch.search.sort.SortOrder; +import org.elasticsearch.search.sort.FieldSortBuilder; import org.sonar.api.measures.Metric; import org.sonar.server.es.BaseIndex; import org.sonar.server.es.DefaultIndexSettingsElement; @@ -50,6 +50,8 @@ import static org.elasticsearch.index.query.QueryBuilders.rangeQuery; import static org.elasticsearch.index.query.QueryBuilders.termQuery; import static org.elasticsearch.index.query.QueryBuilders.termsQuery; import static org.elasticsearch.search.aggregations.AggregationBuilders.filters; +import static org.elasticsearch.search.sort.SortOrder.ASC; +import static org.elasticsearch.search.sort.SortOrder.DESC; import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY; import static org.sonar.api.measures.CoreMetrics.COVERAGE_KEY; import static org.sonar.api.measures.CoreMetrics.DUPLICATED_LINES_DENSITY_KEY; @@ -57,14 +59,14 @@ import static org.sonar.api.measures.CoreMetrics.NCLOC_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; +import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_KEY; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY; -import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_NAME; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_ORGANIZATION_UUID; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.FIELD_QUALITY_GATE; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.INDEX_PROJECT_MEASURES; import static org.sonar.server.measure.index.ProjectMeasuresIndexDefinition.TYPE_PROJECT_MEASURE; +import static org.sonar.server.measure.index.ProjectMeasuresQuery.SORT_BY_NAME; public class ProjectMeasuresIndex extends BaseIndex { @@ -77,8 +79,8 @@ public class ProjectMeasuresIndex extends BaseIndex { SECURITY_RATING_KEY, ALERT_STATUS_KEY); - private static final String FIELD_KEY = FIELD_MEASURES + "." + FIELD_MEASURES_KEY; - private static final String FIELD_VALUE = FIELD_MEASURES + "." + FIELD_MEASURES_VALUE; + private static final String FIELD_MEASURES_KEY = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY; + private static final String FIELD_MEASURES_VALUE = FIELD_MEASURES + "." + ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE; private final AuthorizationTypeSupport authorizationTypeSupport; @@ -93,8 +95,7 @@ public class ProjectMeasuresIndex extends BaseIndex { .setTypes(TYPE_PROJECT_MEASURE) .setFetchSource(false) .setFrom(searchOptions.getOffset()) - .setSize(searchOptions.getLimit()) - .addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), SortOrder.ASC); + .setSize(searchOptions.getLimit()); BoolQueryBuilder esFilter = boolQuery(); Map<String, QueryBuilder> filters = createFilters(query); @@ -102,9 +103,30 @@ public class ProjectMeasuresIndex extends BaseIndex { requestBuilder.setQuery(esFilter); addFacets(requestBuilder, searchOptions, filters); + addSort(query, requestBuilder); return new SearchIdResult<>(requestBuilder.get(), id -> id); } + private static void addSort(ProjectMeasuresQuery query, SearchRequestBuilder requestBuilder) { + String sort = query.getSort(); + if (sort == null || SORT_BY_NAME.equals(sort)) { + requestBuilder.addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), query.isAsc() ? ASC : DESC); + } else { + addNameSort(query, requestBuilder, sort); + requestBuilder.addSort(DefaultIndexSettingsElement.SORTABLE_ANALYZER.subField(FIELD_NAME), ASC); + } + // last sort is by key in order to be deterministic when same value + requestBuilder.addSort(FIELD_KEY, ASC); + } + + private static void addNameSort(ProjectMeasuresQuery query, SearchRequestBuilder requestBuilder, String sort) { + requestBuilder.addSort( + new FieldSortBuilder(FIELD_MEASURES_VALUE) + .setNestedPath(FIELD_MEASURES) + .setNestedFilter(termQuery(FIELD_MEASURES_KEY, sort)) + .order(query.isAsc() ? ASC : DESC)); + } + private static void addFacets(SearchRequestBuilder esSearch, SearchOptions options, Map<String, QueryBuilder> filters) { if (!options.getFacets().isEmpty()) { if (options.getFacets().contains(NCLOC_KEY)) { @@ -151,7 +173,7 @@ public class ProjectMeasuresIndex extends BaseIndex { private static AbstractAggregationBuilder createRangeFacet(String metricKey, List<Double> thresholds) { RangeBuilder rangeAgg = AggregationBuilders.range(metricKey) - .field(FIELD_VALUE); + .field(FIELD_MEASURES_VALUE); final int lastIndex = thresholds.size() - 1; IntStream.range(0, thresholds.size()) .forEach(i -> { @@ -169,7 +191,7 @@ public class ProjectMeasuresIndex extends BaseIndex { .path(FIELD_MEASURES) .subAggregation( AggregationBuilders.filter("filter_" + metricKey) - .filter(termsQuery(FIELD_KEY, metricKey)) + .filter(termsQuery(FIELD_MEASURES_KEY, metricKey)) .subAggregation(rangeAgg)); } @@ -178,13 +200,13 @@ public class ProjectMeasuresIndex extends BaseIndex { .path(FIELD_MEASURES) .subAggregation( AggregationBuilders.filter("filter_" + metricKey) - .filter(termsQuery(FIELD_KEY, metricKey)) + .filter(termsQuery(FIELD_MEASURES_KEY, metricKey)) .subAggregation(filters(metricKey) - .filter("1", termQuery(FIELD_VALUE, 1d)) - .filter("2", termQuery(FIELD_VALUE, 2d)) - .filter("3", termQuery(FIELD_VALUE, 3d)) - .filter("4", termQuery(FIELD_VALUE, 4d)) - .filter("5", termQuery(FIELD_VALUE, 5d)))); + .filter("1", termQuery(FIELD_MEASURES_VALUE, 1d)) + .filter("2", termQuery(FIELD_MEASURES_VALUE, 2d)) + .filter("3", termQuery(FIELD_MEASURES_VALUE, 3d)) + .filter("4", termQuery(FIELD_MEASURES_VALUE, 4d)) + .filter("5", termQuery(FIELD_MEASURES_VALUE, 5d)))); } private static AbstractAggregationBuilder createQualityGateFacet() { @@ -204,7 +226,7 @@ public class ProjectMeasuresIndex extends BaseIndex { entry.getValue() .stream() .map(criterion -> nestedQuery(FIELD_MEASURES, boolQuery() - .filter(termQuery(FIELD_KEY, criterion.getMetricKey())) + .filter(termQuery(FIELD_MEASURES_KEY, criterion.getMetricKey())) .filter(toValueQuery(criterion)))) .forEach(metricFilters::must); filters.put(entry.getKey(), metricFilters); @@ -223,7 +245,7 @@ public class ProjectMeasuresIndex extends BaseIndex { } private static QueryBuilder toValueQuery(MetricCriterion criterion) { - String fieldName = FIELD_VALUE; + String fieldName = FIELD_MEASURES_VALUE; switch (criterion.getOperator()) { case GT: diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresQuery.java b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresQuery.java index a70e8ac945d..cf52b20fb3b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresQuery.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/index/ProjectMeasuresQuery.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.Set; +import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.sonar.api.measures.Metric; @@ -31,10 +32,15 @@ import static java.util.Arrays.stream; import static java.util.Objects.requireNonNull; public class ProjectMeasuresQuery { + + public static final String SORT_BY_NAME = "name"; + private List<MetricCriterion> metricCriteria = new ArrayList<>(); private Metric.Level qualityGateStatus; - private String organizationUuid = null; - private Set<String> projectUuids = null; + private String organizationUuid; + private Set<String> projectUuids; + private String sort; + private boolean asc = true; public ProjectMeasuresQuery addMetricCriterion(MetricCriterion metricCriterion) { this.metricCriteria.add(metricCriterion); @@ -72,25 +78,23 @@ public class ProjectMeasuresQuery { return Optional.ofNullable(projectUuids); } - public enum Operator { - LT("<"), LTE("<="), GT(">"), GTE(">="), EQ("="); - - String value; + @CheckForNull + public String getSort() { + return sort; + } - Operator(String value) { - this.value = value; - } + public ProjectMeasuresQuery setSort(@Nullable String sort) { + this.sort = sort; + return this; + } - String getValue() { - return value; - } + public boolean isAsc() { + return asc; + } - public static Operator getByValue(String value) { - return stream(Operator.values()) - .filter(operator -> operator.getValue().equals(value)) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException(format("Unknown operator '%s'", value))); - } + public ProjectMeasuresQuery setAsc(boolean asc) { + this.asc = asc; + return this; } public static class MetricCriterion { @@ -116,4 +120,25 @@ public class ProjectMeasuresQuery { return value; } } + + public enum Operator { + LT("<"), LTE("<="), GT(">"), GTE(">="), EQ("="); + + String value; + + Operator(String value) { + this.value = value; + } + + String getValue() { + return value; + } + + public static Operator getByValue(String value) { + return stream(Operator.values()) + .filter(operator -> operator.getValue().equals(value)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException(format("Unknown operator '%s'", value))); + } + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java index 5f4c23b610d..b8bc7424388 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProjectMeasuresQueryValidatorTest.java @@ -27,7 +27,6 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.metric.MetricDto; -import org.sonar.server.tester.UserSessionRule; import static java.util.Collections.emptyList; import static java.util.Collections.emptySet; @@ -46,9 +45,6 @@ public class ProjectMeasuresQueryValidatorTest { public ExpectedException expectedException = ExpectedException.none(); @Rule - public UserSessionRule userSession = UserSessionRule.standalone(); - - @Rule public DbTester db = DbTester.create(System2.INSTANCE); private DbClient dbClient = db.getDbClient(); @@ -69,6 +65,21 @@ public class ProjectMeasuresQueryValidatorTest { } @Test + public void does_not_fail_when_sort_is_by_name() throws Exception { + insertValidMetric("ncloc"); + + underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("ncloc > 10"), emptySet()).setSort("name")); + } + + @Test + public void does_not_fail_when_sort_contains_an_existing_metric() throws Exception { + insertValidMetric("ncloc"); + insertValidMetric("debt"); + + underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("ncloc > 10"), emptySet()).setSort("debt")); + } + + @Test public void fail_when_metric_are_not_numeric() throws Exception { insertMetric(createValidMetric("ncloc").setValueType(INT.name())); insertMetric(createValidMetric("debt").setValueType(WORK_DUR.name())); @@ -84,10 +95,11 @@ public class ProjectMeasuresQueryValidatorTest { @Test public void fail_when_metric_is_disabled() throws Exception { insertMetric(createValidMetric("ncloc").setEnabled(false)); + insertMetric(createValidMetric("debt").setEnabled(false)); expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Following metrics are disabled : [ncloc]"); - underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("ncloc > 10"), emptySet())); + expectedException.expectMessage("Following metrics are disabled : [debt, ncloc]"); + underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("ncloc > 10"), emptySet()).setSort("debt")); } @Test @@ -95,8 +107,8 @@ public class ProjectMeasuresQueryValidatorTest { insertValidMetric("ncloc"); expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Unknown metric(s) [unknown]"); - underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("unknown > 10"), emptySet())); + expectedException.expectMessage("Unknown metric(s) [debt, unknown]"); + underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("unknown > 10"), emptySet()).setSort("debt")); } @Test @@ -104,8 +116,8 @@ public class ProjectMeasuresQueryValidatorTest { insertValidMetric("ncloc"); expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Unknown metric(s) [coverage, debt]"); - underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("debt > 10 AND ncloc <= 20 AND coverage > 30"), emptySet())); + expectedException.expectMessage("Unknown metric(s) [coverage, debt, duplications]"); + underTest.validate(dbSession, newProjectMeasuresQuery(toCriteria("debt > 10 AND ncloc <= 20 AND coverage > 30"), emptySet()).setSort("duplications")); } private void insertValidMetric(String metricKey) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java index 033306fc89c..0e3a9b87f40 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchProjectsActionTest.java @@ -62,9 +62,16 @@ import org.sonarqube.ws.client.component.SearchProjectsRequest; import static com.google.common.collect.Lists.newArrayList; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static java.util.Optional.ofNullable; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.sonar.api.measures.Metric.ValueType.INT; +import static org.sonar.api.server.ws.WebService.Param.ASCENDING; +import static org.sonar.api.server.ws.WebService.Param.FACETS; +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.core.util.stream.Collectors.toList; import static org.sonar.db.component.ComponentTesting.newDeveloper; import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newFileDto; @@ -115,10 +122,21 @@ public class SearchProjectsActionTest { assertThat(def.isInternal()).isTrue(); assertThat(def.isPost()).isFalse(); assertThat(def.responseExampleAsString()).isNotEmpty(); + assertThat(def.params().stream().map(Param::key).collect(toList())).containsOnly("organization", "filter", "facets", "s", "asc", "ps", "p"); + Param organization = def.param("organization"); assertThat(organization.isRequired()).isFalse(); assertThat(organization.description()).isEqualTo("the organization to search projects in"); assertThat(organization.since()).isEqualTo("6.3"); + + Param sort = def.param("s"); + assertThat(sort.defaultValue()).isEqualTo("name"); + assertThat(sort.exampleValue()).isEqualTo("ncloc"); + assertThat(sort.possibleValues()).isNull(); + + Param asc = def.param("asc"); + assertThat(asc.defaultValue()).isEqualTo("true"); + assertThat(asc.possibleValues()).containsOnly("true", "false", "yes", "no"); } @Test @@ -348,6 +366,7 @@ public class SearchProjectsActionTest { insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 10_000d))); insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 500_001d))); insertMetrics(COVERAGE, NCLOC); + SearchProjectsWsResponse result = call(request.setFacets(singletonList(NCLOC))); Common.Facet facet = result.getFacets().getFacetsList().stream() @@ -366,11 +385,53 @@ public class SearchProjectsActionTest { } @Test - public void fail_if_metric_is_unknown() { + public void default_sort_is_by_ascending_name() throws Exception { + OrganizationDto organization = db.getDefaultOrganization(); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Groovy"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 10_000d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 500_001d))); + + SearchProjectsWsResponse result = call(request); + + assertThat(result.getComponentsList()).extracting(Component::getName).containsExactly("Sonar Groovy", "Sonar Java", "Sonar Markdown", "Sonar Qube"); + } + + @Test + public void sort_by_name() throws Exception { + OrganizationDto organization = db.getDefaultOrganization(); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Groovy"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 10_000d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 500_001d))); + + assertThat(call(request.setSort("name").setAsc(true)).getComponentsList()).extracting(Component::getName) + .containsExactly("Sonar Groovy", "Sonar Java", "Sonar Markdown", "Sonar Qube"); + assertThat(call(request.setSort("name").setAsc(false)).getComponentsList()).extracting(Component::getName) + .containsExactly("Sonar Qube", "Sonar Markdown", "Sonar Java", "Sonar Groovy"); + } + + @Test + public void sort_by_coverage() throws Exception { + OrganizationDto organization = db.getDefaultOrganization(); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Java"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Groovy"), newArrayList(newMeasure(COVERAGE, 81), newMeasure(NCLOC, 5d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Markdown"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 10_000d))); + insertProjectInDbAndEs(newProjectDto(organization).setName("Sonar Qube"), newArrayList(newMeasure(COVERAGE, 80d), newMeasure(NCLOC, 500_001d))); + insertMetrics(COVERAGE); + + assertThat(call(request.setSort(COVERAGE).setAsc(true)).getComponentsList()).extracting(Component::getName) + .containsExactly("Sonar Markdown", "Sonar Qube", "Sonar Groovy", "Sonar Java"); + assertThat(call(request.setSort(COVERAGE).setAsc(false)).getComponentsList()).extracting(Component::getName) + .containsExactly("Sonar Groovy", "Sonar Java", "Sonar Markdown", "Sonar Qube"); + } + + @Test + public void fail_when_metrics_are_unknown() { expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Unknown metric(s) [coverage]"); + expectedException.expectMessage("Unknown metric(s) [coverage, debt]"); - request.setFilter("coverage > 80"); + request.setFilter("coverage > 80").setSort("debt"); call(request); } @@ -386,19 +447,13 @@ public class SearchProjectsActionTest { SearchProjectsRequest wsRequest = requestBuilder.build(); TestRequest httpRequest = ws.newRequest() .setMediaType(MediaTypes.PROTOBUF); - - String organization = wsRequest.getOrganization(); - if (organization != null) { - httpRequest.setParam(PARAM_ORGANIZATION, organization); - } - httpRequest.setParam(Param.PAGE, String.valueOf(wsRequest.getPage())); - httpRequest.setParam(Param.PAGE_SIZE, String.valueOf(wsRequest.getPageSize())); - String filter = wsRequest.getFilter(); - if (filter != null) { - httpRequest.setParam(PARAM_FILTER, filter); - } - httpRequest.setParam(Param.FACETS, Joiner.on(",").join(wsRequest.getFacets())); - + ofNullable(wsRequest.getOrganization()).ifPresent(organization -> httpRequest.setParam(PARAM_ORGANIZATION, organization)); + ofNullable(wsRequest.getFilter()).ifPresent(filter -> httpRequest.setParam(PARAM_FILTER, filter)); + ofNullable(wsRequest.getSort()).ifPresent(sort -> httpRequest.setParam(SORT, sort)); + ofNullable(wsRequest.getAsc()).ifPresent(asc -> httpRequest.setParam(ASCENDING, Boolean.toString(asc))); + httpRequest.setParam(PAGE, String.valueOf(wsRequest.getPage())); + httpRequest.setParam(PAGE_SIZE, String.valueOf(wsRequest.getPageSize())); + httpRequest.setParam(FACETS, Joiner.on(",").join(wsRequest.getFacets())); try { return SearchProjectsWsResponse.parseFrom(httpRequest.execute().getInputStream()); } catch (IOException e) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java index ecb6a730b17..c6ba98edeb4 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/index/ProjectMeasuresIndexTest.java @@ -71,9 +71,10 @@ public class ProjectMeasuresIndexTest { private static final String NCLOC = "ncloc"; private static final OrganizationDto ORG = OrganizationTesting.newOrganizationDto(); - private static final ComponentDto PROJECT1 = newProjectDto(ORG); - private static final ComponentDto PROJECT2 = newProjectDto(ORG); - private static final ComponentDto PROJECT3 = newProjectDto(ORG); + private static final ComponentDto PROJECT1 = newProjectDto(ORG).setUuid("Project-1").setName("Project 1").setKey("key-1"); + private static final ComponentDto PROJECT2 = newProjectDto(ORG).setUuid("Project-2").setName("Project 2").setKey("key-2"); + private static final ComponentDto PROJECT3 = newProjectDto(ORG).setUuid("Project-3").setName("Project 3").setKey("key-3"); + private static final ComponentDto PROJECT4 = newProjectDto(ORG).setUuid("Project-4").setName("Project 4").setKey("key-4"); private static final UserDto USER1 = newUserDto(); private static final UserDto USER2 = newUserDto(); private static final GroupDto GROUP1 = newGroupDto(); @@ -95,19 +96,58 @@ public class ProjectMeasuresIndexTest { } @Test - public void search_sort_by_case_insensitive_name() { - ComponentDto projectA = newProjectDto(ORG).setName("Windows"); - ComponentDto projectB = newProjectDto(ORG).setName("apachee"); - ComponentDto projectC = newProjectDto(ORG).setName("Apache"); - index(newDoc(projectA), newDoc(projectB), newDoc(projectC)); + public void default_sort_is_by_ascending_case_insensitive_name_then_by_key() { + ComponentDto windows = newProjectDto(ORG).setUuid("windows").setName("Windows").setKey("project1"); + ComponentDto apachee = newProjectDto(ORG).setUuid("apachee").setName("apachee").setKey("project2"); + ComponentDto apache1 = newProjectDto(ORG).setUuid("apache-1").setName("Apache").setKey("project3"); + ComponentDto apache2 = newProjectDto(ORG).setUuid("apache-2").setName("Apache").setKey("project4"); + index(newDoc(windows), newDoc(apachee), newDoc(apache1), newDoc(apache2)); - assertResults(new ProjectMeasuresQuery(), projectC, projectB, projectA); + assertResults(new ProjectMeasuresQuery(), apache1, apache2, apachee, windows); } @Test - public void search_paginate_results() { + public void sort_by_insensitive_name() { + ComponentDto windows = newProjectDto(ORG).setUuid("windows").setName("Windows"); + ComponentDto apachee = newProjectDto(ORG).setUuid("apachee").setName("apachee"); + ComponentDto apache = newProjectDto(ORG).setUuid("apache").setName("Apache"); + index(newDoc(windows), newDoc(apachee), newDoc(apache)); + + assertResults(new ProjectMeasuresQuery().setSort("name").setAsc(true), apache, apachee, windows); + assertResults(new ProjectMeasuresQuery().setSort("name").setAsc(false), windows, apachee, apache); + } + + @Test + public void sort_by_ncloc() { + index( + newDoc(PROJECT1, NCLOC, 15_000d), + newDoc(PROJECT2, NCLOC, 30_000d), + newDoc(PROJECT3, NCLOC, 1_000d)); + + assertResults(new ProjectMeasuresQuery().setSort("ncloc").setAsc(true), PROJECT3, PROJECT1, PROJECT2); + assertResults(new ProjectMeasuresQuery().setSort("ncloc").setAsc(false), PROJECT2, PROJECT1, PROJECT3); + } + + @Test + public void sort_by_a_metric_then_by_name_then_by_key() { + ComponentDto windows = newProjectDto(ORG).setUuid("windows").setName("Windows").setKey("project1"); + ComponentDto apachee = newProjectDto(ORG).setUuid("apachee").setName("apachee").setKey("project2"); + ComponentDto apache1 = newProjectDto(ORG).setUuid("apache-1").setName("Apache").setKey("project3"); + ComponentDto apache2 = newProjectDto(ORG).setUuid("apache-2").setName("Apache").setKey("project4"); + index( + newDoc(windows, NCLOC, 10_000d), + newDoc(apachee, NCLOC, 5_000d), + newDoc(apache1, NCLOC, 5_000d), + newDoc(apache2, NCLOC, 5_000d)); + + assertResults(new ProjectMeasuresQuery().setSort("ncloc").setAsc(true), apache1, apache2, apachee, windows); + assertResults(new ProjectMeasuresQuery().setSort("ncloc").setAsc(false), windows, apache1, apache2, apachee); + } + + @Test + public void paginate_results() { IntStream.rangeClosed(1, 9) - .forEach(i -> index(newDoc(newProjectDto(ORG, "P" + i)))); + .forEach(i -> index(newDoc(newProjectDto(ORG, "P" + i)))); SearchIdResult<String> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().setPage(2, 3)); @@ -118,12 +158,12 @@ public class ProjectMeasuresIndexTest { @Test public void filter_with_lower_than() { index( - newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), - newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); + newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), + newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); ProjectMeasuresQuery query = new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 80d)); + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 80d)); assertResults(query, PROJECT1); } @@ -131,12 +171,12 @@ public class ProjectMeasuresIndexTest { @Test public void filter_with_lower_than_or_equals() { index( - newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), - newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); + newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), + newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); ProjectMeasuresQuery query = new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LTE, 80d)); + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LTE, 80d)); assertResults(query, PROJECT1, PROJECT2); } @@ -144,9 +184,9 @@ public class ProjectMeasuresIndexTest { @Test public void filter_with_greater_than() { index( - newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d), - newDoc(PROJECT3, COVERAGE, 80d, NCLOC, 30_001d)); + newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d), + newDoc(PROJECT3, COVERAGE, 80d, NCLOC, 30_001d)); ProjectMeasuresQuery query = new ProjectMeasuresQuery().addMetricCriterion(new MetricCriterion(NCLOC, Operator.GT, 30_000d)); assertResults(query, PROJECT2, PROJECT3); @@ -158,9 +198,9 @@ public class ProjectMeasuresIndexTest { @Test public void filter_with_greater_than_or_equals() { index( - newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d), - newDoc(PROJECT3, COVERAGE, 80d, NCLOC, 30_001d)); + newDoc(PROJECT1, COVERAGE, 80d, NCLOC, 30_000d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 30_001d), + newDoc(PROJECT3, COVERAGE, 80d, NCLOC, 30_001d)); ProjectMeasuresQuery query = new ProjectMeasuresQuery().addMetricCriterion(new MetricCriterion(NCLOC, Operator.GTE, 30_001d)); assertResults(query, PROJECT2, PROJECT3); @@ -172,12 +212,12 @@ public class ProjectMeasuresIndexTest { @Test public void filter_with_equals() { index( - newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), - newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); + newDoc(PROJECT1, COVERAGE, 79d, NCLOC, 10_000d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_000d), + newDoc(PROJECT3, COVERAGE, 81d, NCLOC, 10_000d)); ProjectMeasuresQuery query = new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.EQ, 80d)); + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.EQ, 80d)); assertResults(query, PROJECT2); } @@ -185,23 +225,23 @@ public class ProjectMeasuresIndexTest { @Test public void filter_on_several_metrics() { index( - newDoc(PROJECT1, COVERAGE, 81d, NCLOC, 10_001d), - newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_001d), - newDoc(PROJECT3, COVERAGE, 79d, NCLOC, 10_000d)); + newDoc(PROJECT1, COVERAGE, 81d, NCLOC, 10_001d), + newDoc(PROJECT2, COVERAGE, 80d, NCLOC, 10_001d), + newDoc(PROJECT3, COVERAGE, 79d, NCLOC, 10_000d)); ProjectMeasuresQuery esQuery = new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LTE, 80d)) - .addMetricCriterion(new MetricCriterion(NCLOC, Operator.GT, 10_000d)) - .addMetricCriterion(new MetricCriterion(NCLOC, Operator.LT, 11_000d)); + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LTE, 80d)) + .addMetricCriterion(new MetricCriterion(NCLOC, Operator.GT, 10_000d)) + .addMetricCriterion(new MetricCriterion(NCLOC, Operator.LT, 11_000d)); assertResults(esQuery, PROJECT2); } @Test public void filter_on_quality_gate_status() { index( - newDoc(PROJECT1).setQualityGate("OK"), - newDoc(PROJECT2).setQualityGate("OK"), - newDoc(PROJECT3).setQualityGate("WARN")); + newDoc(PROJECT1).setQualityGate("OK"), + newDoc(PROJECT2).setQualityGate("OK"), + newDoc(PROJECT3).setQualityGate("WARN")); ProjectMeasuresQuery query = new ProjectMeasuresQuery().setQualityGateStatus(OK); assertResults(query, PROJECT1, PROJECT2); @@ -210,9 +250,9 @@ public class ProjectMeasuresIndexTest { @Test public void filter_on_ids() { index( - newDoc(PROJECT1), - newDoc(PROJECT2), - newDoc(PROJECT3)); + newDoc(PROJECT1), + newDoc(PROJECT2), + newDoc(PROJECT3)); ProjectMeasuresQuery query = new ProjectMeasuresQuery().setProjectUuids(newHashSet(PROJECT1.uuid(), PROJECT3.uuid())); assertResults(query, PROJECT1, PROJECT3); @@ -275,8 +315,8 @@ public class ProjectMeasuresIndexTest { @Test public void does_not_return_facet_when_no_facets_in_options() throws Exception { index( - newDoc(PROJECT1, NCLOC, 10d, COVERAGE_KEY, 30d, MAINTAINABILITY_RATING, 3d) - .setQualityGate(OK.name())); + newDoc(PROJECT1, NCLOC, 10d, COVERAGE_KEY, 30d, MAINTAINABILITY_RATING, 3d) + .setQualityGate(OK.name())); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions()).getFacets(); @@ -286,585 +326,585 @@ public class ProjectMeasuresIndexTest { @Test public void facet_ncloc() { index( - // 3 docs with ncloc<1K - newDoc(NCLOC, 0d), - newDoc(NCLOC, 0d), - newDoc(NCLOC, 999d), - // 2 docs with ncloc>=1K and ncloc<10K - newDoc(NCLOC, 1_000d), - newDoc(NCLOC, 9_999d), - // 4 docs with ncloc>=10K and ncloc<100K - newDoc(NCLOC, 10_000d), - newDoc(NCLOC, 10_000d), - newDoc(NCLOC, 11_000d), - newDoc(NCLOC, 99_000d), - // 2 docs with ncloc>=100K and ncloc<500K - newDoc(NCLOC, 100_000d), - newDoc(NCLOC, 499_000d), - // 5 docs with ncloc>= 500K - newDoc(NCLOC, 500_000d), - newDoc(NCLOC, 100_000_000d), - newDoc(NCLOC, 500_000d), - newDoc(NCLOC, 1_000_000d), - newDoc(NCLOC, 100_000_000_000d)); + // 3 docs with ncloc<1K + newDoc(NCLOC, 0d), + newDoc(NCLOC, 0d), + newDoc(NCLOC, 999d), + // 2 docs with ncloc>=1K and ncloc<10K + newDoc(NCLOC, 1_000d), + newDoc(NCLOC, 9_999d), + // 4 docs with ncloc>=10K and ncloc<100K + newDoc(NCLOC, 10_000d), + newDoc(NCLOC, 10_000d), + newDoc(NCLOC, 11_000d), + newDoc(NCLOC, 99_000d), + // 2 docs with ncloc>=100K and ncloc<500K + newDoc(NCLOC, 100_000d), + newDoc(NCLOC, 499_000d), + // 5 docs with ncloc>= 500K + newDoc(NCLOC, 500_000d), + newDoc(NCLOC, 100_000_000d), + newDoc(NCLOC, 500_000d), + newDoc(NCLOC, 1_000_000d), + newDoc(NCLOC, 100_000_000_000d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(NCLOC)).getFacets(); assertThat(facets.get(NCLOC)).containsExactly( - entry("*-1000.0", 3L), - entry("1000.0-10000.0", 2L), - entry("10000.0-100000.0", 4L), - entry("100000.0-500000.0", 2L), - entry("500000.0-*", 5L)); + entry("*-1000.0", 3L), + entry("1000.0-10000.0", 2L), + entry("10000.0-100000.0", 4L), + entry("100000.0-500000.0", 2L), + entry("500000.0-*", 5L)); } @Test public void facet_ncloc_is_sticky() { index( - // 1 docs with ncloc<1K - newDoc(NCLOC, 999d, COVERAGE, 0d, DUPLICATION, 0d), - // 2 docs with ncloc>=1K and ncloc<10K - newDoc(NCLOC, 1_000d, COVERAGE, 10d, DUPLICATION, 0d), - newDoc(NCLOC, 9_999d, COVERAGE, 20d, DUPLICATION, 0d), - // 3 docs with ncloc>=10K and ncloc<100K - newDoc(NCLOC, 10_000d, COVERAGE, 31d, DUPLICATION, 0d), - newDoc(NCLOC, 11_000d, COVERAGE, 40d, DUPLICATION, 0d), - newDoc(NCLOC, 99_000d, COVERAGE, 50d, DUPLICATION, 0d), - // 2 docs with ncloc>=100K and ncloc<500K - newDoc(NCLOC, 100_000d, COVERAGE, 71d, DUPLICATION, 0d), - newDoc(NCLOC, 499_000d, COVERAGE, 80d, DUPLICATION, 0d), - // 1 docs with ncloc>= 500K - newDoc(NCLOC, 501_000d, COVERAGE, 81d, DUPLICATION, 20d)); + // 1 docs with ncloc<1K + newDoc(NCLOC, 999d, COVERAGE, 0d, DUPLICATION, 0d), + // 2 docs with ncloc>=1K and ncloc<10K + newDoc(NCLOC, 1_000d, COVERAGE, 10d, DUPLICATION, 0d), + newDoc(NCLOC, 9_999d, COVERAGE, 20d, DUPLICATION, 0d), + // 3 docs with ncloc>=10K and ncloc<100K + newDoc(NCLOC, 10_000d, COVERAGE, 31d, DUPLICATION, 0d), + newDoc(NCLOC, 11_000d, COVERAGE, 40d, DUPLICATION, 0d), + newDoc(NCLOC, 99_000d, COVERAGE, 50d, DUPLICATION, 0d), + // 2 docs with ncloc>=100K and ncloc<500K + newDoc(NCLOC, 100_000d, COVERAGE, 71d, DUPLICATION, 0d), + newDoc(NCLOC, 499_000d, COVERAGE, 80d, DUPLICATION, 0d), + // 1 docs with ncloc>= 500K + newDoc(NCLOC, 501_000d, COVERAGE, 81d, DUPLICATION, 20d)); Facets facets = underTest.search(new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(NCLOC, Operator.LT, 10_000d)) - .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)), - new SearchOptions().addFacets(NCLOC, COVERAGE)).getFacets(); + .addMetricCriterion(new MetricCriterion(NCLOC, Operator.LT, 10_000d)) + .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)), + new SearchOptions().addFacets(NCLOC, COVERAGE)).getFacets(); // Sticky facet on ncloc does not take into account ncloc filter assertThat(facets.get(NCLOC)).containsExactly( - entry("*-1000.0", 1L), - entry("1000.0-10000.0", 2L), - entry("10000.0-100000.0", 3L), - entry("100000.0-500000.0", 2L), - entry("500000.0-*", 0L)); + entry("*-1000.0", 1L), + entry("1000.0-10000.0", 2L), + entry("10000.0-100000.0", 3L), + entry("100000.0-500000.0", 2L), + entry("500000.0-*", 0L)); // But facet on coverage does well take into into filters assertThat(facets.get(COVERAGE)).containsExactly( - entry("*-30.0", 3L), - entry("30.0-50.0", 0L), - entry("50.0-70.0", 0L), - entry("70.0-80.0", 0L), - entry("80.0-*", 0L)); + entry("*-30.0", 3L), + entry("30.0-50.0", 0L), + entry("50.0-70.0", 0L), + entry("70.0-80.0", 0L), + entry("80.0-*", 0L)); } @Test public void facet_ncloc_contains_only_projects_authorized_for_user() throws Exception { // User can see these projects indexForUser(USER1, - // docs with ncloc<1K - newDoc(NCLOC, 0d), - newDoc(NCLOC, 100d), - newDoc(NCLOC, 999d), - // docs with ncloc>=1K and ncloc<10K - newDoc(NCLOC, 1_000d), - newDoc(NCLOC, 9_999d)); + // docs with ncloc<1K + newDoc(NCLOC, 0d), + newDoc(NCLOC, 100d), + newDoc(NCLOC, 999d), + // docs with ncloc>=1K and ncloc<10K + newDoc(NCLOC, 1_000d), + newDoc(NCLOC, 9_999d)); // User cannot see these projects indexForUser(USER2, - // doc with ncloc>=10K and ncloc<100K - newDoc(NCLOC, 11_000d), - // doc with ncloc>=100K and ncloc<500K - newDoc(NCLOC, 499_000d), - // doc with ncloc>= 500K - newDoc(NCLOC, 501_000d)); + // doc with ncloc>=10K and ncloc<100K + newDoc(NCLOC, 11_000d), + // doc with ncloc>=100K and ncloc<500K + newDoc(NCLOC, 499_000d), + // doc with ncloc>= 500K + newDoc(NCLOC, 501_000d)); userSession.logIn(USER1); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(NCLOC)).getFacets(); 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)); + 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)); } @Test public void facet_coverage() { index( - // 3 docs with coverage<30% - newDoc(COVERAGE, 0d), - newDoc(COVERAGE, 0d), - newDoc(COVERAGE, 29d), - // 2 docs with coverage>=30% and coverage<50% - newDoc(COVERAGE, 30d), - newDoc(COVERAGE, 49d), - // 4 docs with coverage>=50% and coverage<70% - newDoc(COVERAGE, 50d), - newDoc(COVERAGE, 60d), - newDoc(COVERAGE, 60d), - newDoc(COVERAGE, 69d), - // 2 docs with coverage>=70% and coverage<80% - newDoc(COVERAGE, 70d), - newDoc(COVERAGE, 79d), - // 5 docs with coverage>= 80% - newDoc(COVERAGE, 80d), - newDoc(COVERAGE, 80d), - newDoc(COVERAGE, 90d), - newDoc(COVERAGE, 90.5d), - newDoc(COVERAGE, 100d)); + // 3 docs with coverage<30% + newDoc(COVERAGE, 0d), + newDoc(COVERAGE, 0d), + newDoc(COVERAGE, 29d), + // 2 docs with coverage>=30% and coverage<50% + newDoc(COVERAGE, 30d), + newDoc(COVERAGE, 49d), + // 4 docs with coverage>=50% and coverage<70% + newDoc(COVERAGE, 50d), + newDoc(COVERAGE, 60d), + newDoc(COVERAGE, 60d), + newDoc(COVERAGE, 69d), + // 2 docs with coverage>=70% and coverage<80% + newDoc(COVERAGE, 70d), + newDoc(COVERAGE, 79d), + // 5 docs with coverage>= 80% + newDoc(COVERAGE, 80d), + newDoc(COVERAGE, 80d), + newDoc(COVERAGE, 90d), + newDoc(COVERAGE, 90.5d), + newDoc(COVERAGE, 100d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(COVERAGE)).getFacets(); assertThat(facets.get(COVERAGE)).containsExactly( - entry("*-30.0", 3L), - entry("30.0-50.0", 2L), - entry("50.0-70.0", 4L), - entry("70.0-80.0", 2L), - entry("80.0-*", 5L)); + entry("*-30.0", 3L), + entry("30.0-50.0", 2L), + entry("50.0-70.0", 4L), + entry("70.0-80.0", 2L), + entry("80.0-*", 5L)); } @Test public void facet_coverage_is_sticky() { index( - // docs with coverage<30% - newDoc(NCLOC, 999d, COVERAGE, 0d, DUPLICATION, 0d), - newDoc(NCLOC, 1_000d, COVERAGE, 10d, DUPLICATION, 0d), - newDoc(NCLOC, 9_999d, COVERAGE, 20d, DUPLICATION, 0d), - // docs with coverage>=30% and coverage<50% - newDoc(NCLOC, 10_000d, COVERAGE, 31d, DUPLICATION, 0d), - newDoc(NCLOC, 11_000d, COVERAGE, 40d, DUPLICATION, 0d), - // docs with coverage>=50% and coverage<70% - newDoc(NCLOC, 99_000d, COVERAGE, 50d, DUPLICATION, 0d), - // docs with coverage>=70% and coverage<80% - newDoc(NCLOC, 100_000d, COVERAGE, 71d, DUPLICATION, 0d), - // docs with coverage>= 80% - newDoc(NCLOC, 499_000d, COVERAGE, 80d, DUPLICATION, 15d), - newDoc(NCLOC, 501_000d, COVERAGE, 810d, DUPLICATION, 20d)); + // docs with coverage<30% + newDoc(NCLOC, 999d, COVERAGE, 0d, DUPLICATION, 0d), + newDoc(NCLOC, 1_000d, COVERAGE, 10d, DUPLICATION, 0d), + newDoc(NCLOC, 9_999d, COVERAGE, 20d, DUPLICATION, 0d), + // docs with coverage>=30% and coverage<50% + newDoc(NCLOC, 10_000d, COVERAGE, 31d, DUPLICATION, 0d), + newDoc(NCLOC, 11_000d, COVERAGE, 40d, DUPLICATION, 0d), + // docs with coverage>=50% and coverage<70% + newDoc(NCLOC, 99_000d, COVERAGE, 50d, DUPLICATION, 0d), + // docs with coverage>=70% and coverage<80% + newDoc(NCLOC, 100_000d, COVERAGE, 71d, DUPLICATION, 0d), + // docs with coverage>= 80% + newDoc(NCLOC, 499_000d, COVERAGE, 80d, DUPLICATION, 15d), + newDoc(NCLOC, 501_000d, COVERAGE, 810d, DUPLICATION, 20d)); Facets facets = underTest.search(new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)) - .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)), - new SearchOptions().addFacets(COVERAGE, NCLOC)).getFacets(); + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)) + .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)), + new SearchOptions().addFacets(COVERAGE, NCLOC)).getFacets(); // Sticky facet on coverage does not take into account coverage filter assertThat(facets.get(COVERAGE)).containsExactly( - entry("*-30.0", 3L), - entry("30.0-50.0", 2L), - entry("50.0-70.0", 1L), - entry("70.0-80.0", 1L), - entry("80.0-*", 0L)); + entry("*-30.0", 3L), + entry("30.0-50.0", 2L), + entry("50.0-70.0", 1L), + entry("70.0-80.0", 1L), + entry("80.0-*", 0L)); // But facet on ncloc does well take into into filters assertThat(facets.get(NCLOC)).containsExactly( - entry("*-1000.0", 1L), - entry("1000.0-10000.0", 2L), - entry("10000.0-100000.0", 0L), - entry("100000.0-500000.0", 0L), - entry("500000.0-*", 0L)); + entry("*-1000.0", 1L), + entry("1000.0-10000.0", 2L), + entry("10000.0-100000.0", 0L), + entry("100000.0-500000.0", 0L), + entry("500000.0-*", 0L)); } @Test public void facet_coverage_contains_only_projects_authorized_for_user() throws Exception { // User can see these projects indexForUser(USER1, - // docs with coverage<30% - newDoc(COVERAGE, 0d), - newDoc(COVERAGE, 0d), - newDoc(COVERAGE, 29d), - // docs with coverage>=30% and coverage<50% - newDoc(COVERAGE, 30d), - newDoc(COVERAGE, 49d)); + // docs with coverage<30% + newDoc(COVERAGE, 0d), + newDoc(COVERAGE, 0d), + newDoc(COVERAGE, 29d), + // docs with coverage>=30% and coverage<50% + newDoc(COVERAGE, 30d), + newDoc(COVERAGE, 49d)); // User cannot see these projects indexForUser(USER2, - // docs with coverage>=50% and coverage<70% - newDoc(COVERAGE, 50d), - // docs with coverage>=70% and coverage<80% - newDoc(COVERAGE, 70d), - // docs with coverage>= 80% - newDoc(COVERAGE, 80d)); + // docs with coverage>=50% and coverage<70% + newDoc(COVERAGE, 50d), + // docs with coverage>=70% and coverage<80% + newDoc(COVERAGE, 70d), + // docs with coverage>= 80% + newDoc(COVERAGE, 80d)); userSession.logIn(USER1); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(COVERAGE)).getFacets(); assertThat(facets.get(COVERAGE)).containsExactly( - entry("*-30.0", 3L), - entry("30.0-50.0", 2L), - entry("50.0-70.0", 0L), - entry("70.0-80.0", 0L), - entry("80.0-*", 0L)); + entry("*-30.0", 3L), + entry("30.0-50.0", 2L), + entry("50.0-70.0", 0L), + entry("70.0-80.0", 0L), + entry("80.0-*", 0L)); } @Test public void facet_duplicated_lines_density() { index( - // 3 docs with duplication<3% - newDoc(DUPLICATION, 0d), - newDoc(DUPLICATION, 0d), - newDoc(DUPLICATION, 2.9d), - // 2 docs with duplication>=3% and duplication<5% - newDoc(DUPLICATION, 3d), - newDoc(DUPLICATION, 4.9d), - // 4 docs with duplication>=5% and duplication<10% - newDoc(DUPLICATION, 5d), - newDoc(DUPLICATION, 6d), - newDoc(DUPLICATION, 6d), - newDoc(DUPLICATION, 9.9d), - // 2 docs with duplication>=10% and duplication<20% - newDoc(DUPLICATION, 10d), - newDoc(DUPLICATION, 19.9d), - // 5 docs with duplication>= 20% - newDoc(DUPLICATION, 20d), - newDoc(DUPLICATION, 20d), - newDoc(DUPLICATION, 50d), - newDoc(DUPLICATION, 80d), - newDoc(DUPLICATION, 100d)); + // 3 docs with duplication<3% + newDoc(DUPLICATION, 0d), + newDoc(DUPLICATION, 0d), + newDoc(DUPLICATION, 2.9d), + // 2 docs with duplication>=3% and duplication<5% + newDoc(DUPLICATION, 3d), + newDoc(DUPLICATION, 4.9d), + // 4 docs with duplication>=5% and duplication<10% + newDoc(DUPLICATION, 5d), + newDoc(DUPLICATION, 6d), + newDoc(DUPLICATION, 6d), + newDoc(DUPLICATION, 9.9d), + // 2 docs with duplication>=10% and duplication<20% + newDoc(DUPLICATION, 10d), + newDoc(DUPLICATION, 19.9d), + // 5 docs with duplication>= 20% + newDoc(DUPLICATION, 20d), + newDoc(DUPLICATION, 20d), + newDoc(DUPLICATION, 50d), + newDoc(DUPLICATION, 80d), + newDoc(DUPLICATION, 100d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(DUPLICATION)).getFacets(); assertThat(facets.get(DUPLICATION)).containsExactly( - entry("*-3.0", 3L), - entry("3.0-5.0", 2L), - entry("5.0-10.0", 4L), - entry("10.0-20.0", 2L), - entry("20.0-*", 5L)); + entry("*-3.0", 3L), + entry("3.0-5.0", 2L), + entry("5.0-10.0", 4L), + entry("10.0-20.0", 2L), + entry("20.0-*", 5L)); } @Test public void facet_duplicated_lines_density_is_sticky() { index( - // docs with duplication<3% - newDoc(DUPLICATION, 0d, NCLOC, 999d, COVERAGE, 0d), - // docs with duplication>=3% and duplication<5% - newDoc(DUPLICATION, 3d, NCLOC, 5000d, COVERAGE, 0d), - newDoc(DUPLICATION, 4.9d, NCLOC, 6000d, COVERAGE, 0d), - // docs with duplication>=5% and duplication<10% - newDoc(DUPLICATION, 5d, NCLOC, 11000d, COVERAGE, 0d), - // docs with duplication>=10% and duplication<20% - newDoc(DUPLICATION, 10d, NCLOC, 120000d, COVERAGE, 10d), - newDoc(DUPLICATION, 19.9d, NCLOC, 130000d, COVERAGE, 20d), - // docs with duplication>= 20% - newDoc(DUPLICATION, 20d, NCLOC, 1000000d, COVERAGE, 40d)); + // docs with duplication<3% + newDoc(DUPLICATION, 0d, NCLOC, 999d, COVERAGE, 0d), + // docs with duplication>=3% and duplication<5% + newDoc(DUPLICATION, 3d, NCLOC, 5000d, COVERAGE, 0d), + newDoc(DUPLICATION, 4.9d, NCLOC, 6000d, COVERAGE, 0d), + // docs with duplication>=5% and duplication<10% + newDoc(DUPLICATION, 5d, NCLOC, 11000d, COVERAGE, 0d), + // docs with duplication>=10% and duplication<20% + newDoc(DUPLICATION, 10d, NCLOC, 120000d, COVERAGE, 10d), + newDoc(DUPLICATION, 19.9d, NCLOC, 130000d, COVERAGE, 20d), + // docs with duplication>= 20% + newDoc(DUPLICATION, 20d, NCLOC, 1000000d, COVERAGE, 40d)); Facets facets = underTest.search(new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)) - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)), - new SearchOptions().addFacets(DUPLICATION, NCLOC)).getFacets(); + .addMetricCriterion(new MetricCriterion(DUPLICATION, Operator.LT, 10d)) + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)), + new SearchOptions().addFacets(DUPLICATION, NCLOC)).getFacets(); // Sticky facet on duplication does not take into account duplication filter assertThat(facets.get(DUPLICATION)).containsExactly( - entry("*-3.0", 1L), - entry("3.0-5.0", 2L), - entry("5.0-10.0", 1L), - entry("10.0-20.0", 2L), - entry("20.0-*", 0L)); + entry("*-3.0", 1L), + entry("3.0-5.0", 2L), + entry("5.0-10.0", 1L), + entry("10.0-20.0", 2L), + entry("20.0-*", 0L)); // But facet on ncloc does well take into into filters assertThat(facets.get(NCLOC)).containsExactly( - entry("*-1000.0", 1L), - entry("1000.0-10000.0", 2L), - entry("10000.0-100000.0", 1L), - entry("100000.0-500000.0", 0L), - entry("500000.0-*", 0L)); + entry("*-1000.0", 1L), + entry("1000.0-10000.0", 2L), + entry("10000.0-100000.0", 1L), + entry("100000.0-500000.0", 0L), + entry("500000.0-*", 0L)); } @Test public void facet_duplicated_lines_density_contains_only_projects_authorized_for_user() throws Exception { // User can see these projects indexForUser(USER1, - // docs with duplication<3% - newDoc(DUPLICATION, 0d), - newDoc(DUPLICATION, 0d), - newDoc(DUPLICATION, 2.9d), - // docs with duplication>=3% and duplication<5% - newDoc(DUPLICATION, 3d), - newDoc(DUPLICATION, 4.9d)); + // docs with duplication<3% + newDoc(DUPLICATION, 0d), + newDoc(DUPLICATION, 0d), + newDoc(DUPLICATION, 2.9d), + // docs with duplication>=3% and duplication<5% + newDoc(DUPLICATION, 3d), + newDoc(DUPLICATION, 4.9d)); // User cannot see these projects indexForUser(USER2, - // docs with duplication>=5% and duplication<10% - newDoc(DUPLICATION, 5d), - // docs with duplication>=10% and duplication<20% - newDoc(DUPLICATION, 10d), - // docs with duplication>= 20% - newDoc(DUPLICATION, 20d)); + // docs with duplication>=5% and duplication<10% + newDoc(DUPLICATION, 5d), + // docs with duplication>=10% and duplication<20% + newDoc(DUPLICATION, 10d), + // docs with duplication>= 20% + newDoc(DUPLICATION, 20d)); userSession.logIn(USER1); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(DUPLICATION)).getFacets(); assertThat(facets.get(DUPLICATION)).containsExactly( - entry("*-3.0", 3L), - entry("3.0-5.0", 2L), - entry("5.0-10.0", 0L), - entry("10.0-20.0", 0L), - entry("20.0-*", 0L)); + entry("*-3.0", 3L), + entry("3.0-5.0", 2L), + entry("5.0-10.0", 0L), + entry("10.0-20.0", 0L), + entry("20.0-*", 0L)); } @Test public void facet_maintainability_rating() { index( - // 3 docs with rating A - newDoc(MAINTAINABILITY_RATING, 1d), - newDoc(MAINTAINABILITY_RATING, 1d), - newDoc(MAINTAINABILITY_RATING, 1d), - // 2 docs with rating B - newDoc(MAINTAINABILITY_RATING, 2d), - newDoc(MAINTAINABILITY_RATING, 2d), - // 4 docs with rating C - newDoc(MAINTAINABILITY_RATING, 3d), - newDoc(MAINTAINABILITY_RATING, 3d), - newDoc(MAINTAINABILITY_RATING, 3d), - newDoc(MAINTAINABILITY_RATING, 3d), - // 2 docs with rating D - newDoc(MAINTAINABILITY_RATING, 4d), - newDoc(MAINTAINABILITY_RATING, 4d), - // 5 docs with rating E - newDoc(MAINTAINABILITY_RATING, 5d), - newDoc(MAINTAINABILITY_RATING, 5d), - newDoc(MAINTAINABILITY_RATING, 5d), - newDoc(MAINTAINABILITY_RATING, 5d), - newDoc(MAINTAINABILITY_RATING, 5d)); + // 3 docs with rating A + newDoc(MAINTAINABILITY_RATING, 1d), + newDoc(MAINTAINABILITY_RATING, 1d), + newDoc(MAINTAINABILITY_RATING, 1d), + // 2 docs with rating B + newDoc(MAINTAINABILITY_RATING, 2d), + newDoc(MAINTAINABILITY_RATING, 2d), + // 4 docs with rating C + newDoc(MAINTAINABILITY_RATING, 3d), + newDoc(MAINTAINABILITY_RATING, 3d), + newDoc(MAINTAINABILITY_RATING, 3d), + newDoc(MAINTAINABILITY_RATING, 3d), + // 2 docs with rating D + newDoc(MAINTAINABILITY_RATING, 4d), + newDoc(MAINTAINABILITY_RATING, 4d), + // 5 docs with rating E + newDoc(MAINTAINABILITY_RATING, 5d), + newDoc(MAINTAINABILITY_RATING, 5d), + newDoc(MAINTAINABILITY_RATING, 5d), + newDoc(MAINTAINABILITY_RATING, 5d), + newDoc(MAINTAINABILITY_RATING, 5d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(MAINTAINABILITY_RATING)).getFacets(); assertThat(facets.get(MAINTAINABILITY_RATING)).containsExactly( - entry("1", 3L), - entry("2", 2L), - entry("3", 4L), - entry("4", 2L), - entry("5", 5L)); + entry("1", 3L), + entry("2", 2L), + entry("3", 4L), + entry("4", 2L), + entry("5", 5L)); } @Test public void facet_maintainability_rating_is_sticky() { index( - // docs with rating A - newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 100d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 200d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 999d, COVERAGE, 0d), - // docs with rating B - newDoc(MAINTAINABILITY_RATING, 2d, NCLOC, 2000d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 2d, NCLOC, 5000d, COVERAGE, 0d), - // docs with rating C - newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 20000d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 30000d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 40000d, COVERAGE, 0d), - newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 50000d, COVERAGE, 0d), - // docs with rating D - newDoc(MAINTAINABILITY_RATING, 4d, NCLOC, 120000d, COVERAGE, 0d), - // docs with rating E - newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 600000d, COVERAGE, 40d), - newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 700000d, COVERAGE, 50d), - newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 800000d, COVERAGE, 60d)); + // docs with rating A + newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 100d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 200d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 1d, NCLOC, 999d, COVERAGE, 0d), + // docs with rating B + newDoc(MAINTAINABILITY_RATING, 2d, NCLOC, 2000d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 2d, NCLOC, 5000d, COVERAGE, 0d), + // docs with rating C + newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 20000d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 30000d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 40000d, COVERAGE, 0d), + newDoc(MAINTAINABILITY_RATING, 3d, NCLOC, 50000d, COVERAGE, 0d), + // docs with rating D + newDoc(MAINTAINABILITY_RATING, 4d, NCLOC, 120000d, COVERAGE, 0d), + // docs with rating E + newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 600000d, COVERAGE, 40d), + newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 700000d, COVERAGE, 50d), + newDoc(MAINTAINABILITY_RATING, 5d, NCLOC, 800000d, COVERAGE, 60d)); Facets facets = underTest.search(new ProjectMeasuresQuery() - .addMetricCriterion(new MetricCriterion(MAINTAINABILITY_RATING, Operator.LT, 3d)) - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)), - new SearchOptions().addFacets(MAINTAINABILITY_RATING, NCLOC)).getFacets(); + .addMetricCriterion(new MetricCriterion(MAINTAINABILITY_RATING, Operator.LT, 3d)) + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 30d)), + new SearchOptions().addFacets(MAINTAINABILITY_RATING, NCLOC)).getFacets(); // Sticky facet on maintainability rating does not take into account maintainability rating filter assertThat(facets.get(MAINTAINABILITY_RATING)).containsExactly( - entry("1", 3L), - entry("2", 2L), - entry("3", 4L), - entry("4", 1L), - entry("5", 0L)); + entry("1", 3L), + entry("2", 2L), + entry("3", 4L), + entry("4", 1L), + entry("5", 0L)); // 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)); + 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)); } @Test public void facet_maintainability_rating_contains_only_projects_authorized_for_user() throws Exception { // User can see these projects indexForUser(USER1, - // 3 docs with rating A - newDoc(MAINTAINABILITY_RATING, 1d), - newDoc(MAINTAINABILITY_RATING, 1d), - newDoc(MAINTAINABILITY_RATING, 1d), - // 2 docs with rating B - newDoc(MAINTAINABILITY_RATING, 2d), - newDoc(MAINTAINABILITY_RATING, 2d)); + // 3 docs with rating A + newDoc(MAINTAINABILITY_RATING, 1d), + newDoc(MAINTAINABILITY_RATING, 1d), + newDoc(MAINTAINABILITY_RATING, 1d), + // 2 docs with rating B + newDoc(MAINTAINABILITY_RATING, 2d), + newDoc(MAINTAINABILITY_RATING, 2d)); // User cannot see these projects indexForUser(USER2, - // docs with rating C - newDoc(MAINTAINABILITY_RATING, 3d), - // docs with rating D - newDoc(MAINTAINABILITY_RATING, 4d), - // docs with rating E - newDoc(MAINTAINABILITY_RATING, 5d)); + // docs with rating C + newDoc(MAINTAINABILITY_RATING, 3d), + // docs with rating D + newDoc(MAINTAINABILITY_RATING, 4d), + // docs with rating E + newDoc(MAINTAINABILITY_RATING, 5d)); userSession.logIn(USER1); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(MAINTAINABILITY_RATING)).getFacets(); assertThat(facets.get(MAINTAINABILITY_RATING)).containsExactly( - entry("1", 3L), - entry("2", 2L), - entry("3", 0L), - entry("4", 0L), - entry("5", 0L)); + entry("1", 3L), + entry("2", 2L), + entry("3", 0L), + entry("4", 0L), + entry("5", 0L)); } @Test public void facet_reliability_rating() { index( - // 3 docs with rating A - newDoc(RELIABILITY_RATING, 1d), - newDoc(RELIABILITY_RATING, 1d), - newDoc(RELIABILITY_RATING, 1d), - // 2 docs with rating B - newDoc(RELIABILITY_RATING, 2d), - newDoc(RELIABILITY_RATING, 2d), - // 4 docs with rating C - newDoc(RELIABILITY_RATING, 3d), - newDoc(RELIABILITY_RATING, 3d), - newDoc(RELIABILITY_RATING, 3d), - newDoc(RELIABILITY_RATING, 3d), - // 2 docs with rating D - newDoc(RELIABILITY_RATING, 4d), - newDoc(RELIABILITY_RATING, 4d), - // 5 docs with rating E - newDoc(RELIABILITY_RATING, 5d), - newDoc(RELIABILITY_RATING, 5d), - newDoc(RELIABILITY_RATING, 5d), - newDoc(RELIABILITY_RATING, 5d), - newDoc(RELIABILITY_RATING, 5d)); + // 3 docs with rating A + newDoc(RELIABILITY_RATING, 1d), + newDoc(RELIABILITY_RATING, 1d), + newDoc(RELIABILITY_RATING, 1d), + // 2 docs with rating B + newDoc(RELIABILITY_RATING, 2d), + newDoc(RELIABILITY_RATING, 2d), + // 4 docs with rating C + newDoc(RELIABILITY_RATING, 3d), + newDoc(RELIABILITY_RATING, 3d), + newDoc(RELIABILITY_RATING, 3d), + newDoc(RELIABILITY_RATING, 3d), + // 2 docs with rating D + newDoc(RELIABILITY_RATING, 4d), + newDoc(RELIABILITY_RATING, 4d), + // 5 docs with rating E + newDoc(RELIABILITY_RATING, 5d), + newDoc(RELIABILITY_RATING, 5d), + newDoc(RELIABILITY_RATING, 5d), + newDoc(RELIABILITY_RATING, 5d), + newDoc(RELIABILITY_RATING, 5d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(RELIABILITY_RATING)).getFacets(); assertThat(facets.get(RELIABILITY_RATING)).containsExactly( - entry("1", 3L), - entry("2", 2L), - entry("3", 4L), - entry("4", 2L), - entry("5", 5L)); + entry("1", 3L), + entry("2", 2L), + entry("3", 4L), + entry("4", 2L), + entry("5", 5L)); } @Test public void facet_security_rating() { index( - // 3 docs with rating A - newDoc(SECURITY_RATING, 1.0d), - newDoc(SECURITY_RATING, 1.0d), - newDoc(SECURITY_RATING, 1.0d), - // 2 docs with rating B - newDoc(SECURITY_RATING, 2.0d), - newDoc(SECURITY_RATING, 2.0d), - // 4 docs with rating C - newDoc(SECURITY_RATING, 3.0d), - newDoc(SECURITY_RATING, 3.0d), - newDoc(SECURITY_RATING, 3.0d), - newDoc(SECURITY_RATING, 3.0d), - // 2 docs with rating D - newDoc(SECURITY_RATING, 4.0d), - newDoc(SECURITY_RATING, 4.0d), - // 5 docs with rating E - newDoc(SECURITY_RATING, 5.0d), - newDoc(SECURITY_RATING, 5.0d), - newDoc(SECURITY_RATING, 5.0d), - newDoc(SECURITY_RATING, 5.0d), - newDoc(SECURITY_RATING, 5.0d)); + // 3 docs with rating A + newDoc(SECURITY_RATING, 1.0d), + newDoc(SECURITY_RATING, 1.0d), + newDoc(SECURITY_RATING, 1.0d), + // 2 docs with rating B + newDoc(SECURITY_RATING, 2.0d), + newDoc(SECURITY_RATING, 2.0d), + // 4 docs with rating C + newDoc(SECURITY_RATING, 3.0d), + newDoc(SECURITY_RATING, 3.0d), + newDoc(SECURITY_RATING, 3.0d), + newDoc(SECURITY_RATING, 3.0d), + // 2 docs with rating D + newDoc(SECURITY_RATING, 4.0d), + newDoc(SECURITY_RATING, 4.0d), + // 5 docs with rating E + newDoc(SECURITY_RATING, 5.0d), + newDoc(SECURITY_RATING, 5.0d), + newDoc(SECURITY_RATING, 5.0d), + newDoc(SECURITY_RATING, 5.0d), + newDoc(SECURITY_RATING, 5.0d)); Facets facets = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(SECURITY_RATING)).getFacets(); assertThat(facets.get(SECURITY_RATING)).containsExactly( - entry("1", 3L), - entry("2", 2L), - entry("3", 4L), - entry("4", 2L), - entry("5", 5L)); + entry("1", 3L), + entry("2", 2L), + entry("3", 4L), + entry("4", 2L), + entry("5", 5L)); } @Test public void facet_quality_gate() { index( - // 2 docs with QG OK - newDoc().setQualityGate(OK.name()), - newDoc().setQualityGate(OK.name()), - // 3 docs with QG WARN - newDoc().setQualityGate(WARN.name()), - newDoc().setQualityGate(WARN.name()), - newDoc().setQualityGate(WARN.name()), - // 4 docs with QG ERROR - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name())); + // 2 docs with QG OK + newDoc().setQualityGate(OK.name()), + newDoc().setQualityGate(OK.name()), + // 3 docs with QG WARN + newDoc().setQualityGate(WARN.name()), + newDoc().setQualityGate(WARN.name()), + newDoc().setQualityGate(WARN.name()), + // 4 docs with QG ERROR + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name())); LinkedHashMap<String, Long> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(ALERT_STATUS_KEY)).getFacets().get(ALERT_STATUS_KEY); assertThat(result).containsExactly( - entry(ERROR.name(), 4L), - entry(WARN.name(), 3L), - entry(OK.name(), 2L)); + entry(ERROR.name(), 4L), + entry(WARN.name(), 3L), + entry(OK.name(), 2L)); } @Test public void facet_quality_gate_is_sticky() { index( - // 2 docs with QG OK - newDoc(NCLOC, 10d, COVERAGE, 0d).setQualityGate(OK.name()), - newDoc(NCLOC, 10d, COVERAGE, 0d).setQualityGate(OK.name()), - // 3 docs with QG WARN - newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), - newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), - newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), - // 4 docs with QG ERROR - newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(ERROR.name()), - newDoc(NCLOC, 5000d, COVERAGE, 40d).setQualityGate(ERROR.name()), - newDoc(NCLOC, 12000d, COVERAGE, 50d).setQualityGate(ERROR.name()), - newDoc(NCLOC, 13000d, COVERAGE, 60d).setQualityGate(ERROR.name())); + // 2 docs with QG OK + newDoc(NCLOC, 10d, COVERAGE, 0d).setQualityGate(OK.name()), + newDoc(NCLOC, 10d, COVERAGE, 0d).setQualityGate(OK.name()), + // 3 docs with QG WARN + newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), + newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), + newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(WARN.name()), + // 4 docs with QG ERROR + newDoc(NCLOC, 100d, COVERAGE, 0d).setQualityGate(ERROR.name()), + newDoc(NCLOC, 5000d, COVERAGE, 40d).setQualityGate(ERROR.name()), + newDoc(NCLOC, 12000d, COVERAGE, 50d).setQualityGate(ERROR.name()), + newDoc(NCLOC, 13000d, COVERAGE, 60d).setQualityGate(ERROR.name())); Facets facets = underTest.search(new ProjectMeasuresQuery() - .setQualityGateStatus(ERROR) - .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 55d)), - new SearchOptions().addFacets(ALERT_STATUS_KEY, NCLOC)).getFacets(); + .setQualityGateStatus(ERROR) + .addMetricCriterion(new MetricCriterion(COVERAGE, Operator.LT, 55d)), + new SearchOptions().addFacets(ALERT_STATUS_KEY, NCLOC)).getFacets(); // Sticky facet on quality gate does not take into account quality gate filter assertThat(facets.get(ALERT_STATUS_KEY)).containsOnly( - entry(OK.name(), 2L), - entry(WARN.name(), 3L), - entry(ERROR.name(), 3L)); + entry(OK.name(), 2L), + entry(WARN.name(), 3L), + entry(ERROR.name(), 3L)); // But facet on ncloc does well take into into filters assertThat(facets.get(NCLOC)).containsExactly( - entry("*-1000.0", 1L), - entry("1000.0-10000.0", 1L), - entry("10000.0-100000.0", 1L), - entry("100000.0-500000.0", 0L), - entry("500000.0-*", 0L)); + entry("*-1000.0", 1L), + entry("1000.0-10000.0", 1L), + entry("10000.0-100000.0", 1L), + entry("100000.0-500000.0", 0L), + entry("500000.0-*", 0L)); } @Test public void facet_quality_gate_contains_only_projects_authorized_for_user() throws Exception { // User can see these projects indexForUser(USER1, - // 2 docs with QG OK - newDoc().setQualityGate(OK.name()), - newDoc().setQualityGate(OK.name()), - // 3 docs with QG WARN - newDoc().setQualityGate(WARN.name()), - newDoc().setQualityGate(WARN.name()), - newDoc().setQualityGate(WARN.name())); + // 2 docs with QG OK + newDoc().setQualityGate(OK.name()), + newDoc().setQualityGate(OK.name()), + // 3 docs with QG WARN + newDoc().setQualityGate(WARN.name()), + newDoc().setQualityGate(WARN.name()), + newDoc().setQualityGate(WARN.name())); // User cannot see these projects indexForUser(USER2, - // 4 docs with QG ERROR - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name()), - newDoc().setQualityGate(ERROR.name())); + // 4 docs with QG ERROR + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name()), + newDoc().setQualityGate(ERROR.name())); userSession.logIn(USER1); LinkedHashMap<String, Long> result = underTest.search(new ProjectMeasuresQuery(), new SearchOptions().addFacets(ALERT_STATUS_KEY)).getFacets().get(ALERT_STATUS_KEY); assertThat(result).containsExactly( - entry(ERROR.name(), 0L), - entry(WARN.name(), 3L), - entry(OK.name(), 2L)); + entry(ERROR.name(), 0L), + entry(WARN.name(), 3L), + entry(OK.name(), 2L)); } private void index(ProjectMeasuresDoc... docs) { |