Browse Source

SONAR-13592 add facet to filter by file paths

tags/8.5.0.37579
Jacek 3 years ago
parent
commit
41784809b3

+ 5
- 5
server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java View File

private List<String> directories; private List<String> directories;
private String facetMode; private String facetMode;
private List<String> facets; private List<String> facets;
private List<String> fileUuids;
private List<String> files;
private List<String> issues; private List<String> issues;
private Set<String> scopes; private Set<String> scopes;
private List<String> languages; private List<String> languages;
} }


@CheckForNull @CheckForNull
public List<String> getFileUuids() {
return fileUuids;
public List<String> getFiles() {
return files;
} }


public SearchRequest setFileUuids(@Nullable List<String> fileUuids) {
this.fileUuids = fileUuids;
public SearchRequest setFiles(@Nullable List<String> files) {
this.files = files;
return this; return this;
} }



+ 2
- 2
server/sonar-server-common/src/test/java/org/sonar/server/issue/SearchRequestTest.java View File

.setProjects(singletonList("project-a")) .setProjects(singletonList("project-a"))
.setModuleUuids(singletonList("module-a")) .setModuleUuids(singletonList("module-a"))
.setDirectories(singletonList("aDirPath")) .setDirectories(singletonList("aDirPath"))
.setFileUuids(asList("file-a", "file-b"))
.setFiles(asList("file-a", "file-b"))
.setAssigneesUuid(asList("user-a", "user-b")) .setAssigneesUuid(asList("user-a", "user-b"))
.setScopes(asList("MAIN", "TEST")) .setScopes(asList("MAIN", "TEST"))
.setLanguages(singletonList("xoo")) .setLanguages(singletonList("xoo"))
assertThat(underTest.getProjects()).containsExactly("project-a"); assertThat(underTest.getProjects()).containsExactly("project-a");
assertThat(underTest.getModuleUuids()).containsExactly("module-a"); assertThat(underTest.getModuleUuids()).containsExactly("module-a");
assertThat(underTest.getDirectories()).containsExactly("aDirPath"); assertThat(underTest.getDirectories()).containsExactly("aDirPath");
assertThat(underTest.getFileUuids()).containsExactly("file-a", "file-b");
assertThat(underTest.getFiles()).containsExactly("file-a", "file-b");
assertThat(underTest.getAssigneeUuids()).containsExactly("user-a", "user-b"); assertThat(underTest.getAssigneeUuids()).containsExactly("user-a", "user-b");
assertThat(underTest.getScopes()).containsExactly("MAIN", "TEST"); assertThat(underTest.getScopes()).containsExactly("MAIN", "TEST");
assertThat(underTest.getLanguages()).containsExactly("xoo"); assertThat(underTest.getLanguages()).containsExactly("xoo");

+ 16
- 19
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java View File

import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponse;
import static org.sonar.server.issue.index.IssueIndex.Facet.CREATED_AT; import static org.sonar.server.issue.index.IssueIndex.Facet.CREATED_AT;
import static org.sonar.server.issue.index.IssueIndex.Facet.CWE; import static org.sonar.server.issue.index.IssueIndex.Facet.CWE;
import static org.sonar.server.issue.index.IssueIndex.Facet.DIRECTORIES; import static org.sonar.server.issue.index.IssueIndex.Facet.DIRECTORIES;
import static org.sonar.server.issue.index.IssueIndex.Facet.FILE_UUIDS;
import static org.sonar.server.issue.index.IssueIndex.Facet.FILES;
import static org.sonar.server.issue.index.IssueIndex.Facet.LANGUAGES; import static org.sonar.server.issue.index.IssueIndex.Facet.LANGUAGES;
import static org.sonar.server.issue.index.IssueIndex.Facet.MODULE_UUIDS; import static org.sonar.server.issue.index.IssueIndex.Facet.MODULE_UUIDS;
import static org.sonar.server.issue.index.IssueIndex.Facet.OWASP_TOP_10; import static org.sonar.server.issue.index.IssueIndex.Facet.OWASP_TOP_10;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_OWASP_TOP_10;
AUTHOR(PARAM_AUTHOR, FIELD_ISSUE_AUTHOR_LOGIN, STICKY, MAX_FACET_SIZE), AUTHOR(PARAM_AUTHOR, FIELD_ISSUE_AUTHOR_LOGIN, STICKY, MAX_FACET_SIZE),
PROJECT_UUIDS(FACET_PROJECTS, FIELD_ISSUE_PROJECT_UUID, STICKY, MAX_FACET_SIZE), PROJECT_UUIDS(FACET_PROJECTS, FIELD_ISSUE_PROJECT_UUID, STICKY, MAX_FACET_SIZE),
MODULE_UUIDS(PARAM_MODULE_UUIDS, FIELD_ISSUE_MODULE_UUID, STICKY, MAX_FACET_SIZE), MODULE_UUIDS(PARAM_MODULE_UUIDS, FIELD_ISSUE_MODULE_UUID, STICKY, MAX_FACET_SIZE),
FILE_UUIDS(PARAM_FILE_UUIDS, FIELD_ISSUE_COMPONENT_UUID, STICKY, MAX_FACET_SIZE),
FILES(PARAM_FILES, FIELD_ISSUE_FILE_PATH, STICKY, MAX_FACET_SIZE),
DIRECTORIES(PARAM_DIRECTORIES, FIELD_ISSUE_DIRECTORY_PATH, STICKY, MAX_FACET_SIZE), DIRECTORIES(PARAM_DIRECTORIES, FIELD_ISSUE_DIRECTORY_PATH, STICKY, MAX_FACET_SIZE),
ASSIGNEES(PARAM_ASSIGNEES, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, MAX_FACET_SIZE), ASSIGNEES(PARAM_ASSIGNEES, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, MAX_FACET_SIZE),
ASSIGNED_TO_ME(FACET_ASSIGNED_TO_ME, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, 1), ASSIGNED_TO_ME(FACET_ASSIGNED_TO_ME, FIELD_ISSUE_ASSIGNEE_UUID, STICKY, 1),
filters.addFilter("__authorization", new SimpleFieldFilterScope("parent"), createAuthorizationFilter()); filters.addFilter("__authorization", new SimpleFieldFilterScope("parent"), createAuthorizationFilter());


