Kaynağa Gözat

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 yıl önce
ebeveyn
işleme
27b714e7f3
18 değiştirilmiş dosya ile 561 ekleme ve 220 silme
  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 Dosyayı Görüntüle

@@ -23,6 +23,7 @@ package org.sonar.server.component;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.sonar.api.ServerComponent;
import org.sonar.api.i18n.I18n;
@@ -44,11 +45,7 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
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;

@@ -219,6 +216,30 @@ public class ComponentService implements ServerComponent {
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) {
if (!ComponentKeys.isValidModuleKey(kee)) {
throw new BadRequestException(formatMessage("Malformed key for %s: %s. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.",
@@ -245,5 +266,4 @@ public class ComponentService implements ServerComponent {
private ComponentDto getByKey(DbSession session, String key) {
return dbClient.componentDao().getByKey(session, key);
}

}

+ 24
- 0
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQuery.java Dosyayı Görüntüle

@@ -59,8 +59,10 @@ public class IssueQuery {
private final Collection<String> resolutions;
private final Collection<String> components;
private final Collection<String> modules;
private final Collection<String> moduleRoots;
private final Collection<String> projects;
private final Collection<String> directories;
private final Collection<String> files;
private final Collection<RuleKey> rules;
private final Collection<String> actionPlans;
private final Collection<String> reporters;
@@ -86,8 +88,10 @@ public class IssueQuery {
this.resolutions = defaultCollection(builder.resolutions);
this.components = defaultCollection(builder.components);
this.modules = defaultCollection(builder.modules);
this.moduleRoots = defaultCollection(builder.moduleRoots);
this.projects = defaultCollection(builder.projects);
this.directories = defaultCollection(builder.directories);
this.files = defaultCollection(builder.files);
this.rules = defaultCollection(builder.rules);
this.actionPlans = defaultCollection(builder.actionPlans);
this.reporters = defaultCollection(builder.reporters);
@@ -131,6 +135,10 @@ public class IssueQuery {
return modules;
}

public Collection<String> moduleRootUuids() {
return moduleRoots;
}

public Collection<String> projectUuids() {
return projects;
}
@@ -139,6 +147,10 @@ public class IssueQuery {
return directories;
}

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

public Collection<RuleKey> rules() {
return rules;
}
@@ -237,8 +249,10 @@ public class IssueQuery {
private Collection<String> resolutions;
private Collection<String> components;
private Collection<String> modules;
private Collection<String> moduleRoots;
private Collection<String> projects;
private Collection<String> directories;
private Collection<String> files;
private Collection<RuleKey> rules;
private Collection<String> actionPlans;
private Collection<String> reporters;
@@ -290,6 +304,11 @@ public class IssueQuery {
return this;
}

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

public Builder projectUuids(@Nullable Collection<String> l) {
this.projects = l;
return this;
@@ -300,6 +319,11 @@ public class IssueQuery {
return this;
}

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

public Builder rules(@Nullable Collection<RuleKey> rules) {
this.rules = rules;
return this;

+ 103
- 39
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java Dosyayı Görüntüle

@@ -22,6 +22,7 @@ package org.sonar.server.issue;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
@@ -29,11 +30,14 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.lang.ObjectUtils;
import org.sonar.api.ServerComponent;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ws.Request;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.component.ComponentService;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.IssueQuery.Builder;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.search.ws.SearchRequestHandler;
import org.sonar.server.util.RubyUtils;
@@ -64,6 +68,7 @@ public class IssueQueryService implements ServerComponent {
public IssueQuery createFromMap(Map<String, Object> params) {
DbSession session = dbClient.openSession(false);
try {

IssueQuery.Builder builder = IssueQuery.builder()
.issueKeys(RubyUtils.toStrings(params.get(IssueFilterParameters.ISSUES)))
.severities(RubyUtils.toStrings(params.get(IssueFilterParameters.SEVERITIES)))
@@ -79,19 +84,11 @@ public class IssueQueryService implements ServerComponent {
.onComponentOnly(RubyUtils.toBoolean(params.get(IssueFilterParameters.ON_COMPONENT_ONLY)))
.assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED)))
.planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED)))
.directories(RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES)))
.hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES)))
.createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT)))
.createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER)))
.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,
RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_UUIDS)),
RubyUtils.toStrings(
@@ -101,10 +98,18 @@ public class IssueQueryService implements ServerComponent {
)
),
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_KEYS)));
RubyUtils.toStrings(params.get(IssueFilterParameters.DIRECTORIES)),
RubyUtils.toStrings(params.get(IssueFilterParameters.FILE_UUIDS)));

