]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5531 Fix /api/issues/search when issues are linked on removed file
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 8 Oct 2014 09:33:38 +0000 (11:33 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 8 Oct 2014 09:43:21 +0000 (11:43 +0200)
server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java
sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml

index eaafc3c58630ba7f10eb7b2acfe8330c2fb93cec..7e4d49124d5dbd7f4738a74e97d7ae8b42aa3252 100644 (file)
@@ -151,4 +151,10 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String>
     mapper(session).insert(item);
     return item;
   }
+
+  @Override
+  protected void doDeleteByKey(DbSession session, String key) {
+    // TODO shouldn't we need to also delete snapshots ?
+    mapper(session).deleteByKey(key);
+  }
 }
index c8cce9fdd06339abf04a867a73ec88fb107529c9..3724e0eda028b1d0567964df676ee361eb9b382a 100644 (file)
@@ -342,7 +342,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
         .prop("key", issue.key())
         .prop("component", issue.componentKey())
         // Only used for the compatibility with the Issues Java WS Client <= 4.4 used by Eclipse
-        .prop("componentId", componentDto.getId())
+        .prop("componentId", componentDto != null ? componentDto.getId() : null)
         .prop("project", issue.projectKey())
         .prop("rule", issue.ruleKey().toString())
         .prop("status", issue.status())
index b264446ac735901089558c8ab3a800dc419a4b16..bb492c16a0b4259d17498c6f4a751584b1c64e59 100644 (file)
@@ -349,12 +349,17 @@ public class ComponentDaoTest extends AbstractDaoTestCase {
       );
   }
 
-  @Test(expected = IllegalStateException.class)
+  @Test
   public void delete() {
+    setupData("shared");
+
     dao.delete(session, new ComponentDto()
       .setId(1L)
       .setKey("org.struts:struts-core:src/org/struts/RequestContext.java")
       );
+    session.commit();
+
+    checkTable("delete", "projects");
   }
 
   @Test(expected = IllegalStateException.class)
index 593a6a456c5bb263f65d6b1926d68a9084b523de..c864bccffc080e7e7944c5f1c8b8630c0c5750e1 100644 (file)
@@ -32,11 +32,7 @@ import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.KeyValueFormat;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.ActionPlanDao;
-import org.sonar.core.issue.db.ActionPlanDto;
-import org.sonar.core.issue.db.IssueChangeDao;
-import org.sonar.core.issue.db.IssueChangeDto;
-import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.issue.db.*;
 import org.sonar.core.permission.PermissionFacade;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.rule.RuleDto;
@@ -249,6 +245,27 @@ public class SearchActionMediumTest {
     result.assertJson(this.getClass(), "issue_with_extra_fields.json", false);
   }
 
+  @Test
+  public void issue_linked_on_removed_file() throws Exception {
+    IssueDto issue = IssueTesting.newDto(rule, file, project)
+      .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2")
+      .setRule(rule)
+      .setRootComponent(project)
+      .setComponent(file)
+      .setStatus("OPEN").setResolution("OPEN")
+      .setSeverity("MAJOR")
+      .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+      .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"));
+    db.issueDao().insert(session, issue);
+
+    // Remove the file
+    db.componentDao().deleteByKey(session, file.key());
+    session.commit();
+
+    WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
+    result.assertJson(this.getClass(), "issue_linked_on_removed_file.json", false);
+  }
+
   @Test
   public void issue_contains_component_id_for_eclipse() throws Exception {
     IssueDto issue = IssueTesting.newDto(rule, file, project);
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml
new file mode 100644 (file)
index 0000000..28c0e32
--- /dev/null
@@ -0,0 +1,75 @@
+<dataset>
+
+  <!-- Struts projects is authorized for all user -->
+  <group_roles id="1" group_id="[null]" resource_id="1" role="user"/>
+
+
+  <!-- root project -->
+  <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" deprecated_kee="[null]"
+            description="the description" long_name="Apache Struts"
+            enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" created_at="[null]" authorization_updated_at="2014-06-18" />
+  <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+             status="P" islast="[true]" purge_status="[null]"
+             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path=""/>
+  <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+             status="P" islast="[false]" purge_status="[null]"
+             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-01 13:58:00.00" build_date="2008-12-01 13:58:00.00"
+             version="[null]" path=""/>
+
+  <!-- module -->
+  <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" deprecated_kee="[null]"
+            scope="PRJ" qualifier="BRC" long_name="Struts Core"
+            description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" created_at="[null]" authorization_updated_at="[null]" />
+  <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+             status="P" islast="[true]" purge_status="[null]"
+             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             depth="[null]" scope="PRJ" qualifier="BRC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path="1."/>
+
+  <!-- directory -->
+  <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" deprecated_kee="[null]"
+            name="src/org/struts" root_id="2"
+            description="[null]"
+            enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" created_at="[null]" authorization_updated_at="[null]" />
+  <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+             status="P" islast="[true]" purge_status="[null]"
+             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             depth="[null]" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path="1.2."/>
+
+  <!-- file -->
+  <!--<projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:src/org/struts/RequestContext.java"-->
+            <!--name="RequestContext.java" root_id="2"-->
+            <!--description="[null]"-->
+            <!--enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts/RequestContext.java" authorization_updated_at="[null]" />-->
+
+  <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
+             status="P" islast="[true]" purge_status="[null]"
+             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             depth="[null]" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00"
+             version="[null]" path="1.2.3."/>
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json
new file mode 100644 (file)
index 0000000..e6eba81
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "issues": [
+    {
+      "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2",
+      "component": "MyComponent",
+      "project": "MyProject",
+      "rule": "xoo:x1",
+      "status": "OPEN",
+      "resolution": "OPEN",
+      "severity": "MAJOR",
+      "updateDate": "2014-12-04T00:00:00+0100",
+      "fUpdateAge": "less than a minute"
+    }
+  ]
+}
index 9102b8601d5a006a0838d5568c2e7cbd710df5ee..3ef31f6e61c15880d4c18f36c8a5c4409be8f65d 100644 (file)
@@ -67,4 +67,6 @@ public interface ComponentMapper {
   AuthorizedComponentDto selectAuthorizedComponentByKey(String key);
 
   void insert(ComponentDto rule);
+
+  void deleteByKey(String key);
 }
index a2b4e19ae7720d379c3d69ac8c75267a2c227533..06ae4a5b094d90738cf214af90a814de4ee80379 100644 (file)
     values (#{kee}, #{name}, #{longName}, #{qualifier}, #{scope}, #{language}, #{subProjectId}, #{path}, #{createdAt}, #{authorizationUpdatedAt})
   </insert>
 
+  <insert id="deleteByKey" parameterType="String">
+    delete from projects where kee=#{key}
+  </insert>
+
 </mapper>