Procházet zdrojové kódy

SONAR-8890 Restrict ps parameter of WS api/issues/tags

tags/6.6-RC1
Teryk Bellahsene před 7 roky
rodič
revize
e9b7afec11

+ 165
- 164
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java Zobrazit soubor

@@ -70,7 +70,9 @@ import org.sonar.server.user.UserSession;
import org.sonar.server.view.index.ViewIndexDefinition;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Preconditions.checkArgument;
import static java.lang.String.format;
import static java.util.Collections.emptyList;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
@@ -106,8 +108,6 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPES;
*/
public class IssueIndex {

private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";

public static final List<String> SUPPORTED_FACETS = ImmutableList.of(
PARAM_SEVERITIES,
PARAM_STATUSES,
@@ -126,23 +126,18 @@ public class IssueIndex {
PARAM_TAGS,
PARAM_TYPES,
PARAM_CREATED_AT);

public static final String AGGREGATION_NAME_FOR_TAGS = "tags__issues";
private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";
// TODO to be documented
// TODO move to Facets ?
private static final String FACET_SUFFIX_MISSING = "_missing";

private static final String IS_ASSIGNED_FILTER = "__isAssigned";

private static final SumBuilder EFFORT_AGGREGATION = AggregationBuilders.sum(FACET_MODE_EFFORT).field(IssueIndexDefinition.FIELD_ISSUE_EFFORT);
private static final Order EFFORT_AGGREGATION_ORDER = Order.aggregation(FACET_MODE_EFFORT, false);

private static final int DEFAULT_FACET_SIZE = 15;
private static final Duration TWENTY_DAYS = Duration.standardDays(20L);
private static final Duration TWENTY_WEEKS = Duration.standardDays(20L * 7L);
private static final Duration TWENTY_MONTHS = Duration.standardDays(20L * 30L);

public static final String AGGREGATION_NAME_FOR_TAGS = "tags__issues";

private final Sorting sorting;
private final EsClient client;
private final System2 system;
@@ -176,6 +171,160 @@ public class IssueIndex {
this.sorting.addDefault(IssueIndexDefinition.FIELD_ISSUE_KEY);
}

/**
* Optimization - do not send ES request to all shards when scope is restricted
* to a set of projects. Because project UUID is used for routing, the request
* can be sent to only the shards containing the specified projects.
* Note that sticky facets may involve all projects, so this optimization must be
* disabled when facets are enabled.
*/
private static void configureRouting(IssueQuery query, SearchOptions options, SearchRequestBuilder requestBuilder) {
Collection<String> uuids = query.projectUuids();
if (!uuids.isEmpty() && options.getFacets().isEmpty()) {
requestBuilder.setRouting(uuids.toArray(new String[uuids.size()]));
}
}

private static void configurePagination(SearchOptions options, SearchRequestBuilder esSearch) {
esSearch.setFrom(options.getOffset()).setSize(options.getLimit());
}

private static void addComponentRelatedFilters(IssueQuery query, Map<String, QueryBuilder> filters) {
QueryBuilder viewFilter = createViewFilter(query.viewUuids());
QueryBuilder componentFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
QueryBuilder projectFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids());
QueryBuilder moduleRootFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, query.moduleRootUuids());
QueryBuilder moduleFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids());
QueryBuilder directoryFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories());
QueryBuilder fileFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());

if (BooleanUtils.isTrue(query.onComponentOnly())) {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
} else {
filters.put("__view", viewFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter);
filters.put("__module", moduleRootFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
if (fileFilter != null) {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
} else {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
}
}
}

@CheckForNull
private static QueryBuilder createViewFilter(Collection<String> viewUuids) {
if (viewUuids.isEmpty()) {
return null;
}

BoolQueryBuilder viewsFilter = boolQuery();
for (String viewUuid : viewUuids) {
viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)
.lookupIndex(ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex())
.lookupType(ViewIndexDefinition.INDEX_TYPE_VIEW.getType())
.lookupId(viewUuid)
.lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
}
return viewsFilter;
}