// Issue is assigned Filter // Issue is assigned Filter
if (BooleanUtils.isTrue(query.assigned())) {
if (Boolean.TRUE.equals(query.assigned())) {
filters.addFilter(IS_ASSIGNED_FILTER, Facet.ASSIGNEES.getFilterScope(), existsQuery(FIELD_ISSUE_ASSIGNEE_UUID)); filters.addFilter(IS_ASSIGNED_FILTER, Facet.ASSIGNEES.getFilterScope(), existsQuery(FIELD_ISSUE_ASSIGNEE_UUID));
} else if (BooleanUtils.isFalse(query.assigned())) {
} else if (Boolean.FALSE.equals(query.assigned())) {
filters.addFilter(IS_ASSIGNED_FILTER, ASSIGNEES.getFilterScope(), boolQuery().mustNot(existsQuery(FIELD_ISSUE_ASSIGNEE_UUID))); filters.addFilter(IS_ASSIGNED_FILTER, ASSIGNEES.getFilterScope(), boolQuery().mustNot(existsQuery(FIELD_ISSUE_ASSIGNEE_UUID)));
} }


// Issue is Resolved Filter // Issue is Resolved Filter
if (BooleanUtils.isTrue(query.resolved())) {
if (Boolean.TRUE.equals(query.resolved())) {
filters.addFilter("__isResolved", Facet.RESOLUTIONS.getFilterScope(), existsQuery(FIELD_ISSUE_RESOLUTION)); filters.addFilter("__isResolved", Facet.RESOLUTIONS.getFilterScope(), existsQuery(FIELD_ISSUE_RESOLUTION));
} else if (BooleanUtils.isFalse(query.resolved())) {
} else if (Boolean.FALSE.equals(query.resolved())) {
filters.addFilter("__isResolved", Facet.RESOLUTIONS.getFilterScope(), boolQuery().mustNot(existsQuery(FIELD_ISSUE_RESOLUTION))); filters.addFilter("__isResolved", Facet.RESOLUTIONS.getFilterScope(), boolQuery().mustNot(existsQuery(FIELD_ISSUE_RESOLUTION)));
} }


} }


private static void addCommonComponentRelatedFilters(IssueQuery query, AllFilters filters) { private static void addCommonComponentRelatedFilters(IssueQuery query, AllFilters filters) {
QueryBuilder componentFilter = createTermsFilter(FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
QueryBuilder fileFilter = createTermsFilter(FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());
filters.addFilter(FIELD_ISSUE_COMPONENT_UUID, new SimpleFieldFilterScope(FIELD_ISSUE_COMPONENT_UUID),
createTermsFilter(FIELD_ISSUE_COMPONENT_UUID, query.componentUuids()));


if (BooleanUtils.isTrue(query.onComponentOnly())) {
filters.addFilter(FIELD_ISSUE_COMPONENT_UUID, new SimpleFieldFilterScope(FIELD_ISSUE_COMPONENT_UUID), componentFilter);
} else {
if (!Boolean.TRUE.equals(query.onComponentOnly())) {
filters.addFilter( filters.addFilter(
FIELD_ISSUE_PROJECT_UUID, new SimpleFieldFilterScope(FIELD_ISSUE_PROJECT_UUID), FIELD_ISSUE_PROJECT_UUID, new SimpleFieldFilterScope(FIELD_ISSUE_PROJECT_UUID),
createTermsFilter(FIELD_ISSUE_PROJECT_UUID, query.projectUuids())); createTermsFilter(FIELD_ISSUE_PROJECT_UUID, query.projectUuids()));
FIELD_ISSUE_DIRECTORY_PATH, new SimpleFieldFilterScope(FIELD_ISSUE_DIRECTORY_PATH), FIELD_ISSUE_DIRECTORY_PATH, new SimpleFieldFilterScope(FIELD_ISSUE_DIRECTORY_PATH),
createTermsFilter(FIELD_ISSUE_DIRECTORY_PATH, query.directories())); createTermsFilter(FIELD_ISSUE_DIRECTORY_PATH, query.directories()));
filters.addFilter( filters.addFilter(
FIELD_ISSUE_COMPONENT_UUID, new SimpleFieldFilterScope(FIELD_ISSUE_COMPONENT_UUID),
fileFilter == null ? componentFilter : fileFilter);
FIELD_ISSUE_FILE_PATH, new SimpleFieldFilterScope(FIELD_ISSUE_FILE_PATH),
createTermsFilter(FIELD_ISSUE_FILE_PATH, query.files()));
} }
} }