String sort = (String) params.get(IssueFilterParameters.SORT);
if (!Strings.isNullOrEmpty(sort)) {
builder.sort(sort);
@@ -139,18 +144,19 @@ public class IssueQueryService implements ServerComponent {
.onComponentOnly(request.paramAsBoolean(IssueFilterParameters.ON_COMPONENT_ONLY))
.assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED))
.planned(request.paramAsBoolean(IssueFilterParameters.PLANNED))
.directories(request.paramAsStrings(IssueFilterParameters.DIRECTORIES))
.createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT))
.createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER))
.createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE))
.ignorePaging(request.paramAsBoolean(IssueFilterParameters.IGNORE_PAGING));
addProjectUuids(builder, session,
request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS), request.paramAsStrings(IssueFilterParameters.PROJECT_KEYS));

addComponentUuids(builder, session,
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);
if (!Strings.isNullOrEmpty(sort)) {
builder.sort(sort);
@@ -163,17 +169,6 @@ public class IssueQueryService implements ServerComponent {
}
}

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,
@Nullable Collection<String> componentUuids, @Nullable Collection<String> components,
/*
@@ -181,32 +176,101 @@ public class IssueQueryService implements ServerComponent {
* but "componentKeys" parameter already deprecates "components" parameter,
* 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 (components != null || componentRoots != null) {
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(componentRootUuids, Sets.newHashSet()));
builder.componentUuids(allComponentUuids);
} else {
Set<String> allComponents = Sets.newHashSet();
allComponents.addAll((Collection<String>) ObjectUtils.defaultIfNull(components, 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 {
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) {

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java Dosyayı Görüntüle

@@ -43,12 +43,12 @@ public class IssueFilterParameters {
public static final String COMPONENT_UUIDS = "componentUuids";
public static final String COMPONENT_ROOTS = "componentRoots";
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 PROJECTS = "projects";
public static final String PROJECT_KEYS = "projectKeys";
public static final String PROJECT_UUIDS = "projectUuids";
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 RULES = "rules";
public static final String ACTION_PLANS = "actionPlans";
@@ -70,7 +70,7 @@ public class IssueFilterParameters {

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,
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>() {
@Override

+ 53
- 19
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java Dosyayı Görüntüle

@@ -24,7 +24,6 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang.BooleanUtils;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
@@ -257,25 +256,41 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
}

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 modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, componentUuids);
FilterBuilder compositeFilter = null;
@@ -291,6 +306,23 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
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) {
String user = options.getUserLogin();
Set<String> groups = options.getUserGroups();
@@ -337,12 +369,14 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
IssueFilterParameters.SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY, Severity.ALL.toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
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,
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,
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,
IssueFilterParameters.LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
@@ -507,7 +541,7 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
FilterBuilders.boolFilter()
.must(getAuthorizationFilter(new QueryContext()))
.must(FilterBuilders.missingFilter(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION))
.must(componentFilter(Arrays.asList(componentUuid)))));
.must(moduleRootFilter(Arrays.asList(componentUuid)))));
TermsBuilder aggreg = AggregationBuilders.terms("_ref")
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
.size(pageSize)

+ 12
- 9
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java Dosyayı Görüntüle

@@ -229,11 +229,6 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
.setDescription("Deprecated since 5.1. Use componentKeys instead, with onComponentOnly=false.");
action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS)
.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)
.setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module UUIDs). " +
INTERNAL_PARAMETER_DISCLAIMER +
@@ -241,8 +236,15 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");

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)
.setDescription("Return only issues at the component's level, not on its descendants (modules, directories, files, etc.)")
@@ -257,7 +259,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {

@Override
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())) {
context.setShowFullResult(true);
}
@@ -282,7 +284,8 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
IssueFilterParameters.RULES,
IssueFilterParameters.ASSIGNEES,
IssueFilterParameters.REPORTERS,
IssueFilterParameters.COMPONENT_UUIDS,
IssueFilterParameters.MODULE_UUIDS,
IssueFilterParameters.FILE_UUIDS,
IssueFilterParameters.DIRECTORIES,
IssueFilterParameters.LANGUAGES,
IssueFilterParameters.TAGS,

+ 10
- 5
server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java Dosyayı Görüntüle

@@ -20,6 +20,7 @@

package org.sonar.server.issue;

import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -28,6 +29,7 @@ import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.DbSession;
@@ -92,9 +94,11 @@ public class IssueQueryServiceTest {
map.put("resolved", true);
ArrayList<String> componentKeys = newArrayList("org.apache");
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"));
ArrayList<String> fileUuids = newArrayList("CDEF");
map.put("fileUuids", fileUuids);
map.put("reporters", newArrayList("marilyn"));
map.put("assignees", newArrayList("joanna"));
map.put("languages", newArrayList("xoo"));
@@ -118,21 +122,22 @@ public class IssueQueryServiceTest {
}
if (components.contains("org.apache")) {
return newArrayList("ABCD");
} else if (components.contains("org.sonar")) {
return newArrayList("BCDE");
}
return newArrayList();
}
});

when(componentService.getDistinctQualifiers(eq(session), Matchers.anyCollection())).thenReturn(Sets.newHashSet(Qualifiers.PROJECT));

IssueQuery query = issueQueryService.createFromMap(map);
assertThat(query.issueKeys()).containsOnly("ABCDE1234");
assertThat(query.severities()).containsOnly("MAJOR", "MINOR");
assertThat(query.statuses()).containsOnly("CLOSED");
assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE");
assertThat(query.resolved()).isTrue();
assertThat(query.componentUuids()).containsOnly("ABCD");
assertThat(query.projectUuids()).containsOnly("ABCD");
assertThat(query.moduleUuids()).containsOnly("BCDE");
assertThat(query.fileUuids()).containsOnly("CDEF");
assertThat(query.reporters()).containsOnly("marilyn");
assertThat(query.assignees()).containsOnly("joanna");
assertThat(query.languages()).containsOnly("xoo");

+ 23
- 22
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java Dosyayı Görüntüle

@@ -143,7 +143,6 @@ public class IssueIndexMediumTest {
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())).onComponentOnly(true).build(), new QueryContext()).getHits()).hasSize(1);
assertThat(index.search(IssueQuery.builder().projectUuids(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty();
}

@@ -174,11 +173,16 @@ public class IssueIndexMediumTest {
IssueTesting.newDoc("ISSUE5", subModule),
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
@@ -198,15 +202,12 @@ public class IssueIndexMediumTest {
IssueTesting.newDoc("ISSUE5", subModule),
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
@@ -223,9 +224,9 @@ public class IssueIndexMediumTest {
IssueTesting.newDoc("ISSUE4", file2),
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
@@ -781,7 +782,7 @@ public class IssueIndexMediumTest {
indexIssue(IssueTesting.newDoc("ISSUE1", file1), "sonar-users", null);
// project2 can be seen by sonar-admins
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);

IssueQuery.Builder query = IssueQuery.builder();
@@ -796,10 +797,10 @@ public class IssueIndexMediumTest {
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(2);

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");
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
@@ -829,7 +830,7 @@ public class IssueIndexMediumTest {
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(0);

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

+ 288
- 0
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java Dosyayı Görüntüle

@@ -0,0 +1,288 @@
/*
* 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 Dosyayı Görüntüle

@@ -128,37 +128,6 @@ public class SearchActionMediumTest {
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
public void issue_with_comment() throws Exception {
db.userDao().insert(session, new UserDto().setLogin("john").setName("John").setEmail("john@email.com"));
@@ -305,70 +274,6 @@ public class SearchActionMediumTest {
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
public void ignore_paging_with_one_component() throws Exception {
RuleDto rule = newRule();
@@ -462,7 +367,7 @@ public class SearchActionMediumTest {
MockUserSession.set().setLogin("john");
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.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();
result.assertJson(this.getClass(), "display_facets.json", false);
}
@@ -488,30 +393,11 @@ public class SearchActionMediumTest {
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.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();
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
public void hide_rules() throws Exception {
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 Dosyayı Görüntüle


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 Dosyayı Görüntüle


+ 4
- 0
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/no_issue.json Dosyayı Görüntüle

@@ -0,0 +1,4 @@
{
"total": 0,
"issues": []
}

+ 12
- 0
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_by_directory_uuid.json Dosyayı Görüntüle

@@ -0,0 +1,12 @@
{
"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 Dosyayı Görüntüle


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 Dosyayı Görüntüle


+ 1
- 1
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json Dosyayı Görüntüle

@@ -106,7 +106,7 @@
]
},
{
"property": "componentUuids",
"property": "fileUuids",
"values": [
{
"val": "BCDE",

+ 1
- 1
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_zero_facets.json Dosyayı Görüntüle

@@ -106,7 +106,7 @@
]
},
{
"property": "componentUuids",
"property": "fileUuids",
"values": [
{
"val": "BCDE",

Loading…
İptal
Kaydet