diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2013-05-31 12:42:59 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2013-05-31 12:43:08 +0200 |
commit | 2a37a23b0ff74cd69a3a4c9053f3a2331b234097 (patch) | |
tree | c95368c97f95ac1fc22054c3aa248727df761c4d | |
parent | 700a38778cbc58108fe100571e2127713c0f3912 (diff) | |
download | sonarqube-2a37a23b0ff74cd69a3a4c9053f3a2331b234097.tar.gz sonarqube-2a37a23b0ff74cd69a3a4c9053f3a2331b234097.zip |
SONAR-3755 fix JSON report when directly analyzing module (like in Eclipse plugin)
11 files changed, 192 insertions, 19 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java index d4fb3288a69..a5677fb1894 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java @@ -49,7 +49,7 @@ public class InitialOpenIssuesSensor implements Sensor { @Override public void analyse(Project project, SensorContext context) { Date loadingDate = new Date(); - List<IssueDto> dtos = issueDao.selectNonClosedIssuesByRootComponent(project.getId()); + List<IssueDto> dtos = issueDao.selectNonClosedIssuesByModule(project.getId()); initialOpenIssuesStack.setIssues(dtos, loadingDate); } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java index dc8053e8712..ba380daaec4 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java @@ -46,7 +46,7 @@ public class InitialOpenIssuesSensorTest { project.setId(1); sensor.analyse(project, null); - verify(issueDao).selectNonClosedIssuesByRootComponent(1); + verify(issueDao).selectNonClosedIssuesByModule(1); verify(stack).setIssues(anyListOf(IssueDto.class), any(Date.class)); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java index b4acfe4cb63..c89471ad889 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java @@ -53,6 +53,17 @@ public class CacheTest { } @Test + public void test_key_being_prefix_of_another_key() throws Exception { + Cache<String, String> cache = caches.createCache("components"); + + cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTag", "the Tag"); + cache.put("struts-el:org.apache.strutsel.taglib.html.ELButtonTagBeanInfo", "the BeanInfo"); + + assertThat(cache.get("struts-el:org.apache.strutsel.taglib.html.ELButtonTag")).isEqualTo("the Tag"); + assertThat(cache.get("struts-el:org.apache.strutsel.taglib.html.ELButtonTagBeanInfo")).isEqualTo("the BeanInfo"); + } + + @Test public void test_put_get_remove_on_groups() throws Exception { Cache<String, Float> cache = caches.createCache("measures"); String group = "org/apache/struts/Action.java"; diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java index 0a030d6889c..a3a7ca31bac 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java @@ -61,11 +61,11 @@ public class IssueDao implements BatchComponent, ServerComponent { } } - public List<IssueDto> selectNonClosedIssuesByRootComponent(int componentId) { + public List<IssueDto> selectNonClosedIssuesByModule(int componentId) { SqlSession session = mybatis.openSession(); try { IssueMapper mapper = session.getMapper(IssueMapper.class); - return mapper.selectNonClosedIssues(componentId); + return mapper.selectNonClosedIssuesByModule(componentId); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java index c37fe4803ca..d0f81df029d 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java @@ -31,7 +31,7 @@ public interface IssueMapper { IssueDto selectByKey(String key); - List<IssueDto> selectNonClosedIssues(int rootComponentId); + List<IssueDto> selectNonClosedIssuesByModule(int rootComponentId); List<IssueDto> selectIssues(@Param("query") IssueQuery query, @Param("componentRootKeys") Collection<String> componentRootKeys, @Nullable @Param("userId") Integer userId, @Param("role") String role, @Param("maxResults") Integer maxResult); diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java index 196da80d360..0ecfc403f79 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java @@ -28,7 +28,6 @@ import org.sonar.api.utils.SonarException; import javax.annotation.Nullable; import javax.sql.DataSource; - import java.io.File; import java.io.IOException; import java.sql.SQLException; @@ -77,12 +76,13 @@ public class DryRunDatabaseFactory implements ServerComponent { .copyTable(source, dest, "rules_parameters") .copyTable(source, dest, "rules_profiles"); if (projectId != null) { - String projectsConditionForIssues = "SELECT id from projects where id=" + projectId + " or root_id=" + projectId; String snapshotCondition = "islast=" + database.getDialect().getTrueSqlValue() + " and (project_id=" + projectId + " or root_project_id=" + projectId + ")"; - template - .copyTable(source, dest, "projects", "(id=" + projectId + " or root_id=" + projectId + ")") - .copyTable(source, dest, "issues", "component_id in (" + projectsConditionForIssues + ")", "status<>'" + Issue.STATUS_CLOSED + "'") - .copyTable(source, dest, "snapshots", snapshotCondition); + template.copyTable(source, dest, "projects", "(id=" + projectId + " or root_id=" + projectId + ")"); + template.copyTable(source, dest, "snapshots", snapshotCondition); + + String forRootModule = "(root_component_id in (select id from projects where id=" + projectId + " and qualifier='TRK'))"; + String forSubModule = "(component_id in (select id from projects where id=" + projectId + " or root_id=" + projectId + "))"; + template.copyTable(source, dest, "issues", "(" + forRootModule + ") or( " + forSubModule + ")", "status<>'" + Issue.STATUS_CLOSED + "'"); } } 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 463e7f0fd36..855800149a5 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 @@ -118,14 +118,38 @@ where i.kee=#{kee} and i.rule_id=r.id and p.id=i.component_id and i.root_component_id=root.id </select> - <select id="selectNonClosedIssues" parameterType="int" resultType="Issue"> - select distinct - <include refid="issueColumns"/> - from issues i, rules r, projects p, projects root + <select id="selectNonClosedIssuesByModule" parameterType="int" resultType="Issue"> + select + i.id, + i.kee as kee, + i.component_id as componentId, + i.root_component_id as rootComponentId, + i.rule_id as ruleId, + i.action_plan_key as actionPlanKey, + i.severity as severity, + i.manual_severity as manualSeverity, + i.message as message, + i.line as line, + i.effort_to_fix as effortToFix, + i.status as status, + i.resolution as resolution, + i.checksum as checksum, + i.reporter as reporter, + i.assignee as assignee, + i.author_login as authorLogin, + i.issue_attributes as issueAttributes, + i.issue_creation_date as issueCreationDate, + i.issue_update_date as issueUpdateDate, + i.issue_close_date as issueCloseDate, + i.created_at as createdAt, + i.updated_at as updatedAt, + r.plugin_rule_key as ruleKey, + r.plugin_name as ruleRepo, + p.kee as componentKey + from issues i, rules r, projects p where i.status <> 'CLOSED' and (p.root_id=#{id} or (p.root_id is null and p.id=#{id})) and i.component_id=p.id - and i.root_component_id=root.id and r.id=i.rule_id </select> diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java index ec9f735b8cb..158824845ae 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java @@ -289,16 +289,21 @@ public class IssueDaoTest extends AbstractDaoTestCase { } @Test - public void should_select_open_issues() { - setupData("shared", "should_select_open_issues"); + public void should_select_non_closed_issues_by_module() { + setupData("shared", "should_select_non_closed_issues_by_module"); - List<IssueDto> dtos = dao.selectNonClosedIssuesByRootComponent(400); + // 400 is a non-root module + List<IssueDto> dtos = dao.selectNonClosedIssuesByModule(400); assertThat(dtos).hasSize(2); IssueDto issue = dtos.get(0); assertThat(issue.getRuleRepo()).isNotNull(); assertThat(issue.getRule()).isNotNull(); assertThat(issue.getComponentKey()).isNotNull(); + + // 399 is the root module. It does not have issues. + assertThat(dao.selectNonClosedIssuesByModule(399)).isEmpty(); + } @Test diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java index 9a90a179606..f5cf58d7e5b 100644 --- a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java +++ b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java @@ -21,6 +21,7 @@ package org.sonar.core.persistence; import com.google.common.io.Files; import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.io.FileUtils; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -95,6 +96,43 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase { assertThat(rowCount("issues")).isEqualTo(1); } + @Test + public void should_export_issues_of_project_tree() throws IOException, SQLException { + setupData("multi-modules-with-issues"); + + when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot()); + + // 300 : root module -> export issues of all modules + byte[] database = localDatabaseFactory.createDatabaseForDryRun(300L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(1); + } + + @Test + public void should_export_issues_of_sub_module() throws IOException, SQLException { + setupData("multi-modules-with-issues"); + + when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot()); + + // 301 : sub module with 1 closed issue and 1 open issue + byte[] database = localDatabaseFactory.createDatabaseForDryRun(301L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(1); + } + + @Test + public void should_export_issues_of_sub_module_2() throws IOException, SQLException { + setupData("multi-modules-with-issues"); + + when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot()); + + // 302 : sub module without any issues + byte[] database = localDatabaseFactory.createDatabaseForDryRun(302L); + dataSource = createDatabase(database); + assertThat(rowCount("issues")).isEqualTo(0); + FileUtils.cleanDirectory(temporaryFolder.getRoot()); + } + private BasicDataSource createDatabase(byte[] db) throws IOException { File file = temporaryFolder.newFile("db.h2.db"); Files.write(db, file); diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_open_issues.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module.xml index e276f59a2b1..e276f59a2b1 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_open_issues.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml new file mode 100644 index 00000000000..4fbc3f6c720 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/multi-modules-with-issues.xml @@ -0,0 +1,95 @@ +<!-- + ~ SonarQube, open source software quality management tool. + ~ Copyright (C) 2008-2013 SonarSource + ~ mailto:contact AT sonarsource DOT com + ~ + ~ SonarQube is free software; you can redistribute it and/or + ~ modify it under the terms of the GNU Lesser General Public + ~ License as published by the Free Software Foundation; either + ~ version 3 of the License, or (at your option) any later version. + ~ + ~ SonarQube is distributed in the hope that it will be useful, + ~ but WITHOUT ANY WARRANTY; without even the implied warranty of + ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + ~ Lesser General Public License for more details. + ~ + ~ You should have received a copy of the GNU Lesser General Public License + ~ along with this program; if not, write to the Free Software Foundation, + ~ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + --> +<dataset> + <metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name="" + enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="[false]" delete_historical_data="[null]"/> + <metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name="" + enabled="[true]" worst_value="0" optimized_best_value="[true]" best_value="100" direction="1" hidden="[false]" delete_historical_data="[null]"/> + + <rules_profiles id="1" name="Sonar way with Findbugs" language="java" parent_name="" version="1" + used_profile="[false]"/> + + <projects id="300" kee="struts" root_id="[null]" qualifier="TRK" scope="PRJ" /> + <projects id="301" kee="struts-core" root_id="300" qualifier="BRC" scope="PRJ" /> + <projects id="302" kee="struts-el" root_id="300" qualifier="BRC" scope="PRJ" /> + <projects id="303" kee="Action.java" root_id="301" qualifier="CLA" scope="FIL" /> + + <snapshots id="3000" project_id="300" root_snapshot_id="[null]" path="" islast="[true]"/> + <snapshots id="3001" project_id="301" root_snapshot_id="3000" path="3000." islast="[true]"/> + <snapshots id="3002" project_id="302" root_snapshot_id="3000" path="3000." islast="[true]"/> + <snapshots id="3003" project_id="303" root_snapshot_id="3000" path="3000.3001." islast="[true]"/> + + <rules id="500" plugin_rule_key="AvoidCycle" plugin_name="squid"/> + <rules id="501" plugin_rule_key="NullRef" plugin_name="squid"/> + + <!-- issues in module --> + <issues + id="100" + kee="ISSUE-100" + component_id="303" + root_component_id="300" + + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + message="[null]" + line="200" + effort_to_fix="[null]" + status="OPEN" + resolution="[null]" + checksum="[null]" + reporter="user" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="[null]" + updated_at="[null]" + /> + + <issues + id="101" + kee="ISSUE-101" + component_id="303" + root_component_id="300" + + rule_id="501" + severity="MAJOR" + manual_severity="[false]" + message="[null]" + line="120" + effort_to_fix="[null]" + status="CLOSED" + resolution="FIXED" + checksum="[null]" + reporter="[null]" + assignee="user" + author_login="[null]" + issue_attributes="[null]" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="[null]" + updated_at="[null]" + /> + +</dataset>
\ No newline at end of file |