private static void addBranchComponentRelatedFilters(IssueQuery query, AllFilters allFilters) { private static void addBranchComponentRelatedFilters(IssueQuery query, AllFilters allFilters) {
if (BooleanUtils.isTrue(query.onComponentOnly())) {
if (Boolean.TRUE.equals(query.onComponentOnly())) {
return; return;
} }
allFilters.addFilter( allFilters.addFilter(
} }


private static void addViewRelatedFilters(IssueQuery query, AllFilters allFilters) { private static void addViewRelatedFilters(IssueQuery query, AllFilters allFilters) {
if (BooleanUtils.isTrue(query.onComponentOnly())) {
if (Boolean.TRUE.equals(query.onComponentOnly())) {
return; return;
} }
Collection<String> viewUuids = query.viewUuids(); Collection<String> viewUuids = query.viewUuids();
private List<FieldSortBuilder> createSortBuilders(IssueQuery query) { private List<FieldSortBuilder> createSortBuilders(IssueQuery query) {
String sortField = query.sort(); String sortField = query.sort();
if (sortField != null) { if (sortField != null) {
boolean asc = BooleanUtils.isTrue(query.asc());
boolean asc = Boolean.TRUE.equals(query.asc());
return sorting.fill(sortField, asc); return sorting.fill(sortField, asc);
} }
return sorting.fillDefault(); return sorting.fillDefault();
addFacetIfNeeded(options, aggregationHelper, esRequest, PROJECT_UUIDS, query.projectUuids().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, PROJECT_UUIDS, query.projectUuids().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, MODULE_UUIDS, query.moduleUuids().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, MODULE_UUIDS, query.moduleUuids().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, DIRECTORIES, query.directories().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, DIRECTORIES, query.directories().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, FILE_UUIDS, query.fileUuids().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, FILES, query.files().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, SCOPES, query.scopes().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, SCOPES, query.scopes().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, LANGUAGES, query.languages().toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, LANGUAGES, query.languages().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, RULES, query.rules().stream().map(RuleDefinitionDto::getUuid).toArray()); addFacetIfNeeded(options, aggregationHelper, esRequest, RULES, query.rules().stream().map(RuleDefinitionDto::getUuid).toArray());

+ 2
- 2
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java View File

return directories; return directories;
} }


public Collection<String> fileUuids() {
public Collection<String> files() {
return files; return files;
} }


return this; return this;
} }


public Builder fileUuids(@Nullable Collection<String> l) {
public Builder files(@Nullable Collection<String> l) {
this.files = l; this.files = l;
return this; return this;
} }

+ 2
- 2
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java View File

} }
builder.moduleUuids(request.getModuleUuids()); builder.moduleUuids(request.getModuleUuids());
builder.directories(request.getDirectories()); builder.directories(request.getDirectories());
builder.fileUuids(request.getFileUuids());
builder.files(request.getFiles());


addComponentsBasedOnQualifier(builder, session, components, request); addComponentsBasedOnQualifier(builder, session, components, request);
} }
break; break;
case Qualifiers.FILE: case Qualifiers.FILE:
case Qualifiers.UNIT_TEST_FILE: case Qualifiers.UNIT_TEST_FILE:
builder.fileUuids(components.stream().map(ComponentDto::uuid).collect(toList()));
builder.componentUuids(components.stream().map(ComponentDto::uuid).collect(toList()));
break; break;
default: default:
throw new IllegalArgumentException("Unable to set search root context for components " + Joiner.on(',').join(components)); throw new IllegalArgumentException("Unable to set search root context for components " + Joiner.on(',').join(components));

+ 4
- 4
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexDebtTest.java View File

IssueDocTesting.newDoc("I4", file2).setEffort(10L), IssueDocTesting.newDoc("I4", file2).setEffort(10L),
IssueDocTesting.newDoc("I5", file3).setEffort(10L)); IssueDocTesting.newDoc("I5", file3).setEffort(10L));


Facets facets = search("fileUuids");
assertThat(facets.getNames()).containsOnly("fileUuids", FACET_MODE_EFFORT);
assertThat(facets.get("fileUuids"))
.containsOnly(entry("A", 10L), entry("ABCD", 10L), entry("BCDE", 20L), entry("CDEF", 10L));
Facets facets = search("files");
assertThat(facets.getNames()).containsOnly("files", FACET_MODE_EFFORT);
assertThat(facets.get("files"))
.containsOnly(entry(file1.path(), 10L), entry(file2.path(), 20L), entry(file3.path(), 10L));
assertThat(facets.get(FACET_MODE_EFFORT)).containsOnly(entry("total", 50L)); assertThat(facets.get(FACET_MODE_EFFORT)).containsOnly(entry("total", 50L));
} }



+ 7
- 6
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java View File

@Test @Test
public void facets_on_files() { public void facets_on_files() {
ComponentDto project = newPrivateProjectDto(newOrganizationDto(), "A"); ComponentDto project = newPrivateProjectDto(newOrganizationDto(), "A");
ComponentDto file1 = newFileDto(project, null, "ABCD");
ComponentDto file2 = newFileDto(project, null, "BCDE");
ComponentDto file3 = newFileDto(project, null, "CDEF");
ComponentDto dir = newDirectory(project, "src");
ComponentDto file1 = newFileDto(project, dir, "ABCD");
ComponentDto file2 = newFileDto(project, dir, "BCDE");
ComponentDto file3 = newFileDto(project, dir, "CDEF");


indexIssues( indexIssues(
newDoc("I1", project), newDoc("I1", project),
newDoc("I4", file2), newDoc("I4", file2),
newDoc("I5", file3)); newDoc("I5", file3));


assertThatFacetHasOnly(IssueQuery.builder(), "fileUuids", entry("A", 1L), entry("ABCD", 1L), entry("BCDE", 2L), entry("CDEF", 1L));
assertThatFacetHasOnly(IssueQuery.builder(), "files", entry("src/NAME_ABCD", 1L), entry("src/NAME_BCDE", 2L), entry("src/NAME_CDEF", 1L));
} }


@Test @Test
IssueDoc issue2 = newDoc(newFileDto(project, null, "file2")); IssueDoc issue2 = newDoc(newFileDto(project, null, "file2"));
indexIssues(issue1, issue2); indexIssues(issue1, issue2);


assertThatFacetHasSize(IssueQuery.builder().build(), "fileUuids", 100);
assertThatFacetHasSize(IssueQuery.builder().fileUuids(asList(issue1.componentUuid(), issue2.componentUuid())).build(), "fileUuids", 102);
assertThatFacetHasSize(IssueQuery.builder().build(), "files", 100);
assertThatFacetHasSize(IssueQuery.builder().files(asList(issue1.filePath(), issue2.filePath())).build(), "files", 102);
} }


@Test @Test

+ 10
- 10
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java View File

newDoc("I5", subModule), newDoc("I5", subModule),
newDoc("I6", file3)); newDoc("I6", file3));


