- Use component(Uuid|Key)s to fix top level context of search - Use (project|module|directory|file)Uuids to refine/facettags/latest-silver-master-#65
import com.google.common.base.Function; | import com.google.common.base.Function; | ||||
import com.google.common.base.Joiner; | import com.google.common.base.Joiner; | ||||
import com.google.common.collect.Collections2; | import com.google.common.collect.Collections2; | ||||
import com.google.common.collect.Sets; | |||||
import org.apache.commons.collections.CollectionUtils; | import org.apache.commons.collections.CollectionUtils; | ||||
import org.sonar.api.ServerComponent; | import org.sonar.api.ServerComponent; | ||||
import org.sonar.api.i18n.I18n; | import org.sonar.api.i18n.I18n; | ||||
import javax.annotation.CheckForNull; | import javax.annotation.CheckForNull; | ||||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||
import java.util.Collection; | |||||
import java.util.Date; | |||||
import java.util.List; | |||||
import java.util.Locale; | |||||
import java.util.Map; | |||||
import java.util.*; | |||||
import static com.google.common.collect.Lists.newArrayList; | import static com.google.common.collect.Lists.newArrayList; | ||||
return componentUuids; | return componentUuids; | ||||
} | } | ||||
public Set<String> getDistinctQualifiers(DbSession session, @Nullable Collection<String> componentUuids) { | |||||
Set<String> componentQualifiers = Sets.newHashSet(); | |||||
if (componentUuids != null && !componentUuids.isEmpty()) { | |||||
List<ComponentDto> components = dbClient.componentDao().getByUuids(session, componentUuids); | |||||
for (ComponentDto component : components) { | |||||
componentQualifiers.add(component.qualifier()); | |||||
} | |||||
} | |||||
return componentQualifiers; | |||||
} | |||||
public Collection<ComponentDto> getByUuids(DbSession session, Collection<String> componentUuids) { | |||||
Set<ComponentDto> directoryPaths = Sets.newHashSet(); | |||||
if (componentUuids != null && !componentUuids.isEmpty()) { | |||||
List<ComponentDto> components = dbClient.componentDao().getByUuids(session, componentUuids); | |||||
for (ComponentDto component : components) { | |||||
directoryPaths.add(component); | |||||
} | |||||
} | |||||
return directoryPaths; | |||||
} | |||||
private void checkKeyFormat(String qualifier, String kee) { | private void checkKeyFormat(String qualifier, String kee) { | ||||
if (!ComponentKeys.isValidModuleKey(kee)) { | if (!ComponentKeys.isValidModuleKey(kee)) { | ||||
throw new BadRequestException(formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", | throw new BadRequestException(formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", | ||||
private ComponentDto getByKey(DbSession session, String key) { | private ComponentDto getByKey(DbSession session, String key) { | ||||
return dbClient.componentDao().getByKey(session, key); | return dbClient.componentDao().getByKey(session, key); | ||||
} | } | ||||
} | } |
private final Collection<String> resolutions; | private final Collection<String> resolutions; | ||||
private final Collection<String> components; | private final Collection<String> components; | ||||
private final Collection<String> modules; | private final Collection<String> modules; | ||||
private final Collection<String> moduleRoots; | |||||
private final Collection<String> projects; | private final Collection<String> projects; | ||||
private final Collection<String> directories; | private final Collection<String> directories; | ||||
private final Collection<String> files; | |||||
private final Collection<RuleKey> rules; | private final Collection<RuleKey> rules; | ||||
private final Collection<String> actionPlans; | private final Collection<String> actionPlans; | ||||
private final Collection<String> reporters; | private final Collection<String> reporters; | ||||
this.resolutions = defaultCollection(builder.resolutions); | this.resolutions = defaultCollection(builder.resolutions); | ||||
this.components = defaultCollection(builder.components); | this.components = defaultCollection(builder.components); | ||||
this.modules = defaultCollection(builder.modules); | this.modules = defaultCollection(builder.modules); | ||||
this.moduleRoots = defaultCollection(builder.moduleRoots); | |||||
this.projects = defaultCollection(builder.projects); | this.projects = defaultCollection(builder.projects); | ||||
this.directories = defaultCollection(builder.directories); | this.directories = defaultCollection(builder.directories); | ||||
this.files = defaultCollection(builder.files); | |||||
this.rules = defaultCollection(builder.rules); | this.rules = defaultCollection(builder.rules); | ||||
this.actionPlans = defaultCollection(builder.actionPlans); | this.actionPlans = defaultCollection(builder.actionPlans); | ||||
this.reporters = defaultCollection(builder.reporters); | this.reporters = defaultCollection(builder.reporters); | ||||
return modules; | return modules; | ||||
} | } | ||||
public Collection<String> moduleRootUuids() { | |||||
return moduleRoots; | |||||
} | |||||
public Collection<String> projectUuids() { | public Collection<String> projectUuids() { | ||||
return projects; | return projects; | ||||
} | } | ||||
return directories; | return directories; | ||||
} | } | ||||
public Collection<String> fileUuids() { | |||||
return files; | |||||
} | |||||
public Collection<RuleKey> rules() { | public Collection<RuleKey> rules() { | ||||
return rules; | return rules; | ||||
} | } | ||||
private Collection<String> resolutions; | private Collection<String> resolutions; | ||||
private Collection<String> components; | private Collection<String> components; | ||||
private Collection<String> modules; | private Collection<String> modules; | ||||
private Collection<String> moduleRoots; | |||||
private Collection<String> projects; | private Collection<String> projects; | ||||
private Collection<String> directories; | private Collection<String> directories; | ||||
private Collection<String> files; | |||||
private Collection<RuleKey> rules; | private Collection<RuleKey> rules; | ||||
private Collection<String> actionPlans; | private Collection<String> actionPlans; | ||||
private Collection<String> reporters; | private Collection<String> reporters; | ||||
return this; | return this; | ||||
} | } | ||||
public Builder moduleRootUuids(@Nullable Collection<String> l) { | |||||
this.moduleRoots = l; | |||||
return this; | |||||
} | |||||
public Builder projectUuids(@Nullable Collection<String> l) { | public Builder projectUuids(@Nullable Collection<String> l) { | ||||
this.projects = l; | this.projects = l; | ||||
return this; | return this; | ||||
return this; | return this; | ||||
} | } | ||||
public Builder fileUuids(@Nullable Collection<String> l) { | |||||
this.files = l; | |||||
return this; | |||||
} | |||||
public Builder rules(@Nullable Collection<RuleKey> rules) { | public Builder rules(@Nullable Collection<RuleKey> rules) { | ||||
this.rules = rules; | this.rules = rules; | ||||
return this; | return this; |
import com.google.common.annotations.VisibleForTesting; | import com.google.common.annotations.VisibleForTesting; | ||||
import com.google.common.base.Function; | import com.google.common.base.Function; | ||||
import com.google.common.base.Joiner; | |||||
import com.google.common.base.Splitter; | import com.google.common.base.Splitter; | ||||
import com.google.common.base.Strings; | import com.google.common.base.Strings; | ||||
import com.google.common.collect.Iterables; | import com.google.common.collect.Iterables; | ||||
import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||
import org.apache.commons.lang.ObjectUtils; | import org.apache.commons.lang.ObjectUtils; | ||||
import org.sonar.api.ServerComponent; | import org.sonar.api.ServerComponent; | ||||
import org.sonar.api.resources.Qualifiers; | |||||
import org.sonar.api.rule.RuleKey; | import org.sonar.api.rule.RuleKey; | ||||
import org.sonar.api.server.ws.Request; | import org.sonar.api.server.ws.Request; | ||||
import org.sonar.core.component.ComponentDto; | |||||
import org.sonar.core.persistence.DbSession; | import org.sonar.core.persistence.DbSession; | ||||
import org.sonar.server.component.ComponentService; | import org.sonar.server.component.ComponentService; | ||||
import org.sonar.server.db.DbClient; | import org.sonar.server.db.DbClient; | ||||
import org.sonar.server.issue.IssueQuery.Builder; | |||||
import org.sonar.server.issue.filter.IssueFilterParameters; | import org.sonar.server.issue.filter.IssueFilterParameters; | ||||
import org.sonar.server.search.ws.SearchRequestHandler; | import org.sonar.server.search.ws.SearchRequestHandler; | ||||
import org.sonar.server.util.RubyUtils; | import org.sonar.server.util.RubyUtils; | ||||
public IssueQuery createFromMap(Map<String, Object> params) { | public IssueQuery createFromMap(Map<String, Object> params) { | ||||
DbSession session = dbClient.openSession(false); | DbSession session = dbClient.openSession(false); | ||||
try { | try { | ||||
IssueQuery.Builder builder = IssueQuery.builder() | IssueQuery.Builder builder = IssueQuery.builder() | ||||
.issueKeys(RubyUtils.toStrings(params.get(IssueFilterParameters.ISSUES))) | .issueKeys(RubyUtils.toStrings(params.get(IssueFilterParameters.ISSUES))) | ||||
.severities(RubyUtils.toStrings(params.get(IssueFilterParameters.SEVERITIES))) | .severities(RubyUtils.toStrings(params.get(IssueFilterParameters.SEVERITIES))) | ||||
.onComponentOnly(RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY))) | .onComponentOnly(RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY))) | ||||
.assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED))) | .assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED))) | ||||
.planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED))) | .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED))) | ||||
.directories(RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES))) | |||||
.hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES))) | .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES))) | ||||
.createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT))) | .createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT))) | ||||
.createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER))) | .createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER))) | ||||
.createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE))); | .createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE))); | ||||
addProjectUuids(builder, session, | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.PROJECT_UUIDS)), | |||||
RubyUtils.toStrings( | |||||
ObjectUtils.defaultIfNull( | |||||
params.get(IssueFilterParameters.PROJECT_KEYS), | |||||
params.get(IssueFilterParameters.PROJECTS) | |||||
) | |||||
)); | |||||
addComponentUuids(builder, session, | addComponentUuids(builder, session, | ||||
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_UUIDS)), | RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_UUIDS)), | ||||
RubyUtils.toStrings( | RubyUtils.toStrings( | ||||
) | ) | ||||
), | ), | ||||
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOT_UUIDS)), | RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOT_UUIDS)), | ||||
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS))); | |||||
addModuleUuids(builder, session, | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS)), | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.PROJECT_UUIDS)), | |||||
RubyUtils.toStrings( | |||||
ObjectUtils.defaultIfNull( | |||||
params.get(IssueFilterParameters.PROJECT_KEYS), | |||||
params.get(IssueFilterParameters.PROJECTS) | |||||
) | |||||
), | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.MODULE_UUIDS)), | RubyUtils.toStrings(params.get(IssueFilterParameters.MODULE_UUIDS)), | ||||
RubyUtils.toStrings(params.get(IssueFilterParameters.MODULE_KEYS))); | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES)), | |||||
RubyUtils.toStrings(params.get(IssueFilterParameters.FILE_UUIDS))); | |||||
String sort = (String) params.get(IssueFilterParameters.SORT); | String sort = (String) params.get(IssueFilterParameters.SORT); | ||||
if (!Strings.isNullOrEmpty(sort)) { | if (!Strings.isNullOrEmpty(sort)) { | ||||
builder.sort(sort); | builder.sort(sort); | ||||
.onComponentOnly(request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY)) | .onComponentOnly(request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY)) | ||||
.assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED)) | .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED)) | ||||
.planned(request.paramAsBoolean(IssueFilterParameters.PLANNED)) | .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED)) | ||||
.directories(request.paramAsStrings(IssueFilterParameters.DIRECTORIES)) | |||||
.createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) | .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) | ||||
.createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) | .createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) | ||||
.createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)) | .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)) | ||||
.ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING)); | .ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING)); | ||||
addProjectUuids(builder, session, | |||||
request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS), request.paramAsStrings(IssueFilterParameters.PROJECT_KEYS)); | |||||
addComponentUuids(builder, session, | addComponentUuids(builder, session, | ||||
request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_KEYS), | request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_KEYS), | ||||
request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS)); | |||||
addModuleUuids(builder, session, | |||||
request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS), request.paramAsStrings(IssueFilterParameters.MODULE_KEYS)); | |||||
request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS), request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS), | |||||
request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS), request.paramAsStrings(IssueFilterParameters.PROJECT_KEYS), | |||||
request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS), | |||||
request.paramAsStrings(IssueFilterParameters.DIRECTORIES), | |||||
request.paramAsStrings(IssueFilterParameters.FILE_UUIDS)); | |||||
String sort = request.param(SearchRequestHandler.PARAM_SORT); | String sort = request.param(SearchRequestHandler.PARAM_SORT); | ||||
if (!Strings.isNullOrEmpty(sort)) { | if (!Strings.isNullOrEmpty(sort)) { | ||||
builder.sort(sort); | builder.sort(sort); | ||||
} | } | ||||
} | } | ||||
private void addProjectUuids(IssueQuery.Builder builder, DbSession session, @Nullable Collection<String> projectUuids, @Nullable Collection<String> projects) { | |||||
if (projectUuids != null) { | |||||
if (projects != null) { | |||||
throw new IllegalArgumentException("projects and projectUuids cannot be set simultaneously"); | |||||
} | |||||
builder.projectUuids(projectUuids); | |||||
} else { | |||||
builder.projectUuids(componentUuids(session, projects)); | |||||
} | |||||
} | |||||
private void addComponentUuids(IssueQuery.Builder builder, DbSession session, | private void addComponentUuids(IssueQuery.Builder builder, DbSession session, | ||||
@Nullable Collection<String> componentUuids, @Nullable Collection<String> components, | @Nullable Collection<String> componentUuids, @Nullable Collection<String> components, | ||||
/* | /* | ||||
* but "componentKeys" parameter already deprecates "components" parameter, | * but "componentKeys" parameter already deprecates "components" parameter, | ||||
* so queries specifying "componentRoots" must be handled manually | * so queries specifying "componentRoots" must be handled manually | ||||
*/ | */ | ||||
@Nullable Collection<String> componentRootUuids, @Nullable Collection<String> componentRoots) { | |||||
@Nullable Collection<String> componentRootUuids, @Nullable Collection<String> componentRoots, | |||||
@Nullable Collection<String> projectUuids, @Nullable Collection<String> projects, | |||||
@Nullable Collection<String> moduleUuids, | |||||
@Nullable Collection<String> directories, | |||||
@Nullable Collection<String> fileUuids) { | |||||
Set<String> allComponentUuids = Sets.newHashSet(); | |||||
if (componentUuids != null || componentRootUuids != null) { | if (componentUuids != null || componentRootUuids != null) { | ||||
if (components != null || componentRoots != null) { | if (components != null || componentRoots != null) { | ||||
throw new IllegalArgumentException("components and componentUuids cannot be set simultaneously"); | throw new IllegalArgumentException("components and componentUuids cannot be set simultaneously"); | ||||
} | } | ||||
Set<String> allComponentUuids = Sets.newHashSet(); | |||||
allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentUuids, Sets.newHashSet())); | allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentUuids, Sets.newHashSet())); | ||||
allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRootUuids, Sets.newHashSet())); | allComponentUuids.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRootUuids, Sets.newHashSet())); | ||||
builder.componentUuids(allComponentUuids); | |||||
} else { | } else { | ||||
Set<String> allComponents = Sets.newHashSet(); | Set<String> allComponents = Sets.newHashSet(); | ||||
allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(components, Sets.newHashSet())); | allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(components, Sets.newHashSet())); | ||||
allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRoots, Sets.newHashSet())); | allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(componentRoots, Sets.newHashSet())); | ||||
builder.componentUuids(componentUuids(session, allComponents)); | |||||
allComponentUuids.addAll(componentUuids(session, allComponents)); | |||||
} | |||||
if (allComponentUuids.isEmpty()) { | |||||
addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids); | |||||
} else { | |||||
Set<String> qualifiers = componentService.getDistinctQualifiers(session, allComponentUuids); | |||||
if (qualifiers.isEmpty()) { | |||||
// Qualifier not found, defaulting to componentUuids (e.g <UNKNOWN>) | |||||
builder.componentUuids(allComponentUuids); | |||||
return; | |||||
} | |||||
if (qualifiers.size() > 1) { | |||||
throw new IllegalArgumentException("All components must have the same qualifier, found " + Joiner.on(',').join(qualifiers)); | |||||
} | |||||
String uniqueQualifier = qualifiers.iterator().next(); | |||||
if (Qualifiers.VIEW.equals(uniqueQualifier)) { | |||||
// TODO Handle views | |||||
addComponentsBelowView(builder, session, projects, projectUuids, moduleUuids, directories, fileUuids); | |||||
} else if ("DEV".equals(uniqueQualifier)) { // XXX No constant !!! | |||||
// TODO Get SCM accounts from dev, then search by author | |||||
// TODO addComponentsBelowView(projects, projectUuids, moduleUuids, directories, fileUuids); | |||||
} else if (Qualifiers.PROJECT.equals(uniqueQualifier)) { | |||||
builder.projectUuids(allComponentUuids); | |||||
addComponentsBelowModule(builder, moduleUuids, directories, fileUuids); | |||||
} else if (Qualifiers.MODULE.equals(uniqueQualifier)) { | |||||
builder.moduleRootUuids(allComponentUuids); | |||||
addComponentsBelowModule(builder, moduleUuids, directories, fileUuids); | |||||
} else if (Qualifiers.DIRECTORY.equals(uniqueQualifier)) { | |||||
Collection<String> directoryModuleUuids = Sets.newHashSet(); | |||||
Collection<String> directoryPaths = Sets.newHashSet(); | |||||
for (ComponentDto directory : componentService.getByUuids(session, allComponentUuids)) { | |||||
directoryModuleUuids.add(directory.moduleUuid()); | |||||
directoryPaths.add(directory.path()); | |||||
} | |||||
builder.moduleUuids(directoryModuleUuids); | |||||
builder.directories(directoryPaths); | |||||
addComponentsBelowDirectory(builder, fileUuids); | |||||
} else if (Qualifiers.FILE.equals(uniqueQualifier)) { | |||||
builder.fileUuids(allComponentUuids); | |||||
} else { | |||||
throw new IllegalArgumentException("Unable to set search root context for components " + Joiner.on(',').join(allComponentUuids)); | |||||
} | |||||
} | } | ||||
} | } | ||||
private void addModuleUuids(IssueQuery.Builder builder, DbSession session, @Nullable Collection<String> componentRootUuids, @Nullable Collection<String> componentRoots) { | |||||
if (componentRootUuids != null) { | |||||
if (componentRoots != null) { | |||||
throw new IllegalArgumentException("componentRoots and componentRootUuids cannot be set simultaneously"); | |||||
private void addComponentsBelowView(Builder builder, DbSession session, | |||||
@Nullable Collection<String> projects, @Nullable Collection<String> projectUuids, | |||||
@Nullable Collection<String> moduleUuids, Collection<String> directories, Collection<String> fileUuids) { | |||||
if (projectUuids != null) { | |||||
if (projects != null) { | |||||
throw new IllegalArgumentException("projects and projectUuids cannot be set simultaneously"); | |||||
} | } | ||||
builder.moduleUuids(componentRootUuids); | |||||
builder.projectUuids(projectUuids); | |||||
} else { | } else { | ||||
builder.moduleUuids(componentUuids(session, componentRoots)); | |||||
builder.projectUuids(componentUuids(session, projects)); | |||||
} | } | ||||
addComponentsBelowModule(builder, moduleUuids, directories, fileUuids); | |||||
} | |||||
private void addComponentsBelowModule(Builder builder, | |||||
@Nullable Collection<String> moduleUuids, @Nullable Collection<String> directories, @Nullable Collection<String> fileUuids) { | |||||
builder.moduleUuids(moduleUuids); | |||||
addComponentsBelowModule(builder, directories, fileUuids); | |||||
} | |||||
private void addComponentsBelowModule(Builder builder, | |||||
@Nullable Collection<String> directories, @Nullable Collection<String> fileUuids) { | |||||
builder.directories(directories); | |||||
addComponentsBelowDirectory(builder, fileUuids); | |||||
} | |||||
private void addComponentsBelowDirectory(Builder builder, | |||||
@Nullable Collection<String> fileUuids) { | |||||
builder.fileUuids(fileUuids); | |||||
} | } | ||||
private Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys) { | private Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys) { |
public static final String COMPONENT_UUIDS = "componentUuids"; | public static final String COMPONENT_UUIDS = "componentUuids"; | ||||
public static final String COMPONENT_ROOTS = "componentRoots"; | public static final String COMPONENT_ROOTS = "componentRoots"; | ||||
public static final String COMPONENT_ROOT_UUIDS = "componentRootUuids"; | public static final String COMPONENT_ROOT_UUIDS = "componentRootUuids"; | ||||
public static final String MODULE_KEYS = "moduleKeys"; | |||||
public static final String MODULE_UUIDS = "moduleUuids"; | public static final String MODULE_UUIDS = "moduleUuids"; | ||||
public static final String PROJECTS = "projects"; | public static final String PROJECTS = "projects"; | ||||
public static final String PROJECT_KEYS = "projectKeys"; | public static final String PROJECT_KEYS = "projectKeys"; | ||||
public static final String PROJECT_UUIDS = "projectUuids"; | public static final String PROJECT_UUIDS = "projectUuids"; | ||||
public static final String DIRECTORIES = "directories"; | public static final String DIRECTORIES = "directories"; | ||||
public static final String FILE_UUIDS = "fileUuids"; | |||||
public static final String ON_COMPONENT_ONLY = "onComponentOnly"; | public static final String ON_COMPONENT_ONLY = "onComponentOnly"; | ||||
public static final String RULES = "rules"; | public static final String RULES = "rules"; | ||||
public static final String ACTION_PLANS = "actionPlans"; | public static final String ACTION_PLANS = "actionPlans"; | ||||
public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS, TAGS, | public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS, TAGS, | ||||
ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC, COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS, | ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC, COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS, | ||||
PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_KEYS, MODULE_UUIDS, DIRECTORIES); | |||||
PROJECTS, PROJECT_UUIDS, IGNORE_PAGING, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS); | |||||
public static final List<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() { | public static final List<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() { | ||||
@Override | @Override |
import com.google.common.collect.Collections2; | import com.google.common.collect.Collections2; | ||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import com.google.common.collect.Maps; | import com.google.common.collect.Maps; | ||||
import com.google.common.collect.Sets; | |||||
import org.apache.commons.lang.BooleanUtils; | import org.apache.commons.lang.BooleanUtils; | ||||
import org.elasticsearch.action.search.SearchRequestBuilder; | import org.elasticsearch.action.search.SearchRequestBuilder; | ||||
import org.elasticsearch.action.search.SearchResponse; | import org.elasticsearch.action.search.SearchResponse; | ||||
} | } | ||||
private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) { | private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) { | ||||
Collection<String> componentUuids = query.componentUuids(); | |||||
if (BooleanUtils.isTrue(query.onComponentOnly())) { | |||||
Set<String> allComponents = Sets.newHashSet(); | |||||
allComponents.addAll(query.projectUuids()); | |||||
allComponents.addAll(query.moduleUuids()); | |||||
allComponents.addAll(componentUuids); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, allComponents)); | |||||
} else { | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids())); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids())); | |||||
FilterBuilder compositeFilter = componentFilter(componentUuids); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, compositeFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories())); | |||||
FilterBuilder projectFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids()); | |||||
FilterBuilder moduleRootFilter = moduleRootFilter(query.moduleRootUuids()); | |||||
FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids()); | |||||
FilterBuilder directoryRootFilter = directoryFilter(query.moduleUuids(), query.directories()); | |||||
FilterBuilder directoryFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories()); | |||||
FilterBuilder fileFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids()); | |||||
FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids()); | |||||
if (projectFilter != null) { | |||||
filters.put("__componentRoot", projectFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter); | |||||
} else if (moduleRootFilter != null) { | |||||
filters.put("__componentRoot", moduleRootFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter); | |||||
} else if (directoryRootFilter != null) { | |||||
filters.put("__componentRoot", directoryRootFilter); | |||||
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter); | |||||
} else if (fileFilter != null) { | |||||
filters.put("__componentRoot", fileFilter); | |||||
} else if (componentFilter != null) { | |||||
// Last resort, when component type is unknown | |||||
filters.put("__componentRoot", componentFilter); | |||||
} | } | ||||
} | } | ||||
private FilterBuilder componentFilter(Collection<String> componentUuids) { | |||||
private FilterBuilder moduleRootFilter(Collection<String> componentUuids) { | |||||
if (componentUuids == null || componentUuids.isEmpty()) { | |||||
return null; | |||||
} | |||||
FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentUuids); | FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentUuids); | ||||
FilterBuilder modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, componentUuids); | FilterBuilder modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, componentUuids); | ||||
FilterBuilder compositeFilter = null; | FilterBuilder compositeFilter = null; | ||||
return compositeFilter; | return compositeFilter; | ||||
} | } | ||||
private FilterBuilder directoryFilter(Collection<String> moduleUuids, Collection<String> directoryPaths) { | |||||
BoolFilterBuilder directoryTop = null; | |||||
FilterBuilder moduleFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleUuids); | |||||
FilterBuilder directoryFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryPaths); | |||||
if (moduleFilter != null) { | |||||
directoryTop = FilterBuilders.boolFilter(); | |||||
directoryTop.must(moduleFilter); | |||||
} | |||||
if (directoryFilter != null) { | |||||
if (directoryTop == null) { | |||||
directoryTop = FilterBuilders.boolFilter(); | |||||
} | |||||
directoryTop.must(directoryFilter); | |||||
} | |||||
return directoryTop; | |||||
} | |||||
private FilterBuilder getAuthorizationFilter(QueryContext options) { | private FilterBuilder getAuthorizationFilter(QueryContext options) { | ||||
String user = options.getUserLogin(); | String user = options.getUserLogin(); | ||||
Set<String> groups = options.getUserGroups(); | Set<String> groups = options.getUserGroups(); | ||||
IssueFilterParameters.SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY, Severity.ALL.toArray()); | IssueFilterParameters.SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY, Severity.ALL.toArray()); | ||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | ||||
IssueFilterParameters.STATUSES, IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUSES.toArray()); | IssueFilterParameters.STATUSES, IssueIndexDefinition.FIELD_ISSUE_STATUS, Issue.STATUSES.toArray()); | ||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | |||||
IssueFilterParameters.COMPONENT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids().toArray()); | |||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | ||||
IssueFilterParameters.PROJECT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids().toArray()); | IssueFilterParameters.PROJECT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids().toArray()); | ||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | |||||
IssueFilterParameters.MODULE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids().toArray()); | |||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | ||||
IssueFilterParameters.DIRECTORIES, IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories().toArray()); | IssueFilterParameters.DIRECTORIES, IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories().toArray()); | ||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | |||||
IssueFilterParameters.FILE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids().toArray()); | |||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | ||||
IssueFilterParameters.LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray()); | IssueFilterParameters.LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray()); | ||||
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch, | ||||
FilterBuilders.boolFilter() | FilterBuilders.boolFilter() | ||||
.must(getAuthorizationFilter(new QueryContext())) | .must(getAuthorizationFilter(new QueryContext())) | ||||
.must(FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION)) | .must(FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION)) | ||||
.must(componentFilter(Arrays.asList(componentUuid))))); | |||||
.must(moduleRootFilter(Arrays.asList(componentUuid))))); | |||||
TermsBuilder aggreg = AggregationBuilders.terms("_ref") | TermsBuilder aggreg = AggregationBuilders.terms("_ref") | ||||
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS) | .field(IssueIndexDefinition.FIELD_ISSUE_TAGS) | ||||
.size(pageSize) | .size(pageSize) |
.setDescription("Deprecated since 5.1. Use componentKeys instead, with onComponentOnly=false."); | .setDescription("Deprecated since 5.1. Use componentKeys instead, with onComponentOnly=false."); | ||||
action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS) | action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS) | ||||
.setDescription("Deprecated since 5.1. Use componentUuids instead, with onComponentOnly=false."); | .setDescription("Deprecated since 5.1. Use componentUuids instead, with onComponentOnly=false."); | ||||
action.createParam(IssueFilterParameters.MODULE_KEYS) | |||||
.setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module keys). " + | |||||
INTERNAL_PARAMETER_DISCLAIMER + | |||||
"Views are not supported. If this parameter is set, moduleUuids must not be set.") | |||||
.setExampleValue("org.apache.struts:struts"); | |||||
action.createParam(IssueFilterParameters.MODULE_UUIDS) | action.createParam(IssueFilterParameters.MODULE_UUIDS) | ||||
.setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module UUIDs). " + | .setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module UUIDs). " + | ||||
INTERNAL_PARAMETER_DISCLAIMER + | INTERNAL_PARAMETER_DISCLAIMER + | ||||
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92"); | .setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92"); | ||||
action.createParam(IssueFilterParameters.DIRECTORIES) | action.createParam(IssueFilterParameters.DIRECTORIES) | ||||
.setDescription("Since 5.1. To retrieve issues associated to a specific list of directories (comma-separated list of directory paths). ") | |||||
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92"); | |||||
.setDescription("Since 5.1. To retrieve issues associated to a specific list of directories (comma-separated list of directory paths). " + | |||||
"This parameter is only meaningful when a module is selected. " + | |||||
INTERNAL_PARAMETER_DISCLAIMER) | |||||
.setExampleValue("src/main/java/org/sonar/server/"); | |||||
action.createParam(IssueFilterParameters.FILE_UUIDS) | |||||
.setDescription("To retrieve issues associated to a specific list of files (comma-separated list of file UUIDs). " + | |||||
INTERNAL_PARAMETER_DISCLAIMER) | |||||
.setExampleValue("bdd82933-3070-4903-9188-7d8749e8bb92"); | |||||
action.createParam(IssueFilterParameters.ON_COMPONENT_ONLY) | action.createParam(IssueFilterParameters.ON_COMPONENT_ONLY) | ||||
.setDescription("Return only issues at the component's level, not on its descendants (modules, directories, files, etc.)") | .setDescription("Return only issues at the component's level, not on its descendants (modules, directories, files, etc.)") | ||||
@Override | @Override | ||||
protected Result<Issue> doSearch(IssueQuery query, QueryContext context) { | protected Result<Issue> doSearch(IssueQuery query, QueryContext context) { | ||||
Collection<String> components = query.componentUuids(); | |||||
Collection<String> components = query.fileUuids(); | |||||
if (components != null && components.size() == 1 && BooleanUtils.isTrue(query.ignorePaging())) { | if (components != null && components.size() == 1 && BooleanUtils.isTrue(query.ignorePaging())) { | ||||
context.setShowFullResult(true); | context.setShowFullResult(true); | ||||
} | } | ||||
IssueFilterParameters.RULES, | IssueFilterParameters.RULES, | ||||
IssueFilterParameters.ASSIGNEES, | IssueFilterParameters.ASSIGNEES, | ||||
IssueFilterParameters.REPORTERS, | IssueFilterParameters.REPORTERS, | ||||
IssueFilterParameters.COMPONENT_UUIDS, | |||||
IssueFilterParameters.MODULE_UUIDS, | |||||
IssueFilterParameters.FILE_UUIDS, | |||||
IssueFilterParameters.DIRECTORIES, | IssueFilterParameters.DIRECTORIES, | ||||
IssueFilterParameters.LANGUAGES, | IssueFilterParameters.LANGUAGES, | ||||
IssueFilterParameters.TAGS, | IssueFilterParameters.TAGS, |
package org.sonar.server.issue; | package org.sonar.server.issue; | ||||
import com.google.common.collect.Sets; | |||||
import org.junit.Before; | import org.junit.Before; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.runner.RunWith; | import org.junit.runner.RunWith; | ||||
import org.mockito.invocation.InvocationOnMock; | import org.mockito.invocation.InvocationOnMock; | ||||
import org.mockito.runners.MockitoJUnitRunner; | import org.mockito.runners.MockitoJUnitRunner; | ||||
import org.mockito.stubbing.Answer; | import org.mockito.stubbing.Answer; | ||||
import org.sonar.api.resources.Qualifiers; | |||||
import org.sonar.api.rule.RuleKey; | import org.sonar.api.rule.RuleKey; | ||||
import org.sonar.api.utils.DateUtils; | import org.sonar.api.utils.DateUtils; | ||||
import org.sonar.core.persistence.DbSession; | import org.sonar.core.persistence.DbSession; | ||||
map.put("resolved", true); | map.put("resolved", true); | ||||
ArrayList<String> componentKeys = newArrayList("org.apache"); | ArrayList<String> componentKeys = newArrayList("org.apache"); | ||||
map.put("components", componentKeys); | map.put("components", componentKeys); | ||||
ArrayList<String> moduleKeys = newArrayList("org.sonar"); | |||||
map.put("moduleKeys", moduleKeys); | |||||
ArrayList<String> moduleUuids = newArrayList("BCDE"); | |||||
map.put("moduleUuids", moduleUuids); | |||||
map.put("directories", newArrayList("/src/main/java/example")); | map.put("directories", newArrayList("/src/main/java/example")); | ||||
ArrayList<String> fileUuids = newArrayList("CDEF"); | |||||
map.put("fileUuids", fileUuids); | |||||
map.put("reporters", newArrayList("marilyn")); | map.put("reporters", newArrayList("marilyn")); | ||||
map.put("assignees", newArrayList("joanna")); | map.put("assignees", newArrayList("joanna")); | ||||
map.put("languages", newArrayList("xoo")); | map.put("languages", newArrayList("xoo")); | ||||
} | } | ||||
if (components.contains("org.apache")) { | if (components.contains("org.apache")) { | ||||
return newArrayList("ABCD"); | return newArrayList("ABCD"); | ||||
} else if (components.contains("org.sonar")) { | |||||
return newArrayList("BCDE"); | |||||
} | } | ||||
return newArrayList(); | return newArrayList(); | ||||
} | } | ||||
}); | }); | ||||
when(componentService.getDistinctQualifiers(eq(session), Matchers.anyCollection())).thenReturn(Sets.newHashSet(Qualifiers.PROJECT)); | |||||
IssueQuery query = issueQueryService.createFromMap(map); | IssueQuery query = issueQueryService.createFromMap(map); | ||||
assertThat(query.issueKeys()).containsOnly("ABCDE1234"); | assertThat(query.issueKeys()).containsOnly("ABCDE1234"); | ||||
assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); | assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); | ||||
assertThat(query.statuses()).containsOnly("CLOSED"); | assertThat(query.statuses()).containsOnly("CLOSED"); | ||||
assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); | assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); | ||||
assertThat(query.resolved()).isTrue(); | assertThat(query.resolved()).isTrue(); | ||||
assertThat(query.componentUuids()).containsOnly("ABCD"); | |||||
assertThat(query.projectUuids()).containsOnly("ABCD"); | |||||
assertThat(query.moduleUuids()).containsOnly("BCDE"); | assertThat(query.moduleUuids()).containsOnly("BCDE"); | ||||
assertThat(query.fileUuids()).containsOnly("CDEF"); | |||||
assertThat(query.reporters()).containsOnly("marilyn"); | assertThat(query.reporters()).containsOnly("marilyn"); | ||||
assertThat(query.assignees()).containsOnly("joanna"); | assertThat(query.assignees()).containsOnly("joanna"); | ||||
assertThat(query.languages()).containsOnly("xoo"); | assertThat(query.languages()).containsOnly("xoo"); |
IssueTesting.newDoc("ISSUE6", ComponentTesting.newFileDto(subModule))); | IssueTesting.newDoc("ISSUE6", ComponentTesting.newFileDto(subModule))); | ||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6); | assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6); | ||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | ||||
} | } | ||||
IssueTesting.newDoc("ISSUE5", subModule), | IssueTesting.newDoc("ISSUE5", subModule), | ||||
IssueTesting.newDoc("ISSUE2", file)); | IssueTesting.newDoc("ISSUE2", file)); | ||||
assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(file.uuid())).build(), new QueryContext()).getHits()).isEmpty(); | |||||
assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().moduleUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())) | |||||
.moduleUuids(newArrayList(file.uuid())).build(), new QueryContext()).getHits()).isEmpty(); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())) | |||||
.moduleUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())) | |||||
.moduleUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())) | |||||
.moduleUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())) | |||||
.moduleUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | |||||
} | } | ||||
@Test | @Test | ||||
IssueTesting.newDoc("ISSUE5", subModule), | IssueTesting.newDoc("ISSUE5", subModule), | ||||
IssueTesting.newDoc("ISSUE6", file3)); | IssueTesting.newDoc("ISSUE6", file3)); | ||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new QueryContext()).getHits()).hasSize(3); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(2); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(subModule.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(4); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(module.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList(project.uuid())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().componentUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | |||||
assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid(), file2.uuid(), file3.uuid())).build(), new QueryContext()).getHits()).hasSize(3); | |||||
assertThat(index.search(IssueQuery.builder().fileUuids(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1); | |||||
assertThat(index.search(IssueQuery.builder().moduleRootUuids(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(2); | |||||
assertThat(index.search(IssueQuery.builder().moduleRootUuids(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(4); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(6); | |||||
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); | |||||
} | } | ||||
@Test | @Test | ||||
IssueTesting.newDoc("ISSUE4", file2), | IssueTesting.newDoc("ISSUE4", file2), | ||||
IssueTesting.newDoc("ISSUE5", file3)); | IssueTesting.newDoc("ISSUE5", file3)); | ||||
Result<Issue> result = index.search(IssueQuery.builder().build(), new QueryContext().addFacets(newArrayList("componentUuids"))); | |||||
assertThat(result.getFacets()).containsOnlyKeys("componentUuids"); | |||||
assertThat(result.getFacets().get("componentUuids")).containsOnly(new FacetValue("A", 1), new FacetValue("ABCD", 1), new FacetValue("BCDE", 2), new FacetValue("CDEF", 1)); | |||||
Result<Issue> result = index.search(IssueQuery.builder().build(), new QueryContext().addFacets(newArrayList("fileUuids"))); | |||||
assertThat(result.getFacets()).containsOnlyKeys("fileUuids"); | |||||
assertThat(result.getFacets().get("fileUuids")).containsOnly(new FacetValue("A", 1), new FacetValue("ABCD", 1), new FacetValue("BCDE", 2), new FacetValue("CDEF", 1)); | |||||
} | } | ||||
@Test | @Test | ||||
indexIssue(IssueTesting.newDoc("ISSUE1", file1), "sonar-users", null); | indexIssue(IssueTesting.newDoc("ISSUE1", file1), "sonar-users", null); | ||||
// project2 can be seen by sonar-admins | // project2 can be seen by sonar-admins | ||||
indexIssue(IssueTesting.newDoc("ISSUE2", file2), "sonar-admins", null); | indexIssue(IssueTesting.newDoc("ISSUE2", file2), "sonar-admins", null); | ||||
// project3 cannot be seen by anyone | |||||
// project3 can be seen by nobody | |||||
indexIssue(IssueTesting.newDoc("ISSUE3", file3), null, null); | indexIssue(IssueTesting.newDoc("ISSUE3", file3), null, null); | ||||
IssueQuery.Builder query = IssueQuery.builder(); | IssueQuery.Builder query = IssueQuery.builder(); | ||||
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(2); | assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(2); | ||||
MockUserSession.set().setUserGroups("another group"); | MockUserSession.set().setUserGroups("another group"); | ||||
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0); | |||||
assertThat(index.search(query.build(), new QueryContext()).getHits()).isEmpty(); | |||||
MockUserSession.set().setUserGroups("sonar-users", "sonar-admins"); | MockUserSession.set().setUserGroups("sonar-users", "sonar-admins"); | ||||
assertThat(index.search(query.moduleUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0); | |||||
assertThat(index.search(query.projectUuids(newArrayList(project3.uuid())).build(), new QueryContext()).getHits()).isEmpty(); | |||||
} | } | ||||
@Test | @Test | ||||
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0); | assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0); | ||||
MockUserSession.set().setLogin("john"); | MockUserSession.set().setLogin("john"); | ||||
assertThat(index.search(query.moduleUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0); | |||||
assertThat(index.search(query.projectUuids(newArrayList(project3.key())).build(), new QueryContext()).getHits()).hasSize(0); | |||||
} | } | ||||
@Test | @Test |
/* | |||||
* SonarQube, open source software quality management tool. | |||||
* Copyright (C) 2008-2014 SonarSource | |||||
* mailto:contact AT sonarsource DOT com | |||||
* | |||||
* SonarQube is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public | |||||
* License as published by the Free Software Foundation; either | |||||
* version 3 of the License, or (at your option) any later version. | |||||
* | |||||
* SonarQube is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
* Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public License | |||||
* along with this program; if not, write to the Free Software Foundation, | |||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||||
*/ | |||||
package org.sonar.server.issue.ws; | |||||
import org.junit.After; | |||||
import org.junit.Before; | |||||
import org.junit.ClassRule; | |||||
import org.junit.Test; | |||||
import org.sonar.api.rule.RuleStatus; | |||||
import org.sonar.api.security.DefaultGroups; | |||||
import org.sonar.api.utils.DateUtils; | |||||
import org.sonar.api.web.UserRole; | |||||
import org.sonar.core.component.ComponentDto; | |||||
import org.sonar.core.issue.db.IssueDto; | |||||
import org.sonar.core.permission.GlobalPermissions; | |||||
import org.sonar.core.persistence.DbSession; | |||||
import org.sonar.core.rule.RuleDto; | |||||
import org.sonar.server.component.ComponentTesting; | |||||
import org.sonar.server.db.DbClient; | |||||
import org.sonar.server.issue.IssueTesting; | |||||
import org.sonar.server.issue.filter.IssueFilterParameters; | |||||
import org.sonar.server.issue.index.IssueIndexer; | |||||
import org.sonar.server.permission.InternalPermissionService; | |||||
import org.sonar.server.permission.PermissionChange; | |||||
import org.sonar.server.rule.RuleTesting; | |||||
import org.sonar.server.rule.db.RuleDao; | |||||
import org.sonar.server.tester.ServerTester; | |||||
import org.sonar.server.user.MockUserSession; | |||||
import org.sonar.server.ws.WsTester; | |||||
public class SearchActionComponentsMediumTest { | |||||
@ClassRule | |||||
public static ServerTester tester = new ServerTester(); | |||||
DbClient db; | |||||
DbSession session; | |||||
WsTester wsTester; | |||||
@Before | |||||
public void setUp() throws Exception { | |||||
tester.clearDbAndIndexes(); | |||||
db = tester.get(DbClient.class); | |||||
wsTester = tester.get(WsTester.class); | |||||
session = db.openSession(false); | |||||
} | |||||
@After | |||||
public void after() { | |||||
session.close(); | |||||
} | |||||
@Test | |||||
public void issues_on_different_projects() throws Exception { | |||||
RuleDto rule = newRule(); | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(rule, file, project) | |||||
.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") | |||||
.setStatus("OPEN").setResolution("OPEN") | |||||
.setSeverity("MAJOR") | |||||
.setIssueCreationDate(DateUtils.parseDate("2014-09-04")) | |||||
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04")); | |||||
db.issueDao().insert(session, issue); | |||||
ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("DBCA").setKey("MyProject2")); | |||||
setDefaultProjectPermission(project2); | |||||
ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "EDCB").setKey("MyComponent2")); | |||||
IssueDto issue2 = IssueTesting.newDto(rule, file2, project2) | |||||
.setKee("92fd47d4-b650-4037-80bc-7b112bd4eac2") | |||||
.setStatus("OPEN").setResolution("OPEN") | |||||
.setSeverity("MAJOR") | |||||
.setIssueCreationDate(DateUtils.parseDate("2014-09-04")) | |||||
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04")); | |||||
db.issueDao().insert(session, issue2); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute(); | |||||
result.assertJson(this.getClass(), "issues_on_different_projects.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_project_uuid() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_project_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.PROJECT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, project.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_project_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_file_uuid() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.FILE_UUIDS, file.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.FILE_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_directory_path() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir")); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir") | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_directory_path_in_different_modules() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto module1 = insertComponent(ComponentTesting.newModuleDto(project).setKey("module1")); | |||||
ComponentDto module2 = insertComponent(ComponentTesting.newModuleDto(project).setKey("module2")); | |||||
ComponentDto directory1 = insertComponent(ComponentTesting.newDirectory(module1, "src/main/java/dir")); | |||||
ComponentDto directory2 = insertComponent(ComponentTesting.newDirectory(module2, "src/main/java/dir")); | |||||
ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(module1, "BCDE").setKey("module1:MyComponent").setPath(directory1.path() + "/MyComponent.java")); | |||||
insertComponent(ComponentTesting.newFileDto(module2, "CDEF").setKey("module2:MyComponent").setPath(directory2.path() + "/MyComponent.java")); | |||||
RuleDto rule = newRule(); | |||||
IssueDto issue1 = IssueTesting.newDto(rule, file1, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue1); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory1.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_directory_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory2.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.MODULE_UUIDS, module1.uuid()) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir") | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_directory_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.MODULE_UUIDS, module2.uuid()) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir") | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_directory_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void display_directory_facet() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir")); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
MockUserSession.set().setLogin("john"); | |||||
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam("resolved", "false") | |||||
.setParam(SearchAction.PARAM_FACETS, "directories") | |||||
.execute(); | |||||
result.assertJson(this.getClass(), "display_directory_facet.json", false); | |||||
} | |||||
private RuleDto newRule() { | |||||
RuleDto rule = RuleTesting.newXooX1() | |||||
.setName("Rule name") | |||||
.setDescription("Rule desc") | |||||
.setStatus(RuleStatus.READY); | |||||
tester.get(RuleDao.class).insert(session, rule); | |||||
session.commit(); | |||||
return rule; | |||||
} | |||||
private void setDefaultProjectPermission(ComponentDto project) { | |||||
// project can be seen by anyone and by code viewer | |||||
MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); | |||||
tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER)); | |||||
MockUserSession.set(); | |||||
} | |||||
private ComponentDto insertComponent(ComponentDto component) { | |||||
db.componentDao().insert(session, component); | |||||
session.commit(); | |||||
return component; | |||||
} | |||||
} |
result.assertJson(this.getClass(), "issue.json", false); | result.assertJson(this.getClass(), "issue.json", false); | ||||
} | } | ||||
@Test | |||||
public void issues_on_different_projects() throws Exception { | |||||
RuleDto rule = newRule(); | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(rule, file, project) | |||||
.setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") | |||||
.setStatus("OPEN").setResolution("OPEN") | |||||
.setSeverity("MAJOR") | |||||
.setIssueCreationDate(DateUtils.parseDate("2014-09-04")) | |||||
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04")); | |||||
db.issueDao().insert(session, issue); | |||||
ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("DBCA").setKey("MyProject2")); | |||||
setDefaultProjectPermission(project2); | |||||
ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "EDCB").setKey("MyComponent2")); | |||||
IssueDto issue2 = IssueTesting.newDto(rule, file2, project2) | |||||
.setKee("92fd47d4-b650-4037-80bc-7b112bd4eac2") | |||||
.setStatus("OPEN").setResolution("OPEN") | |||||
.setSeverity("MAJOR") | |||||
.setIssueCreationDate(DateUtils.parseDate("2014-09-04")) | |||||
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04")); | |||||
db.issueDao().insert(session, issue2); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute(); | |||||
result.assertJson(this.getClass(), "issues_on_different_projects.json", false); | |||||
} | |||||
@Test | @Test | ||||
public void issue_with_comment() throws Exception { | public void issue_with_comment() throws Exception { | ||||
db.userDao().insert(session, new UserDto().setLogin("john").setName("John").setEmail("john@email.com")); | db.userDao().insert(session, new UserDto().setLogin("john").setName("John").setEmail("john@email.com")); | ||||
assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ","); | assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ","); | ||||
} | } | ||||
@Test | |||||
public void search_by_project_uuid() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_project_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.PROJECT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_component_uuid() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid()) | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | |||||
public void search_by_directory_path() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir")); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir") | |||||
.execute() | |||||
.assertJson(this.getClass(), "search_by_file_uuid.json", false); | |||||
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java") | |||||
.execute() | |||||
.assertJson(this.getClass(), "no_issue.json", false); | |||||
} | |||||
@Test | @Test | ||||
public void ignore_paging_with_one_component() throws Exception { | public void ignore_paging_with_one_component() throws Exception { | ||||
RuleDto rule = newRule(); | RuleDto rule = newRule(); | ||||
MockUserSession.set().setLogin("john"); | MockUserSession.set().setLogin("john"); | ||||
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | ||||
.setParam("resolved", "false") | .setParam("resolved", "false") | ||||
.setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,componentUuids,assignees,languages,actionPlans") | |||||
.setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans") | |||||
.execute(); | .execute(); | ||||
result.assertJson(this.getClass(), "display_facets.json", false); | result.assertJson(this.getClass(), "display_facets.json", false); | ||||
} | } | ||||
.setParam("resolved", "false") | .setParam("resolved", "false") | ||||
.setParam("severities", "MAJOR,MINOR") | .setParam("severities", "MAJOR,MINOR") | ||||
.setParam("languages", "xoo,polop,palap") | .setParam("languages", "xoo,polop,palap") | ||||
.setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,componentUuids,assignees,languages,actionPlans") | |||||
.setParam(SearchAction.PARAM_FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans") | |||||
.execute(); | .execute(); | ||||
result.assertJson(this.getClass(), "display_zero_facets.json", false); | result.assertJson(this.getClass(), "display_zero_facets.json", false); | ||||
} | } | ||||
@Test | |||||
public void display_directory_facet() throws Exception { | |||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | |||||
setDefaultProjectPermission(project); | |||||
ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "src/main/java/dir")); | |||||
ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "BCDE").setKey("MyComponent").setPath(directory.path() + "/MyComponent.java")); | |||||
IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); | |||||
db.issueDao().insert(session, issue); | |||||
session.commit(); | |||||
tester.get(IssueIndexer.class).indexAll(); | |||||
MockUserSession.set().setLogin("john"); | |||||
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) | |||||
.setParam("resolved", "false") | |||||
.setParam(SearchAction.PARAM_FACETS, "directories") | |||||
.execute(); | |||||
result.assertJson(this.getClass(), "display_directory_facet.json", false); | |||||
} | |||||
@Test | @Test | ||||
public void hide_rules() throws Exception { | public void hide_rules() throws Exception { | ||||
ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); | ComponentDto project = insertComponent(ComponentTesting.newProjectDto("ABCD").setKey("MyProject")); |
{ | |||||
"total": 0, | |||||
"issues": [] | |||||
} |
{ | |||||
"total": 1, | |||||
"p": 1, | |||||
"issues": [ | |||||
{ | |||||
"key": "82fd47d4-b650-4037-80bc-7b112bd4eac2", | |||||
"component": "module1:MyComponent", | |||||
"project": "MyProject", | |||||
"rule": "xoo:x1" | |||||
} | |||||
] | |||||
} |
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"property": "componentUuids", | |||||
"property": "fileUuids", | |||||
"values": [ | "values": [ | ||||
{ | { | ||||
"val": "BCDE", | "val": "BCDE", |
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"property": "componentUuids", | |||||
"property": "fileUuids", | |||||
"values": [ | "values": [ | ||||
{ | { | ||||
"val": "BCDE", | "val": "BCDE", |