Browse Source

SONAR-5953 Update (again) issue search WS API

- Use component(Uuid|Key)s to fix top level context of search
- Use (project|module|directory|file)Uuids to refine/facet
tags/latest-silver-master-#65
Jean-Baptiste Lievremont 9 years ago
parent
commit
27b714e7f3
18 changed files with 561 additions and 220 deletions
  1. 26
    6
      server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java
  2. 24
    0
      server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java
  3. 103
    39
      server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
  4. 2
    2
      server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
  5. 53
    19
      server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
  6. 12
    9
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
  7. 10
    5
      server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java
  8. 23
    22
      server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
  9. 288
    0
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java
  10. 2
    116
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
  11. 0
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/display_directory_facet.json
  12. 0
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/issues_on_different_projects.json
  13. 4
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/no_issue.json
  14. 12
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_directory_uuid.json
  15. 0
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_file_uuid.json
  16. 0
    0
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_project_uuid.json
  17. 1
    1
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json
  18. 1
    1
      server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json

+ 26
- 6
server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java View File

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);
} }

} }

+ 24
- 0
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java View File

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;

+ 103
- 39
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java View File



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) {

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java View File

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

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

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)

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

.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,

+ 10
- 5
server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java View File



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");

+ 23
- 22
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java View File

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

+ 288
- 0
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java View File

/*
* 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;
}

}

+ 2
- 116
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java View File

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"));

server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_directory_facet.json → server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/display_directory_facet.json View File


server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issues_on_different_projects.json → server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/issues_on_different_projects.json View File


+ 4
- 0
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/no_issue.json View File

{
"total": 0,
"issues": []
}

+ 12
- 0
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_directory_uuid.json View File

{
"total": 1,
"p": 1,
"issues": [
{
"key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
"component": "module1:MyComponent",
"project": "MyProject",
"rule": "xoo:x1"
}
]
}

server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/search_by_file_uuid.json → server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_file_uuid.json View File


server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/search_by_project_uuid.json → server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_project_uuid.json View File


+ 1
- 1
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json View File

] ]
}, },
{ {
"property": "componentUuids",
"property": "fileUuids",
"values": [ "values": [
{ {
"val": "BCDE", "val": "BCDE",

+ 1
- 1
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json View File

] ]
}, },
{ {
"property": "componentUuids",
"property": "fileUuids",
"values": [ "values": [
{ {
"val": "BCDE", "val": "BCDE",

Loading…
Cancel
Save