assertThatSearchReturnsOnly(IssueQuery.builder().fileUuids(asList(file1.uuid(), file2.uuid(), file3.uuid())), "I2", "I4", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().fileUuids(singletonList(file1.uuid())), "I2");
assertThatSearchReturnsOnly(IssueQuery.builder().files(asList(file1.path(), file2.path(), file3.path())), "I2", "I4", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().files(singletonList(file1.path())), "I2");
assertThatSearchReturnsOnly(IssueQuery.builder().moduleRootUuids(singletonList(subModule.uuid())), "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().moduleRootUuids(singletonList(subModule.uuid())), "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().moduleRootUuids(singletonList(module.uuid())), "I3", "I4", "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().moduleRootUuids(singletonList(module.uuid())), "I3", "I4", "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().projectUuids(singletonList(project.uuid())), "I1", "I2", "I3", "I4", "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().projectUuids(singletonList(project.uuid())), "I1", "I2", "I3", "I4", "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(view)), "I1", "I2", "I3", "I4", "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(view)), "I1", "I2", "I3", "I4", "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(module.uuid())), "I3", "I4"); assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(module.uuid())), "I3", "I4");
assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(subModule.uuid())), "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(subModule.uuid())), "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().fileUuids(singletonList(file1.uuid())), "I2");
assertThatSearchReturnsOnly(IssueQuery.builder().fileUuids(asList(file1.uuid(), file2.uuid(), file3.uuid())), "I2", "I4", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().files(singletonList(file1.path())), "I2");
assertThatSearchReturnsOnly(IssueQuery.builder().files(asList(file1.path(), file2.path(), file3.path())), "I2", "I4", "I6");
} }


@Test @Test
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(asList(portfolio1.uuid(), portfolio2.uuid())), issueOnProject1.key(), issueOnFile.key(), issueOnProject2.key()); assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(asList(portfolio1.uuid(), portfolio2.uuid())), issueOnProject1.key(), issueOnFile.key(), issueOnProject2.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio1.uuid())).projectUuids(singletonList(project1.uuid())), issueOnProject1.key(), assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio1.uuid())).projectUuids(singletonList(project1.uuid())), issueOnProject1.key(),
issueOnFile.key()); issueOnFile.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio1.uuid())).fileUuids(singletonList(file.uuid())), issueOnFile.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(portfolio1.uuid())).files(singletonList(file.path())), issueOnFile.key());
assertThatSearchReturnsEmpty(IssueQuery.builder().viewUuids(singletonList("unknown"))); assertThatSearchReturnsEmpty(IssueQuery.builder().viewUuids(singletonList("unknown")));
} }




assertThatSearchReturnsOnly(IssueQuery.builder().branchUuid(branch.uuid()).mainBranch(false), "I4", "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().branchUuid(branch.uuid()).mainBranch(false), "I4", "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(branchModule.uuid())).branchUuid(branch.uuid()).mainBranch(false), "I5", "I6"); assertThatSearchReturnsOnly(IssueQuery.builder().moduleUuids(singletonList(branchModule.uuid())).branchUuid(branch.uuid()).mainBranch(false), "I5", "I6");
assertThatSearchReturnsOnly(IssueQuery.builder().fileUuids(singletonList(branchFile.uuid())).branchUuid(branch.uuid()).mainBranch(false), "I6");
assertThatSearchReturnsEmpty(IssueQuery.builder().fileUuids(singletonList(branchFile.uuid())).mainBranch(false).branchUuid("unknown"));
assertThatSearchReturnsOnly(IssueQuery.builder().files(singletonList(branchFile.path())).branchUuid(branch.uuid()).mainBranch(false), "I6");
assertThatSearchReturnsEmpty(IssueQuery.builder().files(singletonList(branchFile.uuid())).mainBranch(false).branchUuid("unknown"));
} }


@Test @Test
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(asList(application1.uuid(), application2.uuid())), issueOnProject1.key(), issueOnFile.key(), issueOnProject2.key()); assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(asList(application1.uuid(), application2.uuid())), issueOnProject1.key(), issueOnFile.key(), issueOnProject2.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application1.uuid())).projectUuids(singletonList(project1.uuid())), issueOnProject1.key(), assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application1.uuid())).projectUuids(singletonList(project1.uuid())), issueOnProject1.key(),
issueOnFile.key()); issueOnFile.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application1.uuid())).fileUuids(singletonList(file.uuid())), issueOnFile.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(application1.uuid())).files(singletonList(file.path())), issueOnFile.key());
assertThatSearchReturnsEmpty(IssueQuery.builder().viewUuids(singletonList("unknown"))); assertThatSearchReturnsEmpty(IssueQuery.builder().viewUuids(singletonList("unknown")));
} }


