From b47468faac1dbfb669d4bca8b22edbc81796a85f Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Mon, 29 Sep 2014 16:33:52 +0200 Subject: [PATCH] SONAR-5531 When only one component is set in /api/issues/search, all issues are returned --- .../sonar/server/issue/ws/SearchAction.java | 4 ++ .../org/sonar/server/search/QueryContext.java | 10 ++- .../batch/UploadReportActionMediumTest.java | 72 ++++++++++++++----- .../IssueAuthorizationIndexMediumTest.java | 3 +- .../issue/index/IssueIndexMediumTest.java | 17 +---- .../issue/ws/SearchActionMediumTest.java | 13 ++++ ...issues_when_only_one_component_is_set.json | 5 ++ 7 files changed, 91 insertions(+), 33 deletions(-) create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/return_full_number_of_issues_when_only_one_component_is_set.json 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 e1f7ca83825..c5f39b98ae5 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 @@ -219,6 +219,10 @@ public class SearchAction extends SearchRequestHandler { @Override protected Result doSearch(IssueQuery query, QueryContext context) { + Collection components = query.components(); + if (components != null && components.size() == 1) { + context.setShowFullResult(true); + } return ((DefaultIssueService) service).search(query, context); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java b/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java index 90799df25c4..87901423b03 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/QueryContext.java @@ -47,6 +47,7 @@ public class QueryContext { private boolean facet = DEFAULT_FACET; private Set fieldsToReturn = newHashSet(); private boolean scroll = false; + private boolean showFullResult = false; private String userLogin; private Set userGroups = newHashSet(); @@ -121,7 +122,7 @@ public class QueryContext { * Limit on the number of results to return. Defaults to {@link #DEFAULT_LIMIT}. */ public int getLimit() { - return limit; + return showFullResult ? 999999 : limit; } /** @@ -137,6 +138,13 @@ public class QueryContext { return this; } + /** + * Careful use, this could lead to massive data transport ! + */ + public void setShowFullResult(boolean showFullResult) { + this.showFullResult = showFullResult; + } + public Set getFieldsToReturn() { return fieldsToReturn; } 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 4522ffc91e3..2804a736dde 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 @@ -20,10 +20,8 @@ package org.sonar.server.batch; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; +import org.junit.*; +import org.sonar.api.issue.IssueQuery; import org.sonar.api.security.DefaultGroups; import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.DateUtils; @@ -37,18 +35,23 @@ import org.sonar.core.rule.RuleDto; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.issue.IssueTesting; +import org.sonar.server.issue.db.IssueDao; import org.sonar.server.issue.index.IssueAuthorizationIndex; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.platform.BackendCleanup; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.search.IndexDefinition; +import org.sonar.server.search.QueryContext; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; import org.sonar.server.ws.WsTester; import java.util.Date; +import java.util.List; +import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; public class UploadReportActionMediumTest { @@ -91,9 +94,7 @@ public class UploadReportActionMediumTest { @Test public void add_project_issue_permission_index() throws Exception { ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setProjectId_unit_test_only(1L); + .setKey("MyProject"); db.componentDao().insert(session, project); // project can be seen by anyone @@ -115,9 +116,7 @@ public class UploadReportActionMediumTest { @Test(expected = ForbiddenException.class) public void fail_without_global_scan_permission() throws Exception { ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setProjectId_unit_test_only(1L); + .setKey("MyProject"); db.componentDao().insert(session, project); session.commit(); @@ -131,9 +130,7 @@ public class UploadReportActionMediumTest { @Test public void index_project_issues() throws Exception { ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setProjectId_unit_test_only(1L); + .setKey("MyProject"); db.componentDao().insert(session, project); // project can be seen by anyone @@ -141,9 +138,8 @@ public class UploadReportActionMediumTest { db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); ComponentDto resource = new ComponentDto() - .setProjectId_unit_test_only(1L) - .setKey("MyComponent") - .setId(2L); + .setProjectId_unit_test_only(project.getId()) + .setKey("MyComponent"); db.componentDao().insert(session, resource); db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource)); @@ -179,4 +175,48 @@ public class UploadReportActionMediumTest { assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNotNull(); } + @Test + @Ignore("To be fixed") + public void index_a_lot_of_issues() throws Exception { + ComponentDto project = new ComponentDto() + .setKey("MyProject"); + db.componentDao().insert(session, 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_unit_test_only(project.getId()) + .setKey("MyComponent"); + db.componentDao().insert(session, resource); + db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource)); + + RuleDto rule = RuleTesting.newXooX1(); + tester.get(RuleDao.class).insert(session, rule); + + List issueKeys = newArrayList(); + for (int i=0; i<2001; i++) { + IssueDto issue = IssueTesting.newDto(rule, resource, project); + tester.get(IssueDao.class).insert(session, issue); + issueKeys.add(issue.getKey()); + } + session.commit(); + session.clearCache(); + + // Clear issue index to simulate that the issue has been inserted by the batch, so that it's not yet index in E/S + tester.get(BackendCleanup.class).clearIndex(IndexDefinition.ISSUES); + + 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.execute(); + + session.commit(); + session.clearCache(); + + // Check that the issue has well be indexed in E/S + assertThat(tester.get(IssueIndex.class).search(IssueQuery.builder().build(), new QueryContext()).getTotal()).isEqualTo(2001); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java index 11abdf1d0d9..94c0f933513 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java @@ -102,7 +102,7 @@ public class IssueAuthorizationIndexMediumTest { } @Test - public void synchronize_all_on_startup_tasks() throws Exception { + public void synchronize_all_with_startup_tasks() throws Exception { project = new ComponentDto() .setKey("Sample") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); @@ -113,7 +113,6 @@ public class IssueAuthorizationIndexMediumTest { tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), "devs", UserRole.USER, session); session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); tester.get(Platform.class).executeStartupTasks(); 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 81f6ba1ddf4..46db6810b71 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 @@ -623,10 +623,9 @@ public class IssueIndexMediumTest { } @Test - public void synchronize_a_lot_of_issues() throws Exception { + public void synchronize_issues() throws Exception { ComponentDto project = new ComponentDto() - .setKey("MyProject") - .setProjectId_unit_test_only(1L); + .setKey("MyProject"); db.componentDao().insert(session, project); // project can be seen by anyone @@ -634,7 +633,7 @@ public class IssueIndexMediumTest { db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); ComponentDto resource = new ComponentDto() - .setProjectId_unit_test_only(project.getId()) + .setSubProjectId(project.getId()) .setKey("MyComponent"); db.componentDao().insert(session, resource); db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource)); @@ -651,29 +650,19 @@ public class IssueIndexMediumTest { assertThat(db.issueDao().findAfterDate(session, new Date(0))).hasSize(11); assertThat(index.countAll()).isEqualTo(11); - // Clear issue index in order to simulate these issues have been inserted without being indexed in E/S (from a previous version of SQ or from batch) tester.get(BackendCleanup.class).clearIndex(IndexDefinition.ISSUES); tester.clearIndexes(); - DbSession newSession = db.openSession(true); - //newSession.setImplicitCommitSize(10); - - System.out.println("index.getLastSynchronization() = " + index.getLastSynchronization()); try { db.issueDao().synchronizeAfter(newSession, index.getLastSynchronization()); newSession.commit(); } finally { newSession.close(); - newSession.clearCache(); } - session.commit(); - session.clearCache(); - // This test is working with executeStartupTasks ! -// tester.get(Platform.class).executeStartupTasks(); assertThat(index.countAll()).isEqualTo(11); } 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 80bf1ddff5f..71fc04829da 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 @@ -43,6 +43,7 @@ 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.search.QueryContext; import org.sonar.server.tester.ServerTester; import org.sonar.server.user.MockUserSession; import org.sonar.server.ws.WsTester; @@ -233,6 +234,18 @@ public class SearchActionMediumTest { result.assertJson(this.getClass(), "issue_with_extra_fields.json", false); } + @Test + public void return_full_number_of_issues_when_only_one_component_is_set() throws Exception { + for (int i = 0; i < QueryContext.MAX_LIMIT + 1; i++) { + IssueDto issue = IssueTesting.newDto(rule, file, project); + tester.get(IssueDao.class).insert(session, issue); + } + session.commit(); + + WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(IssueFilterParameters.COMPONENTS, file.getKey()).execute(); + result.assertJson(this.getClass(), "return_full_number_of_issues_when_only_one_component_is_set.json", false); + } + @Test public void components_contains_sub_projects() throws Exception { ComponentDto project = new ComponentDto() diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/return_full_number_of_issues_when_only_one_component_is_set.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/return_full_number_of_issues_when_only_one_component_is_set.json new file mode 100644 index 00000000000..7da1192f599 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/return_full_number_of_issues_when_only_one_component_is_set.json @@ -0,0 +1,5 @@ +{ + "total": 501, + "p": 1, + "ps": 999999 +} -- 2.39.5