private static StickyFacetBuilder newStickyFacetBuilder(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
if (hasQueryEffortFacet(query)) {
return new StickyFacetBuilder(esQuery, filters, EFFORT_AGGREGATION, EFFORT_AGGREGATION_ORDER);
}
return new StickyFacetBuilder(esQuery, filters);
}

private static void addSimpleStickyFacetIfNeeded(SearchOptions options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch,
String facetName, String fieldName, Object... selectedValues) {
if (options.getFacets().contains(facetName)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_FACET_SIZE, selectedValues));
}
}

private static AggregationBuilder addEffortAggregationIfNeeded(IssueQuery query, AggregationBuilder aggregation) {
if (hasQueryEffortFacet(query)) {
aggregation.subAggregation(EFFORT_AGGREGATION);
}
return aggregation;
}

private static boolean hasQueryEffortFacet(IssueQuery query) {
return FACET_MODE_EFFORT.equals(query.facetMode()) || DEPRECATED_FACET_MODE_DEBT.equals(query.facetMode());
}

private static AggregationBuilder createAssigneesFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
String facetName = PARAM_ASSIGNEES;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> assigneeFilters = Maps.newHashMap(filters);
assigneeFilters.remove(IS_ASSIGNED_FILTER);
assigneeFilters.remove(fieldName);
StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, assigneeFilters, queryBuilder);
BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);

Collection<String> assigneesEscaped = escapeValuesForFacetInclusion(query.assignees());
if (!assigneesEscaped.isEmpty()) {
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t, assigneesEscaped.toArray());
}

// Add missing facet for unassigned issues
facetTopAggregation.subAggregation(
addEffortAggregationIfNeeded(query, AggregationBuilders
.missing(facetName + FACET_SUFFIX_MISSING)
.field(fieldName)));

return AggregationBuilders
.global(facetName)
.subAggregation(facetTopAggregation);
}

private static Collection<String> escapeValuesForFacetInclusion(@Nullable Collection<String> values) {
if (values == null) {
return Collections.emptyList();
}
return values.stream().map(Pattern::quote).collect(MoreCollectors.toArrayList(values.size()));
}

private static AggregationBuilder createResolutionFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
String facetName = PARAM_RESOLUTIONS;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> resolutionFilters = Maps.newHashMap(filters);
resolutionFilters.remove("__isResolved");
resolutionFilters.remove(fieldName);
StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, resolutionFilters, esQuery);
BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t);

// Add missing facet for unresolved issues
facetTopAggregation.subAggregation(
addEffortAggregationIfNeeded(query, AggregationBuilders
.missing(facetName + FACET_SUFFIX_MISSING)
.field(fieldName)));

return AggregationBuilders
.global(facetName)
.subAggregation(facetTopAggregation);
}

@CheckForNull
private static QueryBuilder createTermsFilter(String field, Collection<?> values) {
return values.isEmpty() ? null : termsQuery(field, values);
}

@CheckForNull
private static QueryBuilder createTermFilter(String field, @Nullable String value) {
return value == null ? null : termQuery(field, value);
}

public SearchResponse search(IssueQuery query, SearchOptions options) {
SearchRequestBuilder requestBuilder = client.prepareSearch(INDEX_TYPE_ISSUE);

@@ -202,20 +351,6 @@ public class IssueIndex {
return requestBuilder.get();
}

/**
* Optimization - do not send ES request to all shards when scope is restricted
* to a set of projects. Because project UUID is used for routing, the request
* can be sent to only the shards containing the specified projects.
* Note that sticky facets may involve all projects, so this optimization must be
* disabled when facets are enabled.
*/
private static void configureRouting(IssueQuery query, SearchOptions options, SearchRequestBuilder requestBuilder) {
Collection<String> uuids = query.projectUuids();
if (!uuids.isEmpty() && options.getFacets().isEmpty()) {
requestBuilder.setRouting(uuids.toArray(new String[uuids.size()]));
}
}

private void configureSorting(IssueQuery query, SearchRequestBuilder esRequest) {
String sortField = query.sort();
if (sortField != null) {
@@ -226,10 +361,6 @@ public class IssueIndex {
}
}

private static void configurePagination(SearchOptions options, SearchRequestBuilder esSearch) {
esSearch.setFrom(options.getOffset()).setSize(options.getLimit());
}

private Map<String, QueryBuilder> createFilters(IssueQuery query) {
Map<String, QueryBuilder> filters = new HashMap<>();
filters.put("__authorization", createAuthorizationFilter(query.checkAuthorization()));
@@ -270,48 +401,6 @@ public class IssueIndex {
return filters;
}

private static void addComponentRelatedFilters(IssueQuery query, Map<String, QueryBuilder> filters) {
QueryBuilder viewFilter = createViewFilter(query.viewUuids());
QueryBuilder componentFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids());
QueryBuilder projectFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids());
QueryBuilder moduleRootFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, query.moduleRootUuids());
QueryBuilder moduleFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids());
QueryBuilder directoryFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories());
QueryBuilder fileFilter = createTermsFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids());