assertThatSearchReturnsOnly( assertThatSearchReturnsOnly(
IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(branch1.uuid()).mainBranch(false), IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(branch1.uuid()).mainBranch(false),
issueOnProject1.key(), issueOnFile.key()); issueOnProject1.key(), issueOnFile.key());
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).fileUuids(singletonList(file.uuid())).branchUuid(branch1.uuid()).mainBranch(false),
assertThatSearchReturnsOnly(IssueQuery.builder().viewUuids(singletonList(branch1.uuid())).files(singletonList(file.path())).branchUuid(branch1.uuid()).mainBranch(false),
issueOnFile.key()); issueOnFile.key());
assertThatSearchReturnsEmpty(IssueQuery.builder().branchUuid("unknown")); assertThatSearchReturnsEmpty(IssueQuery.builder().branchUuid("unknown"));
} }
IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(applicationBranch1.uuid()).mainBranch(false), IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).projectUuids(singletonList(project1.uuid())).branchUuid(applicationBranch1.uuid()).mainBranch(false),
issueOnProject1Branch1.key(), issueOnFileOnProject1Branch1.key()); issueOnProject1Branch1.key(), issueOnFileOnProject1Branch1.key());
assertThatSearchReturnsOnly( assertThatSearchReturnsOnly(
IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).fileUuids(singletonList(fileOnProject1Branch1.uuid())).branchUuid(applicationBranch1.uuid())
IssueQuery.builder().viewUuids(singletonList(applicationBranch1.uuid())).files(singletonList(fileOnProject1Branch1.path())).branchUuid(applicationBranch1.uuid())
.mainBranch(false), .mainBranch(false),
issueOnFileOnProject1Branch1.key()); issueOnFileOnProject1Branch1.key());
assertThatSearchReturnsEmpty( assertThatSearchReturnsEmpty(

+ 12
- 12
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java View File

.setProjects(asList(project.getDbKey())) .setProjects(asList(project.getDbKey()))
.setModuleUuids(asList(module.uuid())) .setModuleUuids(asList(module.uuid()))
.setDirectories(asList("aDirPath")) .setDirectories(asList("aDirPath"))
.setFileUuids(asList(file.uuid()))
.setFiles(asList(file.uuid()))
.setAssigneesUuid(asList(user.getUuid())) .setAssigneesUuid(asList(user.getUuid()))
.setScopes(asList("MAIN", "TEST")) .setScopes(asList("MAIN", "TEST"))
.setLanguages(asList("xoo")) .setLanguages(asList("xoo"))
assertThat(query.resolved()).isTrue(); assertThat(query.resolved()).isTrue();
assertThat(query.projectUuids()).containsOnly(project.uuid()); assertThat(query.projectUuids()).containsOnly(project.uuid());
assertThat(query.moduleUuids()).containsOnly(module.uuid()); assertThat(query.moduleUuids()).containsOnly(module.uuid());
assertThat(query.fileUuids()).containsOnly(file.uuid());
assertThat(query.files()).containsOnly(file.uuid());
assertThat(query.assignees()).containsOnly(user.getUuid()); assertThat(query.assignees()).containsOnly(user.getUuid());
assertThat(query.scopes()).containsOnly("TEST", "MAIN"); assertThat(query.scopes()).containsOnly("TEST", "MAIN");
assertThat(query.languages()).containsOnly("xoo"); assertThat(query.languages()).containsOnly("xoo");
assertThat(query.moduleUuids()).isEmpty(); assertThat(query.moduleUuids()).isEmpty();
assertThat(query.moduleRootUuids()).isEmpty(); assertThat(query.moduleRootUuids()).isEmpty();
assertThat(query.directories()).isEmpty(); assertThat(query.directories()).isEmpty();
assertThat(query.fileUuids()).isEmpty();
assertThat(query.files()).isEmpty();
assertThat(query.viewUuids()).isEmpty(); assertThat(query.viewUuids()).isEmpty();
assertThat(query.organizationUuid()).isNull(); assertThat(query.organizationUuid()).isNull();
assertThat(query.branchUuid()).isNull(); assertThat(query.branchUuid()).isNull();


IssueQuery query = underTest.create(request); IssueQuery query = underTest.create(request);


assertThat(query.fileUuids()).containsExactly(file.uuid());
assertThat(query.componentUuids()).containsExactly(file.uuid());
} }


@Test @Test


IssueQuery query = underTest.create(request); IssueQuery query = underTest.create(request);


assertThat(query.fileUuids()).containsExactly(file.uuid());
assertThat(query.componentUuids()).containsExactly(file.uuid());
} }


@Test @Test
assertThat(underTest.create(new SearchRequest() assertThat(underTest.create(new SearchRequest()
.setComponents(singletonList(file.getKey())) .setComponents(singletonList(file.getKey()))
.setBranch(branch.getBranch()))) .setBranch(branch.getBranch())))
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.fileUuids()), IssueQuery::isMainBranch)
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.componentUuids()), IssueQuery::isMainBranch)
.containsOnly(branch.uuid(), singletonList(file.uuid()), false); .containsOnly(branch.uuid(), singletonList(file.uuid()), false);


assertThat(underTest.create(new SearchRequest() assertThat(underTest.create(new SearchRequest()
.setComponents(singletonList(branch.getKey())) .setComponents(singletonList(branch.getKey()))
.setFileUuids(singletonList(file.uuid()))
.setFiles(singletonList(file.path()))
.setBranch(branch.getBranch()))) .setBranch(branch.getBranch())))
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.fileUuids()), IssueQuery::isMainBranch)
.containsOnly(branch.uuid(), singletonList(file.uuid()), false);
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.files()), IssueQuery::isMainBranch)
.containsOnly(branch.uuid(), singletonList(file.path()), false);


assertThat(underTest.create(new SearchRequest() assertThat(underTest.create(new SearchRequest()
.setProjects(singletonList(branch.getKey())) .setProjects(singletonList(branch.getKey()))
.setFileUuids(singletonList(file.uuid()))
.setFiles(singletonList(file.path()))
.setBranch(branch.getBranch()))) .setBranch(branch.getBranch())))
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.fileUuids()), IssueQuery::isMainBranch)
.containsOnly(branch.uuid(), singletonList(file.uuid()), false);
.extracting(IssueQuery::branchUuid, query -> new ArrayList<>(query.files()), IssueQuery::isMainBranch)
.containsOnly(branch.uuid(), singletonList(file.path()), false);
} }


@Test @Test

+ 12
- 11
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java View File

import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_IN_LAST; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CWE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
static final List<String> SUPPORTED_FACETS = ImmutableList.of( static final List<String> SUPPORTED_FACETS = ImmutableList.of(
FACET_PROJECTS, FACET_PROJECTS,
PARAM_MODULE_UUIDS, PARAM_MODULE_UUIDS,
PARAM_FILE_UUIDS,
PARAM_FILES,
FACET_ASSIGNED_TO_ME, FACET_ASSIGNED_TO_ME,
PARAM_SEVERITIES, PARAM_SEVERITIES,
PARAM_STATUSES, PARAM_STATUSES,
PARAM_SONARSOURCE_SECURITY); PARAM_SONARSOURCE_SECURITY);


private static final String INTERNAL_PARAMETER_DISCLAIMER = "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. "; private static final String INTERNAL_PARAMETER_DISCLAIMER = "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. ";
private static final Set<String> FACETS_REQUIRING_PROJECT_OR_ORGANIZATION = newHashSet(PARAM_MODULE_UUIDS, PARAM_FILE_UUIDS, PARAM_DIRECTORIES);
private static final Set<String> FACETS_REQUIRING_PROJECT_OR_ORGANIZATION = newHashSet(PARAM_MODULE_UUIDS, PARAM_FILES, PARAM_DIRECTORIES);


