]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5200 When a module has been removed, related issues are not closed during the...
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 9 Apr 2014 12:00:05 +0000 (14:00 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 9 Apr 2014 12:00:24 +0000 (14:00 +0200)
24 files changed:
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeConfiguration.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues-result.xml
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_all_closed_issues.xml
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues-result.xml
sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/should_delete_old_closed_issues.xml
sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
sonar-server/src/main/java/org/sonar/server/db/migrations/MassUpdater.java
sonar-server/src/main/java/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigration.java
sonar-server/src/main/webapp/WEB-INF/db/migrate/525_update_not_resolved_issues_on_removed_components.rb [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/MassUpdaterTest.java [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/schema.sql [new file with mode: 0644]

index f6a6dc41922cf4d5f8bae1b1fa854edafc0bf810..c09affd1af39cc0fba5aa50e398fb0e686a138f2 100644 (file)
@@ -33,7 +33,7 @@ import java.util.List;
  */
 public class DatabaseVersion implements BatchComponent, ServerComponent {
 
-  public static final int LAST_VERSION = 524;
+  public static final int LAST_VERSION = 525;
 
   public static enum Status {
     UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
index ac8880c46780ed3f9d1a8c528d8bba02356b843c..d026ba606123a305b87b1bc8ea07c9597c652550 100644 (file)
@@ -21,8 +21,10 @@ package org.sonar.core.purge;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.utils.System2;
 
 import javax.annotation.CheckForNull;
+
 import java.util.Date;
 
 public class PurgeConfiguration {
@@ -30,11 +32,18 @@ public class PurgeConfiguration {
   private final long rootProjectId;
   private final String[] scopesWithoutHistoricalData;
   private final int maxAgeInDaysOfClosedIssues;
+  private final System2 system2;
 
   public PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues) {
+    this(rootProjectId, scopesWithoutHistoricalData, maxAgeInDaysOfClosedIssues, System2.INSTANCE);
+  }
+
+  @VisibleForTesting
+  PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, System2 system2) {
     this.rootProjectId = rootProjectId;
     this.scopesWithoutHistoricalData = scopesWithoutHistoricalData;
     this.maxAgeInDaysOfClosedIssues = maxAgeInDaysOfClosedIssues;
+    this.system2 = system2;
   }
 
   public long rootProjectId() {
@@ -47,7 +56,7 @@ public class PurgeConfiguration {
 
   @CheckForNull
   public Date maxLiveDateOfClosedIssues() {
-    return maxLiveDateOfClosedIssues(new Date());
+    return maxLiveDateOfClosedIssues(new Date(system2.now()));
   }
 
   @VisibleForTesting
index 73c95d818c4595064247d1719fa58f1c431940c2..5777908166b5562b78f11a2bd44dade3669b2f67 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.core.purge;
 
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.ibatis.session.ResultContext;
@@ -83,34 +82,35 @@ public class PurgeDao {
     if (hasAbortedBuilds(project.getId(), commands)) {
       LOG.info("<- Delete aborted builds");
       PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-          .setIslast(false)
-          .setStatus(new String[] {"U"})
-          .setRootProjectId(project.getId());
+        .setIslast(false)
+        .setStatus(new String[]{"U"})
+        .setRootProjectId(project.getId());
       commands.deleteSnapshots(query);
     }
   }
 
   private boolean hasAbortedBuilds(Long projectId, PurgeCommands commands) {
     PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-        .setIslast(false)
-        .setStatus(new String[] {"U"})
-        .setResourceId(projectId);
+      .setIslast(false)
+      .setStatus(new String[]{"U"})
+      .setResourceId(projectId);
     return !commands.selectSnapshotIds(query).isEmpty();
   }
 
   private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) {
     List<Long> projectSnapshotIds = purgeCommands.selectSnapshotIds(
-        PurgeSnapshotQuery.create()
-            .setResourceId(project.getId())
-            .setIslast(false)
-            .setNotPurged(true));
+      PurgeSnapshotQuery.create()
+        .setResourceId(project.getId())
+        .setIslast(false)
+        .setNotPurged(true)
+    );
     for (final Long projectSnapshotId : projectSnapshotIds) {
       LOG.info("<- Clean snapshot " + projectSnapshotId);
       if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
         PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
-            .setIslast(false)
-            .setScopes(scopesWithoutHistoricalData)
-            .setRootSnapshotId(projectSnapshotId);
+          .setIslast(false)
+          .setScopes(scopesWithoutHistoricalData)
+          .setRootSnapshotId(projectSnapshotId);
         purgeCommands.deleteSnapshots(query);
       }
 
@@ -170,11 +170,11 @@ public class PurgeDao {
     commands.deleteResources(resourceIds);
   }
 
-  @VisibleForTesting
-  void disableResource(long resourceId, PurgeMapper mapper) {
+  private void disableResource(long resourceId, PurgeMapper mapper) {
     mapper.deleteResourceIndex(Arrays.asList(resourceId));
     mapper.setSnapshotIsLastToFalse(resourceId);
     mapper.disableResource(resourceId);
+    mapper.resolveResourceIssuesNotAlreadyResolved(resourceId);
   }
 
   public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) {
index ba596bccef46ad9b0892179881ce7056c152b558..ff7d36d2d042d44e08f3e77bdfc98056553af928 100644 (file)
@@ -58,16 +58,14 @@ public interface PurgeMapper {
 
   List<Long> selectMetricIdsWithoutHistoricalData();
 
-  List<Long> selectCharacteristicIdsToPurge();
-
   void deleteSnapshotWastedMeasures(@Param("snapshotIds") List<Long> snapshotIds, @Param("mids") List<Long> metricIds);
 
-  void deleteSnapshotMeasuresOnCharacteristics(@Param("snapshotIds") List<Long> snapshotIds, @Param("cids") List<Long> characteristicIds);
-
   void updatePurgeStatusToOne(long snapshotId);
 
   void disableResource(long resourceId);
 
+  void resolveResourceIssuesNotAlreadyResolved(long resourceId);
+
   void deleteResourceIndex(@Param("resourceIds") List<Long> resourceIds);
 
   void deleteEvent(long eventId);
index c2427db7198ec02273c547537bac5b89af61c037..5c2d3bd0be500925caee5510e5dacfca2517ab23 100644 (file)
@@ -223,6 +223,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('521');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('522');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('523');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('524');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('525');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index a7de12225bb11842d83232ef71da34d8ef75d392..cd4dc492f891169a66ab1cd4933b2ae1d1b106d1 100644 (file)
     update projects set enabled=${_false} where id=#{id}
   </update>
 
+  <update id="resolveResourceIssuesNotAlreadyResolved" parameterType="long">
+    update issues set status='CLOSED',resolution='REMOVED' where component_id=#{id} AND resolution IS NULL
+  </update>
+
   <delete id="deleteResourceIndex" parameterType="map">
     delete from resource_index where resource_id in
     <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=",">
index a22b5106384adf0247598061552162a373cda134..bec255186e0a73a9a7b45e01a9dc80335b89cc31 100644 (file)
@@ -24,6 +24,8 @@ import org.hamcrest.Description;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
 import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.resource.ResourceDao;
 
@@ -32,13 +34,20 @@ import java.util.List;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
 import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 public class PurgeDaoTest extends AbstractDaoTestCase {
 
-  private PurgeDao dao;
+  System2 system2;
+
+  PurgeDao dao;
 
   @Before
   public void createDao() {
+    system2 = mock(System2.class);
+    when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime());
+
     dao = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis()), new PurgeProfiler());
   }
 
@@ -64,10 +73,10 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
   }
 
   @Test
-  public void shouldDisableResourcesWithoutLastSnapshot() {
-    setupData("shouldDisableResourcesWithoutLastSnapshot");
-    dao.purge(new PurgeConfiguration(1L, new String[0], 30));
-    checkTables("shouldDisableResourcesWithoutLastSnapshot", "projects", "snapshots");
+  public void disable_resources_without_last_snapshot() {
+    setupData("disable_resources_without_last_snapshot");
+    dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2));
+    checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues");
   }
 
   @Test
@@ -109,7 +118,6 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
     checkTables("should_delete_all_closed_issues", "issues", "issue_changes");
   }
 
-
   static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> {
     long snapshotId;
     boolean isLast;
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot-result.xml
new file mode 100644 (file)
index 0000000..9663761
--- /dev/null
@@ -0,0 +1,97 @@
+<!--
+
+What has been changed :
+* enabled=false on projects
+* purge_status=1 on snapshots
+* resolve not already resolved issues on all components
+
+-->
+<dataset>
+
+  <!-- the project -->
+  <projects id="1" enabled="[false]" root_id="[null]" created_at="[null]"
+            long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <!-- the directory -->
+  <projects id="2" enabled="[false]" root_id="1" created_at="[null]"
+            long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <!-- the file -->
+  <projects id="3" enabled="[false]" root_id="1" created_at="[null]"
+            long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <snapshots id="1"
+             project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+             status="P" islast="[false]" purge_status="1"
+             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="[null]"/>
+
+  <snapshots id="2"
+             project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+             status="P" islast="[false]" purge_status="1"
+             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="[null]"/>
+
+
+  <snapshots id="3"
+             project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+             status="P" islast="[false]" purge_status="1"
+             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="[null]"/>
+
+  <!-- Open issue on file -->
+  <issues id="1" kee="ISSUE-1"
+          component_id="3"
+          root_component_id="1"
+          status="CLOSED"
+          issue_close_date="[null]"
+          resolution="REMOVED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Open issue on directory -->
+  <issues id="2" kee="ISSUE-2"
+          component_id="2"
+          root_component_id="1"
+          status="CLOSED"
+          issue_close_date="[null]"
+          resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Open issue on project -->
+  <issues id="3" kee="ISSUE-3"
+          component_id="1"
+          root_component_id="1"
+          status="CLOSED"
+          issue_close_date="[null]"
+          resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Resolved issue on file -> not to be updated -->
+  <issues id="4" kee="ISSUE-4"
+          component_id="3"
+          root_component_id="1"
+          status="CLOSED"
+          issue_close_date="2014-04-08"
+          resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/disable_resources_without_last_snapshot.xml
new file mode 100644 (file)
index 0000000..e2cc5f4
--- /dev/null
@@ -0,0 +1,89 @@
+<dataset>
+
+  <!-- the project -->
+  <projects id="1" enabled="[true]" root_id="[null]" created_at="[null]"
+            long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <!-- the directory -->
+  <projects id="2" enabled="[true]" root_id="1" created_at="[null]"
+            long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <!-- the file -->
+  <projects id="3" enabled="[true]" root_id="1" created_at="[null]"
+            long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
+            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+  <snapshots id="1"
+             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+  <snapshots id="2"
+             project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+
+  <snapshots id="3"
+             project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+  <!-- Open issue on file -->
+  <issues id="1" kee="ISSUE-1"
+          component_id="3"
+          root_component_id="1"
+          status="OPEN"
+          issue_close_date="[null]"
+          resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Open issue on directory -->
+  <issues id="2" kee="ISSUE-2"
+          component_id="2"
+          root_component_id="1"
+          status="OPEN"
+          issue_close_date="[null]"
+          resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Open issue on project -->
+  <issues id="3" kee="ISSUE-3"
+          component_id="1"
+          root_component_id="1"
+          status="CONFIRM"
+          issue_close_date="[null]"
+          resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+  <!-- Resolved issue on file -> not to be updated -->
+  <issues id="4" kee="ISSUE-4"
+          component_id="3"
+          root_component_id="1"
+          status="CLOSED"
+          issue_close_date="2014-04-08"
+          resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
+          message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
+          updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot-result.xml
deleted file mode 100644 (file)
index 8857dc5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-<!--
-
-What has been changed :
-* enabled=false on projects
-* purge_status=1 on snapshots
-
--->
-<dataset>
-
-  <!-- the project -->
-  <projects id="1" enabled="[false]" root_id="[null]" created_at="[null]"
-            long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <!-- the directory -->
-  <projects id="2" enabled="[false]" root_id="1" created_at="[null]"
-            long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <!-- the file -->
-  <projects id="3" enabled="[false]" root_id="1" created_at="[null]"
-            long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <snapshots id="1"
-             project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
-             status="P" islast="[false]" purge_status="1"
-             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="[null]"/>
-
-  <snapshots id="2"
-             project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
-             status="P" islast="[false]" purge_status="1"
-             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="[null]"/>
-
-
-  <snapshots id="3"
-             project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
-             status="P" islast="[false]" purge_status="1"
-             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="[null]"/>
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDisableResourcesWithoutLastSnapshot.xml
deleted file mode 100644 (file)
index fbda7d8..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<dataset>
-
-  <!-- the project -->
-  <projects id="1" enabled="[true]" root_id="[null]" created_at="[null]"
-            long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <!-- the directory -->
-  <projects id="2" enabled="[true]" root_id="1" created_at="[null]"
-            long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <!-- the file -->
-  <projects id="3" enabled="[true]" root_id="1" created_at="[null]"
-            long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
-            description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
-  <snapshots id="1"
-             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-  <snapshots id="2"
-             project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
-             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-
-  <snapshots id="3"
-             project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
-             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-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-</dataset>
index 9eb87fb10c9e3c187b4ce435f96d9a87bde1a20b..4d55fe35f48c12108223e9ecccde86fc7224eda9 100644 (file)
@@ -9,6 +9,16 @@
             long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
             description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
 
+  <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="[null]"/>
+
 
   <!-- old closed issues on file and project -->
   <!--
index c725ed53d9cc968b52f193b9f6d21cd496765d60..c3c7aed53ed306531fe8ee3eed63df66936078b4 100644 (file)
@@ -4,6 +4,16 @@
             long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
             description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
 
+  <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="[null]"/>
+
 
   <!-- old closed issues on file and project -->
   <issues id="1" kee="ISSUE-1"
index 775d6c17fe6b5e36131cee7e3a74bc16fbdead8b..832ee1082a594d6836c769959aa2e4155d0922b4 100644 (file)
@@ -4,6 +4,15 @@
             long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
             description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
 
+  <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="[null]"/>
 
   <!-- old closed issues on file and project -> to be purged -->
   <!--
index 083dd7af08f9b1948c8c466a30d085f02ec40232..47b40a5fdaf80d4da11fa221f46df19598116a5b 100644 (file)
@@ -4,6 +4,15 @@
             long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
             description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
 
+  <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="[null]"/>
 
   <!-- old closed issues on file and project -> to be purged -->
   <issues id="1" kee="ISSUE-1"
index b2690c3f3d8f1ce75baaf91422e673a39a00b1c6..18662efe7b4d635917e6102869c6794fcec7c98c 100644 (file)
@@ -30,15 +30,19 @@ import java.util.List;
 public interface DatabaseMigrations {
 
   List<Class<? extends DatabaseMigration>> CLASSES = ImmutableList.of(
+    // 3.6
     ViolationMigration.class,
+
+    // 4.2
+    PackageKeysMigration.class, CompleteIssueMessageMigration.class,
+
+    // 4.3
     IssueMigration.class,
     IssueChangelogMigration.class,
     TechnicalDebtMeasuresMigration.class,
     DevelopmentCostMeasuresMigration.class,
     RequirementMeasuresMigration.class,
-
-    // 4.2
-    PackageKeysMigration.class, CompleteIssueMessageMigration.class
+    NotResolvedIssuesOnRemovedComponentsMigration.class
   );
 
 }
index 31f9e0224d08e5266400b792dffe4d655f130324..a6e861e42023bc3cbdffce1195a6ce049c5eefcf 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.sonar.server.db.migrations;
 
+import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.dbutils.DbUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -81,7 +82,7 @@ public class MassUpdater {
       } else {
         stmt.setFetchSize(GROUP_SIZE);
       }
-      rs = stmt.executeQuery(inputLoader.selectSql());
+      rs = stmt.executeQuery(convertSelectSql(inputLoader.selectSql(), db));
 
       int cursor = 0;
       while (rs.next()) {
@@ -120,4 +121,15 @@ public class MassUpdater {
     }
   }
 
+  @VisibleForTesting
+  static String convertSelectSql(String selectSql, Database db){
+    // Replace ${_true}
+    selectSql = selectSql.replace("${_true}", db.getDialect().getTrueSqlValue());
+
+    // Replace ${_false}
+    selectSql = selectSql.replace("${_false}", db.getDialect().getFalseSqlValue());
+
+    return selectSql;
+  }
+
 }
index a851125dab738423121520e0da7982529ea1e5d4..cfd9cc707b20267a76302f12191c66080546a859 100644 (file)
@@ -21,7 +21,7 @@
 package org.sonar.server.db.migrations.v43;
 
 import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.config.Settings;
+import org.sonar.api.issue.Issue;
 import org.sonar.api.utils.System2;
 import org.sonar.core.persistence.Database;
 import org.sonar.server.db.migrations.DatabaseMigration;
@@ -35,22 +35,21 @@ import java.sql.Timestamp;
 
 /**
  * Used in the Active Record Migration 525
+ *
  * @since 4.3
  */
 public class NotResolvedIssuesOnRemovedComponentsMigration implements DatabaseMigration {
 
-  private final WorkDurationConvertor workDurationConvertor;
   private final System2 system2;
   private final Database db;
 
-  public NotResolvedIssuesOnRemovedComponentsMigration(Database database, Settings settings) {
-    this(database, settings, System2.INSTANCE);
+  public NotResolvedIssuesOnRemovedComponentsMigration(Database database) {
+    this(database, System2.INSTANCE);
   }
 
   @VisibleForTesting
-  NotResolvedIssuesOnRemovedComponentsMigration(Database database, Settings settings, System2 system2) {
+  NotResolvedIssuesOnRemovedComponentsMigration(Database database, System2 system2) {
     this.db = database;
-    this.workDurationConvertor = new WorkDurationConvertor(settings);
     this.system2 = system2;
   }
 
@@ -60,28 +59,30 @@ public class NotResolvedIssuesOnRemovedComponentsMigration implements DatabaseMi
       new MassUpdater.InputLoader<Row>() {
         @Override
         public String selectSql() {
-          return "SELECT i.id, i.technical_debt FROM issues i WHERE i.technical_debt IS NOT NULL";
+          return "SELECT i.id FROM issues i " +
+            "INNER JOIN projects p on p.id=i.component_id " +
+            "WHERE p.enabled=${_false} AND i.resolution IS NULL ";
         }
 
         @Override
         public Row load(ResultSet rs) throws SQLException {
           Row row = new Row();
           row.id = SqlUtil.getLong(rs, 1);
-          row.debt = SqlUtil.getLong(rs, 2);
           return row;
         }
       },
       new MassUpdater.InputConverter<Row>() {
         @Override
         public String updateSql() {
-          return "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?";
+          return "UPDATE issues SET status=?,resolution=?,updated_at=? WHERE id=?";
         }
 
         @Override
         public boolean convert(Row row, PreparedStatement updateStatement) throws SQLException {
-          updateStatement.setLong(1, workDurationConvertor.createFromLong(row.debt));
-          updateStatement.setTimestamp(2, new Timestamp(system2.now()));
-          updateStatement.setLong(3, row.id);
+          updateStatement.setString(1, Issue.STATUS_CLOSED);
+          updateStatement.setString(2, Issue.RESOLUTION_REMOVED);
+          updateStatement.setTimestamp(3, new Timestamp(system2.now()));
+          updateStatement.setLong(4, row.id);
           return true;
         }
       }
@@ -90,7 +91,6 @@ public class NotResolvedIssuesOnRemovedComponentsMigration implements DatabaseMi
 
   private static class Row {
     private Long id;
-    private Long debt;
   }
 
 }
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/525_update_not_resolved_issues_on_removed_components.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/525_update_not_resolved_issues_on_removed_components.rb
new file mode 100644 (file)
index 0000000..df7f088
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 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.
+#
+
+#
+# SonarQube 4.3
+# SONAR-5200
+#
+class UpdateNotResolvedIssuesOnRemovedComponents < ActiveRecord::Migration
+
+  def self.up
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.v43.NotResolvedIssuesOnRemovedComponentsMigration')
+  end
+
+end
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/MassUpdaterTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/MassUpdaterTest.java
new file mode 100644 (file)
index 0000000..208c0d5
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.db.migrations;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.dialect.Dialect;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MassUpdaterTest {
+
+  @Mock
+  Database db;
+
+  @Test
+  public void convert_select_sql() throws Exception {
+    Dialect dialect = mock(Dialect.class);
+    when(dialect.getTrueSqlValue()).thenReturn("true");
+    when(dialect.getFalseSqlValue()).thenReturn("false");
+
+    when(db.getDialect()).thenReturn(dialect);
+
+    String result = MassUpdater.convertSelectSql("SELECT * FROM projects WHERE enabled=${_true} AND used=${_true} AND deleted=${_false}", db);
+    assertThat(result).isEqualTo("SELECT * FROM projects WHERE enabled=true AND used=true AND deleted=false");
+  }
+}
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest.java
new file mode 100644 (file)
index 0000000..dae4233
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.
+ */
+
+package org.sonar.server.db.migrations.v43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NotResolvedIssuesOnRemovedComponentsMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(NotResolvedIssuesOnRemovedComponentsMigrationTest.class, "schema.sql");
+
+  @Mock
+  System2 system2;
+
+  NotResolvedIssuesOnRemovedComponentsMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime());
+
+    migration = new NotResolvedIssuesOnRemovedComponentsMigration(db.database(), system2);
+  }
+
+  @Test
+  public void migrate_issues() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_issues.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_issues_result.xml", "issues");
+  }
+
+}
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues.xml
new file mode 100644 (file)
index 0000000..1e7e5ab
--- /dev/null
@@ -0,0 +1,35 @@
+<dataset>
+
+  <projects id="1" root_id="[null]" scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Action.java" name="Action"
+            description="[null]" long_name="org.struts.Action"
+            enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" path="/foo/bar" deprecated_kee="org.struts:struts:org.struts.Action" />
+
+  <projects id="2" root_id="[null]" scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Filter.java" name="Filter"
+            description="[null]" long_name="org.struts.Filter"
+            enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" path="[null]" deprecated_kee="org.struts:struts:org.struts.Filter" />
+
+  <!-- Issue not resolved on not removed component -> Nothing to do -->
+  <issues ID="1" COMPONENT_ID="1" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="10"/>
+
+  <!-- Issue not resolved on removed component -> To be closed -->
+  <issues ID="2" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="10"/>
+
+  <!-- Issue resolved on removed component -> Nothing to do -->
+  <issues ID="3" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="FIXED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="10"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/migrate_issues_result.xml
new file mode 100644 (file)
index 0000000..4509c27
--- /dev/null
@@ -0,0 +1,27 @@
+<dataset>
+
+  <!-- Issue not resolved on not removed component -> Nothing to do -->
+  <issues ID="1" COMPONENT_ID="1" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="10"/>
+
+  <!-- Issue not resolved on removed component -> To be closed -->
+  <issues ID="2" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="REMOVED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2014-04-09 00:00:00.0"
+          TECHNICAL_DEBT="10"/>
+
+  <!-- Issue resolved on removed component -> Nothing to do -->
+  <issues ID="3" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+          ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+          EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+          ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+          RESOLUTION="FIXED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+          TECHNICAL_DEBT="10"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/v43/NotResolvedIssuesOnRemovedComponentsMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..c0129aa
--- /dev/null
@@ -0,0 +1,46 @@
+-- 4.3
+
+CREATE TABLE "ISSUES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(50) UNIQUE NOT NULL,
+  "COMPONENT_ID" INTEGER NOT NULL,
+  "ROOT_COMPONENT_ID" INTEGER,
+  "RULE_ID" INTEGER,
+  "SEVERITY" VARCHAR(10),
+  "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+  "MESSAGE" VARCHAR(4000),
+  "LINE" INTEGER,
+  "EFFORT_TO_FIX" DOUBLE,
+  "STATUS" VARCHAR(20),
+  "RESOLUTION" VARCHAR(20),
+  "CHECKSUM" VARCHAR(1000),
+  "REPORTER" VARCHAR(40),
+  "ASSIGNEE" VARCHAR(40),
+  "AUTHOR_LOGIN" VARCHAR(100),
+  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+  "ISSUE_ATTRIBUTES" VARCHAR(4000),
+  "ISSUE_CREATION_DATE" TIMESTAMP,
+  "ISSUE_CLOSE_DATE" TIMESTAMP,
+  "ISSUE_UPDATE_DATE" TIMESTAMP,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "TECHNICAL_DEBT" INTEGER
+);
+
+CREATE TABLE "PROJECTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(256),
+  "DESCRIPTION" VARCHAR(2000),
+  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "KEE" VARCHAR(400),
+  "DEPRECATED_KEE" VARCHAR(400),
+  "PATH" VARCHAR(2000),
+  "ROOT_ID" INTEGER,
+  "LANGUAGE" VARCHAR(20),
+  "COPY_RESOURCE_ID" INTEGER,
+  "LONG_NAME" VARCHAR(256),
+  "PERSON_ID" INTEGER,
+  "CREATED_AT" TIMESTAMP
+);