if (BooleanUtils.isTrue(query.onComponentOnly())) {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
} else {
filters.put("__view", viewFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, projectFilter);
filters.put("__module", moduleRootFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, moduleFilter);
filters.put(IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, directoryFilter);
if (fileFilter != null) {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, fileFilter);
} else {
filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentFilter);
}
}
}

@CheckForNull
private static QueryBuilder createViewFilter(Collection<String> viewUuids) {
if (viewUuids.isEmpty()) {
return null;
}

BoolQueryBuilder viewsFilter = boolQuery();
for (String viewUuid : viewUuids) {
viewsFilter.should(QueryBuilders.termsLookupQuery(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID)
.lookupIndex(ViewIndexDefinition.INDEX_TYPE_VIEW.getIndex())
.lookupType(ViewIndexDefinition.INDEX_TYPE_VIEW.getType())
.lookupId(viewUuid)
.lookupPath(ViewIndexDefinition.FIELD_PROJECTS));
}
return viewsFilter;
}

private QueryBuilder createAuthorizationFilter(boolean checkAuthorization) {
if (checkAuthorization) {
return authorizationTypeSupport.createQueryFilter();
@@ -395,31 +484,6 @@ public class IssueIndex {
}
}

private static StickyFacetBuilder newStickyFacetBuilder(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
if (hasQueryEffortFacet(query)) {
return new StickyFacetBuilder(esQuery, filters, EFFORT_AGGREGATION, EFFORT_AGGREGATION_ORDER);
}
return new StickyFacetBuilder(esQuery, filters);
}

private static void addSimpleStickyFacetIfNeeded(SearchOptions options, StickyFacetBuilder stickyFacetBuilder, SearchRequestBuilder esSearch,
String facetName, String fieldName, Object... selectedValues) {
if (options.getFacets().contains(facetName)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(fieldName, facetName, DEFAULT_FACET_SIZE, selectedValues));
}
}

private static AggregationBuilder addEffortAggregationIfNeeded(IssueQuery query, AggregationBuilder aggregation) {
if (hasQueryEffortFacet(query)) {
aggregation.subAggregation(EFFORT_AGGREGATION);
}
return aggregation;
}

private static boolean hasQueryEffortFacet(IssueQuery query) {
return FACET_MODE_EFFORT.equals(query.facetMode()) || DEPRECATED_FACET_MODE_DEBT.equals(query.facetMode());
}

private Optional<AggregationBuilder> getCreatedAtFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
long startTime;
Date createdAfter = query.createdAfter();
@@ -483,41 +547,6 @@ public class IssueIndex {
return Optional.of(actualValue.longValue());
}

private static AggregationBuilder createAssigneesFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
String facetName = PARAM_ASSIGNEES;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> assigneeFilters = Maps.newHashMap(filters);
assigneeFilters.remove(IS_ASSIGNED_FILTER);
assigneeFilters.remove(fieldName);
StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, assigneeFilters, queryBuilder);
BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);

Collection<String> assigneesEscaped = escapeValuesForFacetInclusion(query.assignees());
if (!assigneesEscaped.isEmpty()) {
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t, assigneesEscaped.toArray());
}