private final UserSession userSession; private final UserSession userSession;
private final IssueIndex issueIndex; private final IssueIndex issueIndex;
+ "<br/>When issue indexation is in progress returns 503 service unavailable HTTP code.") + "<br/>When issue indexation is in progress returns 503 service unavailable HTTP code.")
.setSince("3.6") .setSince("3.6")
.setChangelog( .setChangelog(
new Change("8.5", "Facet 'fileUuids' is dropped in favour of the new facet 'files'" +
"Note that they are not strictly identical, the latter returns the file paths."),
new Change("8.5", "Internal parameter 'fileUuids' has been dropped"),
new Change("8.4", "parameters 'componentUuids', 'projectKeys' has been dropped."), new Change("8.4", "parameters 'componentUuids', 'projectKeys' has been dropped."),
new Change("8.2", "'REVIEWED', 'TO_REVIEW' status param values are no longer supported"), new Change("8.2", "'REVIEWED', 'TO_REVIEW' status param values are no longer supported"),
new Change("8.2", "Security hotspots are no longer returned as type 'SECURITY_HOTSPOT' is not supported anymore, use dedicated api/hotspots"), new Change("8.2", "Security hotspots are no longer returned as type 'SECURITY_HOTSPOT' is not supported anymore, use dedicated api/hotspots"),
private static void addComponentRelatedParams(WebService.NewAction action) { private static void addComponentRelatedParams(WebService.NewAction action) {
action.createParam(PARAM_ON_COMPONENT_ONLY) action.createParam(PARAM_ON_COMPONENT_ONLY)
.setDescription("Return only issues at a component's level, not on its descendants (modules, directories, files, etc). " + .setDescription("Return only issues at a component's level, not on its descendants (modules, directories, files, etc). " +
"This parameter is only considered when componentKeys or componentUuids is set.")
"This parameter is only considered when componentKeys is set.")
.setBooleanPossibleValues() .setBooleanPossibleValues()
.setDefaultValue("false"); .setDefaultValue("false");


.setSince("5.1") .setSince("5.1")
.setExampleValue("src/main/java/org/sonar/server/"); .setExampleValue("src/main/java/org/sonar/server/");


action.createParam(PARAM_FILE_UUIDS)
.setDescription("To retrieve issues associated to a specific list of files (comma-separated list of file IDs). " +
action.createParam(PARAM_FILES)
.setDescription("To retrieve issues associated to a specific list of files (comma-separated list of file paths). " +
INTERNAL_PARAMETER_DISCLAIMER) INTERNAL_PARAMETER_DISCLAIMER)
.setInternal(true) .setInternal(true)
.setExampleValue("bdd82933-3070-4903-9188-7d8749e8bb92");
.setExampleValue("src/main/java/org/sonar/server/Test.java");


action.createParam(PARAM_BRANCH) action.createParam(PARAM_BRANCH)
.setDescription("Branch key. Not available in the community edition.") .setDescription("Branch key. Not available in the community edition.")
addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), RESOLUTIONS)); addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), RESOLUTIONS));
addMandatoryValuesToFacet(facets, FACET_PROJECTS, query.projectUuids()); addMandatoryValuesToFacet(facets, FACET_PROJECTS, query.projectUuids());
addMandatoryValuesToFacet(facets, PARAM_MODULE_UUIDS, query.moduleUuids()); addMandatoryValuesToFacet(facets, PARAM_MODULE_UUIDS, query.moduleUuids());
addMandatoryValuesToFacet(facets, PARAM_FILE_UUIDS, query.fileUuids());
addMandatoryValuesToFacet(facets, PARAM_FILES, query.files());


List<String> assignees = Lists.newArrayList(""); List<String> assignees = Lists.newArrayList("");
List<String> assigneesFromRequest = request.getAssigneeUuids(); List<String> assigneesFromRequest = request.getAssigneeUuids();
private static void collectFacets(SearchResponseLoader.Collector collector, Facets facets) { private static void collectFacets(SearchResponseLoader.Collector collector, Facets facets) {
collector.addProjectUuids(facets.getBucketKeys(FACET_PROJECTS)); collector.addProjectUuids(facets.getBucketKeys(FACET_PROJECTS));
collector.addComponentUuids(facets.getBucketKeys(PARAM_MODULE_UUIDS)); collector.addComponentUuids(facets.getBucketKeys(PARAM_MODULE_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(PARAM_FILE_UUIDS));
collector.addRuleIds(facets.getBucketKeys(PARAM_RULES)); collector.addRuleIds(facets.getBucketKeys(PARAM_RULES));
collector.addUserUuids(facets.getBucketKeys(PARAM_ASSIGNEES)); collector.addUserUuids(facets.getBucketKeys(PARAM_ASSIGNEES));
} }


private static void collectRequestParams(SearchResponseLoader.Collector collector, SearchRequest request) { private static void collectRequestParams(SearchResponseLoader.Collector collector, SearchRequest request) {
collector.addComponentUuids(request.getFileUuids());
collector.addComponentUuids(request.getModuleUuids()); collector.addComponentUuids(request.getModuleUuids());
collector.addUserUuids(request.getAssigneeUuids()); collector.addUserUuids(request.getAssigneeUuids());
} }
.setDirectories(request.paramAsStrings(PARAM_DIRECTORIES)) .setDirectories(request.paramAsStrings(PARAM_DIRECTORIES))
.setFacetMode(request.mandatoryParam(FACET_MODE)) .setFacetMode(request.mandatoryParam(FACET_MODE))
.setFacets(request.paramAsStrings(FACETS)) .setFacets(request.paramAsStrings(FACETS))
.setFileUuids(request.paramAsStrings(PARAM_FILE_UUIDS))
.setFiles(request.paramAsStrings(PARAM_FILES))
.setIssues(request.paramAsStrings(PARAM_ISSUES)) .setIssues(request.paramAsStrings(PARAM_ISSUES))
.setScopes(request.paramAsStrings(PARAM_SCOPES)) .setScopes(request.paramAsStrings(PARAM_SCOPES))
.setLanguages(request.paramAsStrings(PARAM_LANGUAGES)) .setLanguages(request.paramAsStrings(PARAM_LANGUAGES))

+ 5
- 6
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsTest.java View File

import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH; import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BRANCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;


private WsActionTester ws = new WsActionTester( private WsActionTester ws = new WsActionTester(
new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat, new SearchAction(userSession, issueIndex, issueQueryFactory, issueIndexSyncProgressChecker, searchResponseLoader, searchResponseFormat,
System2.INSTANCE, dbClient));
System2.INSTANCE, dbClient));


