diff options
author | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2016-03-15 16:10:17 +0100 |
---|---|---|
committer | Teryk Bellahsene <teryk.bellahsene@sonarsource.com> | 2016-03-16 16:53:06 +0100 |
commit | 887cda2d00ba7b62ee311bc78a4ea611696e9761 (patch) | |
tree | 92ad7a5df04ca4a7657c42dc450a28e0109e3f60 | |
parent | b7fa24cc420d8ca593af5df68e4147dbe7da1bfa (diff) | |
download | sonarqube-887cda2d00ba7b62ee311bc78a4ea611696e9761.tar.gz sonarqube-887cda2d00ba7b62ee311bc78a4ea611696e9761.zip |
SONAR-7200 WS api/issues/search filter issues on leak period
9 files changed, 233 insertions, 53 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java index 2cc8d64f234..0ddc0f472f8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java @@ -21,7 +21,6 @@ package org.sonar.server.issue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.base.Strings; import com.google.common.collect.Collections2; @@ -30,6 +29,7 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.util.Collection; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -46,20 +46,29 @@ import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.SonarException; import org.sonar.api.utils.System2; import org.sonar.api.web.UserRole; -import org.sonar.server.rule.RuleKeyFunctions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; import org.sonar.server.component.ComponentService; +import org.sonar.server.rule.RuleKeyFunctions; import org.sonar.server.user.UserSession; import org.sonar.server.util.RubyUtils; import org.sonarqube.ws.client.issue.IssueFilterParameters; import org.sonarqube.ws.client.issue.SearchWsRequest; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Lists.newArrayList; +import static java.lang.String.format; +import static org.sonar.api.utils.DateUtils.longToDate; import static org.sonar.db.component.ComponentDtoFunctions.toCopyResourceId; import static org.sonar.db.component.ComponentDtoFunctions.toProjectUuid; import static org.sonar.db.component.ComponentDtoFunctions.toUuid; +import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; +import static org.sonar.server.ws.WsUtils.checkRequest; +import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_AFTER; +import static org.sonarqube.ws.client.issue.IssueFilterParameters.CREATED_IN_LAST; +import static org.sonarqube.ws.client.issue.IssueFilterParameters.SINCE_LEAK_PERIOD; /** * This component is used to create an IssueQuery, in order to transform the component and component roots keys into uuid. @@ -103,7 +112,7 @@ public class IssueQueryService { .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED))) .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES))) .createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT))) - .createdAfter(buildCreatedAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER)), (String) params.get(IssueFilterParameters.CREATED_IN_LAST))) + .createdAfter(buildCreatedAfterFromDates(RubyUtils.toDate(params.get(CREATED_AFTER)), (String) params.get(CREATED_IN_LAST))) .createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE))); Set<String> allComponentUuids = Sets.newHashSet(); @@ -147,12 +156,12 @@ public class IssueQueryService { } } - private Date buildCreatedAfter(@Nullable Date createdAfter, @Nullable String createdSince) { - Preconditions.checkArgument(createdAfter == null || createdSince == null, "createdAfter and createdSince cannot be set simultaneously"); + private Date buildCreatedAfterFromDates(@Nullable Date createdAfter, @Nullable String createdInLast) { + checkArgument(createdAfter == null || createdInLast == null, format("%s and %s cannot be set simultaneously", CREATED_AFTER, CREATED_IN_LAST)); Date actualCreatedAfter = createdAfter; - if (createdSince != null) { - actualCreatedAfter = new DateTime(system.now()).minus(ISOPeriodFormat.standard().parsePeriod("P" + createdSince.toUpperCase())).toDate(); + if (createdInLast != null) { + actualCreatedAfter = new DateTime(system.now()).minus(ISOPeriodFormat.standard().parsePeriod("P" + createdInLast.toUpperCase())).toDate(); } return actualCreatedAfter; } @@ -176,7 +185,6 @@ public class IssueQueryService { .assigned(request.getAssigned()) .planned(request.getPlanned()) .createdAt(parseAsDateTime(request.getCreatedAt())) - .createdAfter(buildCreatedAfter(parseAsDateTime(request.getCreatedAfter()), request.getCreatedInLast())) .createdBefore(parseAsDateTime(request.getCreatedBefore())) .facetMode(request.getFacetMode()); @@ -200,6 +208,8 @@ public class IssueQueryService { request.getFileUuids(), request.getAuthors()); + builder.createdAfter(buildCreatedAfterFromRequest(session, request, allComponentUuids, effectiveOnComponentOnly)); + String sort = request.getSort(); if (!Strings.isNullOrEmpty(sort)) { builder.sort(sort); @@ -212,6 +222,42 @@ public class IssueQueryService { } } + private Date buildCreatedAfterFromRequest(DbSession dbSession, SearchWsRequest request, Set<String> componentUuids, boolean effectiveOnComponentOnly) { + Date createdAfter = parseAsDateTime(request.getCreatedAfter()); + String createdInLast = request.getCreatedInLast(); + + if (request.getSinceLeakPeriod() == null || !request.getSinceLeakPeriod()) { + return buildCreatedAfterFromDates(createdAfter, createdInLast); + } + + checkRequest(createdAfter == null, "'%s' and '%s' cannot be set simultaneously", CREATED_AFTER, SINCE_LEAK_PERIOD); + Set<String> allComponentUuids = new HashSet<>(componentUuids); + if (!effectiveOnComponentOnly) { + if (request.getProjectKeys() != null) { + allComponentUuids.addAll(componentUuids(dbSession, request.getProjectKeys())); + } + if (request.getProjectUuids() != null) { + allComponentUuids.addAll(request.getProjectUuids()); + } + if (request.getModuleUuids() != null) { + allComponentUuids.addAll(request.getModuleUuids()); + } + if (request.getFileUuids() != null) { + allComponentUuids.addAll(request.getFileUuids()); + } + } + + checkArgument(allComponentUuids.size() == 1, "One and only one component must be provided when searching since leak period"); + String uuid = allComponentUuids.iterator().next(); + // TODO use ComponentFinder instead + ComponentDto component = checkFoundWithOptional(componentService.getByUuid(uuid), "Component with id '%s' not found", uuid); + SnapshotDto snapshot = dbClient.snapshotDao().selectLastSnapshotByComponentId(dbSession, component.getId()); + Long projectSnapshotId = snapshot == null ? null : snapshot.getRootId(); + SnapshotDto projectSnapshot = projectSnapshotId == null ? snapshot : dbClient.snapshotDao().selectById(dbSession, projectSnapshotId); + Date createdAfterFromSnapshot = projectSnapshot == null ? null : longToDate(projectSnapshot.getPeriodDate(1)); + return buildCreatedAfterFromDates(createdAfterFromSnapshot, createdInLast); + } + private List<String> buildAssignees(@Nullable List<String> assigneesFromParams) { List<String> assignees = Lists.newArrayList(); if (assigneesFromParams != null) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java index 30dc75db6aa..7430632729a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java @@ -92,6 +92,7 @@ import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLUTIONS; import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLVED; import static org.sonarqube.ws.client.issue.IssueFilterParameters.RULES; import static org.sonarqube.ws.client.issue.IssueFilterParameters.SEVERITIES; +import static org.sonarqube.ws.client.issue.IssueFilterParameters.SINCE_LEAK_PERIOD; import static org.sonarqube.ws.client.issue.IssueFilterParameters.STATUSES; import static org.sonarqube.ws.client.issue.IssueFilterParameters.TAGS; import static org.sonarqube.ws.client.issue.IssueFilterParameters.TYPES; @@ -206,6 +207,11 @@ public class SearchAction implements IssuesWsAction { "Accepted units are 'y' for year, 'm' for month, 'w' for week and 'd' for day. " + "If this parameter is set, createdAfter must not be set") .setExampleValue("1m2w (1 month 2 weeks)"); + action.createParam(SINCE_LEAK_PERIOD) + .setDescription("To retrieve issues created since the leak period.<br>" + + "If this parameter is set to a truthy value, createdAfter must not be set and one component id or key must be provided.") + .setBooleanPossibleValues() + .setDefaultValue("false"); } private static void addComponentRelatedParams(WebService.NewAction action) { @@ -453,6 +459,7 @@ public class SearchAction implements IssuesWsAction { .setResolutions(request.paramAsStrings(RESOLUTIONS)) .setResolved(request.paramAsBoolean(RESOLVED)) .setRules(request.paramAsStrings(RULES)) + .setSinceLeakPeriod(request.mandatoryParamAsBoolean(SINCE_LEAK_PERIOD)) .setSort(request.param(Param.SORT)) .setSeverities(request.paramAsStrings(SEVERITIES)) .setStatuses(request.paramAsStrings(STATUSES)) diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java index b7601b7ed60..659be6dc3c6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java @@ -24,12 +24,14 @@ import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.Map; import org.assertj.core.api.Fail; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Matchers; import org.mockito.Mock; @@ -47,7 +49,9 @@ import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDto; import org.sonar.db.user.AuthorDao; import org.sonar.server.component.ComponentService; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.tester.UserSessionRule; +import org.sonarqube.ws.client.issue.SearchWsRequest; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; @@ -65,6 +69,8 @@ public class IssueQueryServiceTest { @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); + @Rule + public ExpectedException expectedException = ExpectedException.none(); @Mock DbClient dbClient; @@ -444,7 +450,7 @@ public class IssueQueryServiceTest { issueQueryService.createFromMap(map); fail(); } catch (Exception e) { - assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("createdAfter and createdSince cannot be set simultaneously"); + assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("createdAfter and createdInLast cannot be set simultaneously"); } } @@ -456,6 +462,35 @@ public class IssueQueryServiceTest { map.put("createdInLast", "1y2m3w4d"); assertThat(issueQueryService.createFromMap(map).createdAfter()).isEqualTo(DateUtils.parseDateTime("2012-04-30T07:35:00+0100")); + } + + @Test + public void fail_if_since_leak_period_and_created_after_set_at_the_same_time() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("'createdAfter' and 'sinceLeakPeriod' cannot be set simultaneously"); + + issueQueryService.createFromRequest(new SearchWsRequest() + .setSinceLeakPeriod(true) + .setCreatedAfter("2013-07-25T07:35:00+0100")); + } + @Test + public void fail_if_no_component_provided_with_since_leak_period() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("One and only one component must be provided when searching since leak period"); + + issueQueryService.createFromRequest(new SearchWsRequest().setSinceLeakPeriod(true)); + } + + @Test + public void fail_if_several_components_provided_with_since_leak_period() { + expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("One and only one component must be provided when searching since leak period"); + + issueQueryService.createFromRequest(new SearchWsRequest() + .setSinceLeakPeriod(true) + .setComponentUuids(Collections.singletonList("component-uuid")) + .setProjectUuids(Collections.singletonList("project-uuid")) + ); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java index c1c808e8712..23f995b45cd 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java @@ -37,6 +37,8 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; +import org.sonar.db.component.SnapshotDto; +import org.sonar.db.component.SnapshotTesting; import org.sonar.db.issue.IssueDto; import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleDto; @@ -54,11 +56,18 @@ import org.sonar.server.ws.WsActionTester; import org.sonar.server.ws.WsTester; import org.sonar.server.ws.WsTester.Result; import org.sonarqube.ws.Issues; +import org.sonarqube.ws.Issues.SearchWsResponse; import org.sonarqube.ws.MediaTypes; import org.sonarqube.ws.client.issue.IssueFilterParameters; import static com.google.common.collect.Lists.newArrayList; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.utils.DateUtils.parseDateTime; +import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; +import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02; +import static org.sonar.db.component.ComponentTesting.newFileDto; +import static org.sonar.db.component.ComponentTesting.newModuleDto; +import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject; public class SearchActionComponentsMediumTest { @@ -90,7 +99,7 @@ public class SearchActionComponentsMediumTest { RuleDto rule = newRule(); ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); IssueDto issue = IssueTesting.newDto(rule, file, project) .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") .setStatus("OPEN").setResolution("OPEN") @@ -101,7 +110,7 @@ public class SearchActionComponentsMediumTest { ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("P2").setKey("PK2")); setDefaultProjectPermission(project2); - ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "F2").setKey("FK2")); + ComponentDto file2 = insertComponent(newFileDto(project2, "F2").setKey("FK2")); IssueDto issue2 = IssueTesting.newDto(rule, file2, project2) .setKee("92fd47d4-b650-4037-80bc-7b112bd4eac2") .setStatus("OPEN").setResolution("OPEN") @@ -120,8 +129,8 @@ public class SearchActionComponentsMediumTest { public void do_not_return_module_key_on_single_module_projects() throws IOException { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto module = insertComponent(ComponentTesting.newModuleDto("M1", project).setKey("MK1")); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(module, "F1").setKey("FK1")); + ComponentDto module = insertComponent(newModuleDto("M1", project).setKey("MK1")); + ComponentDto file = insertComponent(newFileDto(module, "F1").setKey("FK1")); RuleDto newRule = newRule(); IssueDto issueInModule = IssueTesting.newDto(newRule, file, project).setKee("ISSUE_IN_MODULE"); IssueDto issueInRootModule = IssueTesting.newDto(newRule, project, project).setKee("ISSUE_IN_ROOT_MODULE"); @@ -133,7 +142,7 @@ public class SearchActionComponentsMediumTest { TestResponse response = actionTester.newRequest() .setMediaType(MediaTypes.PROTOBUF) .execute(); - Issues.SearchWsResponse searchResponse = Issues.SearchWsResponse.parseFrom(response.getInputStream()); + SearchWsResponse searchResponse = SearchWsResponse.parseFrom(response.getInputStream()); assertThat(searchResponse.getIssuesCount()).isEqualTo(2); for (Issues.Issue issue : searchResponse.getIssuesList()) { @@ -150,7 +159,7 @@ public class SearchActionComponentsMediumTest { public void search_by_project_uuid() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); db.issueDao().insert(session, issue); session.commit(); @@ -178,6 +187,66 @@ public class SearchActionComponentsMediumTest { } @Test + public void search_since_leak_period_on_project() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); + setDefaultProjectPermission(project); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); + SnapshotDto projectSnapshot = db.snapshotDao().insert(session, + newSnapshotForProject(project) + .setPeriodDate(1, parseDateTime("2015-09-03T00:00:00+0100").getTime())); + db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, projectSnapshot)); + RuleDto rule = newRule(); + IssueDto issueAfterLeak = IssueTesting.newDto(rule, file, project) + .setKee(UUID_EXAMPLE_01) + .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100")) + .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")); + IssueDto issueBeforeLeak = IssueTesting.newDto(rule, file, project) + .setKee(UUID_EXAMPLE_02) + .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100")) + .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")); + db.issueDao().insert(session, issueAfterLeak, issueBeforeLeak); + session.commit(); + tester.get(IssueIndexer.class).indexAll(); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.COMPONENT_UUIDS, project.uuid()) + .setParam(IssueFilterParameters.SINCE_LEAK_PERIOD, "true") + .execute() + .assertJson(this.getClass(), "search_since_leak_period.json"); + } + + @Test + public void search_since_leak_period_on_file_in_module_project() throws Exception { + ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); + setDefaultProjectPermission(project); + ComponentDto module = insertComponent(newModuleDto(project)); + ComponentDto file = insertComponent(newFileDto(module, "F1").setKey("FK1")); + SnapshotDto projectSnapshot = db.snapshotDao().insert(session, + newSnapshotForProject(project) + .setPeriodDate(1, parseDateTime("2015-09-03T00:00:00+0100").getTime())); + SnapshotDto moduleSnapshot = db.snapshotDao().insert(session, SnapshotTesting.createForComponent(module, projectSnapshot)); + db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, moduleSnapshot)); + RuleDto rule = newRule(); + IssueDto issueAfterLeak = IssueTesting.newDto(rule, file, project) + .setKee(UUID_EXAMPLE_01) + .setIssueCreationDate(parseDateTime("2015-09-04T00:00:00+0100")) + .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")); + IssueDto issueBeforeLeak = IssueTesting.newDto(rule, file, project) + .setKee(UUID_EXAMPLE_02) + .setIssueCreationDate(parseDateTime("2014-09-04T00:00:00+0100")) + .setIssueUpdateDate(parseDateTime("2015-10-04T00:00:00+0100")); + db.issueDao().insert(session, issueAfterLeak, issueBeforeLeak); + session.commit(); + tester.get(IssueIndexer.class).indexAll(); + + wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION) + .setParam(IssueFilterParameters.FILE_UUIDS, file.uuid()) + .setParam(IssueFilterParameters.SINCE_LEAK_PERIOD, "true") + .execute() + .assertJson(this.getClass(), "search_since_leak_period.json"); + } + + @Test public void project_facet_is_sticky() throws Exception { ComponentDto project1 = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); ComponentDto project2 = insertComponent(ComponentTesting.newProjectDto("P2").setKey("PK2")); @@ -185,9 +254,9 @@ public class SearchActionComponentsMediumTest { setDefaultProjectPermission(project1); setDefaultProjectPermission(project2); setDefaultProjectPermission(project3); - ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(project1, "F1").setKey("FK1")); - ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project2, "F2").setKey("FK2")); - ComponentDto file3 = insertComponent(ComponentTesting.newFileDto(project3, "F3").setKey("FK3")); + ComponentDto file1 = insertComponent(newFileDto(project1, "F1").setKey("FK1")); + ComponentDto file2 = insertComponent(newFileDto(project2, "F2").setKey("FK2")); + ComponentDto file3 = insertComponent(newFileDto(project3, "F3").setKey("FK3")); RuleDto rule = newRule(); IssueDto issue1 = IssueTesting.newDto(rule, file1, project1).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); IssueDto issue2 = IssueTesting.newDto(rule, file2, project2).setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"); @@ -207,7 +276,7 @@ public class SearchActionComponentsMediumTest { public void search_by_file_uuid() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); db.issueDao().insert(session, issue); session.commit(); @@ -238,8 +307,8 @@ public class SearchActionComponentsMediumTest { public void search_by_file_key() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); - ComponentDto unitTest = insertComponent(ComponentTesting.newFileDto(project, "F2").setQualifier(Qualifiers.UNIT_TEST_FILE).setKey("FK2")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); + ComponentDto unitTest = insertComponent(newFileDto(project, "F2").setQualifier(Qualifiers.UNIT_TEST_FILE).setKey("FK2")); RuleDto rule = newRule(); IssueDto issueOnFile = IssueTesting.newDto(rule, file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); IssueDto issueOnTest = IssueTesting.newDto(rule, unitTest, project).setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"); @@ -256,16 +325,15 @@ public class SearchActionComponentsMediumTest { .setParam(IssueFilterParameters.COMPONENTS, unitTest.key()) .execute() .assertJson(this.getClass(), "search_by_test_key.json"); - } @Test public void display_file_facet() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); - ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(project, "F2").setKey("FK2")); - ComponentDto file3 = insertComponent(ComponentTesting.newFileDto(project, "F3").setKey("FK3")); + ComponentDto file1 = insertComponent(newFileDto(project, "F1").setKey("FK1")); + ComponentDto file2 = insertComponent(newFileDto(project, "F2").setKey("FK2")); + ComponentDto file3 = insertComponent(newFileDto(project, "F3").setKey("FK3")); RuleDto newRule = newRule(); IssueDto issue1 = IssueTesting.newDto(newRule, file1, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); IssueDto issue2 = IssueTesting.newDto(newRule, file2, project).setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"); @@ -286,7 +354,7 @@ public class SearchActionComponentsMediumTest { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "D1", "src/main/java/dir")); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1").setPath(directory.path() + "/MyComponent.java")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1").setPath(directory.path() + "/MyComponent.java")); IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); db.issueDao().insert(session, issue); session.commit(); @@ -317,12 +385,12 @@ public class SearchActionComponentsMediumTest { public void search_by_directory_path_in_different_modules() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto module1 = insertComponent(ComponentTesting.newModuleDto("M1", project).setKey("MK1")); - ComponentDto module2 = insertComponent(ComponentTesting.newModuleDto("M2", project).setKey("MK2")); + ComponentDto module1 = insertComponent(newModuleDto("M1", project).setKey("MK1")); + ComponentDto module2 = insertComponent(newModuleDto("M2", project).setKey("MK2")); ComponentDto directory1 = insertComponent(ComponentTesting.newDirectory(module1, "D1", "src/main/java/dir")); ComponentDto directory2 = insertComponent(ComponentTesting.newDirectory(module2, "D2", "src/main/java/dir")); - ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(module1, "F1").setKey("FK1").setPath(directory1.path() + "/MyComponent.java")); - insertComponent(ComponentTesting.newFileDto(module2, "F2").setKey("FK2").setPath(directory2.path() + "/MyComponent.java")); + ComponentDto file1 = insertComponent(newFileDto(module1, "F1").setKey("FK1").setPath(directory1.path() + "/MyComponent.java")); + insertComponent(newFileDto(module2, "F2").setKey("FK2").setPath(directory2.path() + "/MyComponent.java")); RuleDto rule = newRule(); IssueDto issue1 = IssueTesting.newDto(rule, file1, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); db.issueDao().insert(session, issue1); @@ -367,12 +435,12 @@ public class SearchActionComponentsMediumTest { public void display_module_facet() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto module = insertComponent(ComponentTesting.newModuleDto("M1", project).setKey("MK1")); - ComponentDto subModule1 = insertComponent(ComponentTesting.newModuleDto("SUBM1", module).setKey("SUBMK1")); - ComponentDto subModule2 = insertComponent(ComponentTesting.newModuleDto("SUBM2", module).setKey("SUBMK2")); - ComponentDto subModule3 = insertComponent(ComponentTesting.newModuleDto("SUBM3", module).setKey("SUBMK3")); - ComponentDto file1 = insertComponent(ComponentTesting.newFileDto(subModule1, "F1").setKey("FK1")); - ComponentDto file2 = insertComponent(ComponentTesting.newFileDto(subModule2, "F2").setKey("FK2")); + ComponentDto module = insertComponent(newModuleDto("M1", project).setKey("MK1")); + ComponentDto subModule1 = insertComponent(newModuleDto("SUBM1", module).setKey("SUBMK1")); + ComponentDto subModule2 = insertComponent(newModuleDto("SUBM2", module).setKey("SUBMK2")); + ComponentDto subModule3 = insertComponent(newModuleDto("SUBM3", module).setKey("SUBMK3")); + ComponentDto file1 = insertComponent(newFileDto(subModule1, "F1").setKey("FK1")); + ComponentDto file2 = insertComponent(newFileDto(subModule2, "F2").setKey("FK2")); RuleDto newRule = newRule(); IssueDto issue1 = IssueTesting.newDto(newRule, file1, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); IssueDto issue2 = IssueTesting.newDto(newRule, file2, project).setKee("2bd4eac2-b650-4037-80bc-7b1182fd47d4"); @@ -393,7 +461,7 @@ public class SearchActionComponentsMediumTest { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); ComponentDto directory = insertComponent(ComponentTesting.newDirectory(project, "D1", "src/main/java/dir")); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1").setPath(directory.path() + "/MyComponent.java")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1").setPath(directory.path() + "/MyComponent.java")); IssueDto issue = IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"); db.issueDao().insert(session, issue); session.commit(); @@ -411,7 +479,7 @@ public class SearchActionComponentsMediumTest { public void search_by_view_uuid() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); ComponentDto view = insertComponent(ComponentTesting.newProjectDto("V1").setQualifier(Qualifiers.VIEW).setKey("MyView")); @@ -430,7 +498,7 @@ public class SearchActionComponentsMediumTest { public void search_by_view_uuid_return_only_authorized_view() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); ComponentDto view = insertComponent(ComponentTesting.newProjectDto("V1").setQualifier(Qualifiers.VIEW).setKey("MyView")); @@ -450,7 +518,7 @@ public class SearchActionComponentsMediumTest { public void search_by_sub_view_uuid() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); ComponentDto view = insertComponent(ComponentTesting.newProjectDto("V1").setQualifier(Qualifiers.VIEW).setKey("MyView")); @@ -471,7 +539,7 @@ public class SearchActionComponentsMediumTest { public void search_by_sub_view_uuid_return_only_authorized_view() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); insertIssue(IssueTesting.newDto(newRule(), file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")); ComponentDto view = insertComponent(ComponentTesting.newProjectDto("V1").setQualifier(Qualifiers.VIEW).setKey("MyView")); @@ -493,7 +561,7 @@ public class SearchActionComponentsMediumTest { public void search_by_author() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); RuleDto newRule = newRule(); IssueDto issue1 = IssueTesting.newDto(newRule, file, project).setAuthorLogin("leia").setKee("2bd4eac2-b650-4037-80bc-7b112bd4eac2"); IssueDto issue2 = IssueTesting.newDto(newRule, file, project).setAuthorLogin("luke@skywalker.name").setKee("82fd47d4-b650-4037-80bc-7b1182fd47d4"); @@ -519,7 +587,7 @@ public class SearchActionComponentsMediumTest { public void search_by_developer() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); ComponentDto developer = insertComponent(ComponentTesting.newDeveloper("Anakin Skywalker")); db.authorDao().insertAuthor(session, "vader", developer.getId()); db.authorDao().insertAuthor(session, "anakin@skywalker.name", developer.getId()); @@ -541,11 +609,11 @@ public class SearchActionComponentsMediumTest { public void search_by_developer_technical_project() throws Exception { ComponentDto project = insertComponent(ComponentTesting.newProjectDto("P1").setKey("PK1")); setDefaultProjectPermission(project); - ComponentDto file = insertComponent(ComponentTesting.newFileDto(project, "F1").setKey("FK1")); + ComponentDto file = insertComponent(newFileDto(project, "F1").setKey("FK1")); ComponentDto otherProject = insertComponent(ComponentTesting.newProjectDto("P2").setKey("PK2")); setDefaultProjectPermission(otherProject); - ComponentDto otherFile = insertComponent(ComponentTesting.newFileDto(otherProject, "F2").setKey("FK2")); + ComponentDto otherFile = insertComponent(newFileDto(otherProject, "F2").setKey("FK2")); ComponentDto developer = insertComponent(ComponentTesting.newDeveloper("Anakin Skywalker")); ComponentDto technicalProject = insertComponent(ComponentTesting.newDevProjectCopy("COPY_P1", project, developer)); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java index 8b3ae1755e0..ddae87c0089 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java @@ -94,14 +94,14 @@ public class SearchActionMediumTest { public void define_action() { WebService.Controller controller = wsTester.controller("api/issues"); - WebService.Action show = controller.action("search"); - assertThat(show).isNotNull(); - assertThat(show.handler()).isNotNull(); - assertThat(show.since()).isEqualTo("3.6"); - assertThat(show.isPost()).isFalse(); - assertThat(show.isInternal()).isFalse(); - assertThat(show.responseExampleAsString()).isNotEmpty(); - assertThat(show.params()).hasSize(38); + WebService.Action search = controller.action("search"); + assertThat(search).isNotNull(); + assertThat(search.handler()).isNotNull(); + assertThat(search.since()).isEqualTo("3.6"); + assertThat(search.isPost()).isFalse(); + assertThat(search.isInternal()).isFalse(); + assertThat(search.responseExampleAsString()).isNotEmpty(); + assertThat(search.params()).hasSize(39); } @Test diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_since_leak_period.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_since_leak_period.json new file mode 100644 index 00000000000..0cdf5b8fa6c --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionComponentsMediumTest/search_since_leak_period.json @@ -0,0 +1,10 @@ +{ + "issues": [ + { + "key": "AU-Tpxb--iU5OvuD2FLy", + "component": "FK1", + "project": "PK1", + "rule": "xoo:x1" + } + ] +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssueFilterParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssueFilterParameters.java index 4d32a2de799..90abaf64a31 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssueFilterParameters.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssueFilterParameters.java @@ -62,6 +62,7 @@ public class IssueFilterParameters { public static final String CREATED_AT = "createdAt"; public static final String CREATED_BEFORE = "createdBefore"; public static final String CREATED_IN_LAST = "createdInLast"; + public static final String SINCE_LEAK_PERIOD = "sinceLeakPeriod"; public static final String PAGE_SIZE = "pageSize"; public static final String PAGE_INDEX = "pageIndex"; public static final String SORT = "sort"; diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java index e8c99d569e9..11837e40285 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java @@ -55,6 +55,7 @@ import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLUTIONS; import static org.sonarqube.ws.client.issue.IssueFilterParameters.RESOLVED; import static org.sonarqube.ws.client.issue.IssueFilterParameters.RULES; import static org.sonarqube.ws.client.issue.IssueFilterParameters.SEVERITIES; +import static org.sonarqube.ws.client.issue.IssueFilterParameters.SINCE_LEAK_PERIOD; import static org.sonarqube.ws.client.issue.IssueFilterParameters.STATUSES; import static org.sonarqube.ws.client.issue.IssueFilterParameters.TAGS; @@ -102,6 +103,7 @@ public class IssuesService extends BaseService { .setParam(RULES, inlineMultipleParamValue(request.getRules())) .setParam("s", request.getSort()) .setParam(SEVERITIES, inlineMultipleParamValue(request.getSeverities())) + .setParam(SINCE_LEAK_PERIOD, request.getSinceLeakPeriod()) .setParam(STATUSES, inlineMultipleParamValue(request.getStatuses())) .setParam(TAGS, inlineMultipleParamValue(request.getTags())), SearchWsResponse.parser()); diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SearchWsRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SearchWsRequest.java index c6520738eb4..e782c4d95ab 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SearchWsRequest.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SearchWsRequest.java @@ -57,6 +57,7 @@ public class SearchWsRequest { private List<String> resolutions; private Boolean resolved; private List<String> rules; + private Boolean sinceLeakPeriod; private String sort; private List<String> severities; private List<String> statuses; @@ -354,6 +355,16 @@ public class SearchWsRequest { } @CheckForNull + public Boolean getSinceLeakPeriod() { + return sinceLeakPeriod; + } + + public SearchWsRequest setSinceLeakPeriod(@Nullable Boolean sinceLeakPeriod) { + this.sinceLeakPeriod = sinceLeakPeriod; + return this; + } + + @CheckForNull public String getSort() { return sort; } |