// Add missing facet for unassigned issues
facetTopAggregation.subAggregation(
addEffortAggregationIfNeeded(query, AggregationBuilders
.missing(facetName + FACET_SUFFIX_MISSING)
.field(fieldName)));

return AggregationBuilders
.global(facetName)
.subAggregation(facetTopAggregation);
}

private static Collection<String> escapeValuesForFacetInclusion(@Nullable Collection<String> values) {
if (values == null) {
return Collections.emptyList();
}
return values.stream().map(Pattern::quote).collect(MoreCollectors.toArrayList(values.size()));
}

private void addAssignedToMeFacetIfNeeded(SearchRequestBuilder builder, SearchOptions options, IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
String login = userSession.getLogin();

@@ -544,41 +573,13 @@ public class IssueIndex {
.subAggregation(facetTopAggregation));
}

private static AggregationBuilder createResolutionFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
String facetName = PARAM_RESOLUTIONS;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> resolutionFilters = Maps.newHashMap(filters);
resolutionFilters.remove("__isResolved");
resolutionFilters.remove(fieldName);
StickyFacetBuilder assigneeFacetBuilder = newStickyFacetBuilder(query, resolutionFilters, esQuery);
BoolQueryBuilder facetFilter = assigneeFacetBuilder.getStickyFacetFilter(fieldName);
FilterAggregationBuilder facetTopAggregation = assigneeFacetBuilder.buildTopFacetAggregation(fieldName, facetName, facetFilter, DEFAULT_FACET_SIZE);
facetTopAggregation = assigneeFacetBuilder.addSelectedItemsToFacet(fieldName, facetName, facetTopAggregation, t -> t);

// Add missing facet for unresolved issues
facetTopAggregation.subAggregation(
addEffortAggregationIfNeeded(query, AggregationBuilders
.missing(facetName + FACET_SUFFIX_MISSING)
.field(fieldName)));

return AggregationBuilders
.global(facetName)
.subAggregation(facetTopAggregation);
}

@CheckForNull
private static QueryBuilder createTermsFilter(String field, Collection<?> values) {
return values.isEmpty() ? null : termsQuery(field, values);
}