@Test @Test
public void search_all_issues_when_no_parameter() { public void search_all_issues_when_no_parameter() {


ws.newRequest() ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, project.getDbKey()) .setParam(PARAM_COMPONENT_KEYS, project.getDbKey())
.setParam(PARAM_FILE_UUIDS, file.uuid())
.setParam(PARAM_FILES, file.path())
.setParam(PARAM_SINCE_LEAK_PERIOD, "true") .setParam(PARAM_SINCE_LEAK_PERIOD, "true")
.execute() .execute()
.assertJson(this.getClass(), "search_since_leak_period.json"); .assertJson(this.getClass(), "search_since_leak_period.json");
indexIssues(); indexIssues();


ws.newRequest() ws.newRequest()
.setParam(PARAM_FILE_UUIDS, file.uuid())
.setParam(PARAM_FILES, file.path())
.execute() .execute()
.assertJson(this.getClass(), "search_by_file_uuid.json"); .assertJson(this.getClass(), "search_by_file_uuid.json");


ws.newRequest() ws.newRequest()
.setParam(PARAM_FILE_UUIDS, "unknown")
.setParam(PARAM_FILES, "unknown")
.execute() .execute()
.assertJson(this.getClass(), "no_issue.json"); .assertJson(this.getClass(), "no_issue.json");
} }
.executeProtobuf(SearchWsResponse.class).getIssuesList()) .executeProtobuf(SearchWsResponse.class).getIssuesList())
.extracting(Issue::getKey, Issue::getComponent, Issue::getBranch) .extracting(Issue::getKey, Issue::getComponent, Issue::getBranch)
.containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch())); .containsExactlyInAnyOrder(tuple(branchIssue.getKey(), branchFile.getKey(), branchFile.getBranch()));

// On file key + branch // On file key + branch
assertThat(ws.newRequest() assertThat(ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, branchFile.getKey()) .setParam(PARAM_COMPONENT_KEYS, branchFile.getKey())

+ 20
- 20
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionFacetsTest.java View File

import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT; import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ORGANIZATION; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ORGANIZATION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS; import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;


SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, project.getKey()) .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,fileUuids,assignees")
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,files,assignees")
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L)
tuple("languages", of(rule.getLanguage(), 1L)), tuple("languages", of(rule.getLanguage(), 1L)),
tuple("projects", of(project.getKey(), 1L)), tuple("projects", of(project.getKey(), 1L)),
tuple("moduleUuids", of(module.uuid(), 1L)), tuple("moduleUuids", of(module.uuid(), 1L)),
tuple("fileUuids", of(file.uuid(), 1L)),
tuple("files", of(file.path(), 1L)),
tuple("assignees", of("", 0L, user.getLogin(), 1L))); tuple("assignees", of("", 0L, user.getLogin(), 1L)));
} }




SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, project.getKey()) .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,fileUuids,assignees")
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,files,assignees")
.setParam("facetMode", FACET_MODE_EFFORT) .setParam("facetMode", FACET_MODE_EFFORT)
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


tuple("types", of("CODE_SMELL", 10L, "BUG", 0L, "VULNERABILITY", 0L)), tuple("types", of("CODE_SMELL", 10L, "BUG", 0L, "VULNERABILITY", 0L)),
tuple("languages", of(rule.getLanguage(), 10L)), tuple("languages", of(rule.getLanguage(), 10L)),
tuple("projects", of(project.getKey(), 10L)), tuple("projects", of(project.getKey(), 10L)),
tuple("fileUuids", of(file.uuid(), 10L)),
tuple("files", of(file.path(), 10L)),
tuple("assignees", of("", 10L))); tuple("assignees", of("", 10L)));
} }


} }


@Test @Test
public void display_fileUuids_facet_with_project() {
public void display_files_facet_with_project() {
OrganizationDto organization = db.organizations().insert(); OrganizationDto organization = db.organizations().insert();
ComponentDto project = db.components().insertPublicProject(organization); ComponentDto project = db.components().insertPublicProject(organization);
ComponentDto file1 = db.components().insertComponent(newFileDto(project)); ComponentDto file1 = db.components().insertComponent(newFileDto(project));


SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, project.getKey()) .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(PARAM_FILE_UUIDS, file1.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
.setParam(PARAM_FILES, file1.path())
.setParam(WebService.Param.FACETS, "files")
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


assertThat(response.getFacets().getFacetsList()) assertThat(response.getFacets().getFacetsList())
.extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount)))
.containsExactlyInAnyOrder(tuple("fileUuids", of(file1.uuid(), 1L, file2.uuid(), 1L)));
.containsExactlyInAnyOrder(tuple("files", of(file1.path(), 1L, file2.path(), 1L)));
} }


@Test @Test


SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_ORGANIZATION, organization.getKey()) .setParam(PARAM_ORGANIZATION, organization.getKey())
.setParam(PARAM_FILE_UUIDS, file1.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
.setParam(PARAM_FILES, file1.path())
.setParam(WebService.Param.FACETS, "files")
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


assertThat(response.getFacets().getFacetsList()) assertThat(response.getFacets().getFacetsList())
.extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount))) .extracting(Common.Facet::getProperty, facet -> facet.getValuesList().stream().collect(toMap(FacetValue::getVal, FacetValue::getCount)))
.containsExactlyInAnyOrder(tuple("fileUuids", of(file1.uuid(), 1L, file2.uuid(), 1L)));
.containsExactlyInAnyOrder(tuple("files", of(file1.path(), 1L, file2.path(), 1L)));
} }


