From 023f54edfeb8f88ad79beafe23018e7637cba902 Mon Sep 17 00:00:00 2001 From: Pierre Guillot Date: Tue, 14 May 2019 11:31:26 +0200 Subject: [PATCH] SONAR-12026 add new hotspots statuses to facet --- .../sonar/server/issue/ws/SearchAction.java | 23 +++++++++++++------ .../issue/ws/SearchActionFacetsTest.java | 19 +++++++++++---- .../main/java/org/sonar/api/issue/Issue.java | 6 +++-- 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java index 1c15a9e1ea5..93a7dc2c452 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -34,7 +34,6 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.SearchHit; import org.sonar.api.Startable; import org.sonar.api.config.Configuration; -import org.sonar.api.issue.Issue; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; import org.sonar.api.server.ws.Change; @@ -67,6 +66,15 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; +import static org.sonar.api.issue.Issue.RESOLUTIONS; +import static org.sonar.api.issue.Issue.RESOLUTION_FIXED; +import static org.sonar.api.issue.Issue.RESOLUTION_REMOVED; +import static org.sonar.api.issue.Issue.STATUSES; +import static org.sonar.api.issue.Issue.STATUS_IN_REVIEW; +import static org.sonar.api.issue.Issue.STATUS_OPEN; +import static org.sonar.api.issue.Issue.STATUS_REOPENED; +import static org.sonar.api.issue.Issue.STATUS_REVIEWED; +import static org.sonar.api.issue.Issue.STATUS_TO_REVIEW; import static org.sonar.api.server.ws.WebService.Param.FACETS; import static org.sonar.api.utils.Paging.forPageIndex; import static org.sonar.core.util.stream.MoreCollectors.toSet; @@ -189,6 +197,7 @@ public class SearchAction implements IssuesWsAction, Startable { PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS) .setSince("3.6") .setChangelog( + new Change("7.8", format("added new Security Hotspots statuses : %s, %s and %s", STATUS_TO_REVIEW, STATUS_IN_REVIEW, STATUS_REVIEWED)), new Change("7.8", "Security hotspots are returned by default"), new Change("7.7", format("Value '%s' in parameter '%s' is deprecated, please use '%s' instead", DEPRECATED_PARAM_AUTHORS, FACETS, PARAM_AUTHOR)), new Change("7.6", format("The use of module keys in parameter '%s' is deprecated", PARAM_COMPONENT_KEYS)), @@ -229,12 +238,12 @@ public class SearchAction implements IssuesWsAction, Startable { .setPossibleValues(Severity.ALL); action.createParam(PARAM_STATUSES) .setDescription("Comma-separated list of statuses") - .setExampleValue(Issue.STATUS_OPEN + "," + Issue.STATUS_REOPENED) - .setPossibleValues(Issue.STATUSES); + .setExampleValue(STATUS_OPEN + "," + STATUS_REOPENED) + .setPossibleValues(STATUSES); action.createParam(PARAM_RESOLUTIONS) .setDescription("Comma-separated list of resolutions") - .setExampleValue(Issue.RESOLUTION_FIXED + "," + Issue.RESOLUTION_REMOVED) - .setPossibleValues(Issue.RESOLUTIONS); + .setExampleValue(RESOLUTION_FIXED + "," + RESOLUTION_REMOVED) + .setPossibleValues(RESOLUTIONS); action.createParam(PARAM_RESOLVED) .setDescription("To match resolved or unresolved issues") .setBooleanPossibleValues(); @@ -453,8 +462,8 @@ public class SearchAction implements IssuesWsAction, Startable { private void completeFacets(Facets facets, SearchRequest request, IssueQuery query) { addMandatoryValuesToFacet(facets, PARAM_SEVERITIES, Severity.ALL); - addMandatoryValuesToFacet(facets, PARAM_STATUSES, Issue.STATUSES); - addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), Issue.RESOLUTIONS)); + addMandatoryValuesToFacet(facets, PARAM_STATUSES, STATUSES); + addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), RESOLUTIONS)); addMandatoryValuesToFacet(facets, FACET_PROJECTS, query.projectUuids()); addMandatoryValuesToFacet(facets, PARAM_MODULE_UUIDS, query.moduleUuids()); addMandatoryValuesToFacet(facets, PARAM_FILE_UUIDS, query.fileUuids()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java index c18486f1ff1..8ef8027a667 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java @@ -19,7 +19,9 @@ */ package org.sonar.server.issue.ws; +import com.google.common.collect.ImmutableMap; import java.time.Clock; +import java.util.Map; import java.util.stream.IntStream; import org.junit.Rule; import org.junit.Test; @@ -112,11 +114,14 @@ public class SearchActionFacetsTest { .setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,fileUuids,assignees") .executeProtobuf(SearchWsResponse.class); + Map expectedStatuses = ImmutableMap.builder().put("OPEN", 1L).put("CONFIRMED", 0L) + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); + assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) .containsExactlyInAnyOrder( tuple("severities", of("INFO", 0L, "MINOR", 0L, "MAJOR", 1L, "CRITICAL", 0L, "BLOCKER", 0L)), - tuple("statuses", of("OPEN", 1L, "CONFIRMED", 0L, "REOPENED", 0L, "RESOLVED", 0L, "CLOSED", 0L)), + tuple("statuses", expectedStatuses), tuple("resolutions", of("", 1L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule.getKey().toString(), 1L)), tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), @@ -147,11 +152,14 @@ public class SearchActionFacetsTest { .setParam("facetMode", FACET_MODE_EFFORT) .executeProtobuf(SearchWsResponse.class); + Map expectedStatuses = ImmutableMap.builder().put("OPEN", 10L).put("CONFIRMED", 0L) + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); + assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) .containsExactlyInAnyOrder( tuple("severities", of("INFO", 0L, "MINOR", 0L, "MAJOR", 10L, "CRITICAL", 0L, "BLOCKER", 0L)), - tuple("statuses", of("OPEN", 10L, "CONFIRMED", 0L, "REOPENED", 0L, "RESOLVED", 0L, "CLOSED", 0L)), + tuple("statuses", expectedStatuses), tuple("resolutions", of("", 10L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule.getKey().toString(), 10L)), tuple("types", of("CODE_SMELL", 10L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), @@ -440,7 +448,7 @@ public class SearchActionFacetsTest { // Assignees contains one additional element : it's the empty string that will return number of unassigned issues tuple("assignees", 101), // Following facets returned fixed number of elements - tuple("statuses", 5), + tuple("statuses", 8), tuple("resolutions", 5), tuple("severities", 5), tuple("types", 4)); @@ -498,11 +506,14 @@ public class SearchActionFacetsTest { .setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,fileUuids,assignees") .executeProtobuf(SearchWsResponse.class); + Map expectedStatuses = ImmutableMap.builder().put("OPEN", 1L).put("CONFIRMED", 0L) + .put("REOPENED", 0L).put("RESOLVED", 0L).put("CLOSED", 0L).put("INREVIEW", 0L).put("TOREVIEW", 0L).put("REVIEWED", 0L).build(); + assertThat(response.getFacets().getFacetsList()) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) .containsExactlyInAnyOrder( tuple("severities", of("INFO", 0L, "MINOR", 0L, "MAJOR", 1L, "CRITICAL", 0L, "BLOCKER", 0L)), - tuple("statuses", of("OPEN", 1L, "CONFIRMED", 0L, "REOPENED", 0L, "RESOLVED", 0L, "CLOSED", 0L)), + tuple("statuses", expectedStatuses), tuple("resolutions", of("", 1L, "FALSE-POSITIVE", 0L, "FIXED", 0L, "REMOVED", 0L, "WONTFIX", 0L)), tuple("rules", of(rule1.getKey().toString(), 1L, rule2.getKey().toString(), 0L)), tuple("types", of("CODE_SMELL", 1L, "BUG", 0L, "VULNERABILITY", 0L, "SECURITY_HOTSPOT", 0L)), diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java index 63d072a014a..2f0f25aec86 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java @@ -29,6 +29,7 @@ import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.Duration; import static java.util.Arrays.asList; +import static java.util.Collections.unmodifiableList; /** * @since 3.6 @@ -73,7 +74,7 @@ public interface Issue extends Serializable { */ String RESOLUTION_WONT_FIX = "WONTFIX"; - List RESOLUTIONS = asList(RESOLUTION_FALSE_POSITIVE, RESOLUTION_WONT_FIX, RESOLUTION_FIXED, RESOLUTION_REMOVED); + List RESOLUTIONS = unmodifiableList(asList(RESOLUTION_FALSE_POSITIVE, RESOLUTION_WONT_FIX, RESOLUTION_FIXED, RESOLUTION_REMOVED)); /** * @since 7.8 @@ -95,7 +96,8 @@ public interface Issue extends Serializable { * * @since 4.4 */ - List STATUSES = asList(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED); + List STATUSES = unmodifiableList(asList(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED, + STATUS_TO_REVIEW, STATUS_IN_REVIEW, STATUS_REVIEWED)); /** * Unique generated key. It looks like "d2de809c-1512-4ae2-9f34-f5345c9f1a13". -- 2.39.5