@CheckForNull
private static QueryBuilder createTermFilter(String field, @Nullable String value) {
return value == null ? null : termQuery(field, value);
}
public List<String> listTags(OrganizationDto organization, @Nullable String textQuery, int size) {
int maxPageSize = 500;
checkArgument(size <= maxPageSize, "Page size must be lower than or equals to " + maxPageSize);
if (size <= 0) {
return emptyList();
}

public List<String> listTags(OrganizationDto organization, @Nullable String textQuery, int maxNumberOfTags) {
SearchRequestBuilder requestBuilder = client
.prepareSearch(INDEX_TYPE_ISSUE)
.setQuery(boolQuery()
@@ -588,7 +589,7 @@ public class IssueIndex {

TermsBuilder termsAggregation = AggregationBuilders.terms(AGGREGATION_NAME_FOR_TAGS)
.field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
.size(maxNumberOfTags)
.size(size)
.order(Terms.Order.term(true))
.minDocCount(1L);
if (textQuery != null) {

+ 10
- 16
server/sonar-server/src/main/java/org/sonar/server/issue/ws/TagsAction.java Zobrazit soubor

@@ -41,7 +41,6 @@ import org.sonar.server.organization.DefaultOrganizationProvider;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.ws.WsUtils;

import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_ORGANIZATION;

/**
@@ -62,6 +61,14 @@ public class TagsAction implements IssuesWsAction {
this.defaultOrganizationProvider = defaultOrganizationProvider;
}

private static void writeResponse(Response response, List<String> tags) {
try (JsonWriter json = response.newJsonWriter()) {
json.beginObject().name("tags").beginArray();
tags.forEach(json::value);
json.endArray().endObject();
}
}

@Override
public void define(WebService.NewController controller) {
NewAction action = controller.createAction("tags")
@@ -69,13 +76,8 @@ public class TagsAction implements IssuesWsAction {
.setSince("5.1")
.setDescription("List tags matching a given query")
.setResponseExample(Resources.getResource(getClass(), "tags-example.json"));
action.createParam(Param.TEXT_QUERY)
.setDescription("A pattern to match tags against")
.setExampleValue("misra");
action.createParam(PAGE_SIZE)
.setDescription("The size of the list to return")
.setExampleValue("25")
.setDefaultValue("10");
action.createSearchQuery("misra", "tags");
action.createPageSize(10, 100);
action.createParam(PARAM_ORGANIZATION)
.setDescription("Organization key")
.setRequired(false)
@@ -114,12 +116,4 @@ public class TagsAction implements IssuesWsAction {
}
}

private static void writeResponse(Response response, List<String> tags) {
try (JsonWriter json = response.newJsonWriter()) {
json.beginObject().name("tags").beginArray();
tags.forEach(json::value);
json.endArray().endObject();
}
}

}

+ 18
- 8
server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexTest.java Zobrazit soubor

@@ -77,20 +77,20 @@ import static org.sonar.server.issue.IssueDocTesting.newDoc;

public class IssueIndexTest {

private System2 system2 = mock(System2.class);
private MapSettings settings = new MapSettings();

@Rule
public EsTester es = new EsTester(
new IssueIndexDefinition(settings.asConfig()),
new ViewIndexDefinition(settings.asConfig()),
new RuleIndexDefinition(settings.asConfig()));
@Rule
public DbTester db = DbTester.create(system2);
@Rule
public UserSessionRule userSessionRule = UserSessionRule.standalone();
@Rule
public ExpectedException expectedException = ExpectedException.none();

private System2 system2 = mock(System2.class);
@Rule
public DbTester db = DbTester.create(system2);
private IssueIndexer issueIndexer = new IssueIndexer(es.client(), db.getDbClient(), new IssueIteratorFactory(db.getDbClient()));
private ViewIndexer viewIndexer = new ViewIndexer(db.getDbClient(), es.client());
private RuleIndexer ruleIndexer = new RuleIndexer(es.client(), db.getDbClient());
@@ -1083,12 +1083,22 @@ public class IssueIndexTest {
newDoc("I3", file).setOrganizationUuid(org.getUuid()).setRuleKey(r2.getKey().toString()),
newDoc("I4", file).setOrganizationUuid(org.getUuid()).setRuleKey(r1.getKey().toString()).setTags(of("convention")));

assertThat(underTest.listTags(org, null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug");
assertThat(underTest.listTags(org, null, 100)).containsOnly("convention", "java8", "bug");
assertThat(underTest.listTags(org, null, 2)).containsOnly("bug", "convention");
assertThat(underTest.listTags(org, "vent", Integer.MAX_VALUE)).containsOnly("convention");
assertThat(underTest.listTags(org, "vent", 100)).containsOnly("convention");
assertThat(underTest.listTags(org, null, 1)).containsOnly("bug");
assertThat(underTest.listTags(org, null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug");
assertThat(underTest.listTags(org, "invalidRegexp[", Integer.MAX_VALUE)).isEmpty();
assertThat(underTest.listTags(org, null, 100)).containsOnly("convention", "java8", "bug");
assertThat(underTest.listTags(org, "invalidRegexp[", 100)).isEmpty();
}

@Test
public void fail_to_list_tags_when_size_greater_than_500() {
OrganizationDto organization = db.organizations().insert();

expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Page size must be lower than or equals to 500");

underTest.listTags(organization, null, 501);
}

@Test

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java Zobrazit soubor

@@ -45,11 +45,11 @@ public class SearchActionTest {
private SearchResponseLoader searchResponseLoader = mock(SearchResponseLoader.class);
private SearchResponseFormat searchResponseFormat = mock(SearchResponseFormat.class);
private SearchAction underTest = new SearchAction(userSession, index, issueQueryFactory, searchResponseLoader, searchResponseFormat);
private WsActionTester wsTester = new WsActionTester(underTest);
private WsActionTester ws = new WsActionTester(underTest);

@Test
public void test_definition() {
WebService.Action def = wsTester.getDef();
WebService.Action def = ws.getDef();
assertThat(def.key()).isEqualTo("search");
assertThat(def.isInternal()).isFalse();
assertThat(def.isPost()).isFalse();

+ 15
- 16
server/sonar-server/src/test/java/org/sonar/server/issue/ws/TagsActionTest.java Zobrazit soubor

@@ -70,7 +70,7 @@ public class TagsActionTest {
private IssueIndex issueIndex = new IssueIndex(esTester.client(), System2.INSTANCE, userSession, new AuthorizationTypeSupport(userSession));
private RuleIndex ruleIndex = new RuleIndex(esTester.client());

private WsActionTester tester = new WsActionTester(new TagsAction(issueIndex, ruleIndex, dbTester.getDbClient(), TestDefaultOrganizationProvider.from(dbTester)));
private WsActionTester ws = new WsActionTester(new TagsAction(issueIndex, ruleIndex, dbTester.getDbClient(), TestDefaultOrganizationProvider.from(dbTester)));
private OrganizationDto organization;

@Before
@@ -84,7 +84,7 @@ public class TagsActionTest {
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4", "tag5");

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]}");
@@ -103,7 +103,7 @@ public class TagsActionTest {
dbTester.rules().insertOrUpdateMetadata(r2, organization, setTags("tag4", "tag5"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r2.getKey(), organization);

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]}");
@@ -120,7 +120,7 @@ public class TagsActionTest {
dbTester.rules().insertOrUpdateMetadata(r, organization, setTags("tag7"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r.getKey(), organization);

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\", \"tag6\", \"tag7\"]}");
@@ -132,7 +132,7 @@ public class TagsActionTest {
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4", "tag5");

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("ps", "2")
.setParam("organization", organization.getKey())
.execute().getInput();
@@ -145,7 +145,7 @@ public class TagsActionTest {
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag12", "tag4", "tag5");

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("q", "ag1")
.setParam("organization", organization.getKey())
.execute().getInput();
@@ -158,7 +158,7 @@ public class TagsActionTest {
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "tag1", "tag2");
insertIssueWithoutBrowsePermission(insertRuleWithoutTags(), "tag3", "tag4");

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[\"tag1\", \"tag2\"]}");
@@ -166,14 +166,14 @@ public class TagsActionTest {
}

@Test
public void return_empty_list() throws Exception {
public void empty_list() throws Exception {
userSession.logIn();
String result = tester.newRequest().execute().getInput();
String result = ws.newRequest().execute().getInput();
assertJson(result).isSimilarTo("{\"tags\":[]}");
}

@Test
public void test_example() throws Exception {
public void json_example() throws Exception {
userSession.logIn();
insertIssueWithBrowsePermission(insertRuleWithoutTags(), "convention");

@@ -182,16 +182,17 @@ public class TagsActionTest {
dbTester.rules().insertOrUpdateMetadata(r, organization, setTags("security"));
ruleIndexer.commitAndIndex(dbTester.getSession(), r.getKey(), organization);

String result = tester.newRequest()
String result = ws.newRequest()
.setParam("organization", organization.getKey())
.execute().getInput();
assertJson(result).isSimilarTo(tester.getDef().responseExampleAsString());

assertJson(result).isSimilarTo(ws.getDef().responseExampleAsString());
}

@Test
public void test_definition() {
public void definition() {
userSession.logIn();
Action action = tester.getDef();
Action action = ws.getDef();
assertThat(action.description()).isNotEmpty();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.isPost()).isFalse();
@@ -199,13 +200,11 @@ public class TagsActionTest {
assertThat(action.params()).extracting(Param::key).containsExactlyInAnyOrder("q", "ps", "organization");

Param query = action.param("q");
assertThat(query).isNotNull();
assertThat(query.isRequired()).isFalse();
assertThat(query.description()).isNotEmpty();
assertThat(query.exampleValue()).isNotEmpty();

Param pageSize = action.param("ps");
assertThat(pageSize).isNotNull();
assertThat(pageSize.isRequired()).isFalse();
assertThat(pageSize.defaultValue()).isEqualTo("10");
assertThat(pageSize.description()).isNotEmpty();

Načítá se…
Zrušit
Uložit