@Test @Test
indexIssues(); indexIssues();


expectedException.expect(IllegalArgumentException.class); expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Facet(s) 'fileUuids' require to also filter by project or organization");
expectedException.expectMessage("Facet(s) 'files' require to also filter by project or organization");


ws.newRequest() ws.newRequest()
.setParam(PARAM_FILE_UUIDS, file.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
.setParam(PARAM_FILES, file.path())
.setParam(WebService.Param.FACETS, "files")
.execute(); .execute();
} }




SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_COMPONENT_KEYS, project.getKey()) .setParam(PARAM_COMPONENT_KEYS, project.getKey())
.setParam(FACETS, "fileUuids,directories,moduleUuids,statuses,resolutions,severities,types,rules,languages,assignees")
.setParam(FACETS, "files,directories,moduleUuids,statuses,resolutions,severities,types,rules,languages,assignees")
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


assertThat(response.getFacets().getFacetsList()) assertThat(response.getFacets().getFacetsList())
.extracting(Common.Facet::getProperty, Common.Facet::getValuesCount) .extracting(Common.Facet::getProperty, Common.Facet::getValuesCount)
.containsExactlyInAnyOrder( .containsExactlyInAnyOrder(
tuple("fileUuids", 100),
tuple("files", 100),
tuple("directories", 100), tuple("directories", 100),
tuple("moduleUuids", 100), tuple("moduleUuids", 100),
tuple("rules", 100), tuple("rules", 100),
SearchWsResponse response = ws.newRequest() SearchWsResponse response = ws.newRequest()
.setParam(PARAM_PROJECTS, project1.getKey() + "," + project2.getKey()) .setParam(PARAM_PROJECTS, project1.getKey() + "," + project2.getKey())
.setParam(PARAM_MODULE_UUIDS, module1.uuid() + "," + module2.uuid()) .setParam(PARAM_MODULE_UUIDS, module1.uuid() + "," + module2.uuid())
.setParam(PARAM_FILE_UUIDS, file1.uuid() + "," + file2.uuid())
.setParam(PARAM_FILES, file1.path() + "," + file2.path())
.setParam("rules", rule1.getKey().toString() + "," + rule2.getKey().toString()) .setParam("rules", rule1.getKey().toString() + "," + rule2.getKey().toString())
.setParam("severities", "MAJOR,MINOR") .setParam("severities", "MAJOR,MINOR")
.setParam("languages", rule1.getLanguage() + "," + rule2.getLanguage()) .setParam("languages", rule1.getLanguage() + "," + rule2.getLanguage())
.setParam("assignees", user1.getLogin() + "," + user2.getLogin()) .setParam("assignees", user1.getLogin() + "," + user2.getLogin())
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,fileUuids,assignees")
.setParam(FACETS, "severities,statuses,resolutions,rules,types,languages,projects,moduleUuids,files,assignees")
.executeProtobuf(SearchWsResponse.class); .executeProtobuf(SearchWsResponse.class);


Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L) Map<String, Number> expectedStatuses = ImmutableMap.<String, Number>builder().put("OPEN", 1L).put("CONFIRMED", 0L)
tuple("languages", of(rule1.getLanguage(), 1L, rule2.getLanguage(), 0L)), tuple("languages", of(rule1.getLanguage(), 1L, rule2.getLanguage(), 0L)),
tuple("projects", of(project1.getKey(), 1L, project2.getKey(), 0L)), tuple("projects", of(project1.getKey(), 1L, project2.getKey(), 0L)),
tuple("moduleUuids", of(module1.uuid(), 1L, module2.uuid(), 0L)), tuple("moduleUuids", of(module1.uuid(), 1L, module2.uuid(), 0L)),
tuple("fileUuids", of(file1.uuid(), 1L, file2.uuid(), 0L)),
tuple("files", of(file1.path(), 1L, file2.path(), 0L)),
tuple("assignees", of("", 0L, user1.getLogin(), 1L, user2.getLogin(), 0L))); tuple("assignees", of("", 0L, user1.getLogin(), 1L, user2.getLogin(), 0L)));
} }



+ 1
- 1
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java View File

assertThat(def.params()).extracting("key").containsExactlyInAnyOrder( assertThat(def.params()).extracting("key").containsExactlyInAnyOrder(
"additionalFields", "asc", "assigned", "assignees", "authors", "author", "componentKeys", "branch", "additionalFields", "asc", "assigned", "assignees", "authors", "author", "componentKeys", "branch",
"pullRequest", "organization", "pullRequest", "organization",
"createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facetMode", "facets", "fileUuids", "issues", "scopes", "languages", "moduleUuids",
"createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facetMode", "facets", "files", "issues", "scopes", "languages", "moduleUuids",
"onComponentOnly", "onComponentOnly",
"p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", "p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod",
"statuses", "tags", "types", "owaspTop10", "sansTop25", "cwe", "sonarsourceSecurity"); "statuses", "tags", "types", "owaspTop10", "sansTop25", "cwe", "sonarsourceSecurity");

+ 1
- 1
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java View File

public static final String PARAM_MODULE_UUIDS = "moduleUuids"; public static final String PARAM_MODULE_UUIDS = "moduleUuids";
public static final String PARAM_PROJECTS = "projects"; public static final String PARAM_PROJECTS = "projects";
public static final String PARAM_DIRECTORIES = "directories"; public static final String PARAM_DIRECTORIES = "directories";
public static final String PARAM_FILE_UUIDS = "fileUuids";
public static final String PARAM_FILES = "files";
public static final String PARAM_ON_COMPONENT_ONLY = "onComponentOnly"; public static final String PARAM_ON_COMPONENT_ONLY = "onComponentOnly";
public static final String PARAM_BRANCH = "branch"; public static final String PARAM_BRANCH = "branch";
public static final String PARAM_PULL_REQUEST = "pullRequest"; public static final String PARAM_PULL_REQUEST = "pullRequest";

Loading…
Cancel
Save