- stop using ComponentService - improve readability - stop loading directories twice - remove usage of Guava Predicate - remove ComponentService from Compute Enginetags/6.4-RC1
import org.sonar.process.logging.LogbackHelper; | import org.sonar.process.logging.LogbackHelper; | ||||
import org.sonar.server.component.ComponentCleanerService; | import org.sonar.server.component.ComponentCleanerService; | ||||
import org.sonar.server.component.ComponentFinder; | import org.sonar.server.component.ComponentFinder; | ||||
import org.sonar.server.component.ComponentService; | |||||
import org.sonar.server.component.index.ComponentIndexer; | import org.sonar.server.component.index.ComponentIndexer; | ||||
import org.sonar.server.computation.queue.PurgeCeActivities; | import org.sonar.server.computation.queue.PurgeCeActivities; | ||||
import org.sonar.server.computation.task.projectanalysis.ProjectAnalysisTaskModule; | import org.sonar.server.computation.task.projectanalysis.ProjectAnalysisTaskModule; | ||||
// components | // components | ||||
ComponentFinder.class, // used in ComponentService | ComponentFinder.class, // used in ComponentService | ||||
ComponentService.class, // used in ReportSubmitter | |||||
NewAlerts.class, | NewAlerts.class, | ||||
NewAlerts.newMetadata(), | NewAlerts.newMetadata(), | ||||
ComponentCleanerService.class, | ComponentCleanerService.class, |
assertThat(picoContainer.getComponentAdapters()) | assertThat(picoContainer.getComponentAdapters()) | ||||
.hasSize( | .hasSize( | ||||
CONTAINER_ITSELF | CONTAINER_ITSELF | ||||
+ 74 // level 4 | |||||
+ 73 // level 4 | |||||
+ 4 // content of CeConfigurationModule | + 4 // content of CeConfigurationModule | ||||
+ 5 // content of CeQueueModule | + 5 // content of CeQueueModule | ||||
+ 3 // content of CeHttpModule | + 3 // content of CeHttpModule |
*/ | */ | ||||
package org.sonar.server.component; | package org.sonar.server.component; | ||||
import com.google.common.base.Joiner; | |||||
import com.google.common.collect.Collections2; | |||||
import com.google.common.collect.Sets; | |||||
import java.util.Collection; | |||||
import java.util.List; | |||||
import java.util.Set; | |||||
import javax.annotation.Nullable; | |||||
import org.sonar.api.ce.ComputeEngineSide; | |||||
import org.sonar.api.server.ServerSide; | import org.sonar.api.server.ServerSide; | ||||
import org.sonar.api.web.UserRole; | import org.sonar.api.web.UserRole; | ||||
import org.sonar.db.DbClient; | import org.sonar.db.DbClient; | ||||
import org.sonar.db.DbSession; | import org.sonar.db.DbSession; | ||||
import org.sonar.db.component.ComponentDto; | import org.sonar.db.component.ComponentDto; | ||||
import org.sonar.server.es.ProjectIndexer; | import org.sonar.server.es.ProjectIndexer; | ||||
import org.sonar.server.exceptions.NotFoundException; | |||||
import org.sonar.server.user.UserSession; | import org.sonar.server.user.UserSession; | ||||
import static com.google.common.collect.Lists.newArrayList; | |||||
import static org.sonar.core.component.ComponentKeys.isValidModuleKey; | import static org.sonar.core.component.ComponentKeys.isValidModuleKey; | ||||
import static org.sonar.db.component.ComponentKeyUpdaterDao.checkIsProjectOrModule; | import static org.sonar.db.component.ComponentKeyUpdaterDao.checkIsProjectOrModule; | ||||
import static org.sonar.server.ws.WsUtils.checkRequest; | import static org.sonar.server.ws.WsUtils.checkRequest; | ||||
@ServerSide | @ServerSide | ||||
@ComputeEngineSide | |||||
public class ComponentService { | public class ComponentService { | ||||
private final DbClient dbClient; | private final DbClient dbClient; | ||||
private final UserSession userSession; | private final UserSession userSession; | ||||
} | } | ||||
} | } | ||||
public Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys, boolean ignoreMissingComponents) { | |||||
Collection<String> componentUuids = newArrayList(); | |||||
if (componentKeys != null && !componentKeys.isEmpty()) { | |||||
List<ComponentDto> components = dbClient.componentDao().selectByKeys(session, componentKeys); | |||||
if (!ignoreMissingComponents && components.size() < componentKeys.size()) { | |||||
Collection<String> foundKeys = Collections2.transform(components, ComponentDto::getKey); | |||||
Set<String> missingKeys = Sets.newHashSet(componentKeys); | |||||
missingKeys.removeAll(foundKeys); | |||||
throw new NotFoundException("The following component keys do not match any component:\n" + | |||||
Joiner.on('\n').join(missingKeys)); | |||||
} | |||||
for (ComponentDto component : components) { | |||||
componentUuids.add(component.uuid()); | |||||
} | |||||
} | |||||
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().selectByUuids(session, componentUuids); | |||||
for (ComponentDto component : components) { | |||||
componentQualifiers.add(component.qualifier()); | |||||
} | |||||
} | |||||
return componentQualifiers; | |||||
} | |||||
public Collection<ComponentDto> getByUuids(DbSession session, @Nullable Collection<String> componentUuids) { | |||||
Set<ComponentDto> directoryPaths = Sets.newHashSet(); | |||||
if (componentUuids != null && !componentUuids.isEmpty()) { | |||||
List<ComponentDto> components = dbClient.componentDao().selectByUuids(session, componentUuids); | |||||
for (ComponentDto component : components) { | |||||
directoryPaths.add(component); | |||||
} | |||||
} | |||||
return directoryPaths; | |||||
} | |||||
private static void checkProjectOrModuleKeyFormat(String key) { | private static void checkProjectOrModuleKeyFormat(String key) { | ||||
checkRequest(isValidModuleKey(key), "Malformed key for '%s'. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", key); | checkRequest(isValidModuleKey(key), "Malformed key for '%s'. Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", key); | ||||
} | } |
private final Boolean onComponentOnly; | private final Boolean onComponentOnly; | ||||
private final Boolean assigned; | private final Boolean assigned; | ||||
private final Boolean resolved; | private final Boolean resolved; | ||||
private final Boolean hideRules; | |||||
private final Boolean hideComments; | |||||
private final Date createdAt; | private final Date createdAt; | ||||
private final Date createdAfter; | private final Date createdAfter; | ||||
private final Date createdBefore; | private final Date createdBefore; | ||||
this.onComponentOnly = builder.onComponentOnly; | this.onComponentOnly = builder.onComponentOnly; | ||||
this.assigned = builder.assigned; | this.assigned = builder.assigned; | ||||
this.resolved = builder.resolved; | this.resolved = builder.resolved; | ||||
this.hideRules = builder.hideRules; | |||||
this.hideComments = builder.hideComments; | |||||
this.createdAt = builder.createdAt; | this.createdAt = builder.createdAt; | ||||
this.createdAfter = builder.createdAfter; | this.createdAfter = builder.createdAfter; | ||||
this.createdBefore = builder.createdBefore; | this.createdBefore = builder.createdBefore; | ||||
return resolved; | return resolved; | ||||
} | } | ||||
/** | |||||
* @since 4.2 | |||||
*/ | |||||
@CheckForNull | |||||
public Boolean hideRules() { | |||||
return hideRules; | |||||
} | |||||
/** | |||||
* @since 5.1 | |||||
*/ | |||||
@CheckForNull | |||||
public Boolean hideComments() { | |||||
return hideComments; | |||||
} | |||||
@CheckForNull | @CheckForNull | ||||
public Date createdAfter() { | public Date createdAfter() { | ||||
return createdAfter == null ? null : new Date(createdAfter.getTime()); | return createdAfter == null ? null : new Date(createdAfter.getTime()); | ||||
private Boolean onComponentOnly = false; | private Boolean onComponentOnly = false; | ||||
private Boolean assigned = null; | private Boolean assigned = null; | ||||
private Boolean resolved = null; | private Boolean resolved = null; | ||||
private Boolean hideRules = false; | |||||
private Boolean hideComments = false; | |||||
private Date createdAt; | private Date createdAt; | ||||
private Date createdAfter; | private Date createdAfter; | ||||
private Date createdBefore; | private Date createdBefore; | ||||
return this; | return this; | ||||
} | } | ||||
/** | |||||
* If true, rules will not be loaded | |||||
* If false, rules will be loaded | |||||
* | |||||
* @since 4.2 | |||||
* | |||||
*/ | |||||
public Builder hideRules(@Nullable Boolean b) { | |||||
this.hideRules = b; | |||||
return this; | |||||
} | |||||
/** | |||||
* If true, comments will not be loaded | |||||
* If false, comments will be loaded | |||||
* | |||||
* @since 5.1 | |||||
* | |||||
*/ | |||||
public Builder hideComments(@Nullable Boolean b) { | |||||
this.hideComments = b; | |||||
return this; | |||||
} | |||||
public Builder createdAt(@Nullable Date d) { | public Builder createdAt(@Nullable Date d) { | ||||
this.createdAt = d == null ? null : new Date(d.getTime()); | this.createdAt = d == null ? null : new Date(d.getTime()); | ||||
return this; | return this; |
import com.google.common.annotations.VisibleForTesting; | import com.google.common.annotations.VisibleForTesting; | ||||
import com.google.common.base.Joiner; | import com.google.common.base.Joiner; | ||||
import com.google.common.base.Predicate; | |||||
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.Collections2; | import com.google.common.collect.Collections2; | ||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||
import java.util.ArrayList; | |||||
import java.util.Arrays; | import java.util.Arrays; | ||||
import java.util.Collection; | import java.util.Collection; | ||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.List; | import java.util.List; | ||||
import java.util.Locale; | import java.util.Locale; | ||||
import java.util.Map; | |||||
import java.util.Objects; | import java.util.Objects; | ||||
import java.util.Optional; | import java.util.Optional; | ||||
import java.util.Set; | import java.util.Set; | ||||
import java.util.concurrent.atomic.AtomicInteger; | |||||
import javax.annotation.CheckForNull; | import javax.annotation.CheckForNull; | ||||
import javax.annotation.Nonnull; | |||||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | ||||
import org.apache.commons.lang.BooleanUtils; | import org.apache.commons.lang.BooleanUtils; | ||||
import org.apache.commons.lang.ObjectUtils; | |||||
import org.joda.time.DateTime; | import org.joda.time.DateTime; | ||||
import org.joda.time.format.ISOPeriodFormat; | import org.joda.time.format.ISOPeriodFormat; | ||||
import org.sonar.api.resources.Qualifiers; | import org.sonar.api.resources.Qualifiers; | ||||
import org.sonar.api.server.ServerSide; | import org.sonar.api.server.ServerSide; | ||||
import org.sonar.api.utils.System2; | import org.sonar.api.utils.System2; | ||||
import org.sonar.api.web.UserRole; | import org.sonar.api.web.UserRole; | ||||
import org.sonar.core.util.stream.Collectors; | |||||
import org.sonar.db.DbClient; | import org.sonar.db.DbClient; | ||||
import org.sonar.db.DbSession; | import org.sonar.db.DbSession; | ||||
import org.sonar.db.component.ComponentDto; | import org.sonar.db.component.ComponentDto; | ||||
import org.sonar.db.component.SnapshotDto; | import org.sonar.db.component.SnapshotDto; | ||||
import org.sonar.db.organization.OrganizationDto; | import org.sonar.db.organization.OrganizationDto; | ||||
import org.sonar.server.component.ComponentService; | |||||
import org.sonar.server.user.UserSession; | import org.sonar.server.user.UserSession; | ||||
import org.sonar.server.util.RubyUtils; | |||||
import org.sonarqube.ws.client.issue.IssuesWsParameters; | |||||
import org.sonarqube.ws.client.issue.SearchWsRequest; | import org.sonarqube.ws.client.issue.SearchWsRequest; | ||||
import static com.google.common.base.Preconditions.checkArgument; | import static com.google.common.base.Preconditions.checkArgument; | ||||
import static com.google.common.base.Predicates.notNull; | |||||
import static com.google.common.collect.FluentIterable.from; | |||||
import static com.google.common.collect.Lists.newArrayList; | import static com.google.common.collect.Lists.newArrayList; | ||||
import static java.lang.String.format; | import static java.lang.String.format; | ||||
import static java.util.Collections.singletonList; | |||||
import static org.sonar.api.utils.DateUtils.longToDate; | import static org.sonar.api.utils.DateUtils.longToDate; | ||||
import static org.sonar.api.utils.DateUtils.parseDateOrDateTime; | import static org.sonar.api.utils.DateUtils.parseDateOrDateTime; | ||||
import static org.sonar.api.utils.DateUtils.parseEndingDateOrDateTime; | import static org.sonar.api.utils.DateUtils.parseEndingDateOrDateTime; | ||||
private static final String UNKNOWN = "<UNKNOWN>"; | private static final String UNKNOWN = "<UNKNOWN>"; | ||||
private final DbClient dbClient; | private final DbClient dbClient; | ||||
private final ComponentService componentService; | |||||
private final System2 system; | private final System2 system; | ||||
private final UserSession userSession; | private final UserSession userSession; | ||||
public IssueQueryFactory(DbClient dbClient, ComponentService componentService, System2 system, UserSession userSession) { | |||||
public IssueQueryFactory(DbClient dbClient, System2 system, UserSession userSession) { | |||||
this.dbClient = dbClient; | this.dbClient = dbClient; | ||||
this.componentService = componentService; | |||||
this.system = system; | this.system = system; | ||||
this.userSession = userSession; | this.userSession = userSession; | ||||
} | } | ||||
public IssueQuery createFromMap(Map<String, Object> params) { | |||||
try (DbSession dbSession = dbClient.openSession(false)) { | |||||
IssueQuery.Builder builder = IssueQuery.builder() | |||||
.issueKeys(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_ISSUES))) | |||||
.severities(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_SEVERITIES))) | |||||
.statuses(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_STATUSES))) | |||||
.resolutions(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_RESOLUTIONS))) | |||||
.resolved(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_RESOLVED))) | |||||
.rules(toRules(params.get(IssuesWsParameters.PARAM_RULES))) | |||||
.assignees(buildAssignees(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_ASSIGNEES)))) | |||||
.languages(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_LANGUAGES))) | |||||
.tags(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_TAGS))) | |||||
.types(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_TYPES))) | |||||
.assigned(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ASSIGNED))) | |||||
.hideRules(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_HIDE_RULES))) | |||||
.createdAt(RubyUtils.toDate(params.get(IssuesWsParameters.PARAM_CREATED_AT))) | |||||
.createdAfter(buildCreatedAfterFromDates(RubyUtils.toDate(params.get(PARAM_CREATED_AFTER)), (String) params.get(PARAM_CREATED_IN_LAST))) | |||||
.createdBefore(RubyUtils.toDate(parseEndingDateOrDateTime((String) params.get(IssuesWsParameters.PARAM_CREATED_BEFORE)))) | |||||
.organizationUuid(convertOrganizationKeyToUuid(dbSession, (String) params.get(IssuesWsParameters.PARAM_ORGANIZATION))); | |||||
Set<String> allComponentUuids = Sets.newHashSet(); | |||||
boolean effectiveOnComponentOnly = mergeDeprecatedComponentParameters(dbSession, | |||||
RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ON_COMPONENT_ONLY)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENTS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_UUIDS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_KEYS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_ROOT_UUIDS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_ROOTS)), | |||||
allComponentUuids); | |||||
addComponentParameters(builder, dbSession, | |||||
effectiveOnComponentOnly, | |||||
allComponentUuids, | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_PROJECT_UUIDS)), | |||||
RubyUtils.toStrings( | |||||
ObjectUtils.defaultIfNull( | |||||
params.get(IssuesWsParameters.PARAM_PROJECT_KEYS), | |||||
params.get(IssuesWsParameters.PARAM_PROJECTS))), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_MODULE_UUIDS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_DIRECTORIES)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_FILE_UUIDS)), | |||||
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_AUTHORS))); | |||||
String sort = (String) params.get(IssuesWsParameters.PARAM_SORT); | |||||
if (!Strings.isNullOrEmpty(sort)) { | |||||
builder.sort(sort); | |||||
builder.asc(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ASC))); | |||||
} | |||||
String facetMode = (String) params.get(IssuesWsParameters.FACET_MODE); | |||||
if (!Strings.isNullOrEmpty(facetMode)) { | |||||
builder.facetMode(facetMode); | |||||
} else { | |||||
builder.facetMode(IssuesWsParameters.FACET_MODE_COUNT); | |||||
} | |||||
return builder.build(); | |||||
} | |||||
} | |||||
@CheckForNull | |||||
private Date buildCreatedAfterFromDates(@Nullable Date createdAfter, @Nullable String createdInLast) { | |||||
checkArgument(createdAfter == null || createdInLast == null, format("%s and %s cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_CREATED_IN_LAST)); | |||||
Date actualCreatedAfter = createdAfter; | |||||
if (createdInLast != null) { | |||||
actualCreatedAfter = new DateTime(system.now()).minus( | |||||
ISOPeriodFormat.standard().parsePeriod("P" + createdInLast.toUpperCase(Locale.ENGLISH))).toDate(); | |||||
} | |||||
return actualCreatedAfter; | |||||
} | |||||
public IssueQuery createFromRequest(SearchWsRequest request) { | |||||
public IssueQuery create(SearchWsRequest request) { | |||||
try (DbSession dbSession = dbClient.openSession(false)) { | try (DbSession dbSession = dbClient.openSession(false)) { | ||||
IssueQuery.Builder builder = IssueQuery.builder() | IssueQuery.Builder builder = IssueQuery.builder() | ||||
.issueKeys(request.getIssues()) | .issueKeys(request.getIssues()) | ||||
} | } | ||||
} | } | ||||
@CheckForNull | |||||
private Date buildCreatedAfterFromDates(@Nullable Date createdAfter, @Nullable String createdInLast) { | |||||
checkArgument(createdAfter == null || createdInLast == null, format("Parameters %s and %s cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_CREATED_IN_LAST)); | |||||
Date actualCreatedAfter = createdAfter; | |||||
if (createdInLast != null) { | |||||
actualCreatedAfter = new DateTime(system.now()).minus( | |||||
ISOPeriodFormat.standard().parsePeriod("P" + createdInLast.toUpperCase(Locale.ENGLISH))).toDate(); | |||||
} | |||||
return actualCreatedAfter; | |||||
} | |||||
@CheckForNull | @CheckForNull | ||||
private String convertOrganizationKeyToUuid(DbSession dbSession, @Nullable String organizationKey) { | private String convertOrganizationKeyToUuid(DbSession dbSession, @Nullable String organizationKey) { | ||||
if (organizationKey == null) { | if (organizationKey == null) { | ||||
return buildCreatedAfterFromDates(createdAfter, createdInLast); | return buildCreatedAfterFromDates(createdAfter, createdInLast); | ||||
} | } | ||||
checkRequest(createdAfter == null, "'%s' and '%s' cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_SINCE_LEAK_PERIOD); | |||||
checkRequest(createdAfter == null, "Parameters '%s' and '%s' cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_SINCE_LEAK_PERIOD); | |||||
checkArgument(componentUuids.size() == 1, "One and only one component must be provided when searching since leak period"); | checkArgument(componentUuids.size() == 1, "One and only one component must be provided when searching since leak period"); | ||||
String uuid = componentUuids.iterator().next(); | String uuid = componentUuids.iterator().next(); | ||||
allComponentUuids.addAll(componentRootUuids); | allComponentUuids.addAll(componentRootUuids); | ||||
effectiveOnComponentOnly = false; | effectiveOnComponentOnly = false; | ||||
} else if (componentRoots != null) { | } else if (componentRoots != null) { | ||||
allComponentUuids.addAll(componentUuids(session, componentRoots)); | |||||
allComponentUuids.addAll(convertComponentKeysToUuids(session, componentRoots)); | |||||
effectiveOnComponentOnly = false; | effectiveOnComponentOnly = false; | ||||
} else if (components != null) { | } else if (components != null) { | ||||
allComponentUuids.addAll(componentUuids(session, components)); | |||||
allComponentUuids.addAll(convertComponentKeysToUuids(session, components)); | |||||
effectiveOnComponentOnly = true; | effectiveOnComponentOnly = true; | ||||
} else if (componentUuids != null) { | } else if (componentUuids != null) { | ||||
allComponentUuids.addAll(componentUuids); | allComponentUuids.addAll(componentUuids); | ||||
effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly); | effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly); | ||||
} else if (componentKeys != null) { | } else if (componentKeys != null) { | ||||
allComponentUuids.addAll(componentUuids(session, componentKeys)); | |||||
allComponentUuids.addAll(convertComponentKeysToUuids(session, componentKeys)); | |||||
effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly); | effectiveOnComponentOnly = BooleanUtils.isTrue(onComponentOnly); | ||||
} | } | ||||
return effectiveOnComponentOnly; | return effectiveOnComponentOnly; | ||||
} | } | ||||
private static boolean atMostOneNonNullElement(Object... objects) { | private static boolean atMostOneNonNullElement(Object... objects) { | ||||
return !from(Arrays.asList(objects)) | |||||
.filter(notNull()) | |||||
.anyMatch(new HasTwoOrMoreElements()); | |||||
return Arrays.stream(objects) | |||||
.filter(Objects::nonNull) | |||||
.count() <= 1; | |||||
} | } | ||||
private void addComponentParameters(IssueQuery.Builder builder, DbSession session, | private void addComponentParameters(IssueQuery.Builder builder, DbSession session, | ||||
boolean onComponentOnly, | boolean onComponentOnly, | ||||
Collection<String> componentUuids, | Collection<String> componentUuids, | ||||
@Nullable Collection<String> projectUuids, @Nullable Collection<String> projects, | |||||
@Nullable Collection<String> projectUuids, @Nullable Collection<String> projectKeys, | |||||
@Nullable Collection<String> moduleUuids, | @Nullable Collection<String> moduleUuids, | ||||
@Nullable Collection<String> directories, | @Nullable Collection<String> directories, | ||||
@Nullable Collection<String> fileUuids, | @Nullable Collection<String> fileUuids, | ||||
} | } | ||||
builder.authors(authors); | builder.authors(authors); | ||||
checkArgument(projectUuids == null || projects == null, "projects and projectUuids cannot be set simultaneously"); | |||||
checkArgument(projectUuids == null || projectKeys == null, "Parameters projects and projectUuids cannot be set simultaneously"); | |||||
if (projectUuids != null) { | if (projectUuids != null) { | ||||
builder.projectUuids(projectUuids); | builder.projectUuids(projectUuids); | ||||
} else { | |||||
builder.projectUuids(componentUuids(session, projects)); | |||||
} else if (projectKeys != null) { | |||||
builder.projectUuids(convertComponentKeysToUuids(session, projectKeys)); | |||||
} | } | ||||
builder.moduleUuids(moduleUuids); | builder.moduleUuids(moduleUuids); | ||||
builder.directories(directories); | builder.directories(directories); | ||||
} | } | ||||
private void addComponentsBasedOnQualifier(IssueQuery.Builder builder, DbSession session, Collection<String> componentUuids) { | private void addComponentsBasedOnQualifier(IssueQuery.Builder builder, DbSession session, Collection<String> componentUuids) { | ||||
Set<String> qualifiers = componentService.getDistinctQualifiers(session, componentUuids); | |||||
if (qualifiers.isEmpty()) { | |||||
// Qualifier not found, defaulting to componentUuids (e.g <UNKNOWN>) | |||||
if (componentUuids.isEmpty()) { | |||||
builder.componentUuids(componentUuids); | builder.componentUuids(componentUuids); | ||||
return; | return; | ||||
} | } | ||||
List<ComponentDto> components = dbClient.componentDao().selectByUuids(session, componentUuids); | |||||
if (components.isEmpty()) { | |||||
builder.componentUuids(componentUuids); | |||||
return; | |||||
} | |||||
Set<String> qualifiers = components.stream().map(ComponentDto::qualifier).collect(Collectors.toHashSet()); | |||||
if (qualifiers.size() > 1) { | if (qualifiers.size() > 1) { | ||||
throw new IllegalArgumentException("All components must have the same qualifier, found " + Joiner.on(',').join(qualifiers)); | throw new IllegalArgumentException("All components must have the same qualifier, found " + Joiner.on(',').join(qualifiers)); | ||||
} | } | ||||
String uniqueQualifier = qualifiers.iterator().next(); | |||||
switch (uniqueQualifier) { | |||||
String qualifier = qualifiers.iterator().next(); | |||||
switch (qualifier) { | |||||
case Qualifiers.VIEW: | case Qualifiers.VIEW: | ||||
case Qualifiers.SUBVIEW: | case Qualifiers.SUBVIEW: | ||||
addViewsOrSubViews(builder, componentUuids, uniqueQualifier); | |||||
addViewsOrSubViews(builder, componentUuids); | |||||
break; | break; | ||||
case Qualifiers.PROJECT: | case Qualifiers.PROJECT: | ||||
builder.projectUuids(componentUuids); | builder.projectUuids(componentUuids); | ||||
builder.moduleRootUuids(componentUuids); | builder.moduleRootUuids(componentUuids); | ||||
break; | break; | ||||
case Qualifiers.DIRECTORY: | case Qualifiers.DIRECTORY: | ||||
addDirectories(builder, session, componentUuids); | |||||
addDirectories(builder, components); | |||||
break; | break; | ||||
case Qualifiers.FILE: | case Qualifiers.FILE: | ||||
case Qualifiers.UNIT_TEST_FILE: | case Qualifiers.UNIT_TEST_FILE: | ||||
} | } | ||||
} | } | ||||
private void addViewsOrSubViews(IssueQuery.Builder builder, Collection<String> componentUuids, String uniqueQualifier) { | |||||
List<String> filteredViewUuids = newArrayList(); | |||||
for (String viewUuid : componentUuids) { | |||||
if ((Qualifiers.VIEW.equals(uniqueQualifier) && userSession.hasComponentUuidPermission(UserRole.USER, viewUuid)) | |||||
|| (Qualifiers.SUBVIEW.equals(uniqueQualifier) && userSession.hasComponentUuidPermission(UserRole.USER, viewUuid))) { | |||||
private void addViewsOrSubViews(IssueQuery.Builder builder, Collection<String> viewOrSubViewUuids) { | |||||
List<String> filteredViewUuids = new ArrayList<>(); | |||||
for (String viewUuid : viewOrSubViewUuids) { | |||||
if (userSession.hasComponentUuidPermission(UserRole.USER, viewUuid)) { | |||||
filteredViewUuids.add(viewUuid); | filteredViewUuids.add(viewUuid); | ||||
} | } | ||||
} | } | ||||
builder.viewUuids(filteredViewUuids); | builder.viewUuids(filteredViewUuids); | ||||
} | } | ||||
private void addDirectories(IssueQuery.Builder builder, DbSession session, Collection<String> componentUuids) { | |||||
private static void addDirectories(IssueQuery.Builder builder, List<ComponentDto> directories) { | |||||
Collection<String> directoryModuleUuids = Sets.newHashSet(); | Collection<String> directoryModuleUuids = Sets.newHashSet(); | ||||
Collection<String> directoryPaths = Sets.newHashSet(); | Collection<String> directoryPaths = Sets.newHashSet(); | ||||
for (ComponentDto directory : componentService.getByUuids(session, componentUuids)) { | |||||
for (ComponentDto directory : directories) { | |||||
directoryModuleUuids.add(directory.moduleUuid()); | directoryModuleUuids.add(directory.moduleUuid()); | ||||
directoryPaths.add(directory.path()); | directoryPaths.add(directory.path()); | ||||
} | } | ||||
builder.directories(directoryPaths); | builder.directories(directoryPaths); | ||||
} | } | ||||
private Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys) { | |||||
Collection<String> componentUuids = Lists.newArrayList(); | |||||
componentUuids.addAll(componentService.componentUuids(session, componentKeys, true)); | |||||
private Collection<String> convertComponentKeysToUuids(DbSession dbSession, Collection<String> componentKeys) { | |||||
List<String> componentUuids = dbClient.componentDao().selectByKeys(dbSession, componentKeys).stream().map(ComponentDto::uuid).collect(Collectors.toList()); | |||||
// If unknown components are given, but no components are found, then all issues will be returned, | // If unknown components are given, but no components are found, then all issues will be returned, | ||||
// so we add this hack in order to return no issue in this case. | // so we add this hack in order to return no issue in this case. | ||||
if (componentKeys != null && !componentKeys.isEmpty() && componentUuids.isEmpty()) { | |||||
componentUuids.add(UNKNOWN); | |||||
if (!componentKeys.isEmpty() && componentUuids.isEmpty()) { | |||||
return singletonList(UNKNOWN); | |||||
} | } | ||||
return componentUuids; | return componentUuids; | ||||
} | } | ||||
} | } | ||||
return null; | return null; | ||||
} | } | ||||
private static class HasTwoOrMoreElements implements Predicate<Object> { | |||||
private AtomicInteger counter; | |||||
private HasTwoOrMoreElements() { | |||||
this.counter = new AtomicInteger(); | |||||
} | |||||
@Override | |||||
public boolean apply(@Nonnull Object input) { | |||||
Objects.requireNonNull(input); | |||||
return counter.incrementAndGet() >= 2; | |||||
} | |||||
} | |||||
} | } |
type.stringFieldBuilder(FIELD_ISSUE_MESSAGE).disableNorms().build(); | type.stringFieldBuilder(FIELD_ISSUE_MESSAGE).disableNorms().build(); | ||||
type.stringFieldBuilder(FIELD_ISSUE_MODULE_UUID).disableNorms().build(); | type.stringFieldBuilder(FIELD_ISSUE_MODULE_UUID).disableNorms().build(); | ||||
type.createUuidPathField(FIELD_ISSUE_MODULE_PATH); | type.createUuidPathField(FIELD_ISSUE_MODULE_PATH); | ||||
type.stringFieldBuilder(FIELD_ISSUE_ORGANIZATION_UUID).build(); | |||||
type.stringFieldBuilder(FIELD_ISSUE_ORGANIZATION_UUID).disableNorms().build(); | |||||
type.stringFieldBuilder(FIELD_ISSUE_PROJECT_UUID).disableNorms().addSubFields(SORTABLE_ANALYZER).build(); | type.stringFieldBuilder(FIELD_ISSUE_PROJECT_UUID).disableNorms().addSubFields(SORTABLE_ANALYZER).build(); | ||||
type.stringFieldBuilder(FIELD_ISSUE_DIRECTORY_PATH).disableNorms().build(); | type.stringFieldBuilder(FIELD_ISSUE_DIRECTORY_PATH).disableNorms().build(); | ||||
type.stringFieldBuilder(FIELD_ISSUE_RESOLUTION).disableNorms().build(); | type.stringFieldBuilder(FIELD_ISSUE_RESOLUTION).disableNorms().build(); |
*/ | */ | ||||
package org.sonar.server.issue.ws; | package org.sonar.server.issue.ws; | ||||
import com.google.common.collect.ImmutableMap; | |||||
import com.google.common.collect.ImmutableMap.Builder; | |||||
import com.google.common.io.Resources; | import com.google.common.io.Resources; | ||||
import java.util.Map; | import java.util.Map; | ||||
import org.sonar.api.server.ws.Request; | import org.sonar.api.server.ws.Request; | ||||
import org.sonar.server.issue.IssueQuery; | import org.sonar.server.issue.IssueQuery; | ||||
import org.sonar.server.issue.IssueQueryFactory; | import org.sonar.server.issue.IssueQueryFactory; | ||||
import org.sonar.server.issue.IssueService; | import org.sonar.server.issue.IssueService; | ||||
import org.sonarqube.ws.client.issue.IssuesWsParameters; | |||||
import org.sonarqube.ws.client.issue.SearchWsRequest; | |||||
import static java.util.Collections.singletonList; | |||||
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; | import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; | ||||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_COMPONENT_TAGS; | import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_COMPONENT_TAGS; | ||||
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUID; | import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUID; | ||||
/** | /** | ||||
* List issue tags matching a given query. | * List issue tags matching a given query. | ||||
* @since 5.1 | |||||
*/ | */ | ||||
public class ComponentTagsAction implements IssuesWsAction { | public class ComponentTagsAction implements IssuesWsAction { | ||||
@Override | @Override | ||||
public void handle(Request request, Response response) throws Exception { | public void handle(Request request, Response response) throws Exception { | ||||
Builder<String, Object> paramBuilder = ImmutableMap.<String, Object>builder() | |||||
.put(IssuesWsParameters.PARAM_COMPONENT_UUIDS, request.mandatoryParam(PARAM_COMPONENT_UUID)) | |||||
.put(IssuesWsParameters.PARAM_RESOLVED, false); | |||||
if (request.hasParam(PARAM_CREATED_AFTER)) { | |||||
paramBuilder.put(PARAM_CREATED_AFTER, request.param(PARAM_CREATED_AFTER)); | |||||
} | |||||
IssueQuery query = queryService.createFromMap(paramBuilder.build()); | |||||
SearchWsRequest searchWsRequest = new SearchWsRequest() | |||||
.setComponentUuids(singletonList(request.mandatoryParam(PARAM_COMPONENT_UUID))) | |||||
.setResolved(false) | |||||
.setCreatedAfter(request.param(PARAM_CREATED_AFTER)); | |||||
IssueQuery query = queryService.create(searchWsRequest); | |||||
int pageSize = request.mandatoryParamAsInt(PAGE_SIZE); | int pageSize = request.mandatoryParamAsInt(PAGE_SIZE); | ||||
try (JsonWriter json = response.newJsonWriter()) { | try (JsonWriter json = response.newJsonWriter()) { | ||||
json.beginObject().name("tags").beginArray(); | json.beginObject().name("tags").beginArray(); |
"If this parameter is set to a truthy value, createdAfter must not be set and one component id or key must be provided.") | "If this parameter is set to a truthy value, createdAfter must not be set and one component id or key must be provided.") | ||||
.setBooleanPossibleValues() | .setBooleanPossibleValues() | ||||
.setDefaultValue("false"); | .setDefaultValue("false"); | ||||
} | } | ||||
private static void addComponentRelatedParams(WebService.NewAction action) { | private static void addComponentRelatedParams(WebService.NewAction action) { | ||||
// prepare the Elasticsearch request | // prepare the Elasticsearch request | ||||
SearchOptions options = createSearchOptionsFromRequest(request); | SearchOptions options = createSearchOptionsFromRequest(request); | ||||
EnumSet<SearchAdditionalField> additionalFields = SearchAdditionalField.getFromRequest(request); | EnumSet<SearchAdditionalField> additionalFields = SearchAdditionalField.getFromRequest(request); | ||||
IssueQuery query = issueQueryFactory.createFromRequest(request); | |||||
IssueQuery query = issueQueryFactory.create(request); | |||||
// execute request | // execute request | ||||
SearchResult<IssueDoc> result = issueIndex.search(query, options); | SearchResult<IssueDoc> result = issueIndex.search(query, options); |
*/ | */ | ||||
package org.sonar.server.component; | package org.sonar.server.component; | ||||
import java.util.Arrays; | |||||
import org.junit.Rule; | import org.junit.Rule; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.rules.ExpectedException; | import org.junit.rules.ExpectedException; | ||||
import org.sonar.server.es.ProjectIndexer; | import org.sonar.server.es.ProjectIndexer; | ||||
import org.sonar.server.tester.UserSessionRule; | import org.sonar.server.tester.UserSessionRule; | ||||
import static org.assertj.core.api.Assertions.assertThat; | |||||
import static org.assertj.guava.api.Assertions.assertThat; | import static org.assertj.guava.api.Assertions.assertThat; | ||||
import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||
import static org.sonar.db.component.ComponentTesting.newFileDto; | import static org.sonar.db.component.ComponentTesting.newFileDto; | ||||
private ComponentService underTest = new ComponentService(dbClient, userSession, projectIndexer); | private ComponentService underTest = new ComponentService(dbClient, userSession, projectIndexer); | ||||
@Test | |||||
public void should_fail_silently_on_components_not_found_if_told_so() { | |||||
String moduleKey = "sample:root:module"; | |||||
String fileKey = "sample:root:module:Foo.xoo"; | |||||
assertThat(underTest.componentUuids(dbSession, Arrays.asList(moduleKey, fileKey), true)).isEmpty(); | |||||
} | |||||
@Test | @Test | ||||
public void bulk_update() { | public void bulk_update() { | ||||
ComponentDto project = componentDb.insertComponent(newProjectDto(dbTester.organizations().insert()).setKey("my_project")); | ComponentDto project = componentDb.insertComponent(newProjectDto(dbTester.organizations().insert()).setKey("my_project")); |
package org.sonar.server.issue; | package org.sonar.server.issue; | ||||
import java.util.Date; | import java.util.Date; | ||||
import java.util.HashMap; | |||||
import java.util.Map; | |||||
import org.junit.Rule; | import org.junit.Rule; | ||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.rules.ExpectedException; | import org.junit.rules.ExpectedException; | ||||
import org.sonar.db.component.ComponentDto; | import org.sonar.db.component.ComponentDto; | ||||
import org.sonar.db.component.ComponentTesting; | import org.sonar.db.component.ComponentTesting; | ||||
import org.sonar.db.organization.OrganizationDto; | import org.sonar.db.organization.OrganizationDto; | ||||
import org.sonar.server.component.ComponentService; | |||||
import org.sonar.server.exceptions.BadRequestException; | import org.sonar.server.exceptions.BadRequestException; | ||||
import org.sonar.server.tester.UserSessionRule; | import org.sonar.server.tester.UserSessionRule; | ||||
import org.sonarqube.ws.client.issue.SearchWsRequest; | import org.sonarqube.ws.client.issue.SearchWsRequest; | ||||
@Rule | @Rule | ||||
public DbTester db = DbTester.create(); | public DbTester db = DbTester.create(); | ||||
private ComponentService componentService = new ComponentService(db.getDbClient(), userSession); | |||||
private System2 system = mock(System2.class); | private System2 system = mock(System2.class); | ||||
private IssueQueryFactory underTest = new IssueQueryFactory(db.getDbClient(), componentService, system, userSession); | |||||
private IssueQueryFactory underTest = new IssueQueryFactory(db.getDbClient(), system, userSession); | |||||
@Test | @Test | ||||
public void create_from_parameters() { | public void create_from_parameters() { | ||||
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | ||||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("issues", newArrayList("anIssueKey")); | |||||
map.put("severities", newArrayList("MAJOR", "MINOR")); | |||||
map.put("statuses", newArrayList("CLOSED")); | |||||
map.put("resolutions", newArrayList("FALSE-POSITIVE")); | |||||
map.put("resolved", true); | |||||
map.put("projectKeys", newArrayList(project.key())); | |||||
map.put("moduleUuids", newArrayList(module.uuid())); | |||||
map.put("directories", newArrayList("aDirPath")); | |||||
map.put("fileUuids", newArrayList(file.uuid())); | |||||
map.put("assignees", newArrayList("joanna")); | |||||
map.put("languages", newArrayList("xoo")); | |||||
map.put("tags", newArrayList("tag1", "tag2")); | |||||
map.put("organization", organization.getKey()); | |||||
map.put("assigned", true); | |||||
map.put("planned", true); | |||||
map.put("hideRules", true); | |||||
map.put("createdAfter", "2013-04-16T09:08:24+0200"); | |||||
map.put("createdBefore", "2013-04-17T09:08:24+0200"); | |||||
map.put("rules", "squid:AvoidCycle,findbugs:NullReference"); | |||||
map.put("sort", "CREATION_DATE"); | |||||
map.put("asc", true); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setIssues(asList("anIssueKey")) | |||||
.setSeverities(asList("MAJOR", "MINOR")) | |||||
.setStatuses(asList("CLOSED")) | |||||
.setResolutions(asList("FALSE-POSITIVE")) | |||||
.setResolved(true) | |||||
.setProjectKeys(asList(project.key())) | |||||
.setModuleUuids(asList(module.uuid())) | |||||
.setDirectories(asList("aDirPath")) | |||||
.setFileUuids(asList(file.uuid())) | |||||
.setAssignees(asList("joanna")) | |||||
.setLanguages(asList("xoo")) | |||||
.setTags(asList("tag1", "tag2")) | |||||
.setOrganization(organization.getKey()) | |||||
.setAssigned(true) | |||||
.setCreatedAfter("2013-04-16T09:08:24+0200") | |||||
.setCreatedBefore("2013-04-17T09:08:24+0200") | |||||
.setRules(asList("squid:AvoidCycle", "findbugs:NullReference")) | |||||
.setSort("CREATION_DATE") | |||||
.setAsc(true); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.issueKeys()).containsOnly("anIssueKey"); | assertThat(query.issueKeys()).containsOnly("anIssueKey"); | ||||
assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); | assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); | ||||
assertThat(query.organizationUuid()).isEqualTo(organization.getUuid()); | assertThat(query.organizationUuid()).isEqualTo(organization.getUuid()); | ||||
assertThat(query.onComponentOnly()).isFalse(); | assertThat(query.onComponentOnly()).isFalse(); | ||||
assertThat(query.assigned()).isTrue(); | assertThat(query.assigned()).isTrue(); | ||||
assertThat(query.hideRules()).isTrue(); | |||||
assertThat(query.rules()).hasSize(2); | assertThat(query.rules()).hasSize(2); | ||||
assertThat(query.directories()).containsOnly("aDirPath"); | assertThat(query.directories()).containsOnly("aDirPath"); | ||||
assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200")); | assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200")); | ||||
.setCreatedAfter("2013-04-16") | .setCreatedAfter("2013-04-16") | ||||
.setCreatedBefore("2013-04-17"); | .setCreatedBefore("2013-04-17"); | ||||
IssueQuery query = underTest.createFromRequest(request); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDate("2013-04-16")); | assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDate("2013-04-16")); | ||||
assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDate("2013-04-18")); | assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDate("2013-04-18")); | ||||
@Test | @Test | ||||
public void add_unknown_when_no_component_found() { | public void add_unknown_when_no_component_found() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("components", newArrayList("does_not_exist")); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentKeys(asList("does_not_exist")); | |||||
IssueQuery query = underTest.create(request); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
assertThat(query.componentUuids()).containsOnly("<UNKNOWN>"); | assertThat(query.componentUuids()).containsOnly("<UNKNOWN>"); | ||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_components_and_components_uuid_params_are_set_at_the_same_time() { | public void fail_if_components_and_components_uuid_params_are_set_at_the_same_time() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("components", newArrayList("foo")); | |||||
map.put("componentUuids", newArrayList("bar")); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentKeys(asList("foo")) | |||||
.setComponentUuids(asList("bar")); | |||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("At most one of the following parameters can be provided: componentKeys, componentUuids, components, componentRoots, componentUuids"); | expectedException.expectMessage("At most one of the following parameters can be provided: componentKeys, componentUuids, components, componentRoots, componentUuids"); | ||||
underTest.createFromMap(map); | |||||
underTest.create(request); | |||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_both_projects_and_projectUuids_params_are_set() { | public void fail_if_both_projects_and_projectUuids_params_are_set() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("projects", newArrayList("foo")); | |||||
map.put("projectUuids", newArrayList("bar")); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setProjectKeys(asList("foo")) | |||||
.setProjectUuids(asList("bar")); | |||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("projects and projectUuids cannot be set simultaneously"); | |||||
expectedException.expectMessage("Parameters projects and projectUuids cannot be set simultaneously"); | |||||
underTest.createFromMap(map); | |||||
underTest.create(request); | |||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_both_componentRoots_and_componentRootUuids_params_are_set() { | public void fail_if_both_componentRoots_and_componentRootUuids_params_are_set() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentRoots", newArrayList("foo")); | |||||
map.put("componentRootUuids", newArrayList("bar")); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentRoots(asList("foo")) | |||||
.setComponentRootUuids(asList("bar")); | |||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("At most one of the following parameters can be provided: componentKeys, componentUuids, components, componentRoots, componentUuids"); | expectedException.expectMessage("At most one of the following parameters can be provided: componentKeys, componentUuids, components, componentRoots, componentUuids"); | ||||
underTest.createFromMap(map); | |||||
underTest.create(request); | |||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_componentRoots_references_components_with_different_qualifier() { | public void fail_if_componentRoots_references_components_with_different_qualifier() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentRoots", newArrayList(project.key(), file.key())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentRoots(asList(project.key(), file.key())); | |||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("All components must have the same qualifier, found FIL,TRK"); | expectedException.expectMessage("All components must have the same qualifier, found FIL,TRK"); | ||||
underTest.createFromMap(map); | |||||
underTest.create(request); | |||||
} | } | ||||
@Test | @Test | ||||
public void param_componentRootUuids_enables_search_in_view_tree_if_user_has_permission_on_view() { | public void param_componentRootUuids_enables_search_in_view_tree_if_user_has_permission_on_view() { | ||||
ComponentDto view = db.components().insertView(); | ComponentDto view = db.components().insertView(); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentRootUuids", newArrayList(view.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentRootUuids(asList(view.uuid())); | |||||
userSession.addProjectUuidPermissions(UserRole.USER, view.uuid()); | userSession.addProjectUuidPermissions(UserRole.USER, view.uuid()); | ||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.viewUuids()).containsOnly(view.uuid()); | assertThat(query.viewUuids()).containsOnly(view.uuid()); | ||||
assertThat(query.onComponentOnly()).isFalse(); | assertThat(query.onComponentOnly()).isFalse(); | ||||
public void return_empty_results_if_not_allowed_to_search_for_subview() { | public void return_empty_results_if_not_allowed_to_search_for_subview() { | ||||
ComponentDto view = db.components().insertView(); | ComponentDto view = db.components().insertView(); | ||||
ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubView(view)); | ComponentDto subView = db.components().insertComponent(ComponentTesting.newSubView(view)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentRootUuids", newArrayList(subView.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentRootUuids(asList(subView.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.viewUuids()).containsOnly("<UNKNOWN>"); | assertThat(query.viewUuids()).containsOnly("<UNKNOWN>"); | ||||
} | } | ||||
@Test | @Test | ||||
public void param_componentUuids_enables_search_on_project_tree_by_default() { | public void param_componentUuids_enables_search_on_project_tree_by_default() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentUuids", newArrayList(project.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentUuids(asList(project.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.projectUuids()).containsExactly(project.uuid()); | assertThat(query.projectUuids()).containsExactly(project.uuid()); | ||||
assertThat(query.onComponentOnly()).isFalse(); | assertThat(query.onComponentOnly()).isFalse(); | ||||
} | } | ||||
@Test | @Test | ||||
public void onComponentOnly_restricts_search_to_specified_componentKeys() { | public void onComponentOnly_restricts_search_to_specified_componentKeys() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentKeys", newArrayList(project.key())); | |||||
map.put("onComponentOnly", true); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentKeys(asList(project.key())) | |||||
.setOnComponentOnly(true); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.projectUuids()).isEmpty(); | assertThat(query.projectUuids()).isEmpty(); | ||||
assertThat(query.componentUuids()).containsExactly(project.uuid()); | assertThat(query.componentUuids()).containsExactly(project.uuid()); | ||||
public void should_search_in_tree_with_module_uuid() { | public void should_search_in_tree_with_module_uuid() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentUuids", newArrayList(module.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentUuids(asList(module.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.moduleRootUuids()).containsExactly(module.uuid()); | assertThat(query.moduleRootUuids()).containsExactly(module.uuid()); | ||||
assertThat(query.onComponentOnly()).isFalse(); | assertThat(query.onComponentOnly()).isFalse(); | ||||
} | } | ||||
public void param_componentUuids_enables_search_in_directory_tree() { | public void param_componentUuids_enables_search_in_directory_tree() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo")); | ComponentDto dir = db.components().insertComponent(ComponentTesting.newDirectory(project, "src/main/java/foo")); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentUuids", newArrayList(dir.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentUuids(asList(dir.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.moduleUuids()).containsOnly(dir.moduleUuid()); | assertThat(query.moduleUuids()).containsOnly(dir.moduleUuid()); | ||||
assertThat(query.directories()).containsOnly(dir.path()); | assertThat(query.directories()).containsOnly(dir.path()); | ||||
public void param_componentUuids_enables_search_by_file() { | public void param_componentUuids_enables_search_by_file() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentUuids", newArrayList(file.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentUuids(asList(file.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.fileUuids()).containsExactly(file.uuid()); | assertThat(query.fileUuids()).containsExactly(file.uuid()); | ||||
} | } | ||||
public void param_componentUuids_enables_search_by_test_file() { | public void param_componentUuids_enables_search_by_test_file() { | ||||
ComponentDto project = db.components().insertProject(); | ComponentDto project = db.components().insertProject(); | ||||
ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project).setQualifier(Qualifiers.UNIT_TEST_FILE)); | ComponentDto file = db.components().insertComponent(ComponentTesting.newFileDto(project).setQualifier(Qualifiers.UNIT_TEST_FILE)); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("componentUuids", newArrayList(file.uuid())); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setComponentUuids(asList(file.uuid())); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.fileUuids()).containsExactly(file.uuid()); | assertThat(query.fileUuids()).containsExactly(file.uuid()); | ||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_created_after_and_created_since_are_both_set() { | public void fail_if_created_after_and_created_since_are_both_set() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("createdAfter", "2013-07-25T07:35:00+0100"); | |||||
map.put("createdInLast", "palap"); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setCreatedAfter("2013-07-25T07:35:00+0100") | |||||
.setCreatedInLast("palap"); | |||||
try { | try { | ||||
underTest.createFromMap(map); | |||||
underTest.create(request); | |||||
fail(); | fail(); | ||||
} catch (Exception e) { | } catch (Exception e) { | ||||
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("createdAfter and createdInLast cannot be set simultaneously"); | |||||
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Parameters createdAfter and createdInLast cannot be set simultaneously"); | |||||
} | } | ||||
} | } | ||||
public void set_created_after_from_created_since() { | public void set_created_after_from_created_since() { | ||||
Date now = DateUtils.parseDateTime("2013-07-25T07:35:00+0100"); | Date now = DateUtils.parseDateTime("2013-07-25T07:35:00+0100"); | ||||
when(system.now()).thenReturn(now.getTime()); | when(system.now()).thenReturn(now.getTime()); | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("createdInLast", "1y2m3w4d"); | |||||
assertThat(underTest.createFromMap(map).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100")); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setCreatedInLast("1y2m3w4d"); | |||||
assertThat(underTest.create(request).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100")); | |||||
} | } | ||||
@Test | @Test | ||||
public void fail_if_since_leak_period_and_created_after_set_at_the_same_time() { | public void fail_if_since_leak_period_and_created_after_set_at_the_same_time() { | ||||
expectedException.expect(BadRequestException.class); | expectedException.expect(BadRequestException.class); | ||||
expectedException.expectMessage("'createdAfter' and 'sinceLeakPeriod' cannot be set simultaneously"); | |||||
expectedException.expectMessage("Parameters 'createdAfter' and 'sinceLeakPeriod' cannot be set simultaneously"); | |||||
underTest.createFromRequest(new SearchWsRequest() | |||||
underTest.create(new SearchWsRequest() | |||||
.setSinceLeakPeriod(true) | .setSinceLeakPeriod(true) | ||||
.setCreatedAfter("2013-07-25T07:35:00+0100")); | .setCreatedAfter("2013-07-25T07:35:00+0100")); | ||||
} | } | ||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("One and only one component must be provided when searching since leak period"); | expectedException.expectMessage("One and only one component must be provided when searching since leak period"); | ||||
underTest.createFromRequest(new SearchWsRequest().setSinceLeakPeriod(true)); | |||||
underTest.create(new SearchWsRequest().setSinceLeakPeriod(true)); | |||||
} | } | ||||
@Test | @Test | ||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("One and only one component must be provided when searching since leak period"); | expectedException.expectMessage("One and only one component must be provided when searching since leak period"); | ||||
underTest.createFromRequest(new SearchWsRequest() | |||||
underTest.create(new SearchWsRequest() | |||||
.setSinceLeakPeriod(true) | .setSinceLeakPeriod(true) | ||||
.setComponentUuids(newArrayList("component-uuid", "project-uuid"))); | |||||
.setComponentUuids(newArrayList("foo", "bar"))); | |||||
} | } | ||||
@Test | @Test | ||||
expectedException.expect(IllegalArgumentException.class); | expectedException.expect(IllegalArgumentException.class); | ||||
expectedException.expectMessage("'unknown-date' cannot be parsed as either a date or date+time"); | expectedException.expectMessage("'unknown-date' cannot be parsed as either a date or date+time"); | ||||
underTest.createFromRequest(new SearchWsRequest() | |||||
underTest.create(new SearchWsRequest() | |||||
.setCreatedAfter("unknown-date")); | .setCreatedAfter("unknown-date")); | ||||
} | } | ||||
@Test | @Test | ||||
public void return_empty_results_if_organization_with_specified_key_does_not_exist() { | public void return_empty_results_if_organization_with_specified_key_does_not_exist() { | ||||
Map<String, Object> map = new HashMap<>(); | |||||
map.put("organization", "does_not_exist"); | |||||
SearchWsRequest request = new SearchWsRequest() | |||||
.setOrganization("does_not_exist"); | |||||
IssueQuery query = underTest.createFromMap(map); | |||||
IssueQuery query = underTest.create(request); | |||||
assertThat(query.organizationUuid()).isEqualTo("<UNKNOWN>"); | assertThat(query.organizationUuid()).isEqualTo("<UNKNOWN>"); | ||||
} | } | ||||
} | } |
.tags(newArrayList("tag1", "tag2")) | .tags(newArrayList("tag1", "tag2")) | ||||
.types(newArrayList("RELIABILITY", "SECURITY")) | .types(newArrayList("RELIABILITY", "SECURITY")) | ||||
.assigned(true) | .assigned(true) | ||||
.hideRules(true) | |||||
.createdAfter(new Date()) | .createdAfter(new Date()) | ||||
.createdBefore(new Date()) | .createdBefore(new Date()) | ||||
.createdAt(new Date()) | .createdAt(new Date()) | ||||
assertThat(query.tags()).containsOnly("tag1", "tag2"); | assertThat(query.tags()).containsOnly("tag1", "tag2"); | ||||
assertThat(query.types()).containsOnly("RELIABILITY", "SECURITY"); | assertThat(query.types()).containsOnly("RELIABILITY", "SECURITY"); | ||||
assertThat(query.assigned()).isTrue(); | assertThat(query.assigned()).isTrue(); | ||||
assertThat(query.hideRules()).isTrue(); | |||||
assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle")); | assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle")); | ||||
assertThat(query.createdAfter()).isNotNull(); | assertThat(query.createdAfter()).isNotNull(); | ||||
assertThat(query.createdBefore()).isNotNull(); | assertThat(query.createdBefore()).isNotNull(); |
import com.google.common.collect.ImmutableMap; | import com.google.common.collect.ImmutableMap; | ||||
import java.util.Map; | import java.util.Map; | ||||
import org.junit.Before; | |||||
import org.junit.Test; | import org.junit.Test; | ||||
import org.junit.runner.RunWith; | |||||
import org.mockito.ArgumentCaptor; | import org.mockito.ArgumentCaptor; | ||||
import org.mockito.Mock; | |||||
import org.mockito.runners.MockitoJUnitRunner; | |||||
import org.mockito.Mockito; | |||||
import org.sonar.api.server.ws.WebService.Action; | import org.sonar.api.server.ws.WebService.Action; | ||||
import org.sonar.api.server.ws.WebService.Param; | import org.sonar.api.server.ws.WebService.Param; | ||||
import org.sonar.server.issue.IssueQuery; | import org.sonar.server.issue.IssueQuery; | ||||
import org.sonar.server.issue.IssueQueryFactory; | import org.sonar.server.issue.IssueQueryFactory; | ||||
import org.sonar.server.issue.IssueService; | import org.sonar.server.issue.IssueService; | ||||
import org.sonar.server.ws.WsTester; | |||||
import org.sonar.server.ws.TestResponse; | |||||
import org.sonar.server.ws.WsActionTester; | |||||
import org.sonarqube.ws.client.issue.SearchWsRequest; | |||||
import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||
import static org.mockito.Matchers.any; | |||||
import static org.mockito.Matchers.eq; | |||||
import static org.mockito.Mockito.mock; | import static org.mockito.Mockito.mock; | ||||
import static org.mockito.Mockito.verify; | |||||
import static org.mockito.Mockito.when; | import static org.mockito.Mockito.when; | ||||
import static org.sonar.test.JsonAssert.assertJson; | |||||
@RunWith(MockitoJUnitRunner.class) | |||||
public class ComponentTagsActionTest { | public class ComponentTagsActionTest { | ||||
@Mock | |||||
private IssueService service; | |||||
@Mock | |||||
private IssueQueryFactory queryService; | |||||
private ComponentTagsAction componentTagsAction; | |||||
private WsTester tester; | |||||
@Before | |||||
public void setUp() { | |||||
componentTagsAction = new ComponentTagsAction(service, queryService); | |||||
tester = new WsTester(new IssuesWs(componentTagsAction)); | |||||
} | |||||
private IssueService service = mock(IssueService.class); | |||||
private IssueQueryFactory issueQueryFactory = mock(IssueQueryFactory.class, Mockito.RETURNS_DEEP_STUBS); | |||||
private ComponentTagsAction underTest = new ComponentTagsAction(service, issueQueryFactory); | |||||
private WsActionTester tester = new WsActionTester(underTest); | |||||
@Test | @Test | ||||
public void should_define() { | public void should_define() { | ||||
Action action = tester.controller("api/issues").action("component_tags"); | |||||
Action action = tester.getDef(); | |||||
assertThat(action.description()).isNotEmpty(); | assertThat(action.description()).isNotEmpty(); | ||||
assertThat(action.responseExampleAsString()).isNotEmpty(); | assertThat(action.responseExampleAsString()).isNotEmpty(); | ||||
assertThat(action.isPost()).isFalse(); | assertThat(action.isPost()).isFalse(); | ||||
assertThat(action.isInternal()).isTrue(); | assertThat(action.isInternal()).isTrue(); | ||||
assertThat(action.handler()).isEqualTo(componentTagsAction); | |||||
assertThat(action.handler()).isEqualTo(underTest); | |||||
assertThat(action.params()).hasSize(3); | assertThat(action.params()).hasSize(3); | ||||
Param query = action.param("componentUuid"); | Param query = action.param("componentUuid"); | ||||
@Test | @Test | ||||
public void should_return_empty_list() throws Exception { | public void should_return_empty_list() throws Exception { | ||||
tester.newGetRequest("api/issues", "component_tags").setParam("componentUuid", "polop").execute().assertJson("{\"tags\":[]}"); | |||||
TestResponse response = tester.newRequest() | |||||
.setParam("componentUuid", "polop") | |||||
.execute(); | |||||
assertJson(response.getInput()).isSimilarTo("{\"tags\":[]}"); | |||||
} | } | ||||
@Test | @Test | ||||
.put("bug", 32L) | .put("bug", 32L) | ||||
.put("cert", 2L) | .put("cert", 2L) | ||||
.build(); | .build(); | ||||
IssueQuery query = mock(IssueQuery.class); | |||||
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class); | |||||
when(queryService.createFromMap(captor.capture())).thenReturn(query); | |||||
when(service.listTagsForComponent(query, 5)).thenReturn(tags); | |||||
ArgumentCaptor<SearchWsRequest> captor = ArgumentCaptor.forClass(SearchWsRequest.class); | |||||
when(issueQueryFactory.create(captor.capture())).thenReturn(mock(IssueQuery.class)); | |||||
when(service.listTagsForComponent(any(IssueQuery.class), eq(5))).thenReturn(tags); | |||||
TestResponse response = tester.newRequest() | |||||
.setParam("componentUuid", "polop") | |||||
.setParam("ps", "5") | |||||
.execute(); | |||||
assertJson(response.getInput()).isSimilarTo(getClass().getResource("ComponentTagsActionTest/component-tags.json")); | |||||
tester.newGetRequest("api/issues", "component_tags").setParam("componentUuid", "polop").setParam("ps", "5").execute() | |||||
.assertJson(getClass(), "component-tags.json"); | |||||
assertThat(captor.getValue()) | |||||
.containsEntry("componentUuids", "polop") | |||||
.containsEntry("resolved", false); | |||||
verify(service).listTagsForComponent(query, 5); | |||||
assertThat(captor.getValue().getComponentUuids()).containsOnly("polop"); | |||||
assertThat(captor.getValue().getResolved()).isFalse(); | |||||
assertThat(captor.getValue().getCreatedAfter()).isNull(); | |||||
} | } | ||||
@Test | @Test | ||||
.put("bug", 32L) | .put("bug", 32L) | ||||
.put("cert", 2L) | .put("cert", 2L) | ||||
.build(); | .build(); | ||||
IssueQuery query = mock(IssueQuery.class); | |||||
ArgumentCaptor<Map> captor = ArgumentCaptor.forClass(Map.class); | |||||
when(queryService.createFromMap(captor.capture())).thenReturn(query); | |||||
when(service.listTagsForComponent(query, 5)).thenReturn(tags); | |||||
ArgumentCaptor<SearchWsRequest> captor = ArgumentCaptor.forClass(SearchWsRequest.class); | |||||
when(issueQueryFactory.create(captor.capture())).thenReturn(mock(IssueQuery.class)); | |||||
when(service.listTagsForComponent(any(IssueQuery.class), eq(5))).thenReturn(tags); | |||||
String componentUuid = "polop"; | String componentUuid = "polop"; | ||||
String createdAfter = "2011-04-25"; | String createdAfter = "2011-04-25"; | ||||
tester.newGetRequest("api/issues", "component_tags") | |||||
TestResponse response = tester.newRequest() | |||||
.setParam("componentUuid", componentUuid) | .setParam("componentUuid", componentUuid) | ||||
.setParam("createdAfter", createdAfter) | .setParam("createdAfter", createdAfter) | ||||
.setParam("ps", "5") | .setParam("ps", "5") | ||||
.execute() | |||||
.assertJson(getClass(), "component-tags.json"); | |||||
assertThat(captor.getValue()) | |||||
.containsEntry("componentUuids", componentUuid) | |||||
.containsEntry("resolved", false) | |||||
.containsEntry("createdAfter", createdAfter); | |||||
verify(service).listTagsForComponent(query, 5); | |||||
.execute(); | |||||
assertJson(response.getInput()).isSimilarTo(getClass().getResource("ComponentTagsActionTest/component-tags.json")); | |||||
assertThat(captor.getValue().getComponentUuids()).containsOnly(componentUuid); | |||||
assertThat(captor.getValue().getResolved()).isFalse(); | |||||
assertThat(captor.getValue().getCreatedAfter()).isEqualTo(createdAfter); | |||||
} | } | ||||
} | } |
assertThat(def.since()).isEqualTo("3.6"); | assertThat(def.since()).isEqualTo("3.6"); | ||||
assertThat(def.responseExampleAsString()).isNotEmpty(); | assertThat(def.responseExampleAsString()).isNotEmpty(); | ||||
assertThat(def.params()).extracting("key").containsOnly( | |||||
assertThat(def.params()).extracting("key").containsExactlyInAnyOrder( | |||||
"actionPlans", "additionalFields", "asc", "assigned", "assignees", "authors", "componentKeys", "componentRootUuids", "componentRoots", "componentUuids", "components", | "actionPlans", "additionalFields", "asc", "assigned", "assignees", "authors", "componentKeys", "componentRootUuids", "componentRoots", "componentUuids", "components", | ||||
"createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facetMode", "facets", "fileUuids", "issues", "languages", "moduleUuids", "onComponentOnly", | "createdAfter", "createdAt", "createdBefore", "createdInLast", "directories", "facetMode", "facets", "fileUuids", "issues", "languages", "moduleUuids", "onComponentOnly", | ||||
"organization", "p", "planned", "projectKeys", "projectUuids", "projects", "ps", "reporters", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", | "organization", "p", "planned", "projectKeys", "projectUuids", "projects", "ps", "reporters", "resolutions", "resolved", "rules", "s", "severities", "sinceLeakPeriod", |