diff options
21 files changed, 298 insertions, 180 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java index 547accceb03..f8c670f0733 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/UploadReportAction.java @@ -41,7 +41,6 @@ public class UploadReportAction implements RequestHandler { public static final String UPLOAD_REPORT_ACTION = "upload_report"; static final String PARAM_PROJECT = "project"; - static final String PARAM_FIRST_ANALYSIS = "firstAnalysis"; private final DbClient dbClient; private final IndexClient index; @@ -68,12 +67,6 @@ public class UploadReportAction implements RequestHandler { .setRequired(true) .setDescription("Project key") .setExampleValue("org.codehaus.sonar:sonar"); - - action - .createParam(PARAM_FIRST_ANALYSIS) - .setDescription("Is it the first analysis of this project ?") - .setDefaultValue(false) - .setBooleanPossibleValues(); } @Override @@ -88,11 +81,9 @@ public class UploadReportAction implements RequestHandler { AuthorizedComponentDto project = dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); // Synchronize project permission indexes - boolean isFirstAnalysis = request.mandatoryParamAsBoolean(PARAM_FIRST_ANALYSIS); - if (isFirstAnalysis) { - permissionService.synchronizePermissions(session, project.key()); - session.commit(); - } + // TODO only update permission if no permission for a project + permissionService.synchronizePermissions(session, project.key()); + session.commit(); // Index project's issues dbClient.issueDao().synchronizeAfter(session, diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java index c0552d9c752..f025ccbd874 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java @@ -27,6 +27,7 @@ import org.sonar.server.search.BaseDoc; import org.sonar.server.search.IndexUtils; import javax.annotation.CheckForNull; + import java.util.Collections; import java.util.Date; import java.util.List; @@ -50,9 +51,12 @@ public class IssueDoc extends BaseDoc implements Issue { @Override public RuleKey ruleKey() { - return RuleKey.of( - (String) getField(IssueNormalizer.IssueField.REPOSITORY.field()), - (String) getField(IssueNormalizer.IssueField.RULE.field())); + return RuleKey.parse((String) getField(IssueNormalizer.IssueField.RULE_KEY.field())); + } + + @Override + public String language() { + return getField(IssueNormalizer.IssueField.LANGUAGE.field()); } @Override diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index f5b67dfca6d..7825074a811 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -35,6 +35,8 @@ import org.sonar.api.web.UserRole; import org.sonar.core.issue.db.IssueDto; import org.sonar.server.search.*; +import javax.annotation.Nullable; + import java.io.IOException; import java.util.Collection; import java.util.HashMap; @@ -172,16 +174,15 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { } // Field Filters + matchFilter(esFilter, IssueNormalizer.IssueField.KEY, query.issueKeys()); matchFilter(esFilter, IssueNormalizer.IssueField.ACTION_PLAN, query.actionPlans()); matchFilter(esFilter, IssueNormalizer.IssueField.ASSIGNEE, query.assignees()); matchFilter(esFilter, IssueNormalizer.IssueField.PROJECT, query.componentRoots()); matchFilter(esFilter, IssueNormalizer.IssueField.COMPONENT, query.components()); - matchFilter(esFilter, IssueNormalizer.IssueField.KEY, query.issueKeys()); - // TODO need to either materialize the language or join with rule - // query.languages(esFilter, IssueNormalizer.IssueField.L, query.issueKeys()); + matchFilter(esFilter, IssueNormalizer.IssueField.LANGUAGE, query.languages()); matchFilter(esFilter, IssueNormalizer.IssueField.RESOLUTION, query.resolutions()); matchFilter(esFilter, IssueNormalizer.IssueField.REPORTER, query.reporters()); - matchFilter(esFilter, IssueNormalizer.IssueField.RULE, query.rules()); + matchFilter(esFilter, IssueNormalizer.IssueField.RULE_KEY, query.rules()); matchFilter(esFilter, IssueNormalizer.IssueField.SEVERITY, query.severities()); matchFilter(esFilter, IssueNormalizer.IssueField.STATUS, query.statuses()); @@ -227,7 +228,7 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { return new Result<Issue>(this, response); } - private void matchFilter(BoolFilterBuilder filter, IndexField field, Collection<?> values) { + private void matchFilter(BoolFilterBuilder filter, IndexField field, @Nullable Collection<?> values) { if (values != null && !values.isEmpty()) { filter.must(FilterBuilders.termsFilter(field.field(), values)); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java index 4fc6977e070..ba91903c0e9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java @@ -60,9 +60,8 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { public static final IndexField REPORTER = add(IndexField.Type.STRING, "reporter"); public static final IndexField STATUS = add(IndexField.Type.STRING, "status"); public static final IndexField SEVERITY = add(IndexField.Type.STRING, "severity"); - - public static final IndexField RULE = addSearchable(IndexField.Type.STRING, "rule"); - public static final IndexField REPOSITORY = addSearchable(IndexField.Type.STRING, "repository"); + public static final IndexField LANGUAGE = add(IndexField.Type.STRING, "language"); + public static final IndexField RULE_KEY = addSearchable(IndexField.Type.STRING, "ruleKey"); public static final Set<IndexField> ALL_FIELDS = getAllFields(); @@ -115,10 +114,8 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { update.put(IssueField.STATUS.field(), dto.getStatus()); update.put(IssueField.SEVERITY.field(), dto.getSeverity()); update.put(IssueField.DEBT.field(), dto.getDebt()); - - // issueDoc.ruleKey(); - update.put(IssueField.RULE.field(), dto.getRule()); - update.put(IssueField.REPOSITORY.field(), dto.getRuleRepo()); + update.put(IssueField.LANGUAGE.field(), dto.getLanguage()); + update.put(IssueField.RULE_KEY.field(), dto.getRuleKey().toString()); // TODO Not yet normalized // IssueDoc issueDoc = new IssueDoc(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 30fd11a0cc2..56c07d46e87 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 @@ -167,19 +167,12 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { action.createParam(IssueFilterParameters.CREATED_BEFORE) .setDescription("To retrieve issues created before the given date (exclusive). Format: date or datetime ISO formats") .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)"); - action.createParam(IssueFilterParameters.PAGE_SIZE) - .setDescription("Maximum number of results per page. " + - "Default value: 100 (except when the 'components' parameter is set, value is set to \"-1\" in this case). " + - "If set to \"-1\", the max possible value is used") - .setExampleValue("50"); - action.createParam(IssueFilterParameters.PAGE_INDEX) - .setDescription("Index of the selected page") - .setDefaultValue("1") - .setExampleValue("2"); - action.createParam(IssueFilterParameters.SORT) + action.createParam(SearchRequestHandler.PARAM_SORT) .setDescription("Sort field") + .setDeprecatedKey(IssueFilterParameters.SORT) .setPossibleValues(IssueQuery.SORTS); - action.createParam(IssueFilterParameters.ASC) + action.createParam(SearchRequestHandler.PARAM_ASCENDING) + .setDeprecatedKey(IssueFilterParameters.ASC) .setDescription("Ascending sort") .setBooleanPossibleValues(); action.createParam("format") @@ -207,19 +200,18 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { .hideRules(request.paramAsBoolean(IssueFilterParameters.HIDE_RULES)) .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) .createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) - .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)) - .pageSize(request.paramAsInt(IssueFilterParameters.PAGE_SIZE)) - .pageIndex(request.paramAsInt(IssueFilterParameters.PAGE_INDEX)); - String sort = request.param(IssueFilterParameters.SORT); + .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)); + String sort = request.param(SearchRequestHandler.PARAM_SORT); if (!Strings.isNullOrEmpty(sort)) { builder.sort(sort); - builder.asc(request.paramAsBoolean(IssueFilterParameters.ASC)); + builder.asc(request.paramAsBoolean(SearchRequestHandler.PARAM_ASCENDING)); } return builder.build(); } @Override protected Result<Issue> doSearch(IssueQuery query, QueryContext context) { + // Set limit to context ? return ((DefaultIssueService)service).search(query, context); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java b/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java index 0379aedf1b1..4ccc0d56aca 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/ws/SearchRequestHandler.java @@ -29,6 +29,7 @@ import org.sonar.server.search.QueryContext; import org.sonar.server.search.Result; import javax.annotation.CheckForNull; + import java.util.Collection; import java.util.List; import java.util.Map; @@ -44,8 +45,6 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand public static final String PARAM_FACETS = "facets"; - private int pageSize; - private int page; private List<String> fields; private final String actionName; @@ -79,15 +78,17 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand action .createParam(PARAM_PAGE) + .setDeprecatedKey("pageIndex") .setDescription("1-based page number") .setExampleValue("42") .setDefaultValue("1"); action .createParam(PARAM_PAGE_SIZE) + .setDeprecatedKey("pageSize") .setDescription("Page size. Must be greater than 0.") .setExampleValue("20") - .setDefaultValue(String.valueOf(QueryContext.DEFAULT_LIMIT)); + .setDefaultValue("100"); action.createParam(PARAM_FACETS) .setDescription("Compute predefined facets") @@ -114,7 +115,7 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand Result<DOMAIN> result = doSearch(query, context); JsonWriter json = response.newJsonWriter().beginObject(); - this.writeStatistics(json, result); + this.writeStatistics(json, result, context); doResultResponse(request, context, result, json); doContextResponse(request, context, result, json); if (context.isFacet()) { @@ -130,10 +131,10 @@ public abstract class SearchRequestHandler<QUERY, DOMAIN> implements RequestHand request.mandatoryParamAsInt(PARAM_PAGE_SIZE)); } - protected void writeStatistics(JsonWriter json, Result searchResult) { + protected void writeStatistics(JsonWriter json, Result searchResult, QueryContext context) { json.prop("total", searchResult.getTotal()); - json.prop(PARAM_PAGE, page); - json.prop(PARAM_PAGE_SIZE, pageSize); + json.prop(PARAM_PAGE, context.getPage()); + json.prop(PARAM_PAGE_SIZE, context.getLimit()); } protected void writeFacets(Result<?> results, JsonWriter json) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionMediumTest.java index 2f2fb36c024..73d2a074597 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/UploadReportActionMediumTest.java @@ -86,11 +86,11 @@ public class UploadReportActionMediumTest { public void define() throws Exception { WebService.Action restoreProfiles = controller.action(UploadReportAction.UPLOAD_REPORT_ACTION); assertThat(restoreProfiles).isNotNull(); - assertThat(restoreProfiles.params()).hasSize(2); + assertThat(restoreProfiles.params()).hasSize(1); } @Test - public void add_project_issue_permission_index_on_first_analysis() throws Exception { + public void add_project_issue_permission_index() throws Exception { ComponentDto project = new ComponentDto() .setId(1L) .setKey("MyProject") @@ -107,7 +107,6 @@ public class UploadReportActionMediumTest { MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); WsTester.TestRequest request = wsTester.newGetRequest(BatchWs.API_ENDPOINT, UploadReportAction.UPLOAD_REPORT_ACTION); request.setParam(UploadReportAction.PARAM_PROJECT, project.key()); - request.setParam(UploadReportAction.PARAM_FIRST_ANALYSIS, "true"); request.execute(); // Check that issue authorization index has been created diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java index 5034e196290..962af1149af 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java @@ -66,6 +66,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getComponentId()).isEqualTo(401); assertThat(issue.getRootComponentId()).isEqualTo(399); assertThat(issue.getRuleId()).isEqualTo(500); + assertThat(issue.getLanguage()).isEqualTo("java"); assertThat(issue.getSeverity()).isEqualTo("BLOCKER"); assertThat(issue.isManualSeverity()).isFalse(); assertThat(issue.getMessage()).isNull(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java index 8312ebf1c98..7e3261f7b62 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java @@ -20,12 +20,10 @@ package org.sonar.server.issue.index; import com.google.common.collect.ImmutableList; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.*; import org.sonar.api.issue.Issue; import org.sonar.api.issue.IssueQuery; +import org.sonar.api.rule.RuleKey; import org.sonar.api.security.DefaultGroups; import org.sonar.api.utils.DateUtils; import org.sonar.api.web.UserRole; @@ -148,6 +146,26 @@ public class IssueIndexMediumTest { } @Test + public void filter_by_rule() throws Exception { + db.issueDao().insert(session, createIssue().setRule(rule)); + + tester.get(RuleDao.class).insert(session, RuleTesting.newDto(RuleKey.of("rule", "without issue"))); + session.commit(); + + assertThat(index.search(IssueQuery.builder().rules(newArrayList(rule.getKey())).build(), new QueryContext()).getHits()).hasSize(1); + assertThat(index.search(IssueQuery.builder().rules(newArrayList(RuleKey.of("rule", "without issue"))).build(), new QueryContext()).getHits()).isEmpty(); + } + + @Test + public void filter_by_language() throws Exception { + db.issueDao().insert(session, createIssue().setRule(rule)); + session.commit(); + + assertThat(index.search(IssueQuery.builder().languages(newArrayList(rule.getLanguage())).build(), new QueryContext()).getHits()).hasSize(1); + assertThat(index.search(IssueQuery.builder().languages(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); + } + + @Test public void is_assigned_filter() throws Exception { String assignee = "steph"; IssueDto issue1 = createIssue() @@ -237,6 +255,27 @@ public class IssueIndexMediumTest { } @Test + @Ignore("TODO") + public void sort_by_assignee() throws Exception { + IssueDto issue1 = createIssue().setAssignee("steph"); + IssueDto issue2 = createIssue().setAssignee("simon"); + db.issueDao().insert(session, issue1, issue2); + session.commit(); + + IssueQuery.Builder query = IssueQuery.builder().sort(IssueQuery.SORT_BY_ASSIGNEE).asc(true); + Result<Issue> result = index.search(query.build(), new QueryContext()); + assertThat(result.getHits()).hasSize(2); + assertThat(result.getHits().get(0).assignee()).isEqualTo("simon"); + assertThat(result.getHits().get(1).assignee()).isEqualTo("steph"); + + query = IssueQuery.builder().sort(IssueQuery.SORT_BY_ASSIGNEE).asc(false); + result = index.search(query.build(), new QueryContext()); + assertThat(result.getHits()).hasSize(2); + assertThat(result.getHits().get(0).assignee()).isEqualTo("steph"); + assertThat(result.getHits().get(1).assignee()).isEqualTo("simon"); + } + + @Test public void authorized_issues_on_groups() throws Exception { ComponentDto project1 = new ComponentDto() .setId(10L) diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java index fb8d9428188..5183b725c80 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java @@ -17,6 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + package org.sonar.server.issue.ws; import org.junit.After; @@ -24,17 +25,18 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.sonar.api.security.DefaultGroups; -import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.DateUtils; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.db.IssueDto; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.persistence.DbSession; import org.sonar.core.rule.RuleDto; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.db.DbClient; +import org.sonar.server.issue.IssueTesting; +import org.sonar.server.issue.db.IssueDao; +import org.sonar.server.issue.filter.IssueFilterParameters; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.tester.ServerTester; @@ -45,7 +47,7 @@ import java.util.Date; import static org.fest.assertions.Assertions.assertThat; -public class IssuesWsMediumTest { +public class SearchActionMediumTest { @ClassRule public static ServerTester tester = new ServerTester() @@ -56,6 +58,10 @@ public class IssuesWsMediumTest { DbSession session; WsTester wsTester; + RuleDto rule; + ComponentDto project; + ComponentDto file; + @Before public void setUp() throws Exception { tester.clearDbAndIndexes(); @@ -63,7 +69,31 @@ public class IssuesWsMediumTest { ws = tester.get(IssuesWs.class); wsTester = tester.get(WsTester.class); session = db.openSession(false); - MockUserSession.set().setLogin("gandalf").setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN); + + rule = RuleTesting.newXooX1(); + tester.get(RuleDao.class).insert(session, rule); + + project = new ComponentDto() + .setId(1L) + .setKey("MyProject") + .setProjectId(1L); + db.componentDao().insert(session, project); + db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project)); + + // project can be seen by anyone + tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); + db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); + + file = new ComponentDto() + .setProjectId(1L) + .setKey("MyComponent") + .setId(2L); + db.componentDao().insert(session, file); + db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file)); + + session.commit(); + + MockUserSession.set().setLogin("gandalf"); } @After @@ -72,30 +102,7 @@ public class IssuesWsMediumTest { } @Test - public void define() throws Exception { - WebService.Controller controller = wsTester.controller(IssuesWs.API_ENDPOINT); - - assertThat(controller).isNotNull(); - assertThat(controller.actions()).hasSize(14); - assertThat(controller.action(IssuesWs.ADD_COMMENT_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.ASSIGN_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.BULK_CHANGE_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.CHANGELOG_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.CREATE_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.DELETE_COMMENT_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.DO_ACTION_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.DO_TRANSITION_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.EDIT_COMMENT_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.PLAN_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.SET_SEVERITY_ACTION)).isNotNull(); - assertThat(controller.action(IssuesWs.TRANSITIONS_ACTION)).isNotNull(); - - assertThat(controller.action(SearchAction.SEARCH_ACTION)).isNotNull(); - } - - @Test public void empty_search() throws Exception { - WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION); WsTester.Result result = request.execute(); @@ -105,48 +112,65 @@ public class IssuesWsMediumTest { @Test public void find_single_result() throws Exception { - - RuleDto rule = RuleTesting.newXooX1(); - tester.get(RuleDao.class).insert(session, rule); - - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setProjectId(1L); - db.componentDao().insert(session, project); - db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project)); - - // project can be seen by anyone - tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); - db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); - - ComponentDto resource = new ComponentDto() - .setProjectId(1L) - .setKey("MyComponent") - .setId(2L); - db.componentDao().insert(session, resource); - db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource)); - - IssueDto issue = new IssueDto() + IssueDto issue = IssueTesting.newDto(rule, file, project) .setIssueCreationDate(DateUtils.parseDate("2014-09-04")) .setIssueUpdateDate(DateUtils.parseDate("2014-12-04")) .setRule(rule) .setDebt(10L) .setRootComponent(project) - .setComponent(resource) + .setComponent(file) .setStatus("OPEN").setResolution("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") .setSeverity("MAJOR"); db.issueDao().insert(session, issue); - session.commit(); WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION); request.setParam(SearchAction.PARAM_FACETS, "true"); - WsTester.Result result = request.execute(); - assertThat(result).isNotNull(); + WsTester.Result result = request.execute(); // TODO Date assertion is complex du to System2 result.assertJson(this.getClass(), "single_result.json", false); } + + @Test + public void paging() throws Exception { + for (int i=0; i<12; i++) { + IssueDto issue = IssueTesting.newDto(rule, file, project); + tester.get(IssueDao.class).insert(session, issue); + } + session.commit(); + + WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION); + request.setParam(SearchAction.PARAM_PAGE, "2"); + request.setParam(SearchAction.PARAM_PAGE_SIZE, "9"); + + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "paging.json", false); + } + + @Test + public void paging_with_deprecated_params() throws Exception { + for (int i=0; i<12; i++) { + IssueDto issue = IssueTesting.newDto(rule, file, project); + tester.get(IssueDao.class).insert(session, issue); + } + session.commit(); + + WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION); + request.setParam(IssueFilterParameters.PAGE_INDEX, "2"); + request.setParam(IssueFilterParameters.PAGE_SIZE, "9"); + + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "paging.json", false); + } + + @Test + public void default_page_size_is_100() throws Exception { + WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION); + + WsTester.Result result = request.execute(); + result.assertJson(this.getClass(), "default_page_size_is_100.json", false); + } + } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/empty_result.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/empty_result.json deleted file mode 100644 index 60269eb00c9..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/empty_result.json +++ /dev/null @@ -1,7 +0,0 @@ -{"maxResultsReached": false, "paging": { - "pageIndex": 1, - "pageSize": 10, - "total": 0, - "fTotal": "0", - "pages": 0 -}, "issues": [], "components": [], "projects": []} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/single_result.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/single_result.json deleted file mode 100644 index 4fa5dc29b8a..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssuesWsMediumTest/single_result.json +++ /dev/null @@ -1,57 +0,0 @@ -{"maxResultsReached": false, "paging": { - "pageIndex": 1, - "pageSize": 10, - "total": 1, - "fTotal": "1", - "pages": 1 -}, "issues": [ - { - "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2", - "component": "MyComponent", - "project": "MyProject", - "rule": "xoo:x1", - "status": "OPEN", - "resolution": "OPEN", - "severity": "MAJOR", - "debt": "10min", - "fUpdateAge": "less than a minute" - } -], "components": [ - { - "key": "MyComponent", - "id": 2 - } -], "projects": [ - { - "key": "MyProject", - "id": 1 - } -], "facets": [ - { - "property": "status", - "values": [ - { - "val": "OPEN", - "count": 1 - } - ] - }, - { - "property": "severity", - "values": [ - { - "val": "MAJOR", - "count": 1 - } - ] - }, - { - "property": "resolution", - "values": [ - { - "val": "OPEN", - "count": 1 - } - ] - } -]} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/default_page_size_is_100.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/default_page_size_is_100.json new file mode 100644 index 00000000000..0fc07a00b50 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/default_page_size_is_100.json @@ -0,0 +1,13 @@ +{ + "total": 0, + "p": 1, + "ps": 100, + "maxResultsReached": false, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 0, + "fTotal": "0", + "pages": 0 + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/empty_result.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/empty_result.json new file mode 100644 index 00000000000..4d91f3e640f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/empty_result.json @@ -0,0 +1,16 @@ +{ + "total": 0, + "p": 1, + "ps": 100, + "maxResultsReached": false, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 0, + "fTotal": "0", + "pages": 0 + }, + "issues": [], + "components": [], + "projects": [] +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/paging.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/paging.json new file mode 100644 index 00000000000..ec4dd63a356 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/paging.json @@ -0,0 +1,13 @@ +{ + "total": 12, + "p": 2, + "ps": 9, + "maxResultsReached": false, + "paging": { + "pageIndex": 2, + "pageSize": 9, + "total": 12, + "fTotal": "12", + "pages": 2 + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/single_result.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/single_result.json new file mode 100644 index 00000000000..28202fd070f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/single_result.json @@ -0,0 +1,63 @@ +{ + "maxResultsReached": false, + "paging": { + "pageIndex": 1, + "pageSize": 100, + "total": 1, + "fTotal": "1", + "pages": 1 + }, + "issues": [ + { + "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2", + "component": "MyComponent", + "project": "MyProject", + "rule": "xoo:x1", + "status": "OPEN", + "resolution": "OPEN", + "severity": "MAJOR", + "debt": "10min", + "fUpdateAge": "less than a minute" + } + ], + "components": [ + { + "key": "MyComponent", + "id": 2 + } + ], + "projects": [ + { + "key": "MyProject", + "id": 1 + } + ], + "facets": [ + { + "property": "status", + "values": [ + { + "val": "OPEN", + "count": 1 + } + ] + }, + { + "property": "severity", + "values": [ + { + "val": "MAJOR", + "count": 1 + } + ] + }, + { + "property": "resolution", + "values": [ + { + "val": "OPEN", + "count": 1 + } + ] + } + ]} diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java index fa67f6872a9..15092940d68 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java @@ -78,6 +78,7 @@ public final class IssueDto extends Dto<String> implements Serializable { // joins private String ruleKey; private String ruleRepo; + private String language; private String componentKey; private String rootComponentKey; @@ -153,6 +154,7 @@ public final class IssueDto extends Dto<String> implements Serializable { this.ruleId = rule.getId(); this.ruleKey = rule.getRuleKey(); this.ruleRepo = rule.getRepositoryKey(); + this.language = rule.getLanguage(); return this; } @@ -353,6 +355,10 @@ public final class IssueDto extends Dto<String> implements Serializable { return RuleKey.of(ruleRepo, ruleKey); } + public String getLanguage(){ + return language; + } + public String getComponentKey() { return componentKey; } @@ -385,6 +391,16 @@ public final class IssueDto extends Dto<String> implements Serializable { /** * Should only be used to persist in E/S * + * Please use {@link #setRule(org.sonar.core.rule.RuleDto)} instead + */ + public IssueDto setLanguage(String language) { + this.language = language; + return this; + } + + /** + * Should only be used to persist in E/S + * * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead */ public IssueDto setComponentKey(String componentKey) { @@ -485,6 +501,7 @@ public final class IssueDto extends Dto<String> implements Serializable { issue.setProjectKey(rootComponentKey); issue.setManualSeverity(manualSeverity); issue.setRuleKey(getRuleKey()); + issue.setLanguage(language); issue.setActionPlanKey(actionPlanKey); issue.setAuthorLogin(authorLogin); issue.setNew(false); diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index 76fb97eaadf..cd9e5cfa79d 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -31,6 +31,7 @@ i.updated_at as updatedAt, r.plugin_rule_key as ruleKey, r.plugin_name as ruleRepo, + r.language as language, p.kee as componentKey, root.kee as rootComponentKey </sql> diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java index ddda3b57f71..791c7125556 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java @@ -59,6 +59,7 @@ public class IssueDtoTest { .setKee("100") .setRuleId(1) .setRuleKey("squid", "AvoidCycle") + .setLanguage("xoo") .setComponentKey("org.sonar.sample:Sample") .setRootComponentKey("org.sonar.sample") .setComponentId(1l) @@ -82,6 +83,7 @@ public class IssueDtoTest { DefaultIssue issue = dto.toDefaultIssue(); assertThat(issue.key()).isEqualTo("100"); assertThat(issue.ruleKey().toString()).isEqualTo("squid:AvoidCycle"); + assertThat(issue.language()).isEqualTo("xoo"); assertThat(issue.componentKey()).isEqualTo("org.sonar.sample:Sample"); assertThat(issue.componentId()).isEqualTo(1L); assertThat(issue.projectKey()).isEqualTo("org.sonar.sample"); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java index b3907d233de..44c8b456fd3 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java @@ -83,6 +83,8 @@ public interface Issue extends Serializable { RuleKey ruleKey(); + String language(); + /** * See constants in {@link org.sonar.api.rule.Severity}. */ diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java index 51a5abfd174..a6c528dc2a6 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java @@ -39,11 +39,7 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import java.io.Serializable; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; +import java.util.*; import static com.google.common.collect.Lists.newArrayList; @@ -59,6 +55,7 @@ public class DefaultIssue implements Issue { private Long componentId; private String projectKey; private RuleKey ruleKey; + private String language; private String severity; private boolean manualSeverity = false; private String message; @@ -159,6 +156,15 @@ public class DefaultIssue implements Issue { return this; } + public String language() { + return language; + } + + public DefaultIssue setLanguage(String l) { + this.language = l; + return this; + } + public String severity() { return severity; } |