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; | ||||
} | } | ||||
.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"); |
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()); |
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; | ||||
} | } |
} | } | ||||
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)); |
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)); | ||||
} | } | ||||
@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 |
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( |
.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 |
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)) |
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()) |
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))); | ||||
} | } | ||||
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"); |
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"; |