]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4996 Create migration on debt measures
authorJulien Lancelot <julien.lancelot@gmail.com>
Fri, 21 Feb 2014 16:00:57 +0000 (17:00 +0100)
committerJulien Lancelot <julien.lancelot@gmail.com>
Tue, 25 Feb 2014 18:01:13 +0000 (19:01 +0100)
15 files changed:
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql
sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java
sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb [new file with mode: 0644]
sonar-server/src/test/java/org/sonar/server/db/migrations/DatabaseMigrationsTest.java
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java
sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql [new file with mode: 0644]

index b506de4860519a4df1fccb539d446b9d5bc25007..756e5ec3e76269e2c4f7291e24dda932171dc820 100644 (file)
@@ -33,7 +33,7 @@ import java.util.List;
  */
 public class DatabaseVersion implements BatchComponent, ServerComponent {
 
-  public static final int LAST_VERSION = 514;
+  public static final int LAST_VERSION = 515;
 
   public static enum Status {
     UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
index 558541de844337eeac29878e749c4121fc17b5b6..c19f22072d77cad37f52a3e4a153bcf132c69713 100644 (file)
@@ -212,6 +212,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('510');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('511');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('513');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('514');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('515');
 
 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 154e09fcfe9530059921401f7f34e7f6b6e07bf3..14cd9a5d9b50155c23054c05965be1c4e173607c 100644 (file)
@@ -22,6 +22,7 @@ package org.sonar.server.db.migrations;
 import com.google.common.collect.ImmutableList;
 import org.sonar.server.db.migrations.debt.IssueChangelogMigration;
 import org.sonar.server.db.migrations.debt.IssueMigration;
+import org.sonar.server.db.migrations.debt.TechnicalDebtMeasureMigration;
 import org.sonar.server.db.migrations.violation.ViolationMigration;
 
 import java.util.List;
@@ -31,7 +32,8 @@ public interface DatabaseMigrations {
   List<Class<? extends DatabaseMigration>> CLASSES = ImmutableList.of(
     ViolationMigration.class,
     IssueMigration.class,
-    IssueChangelogMigration.class
+    IssueChangelogMigration.class,
+    TechnicalDebtMeasureMigration.class
   );
 
 }
index 4ae3b4ef18533fb6e70819025d8f19751b2215a1..ed47bd785c5506635298adf7e29c6c2d44d6c8d8 100644 (file)
@@ -57,6 +57,10 @@ class DebtConvertor {
     return durationInSeconds;
   }
 
+  long createFromDays(double days) {
+    return ((Double) (days * hoursInDay() * 3600L)).longValue();
+  }
+
   private int hoursInDay() {
     int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY);
     if (hoursInDay < 0) {
index 432039cd254ae5b462bed7002d90c72473c1c995..df57ca9a3898b7d60c5f2772260d02acbcb3647f 100644 (file)
@@ -60,7 +60,7 @@ public class IssueChangelogMigration implements DatabaseMigration {
   private static final String SQL_SELECT = "SELECT * FROM issue_changes WHERE change_type = 'diff' and change_data LIKE '%technicalDebt%'";
   private static final String SQL_UPDATE = "UPDATE issue_changes SET change_data=?,updated_at=? WHERE id=?";
 
-  static final String SQL_SELECT_ISSUES;
+  static final String SQL_SELECT_ALL;
 
   static {
     StringBuilder sb = new StringBuilder("SELECT c.id AS "+ ID +", c.change_data AS " + CHANGE_DATA +
@@ -72,7 +72,7 @@ public class IssueChangelogMigration implements DatabaseMigration {
       }
       sb.append("c.id=?");
     }
-    SQL_SELECT_ISSUES = sb.toString();
+    SQL_SELECT_ALL = sb.toString();
   }
 
   private final DebtConvertor debtConvertor;
@@ -126,7 +126,7 @@ public class IssueChangelogMigration implements DatabaseMigration {
     try {
       readConnection = db.getDataSource().getConnection();
       RowHandler rowHandler = new RowHandler();
-      return new QueryRunner().query(readConnection, SQL_SELECT_ISSUES, rowHandler, ids);
+      return new QueryRunner().query(readConnection, SQL_SELECT_ALL, rowHandler, ids);
 
     } finally {
       DbUtils.closeQuietly(readConnection);
diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java
new file mode 100644 (file)
index 0000000..6e59af2
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+package org.sonar.server.db.migrations.debt;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.dbutils.QueryRunner;
+import org.apache.commons.dbutils.handlers.AbstractListHandler;
+import org.picocontainer.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.MessageException;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.DatabaseMigration;
+import org.sonar.server.db.migrations.util.SqlUtil;
+
+import javax.annotation.CheckForNull;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Used in the Active Record Migration 515
+ */
+public class TechnicalDebtMeasureMigration implements DatabaseMigration {
+
+  private Logger logger = LoggerFactory.getLogger(TechnicalDebtMeasureMigration.class);
+
+  private static final String ID = "id";
+  private static final String VALUE = "changeData";
+  private static final String VAR1 = "var1";
+  private static final String VAR2 = "var2";
+  private static final String VAR3 = "var3";
+  private static final String VAR4 = "var4";
+  private static final String VAR5 = "var5";
+
+  private static final String FAILURE_MESSAGE = "Fail to migrate data";
+
+  private static final String SQL_SELECT = "SELECT * FROM project_measures INNER JOIN metrics on metrics.id=project_measures.metric_id " +
+    "WHERE metrics.name='sqale_index' or metrics.name='new_technical_debt'";
+  private static final String SQL_UPDATE = "UPDATE project_measures SET value=?," +
+    "variation_value_1=?,variation_value_2=?,variation_value_3=?,variation_value_4=?,variation_value_5=? WHERE id=?";
+  private static final String SQL_SELECT_ALL;
+
+  static {
+    StringBuilder sb = new StringBuilder("SELECT pm.id AS " + ID + ", pm.value AS " + VALUE +
+      ", pm.variation_value_1 AS " + VAR1 + ", pm.variation_value_2 AS " + VAR2 + ", pm.variation_value_3 AS " + VAR3 +
+      ", pm.variation_value_4 AS " + VAR4 + ", pm.variation_value_5 AS " + VAR5 +
+      " FROM project_measures pm " +
+      " WHERE ");
+    for (int i = 0; i < Referentials.GROUP_SIZE; i++) {
+      if (i > 0) {
+        sb.append(" OR ");
+      }
+      sb.append("pm.id=?");
+    }
+    SQL_SELECT_ALL = sb.toString();
+  }
+
+  private final DebtConvertor debtConvertor;
+  private final Database db;
+
+  public TechnicalDebtMeasureMigration(Database database, Settings settings) {
+    this.db = database;
+    this.debtConvertor = new DebtConvertor(settings);
+  }
+
+  @Override
+  public void execute() {
+    try {
+      logger.info("Initialize input");
+      Referentials referentials = new Referentials(db, SQL_SELECT);
+      if (referentials.size() > 0) {
+        logger.info("Migrate {} rows", referentials.size());
+        convert(referentials);
+      }
+    } catch (SQLException e) {
+      logger.error(FAILURE_MESSAGE, e);
+      SqlUtil.log(logger, e);
+      throw MessageException.of(FAILURE_MESSAGE);
+
+    } catch (Exception e) {
+      logger.error(FAILURE_MESSAGE, e);
+      throw MessageException.of(FAILURE_MESSAGE);
+    }
+  }
+
+  public Object convert(Referentials referentials) throws Exception {
+    Long[] ids = referentials.pollGroupOfIds();
+    while (ids.length > 0) {
+      List<Map<String, Object>> rows = selectRows(ids);
+      convert(rows, ids);
+
+      ids = referentials.pollGroupOfIds();
+    }
+    return null;
+  }
+
+  private List<Map<String, Object>> selectRows(Long[] ids) throws SQLException {
+    Connection readConnection = null;
+    try {
+      readConnection = db.getDataSource().getConnection();
+      RowHandler rowHandler = new RowHandler();
+      return new QueryRunner().query(readConnection, SQL_SELECT_ALL, rowHandler, ids);
+
+    } finally {
+      DbUtils.closeQuietly(readConnection);
+    }
+  }
+
+  private void convert(List<Map<String, Object>> rows, Long[] ids) throws SQLException {
+    Connection readConnection = null;
+    Connection writeConnection = null;
+    try {
+      readConnection = db.getDataSource().getConnection();
+      writeConnection = db.getDataSource().getConnection();
+      writeConnection.setAutoCommit(false);
+
+      List<Object[]> allParams = Lists.newArrayList();
+      QueryRunner runner = new QueryRunner();
+      for (Map<String, Object> row : rows) {
+        Object[] params = new Object[7];
+        params[0] = convertDebtForDays((Double) row.get(VALUE));
+        params[1] = convertDebtForDays((Double) row.get(VAR1));
+        params[2] = convertDebtForDays((Double) row.get(VAR2));
+        params[3] = convertDebtForDays((Double) row.get(VAR3));
+        params[4] = convertDebtForDays((Double) row.get(VAR4));
+        params[5] = convertDebtForDays((Double) row.get(VAR5));
+        params[6] = row.get(ID);
+        allParams.add(params);
+      }
+      runner.batch(writeConnection, SQL_UPDATE, allParams.toArray(new Object[allParams.size()][]));
+      writeConnection.commit();
+
+    } finally {
+      DbUtils.closeQuietly(readConnection);
+      DbUtils.closeQuietly(writeConnection);
+    }
+  }
+
+  @VisibleForTesting
+  @CheckForNull
+  Long convertDebtForDays(@Nullable Double data) {
+    if (data == null) {
+      return null;
+    }
+    return debtConvertor.createFromDays(data);
+  }
+
+  private static class RowHandler extends AbstractListHandler<Map<String, Object>> {
+    @Override
+    protected Map<String, Object> handleRow(ResultSet rs) throws SQLException {
+      Map<String, Object> map = Maps.newHashMap();
+      map.put(ID, SqlUtil.getLong(rs, ID));
+      map.put(VALUE, SqlUtil.getDouble(rs, VALUE));
+      map.put(VAR1, SqlUtil.getDouble(rs, VAR1));
+      map.put(VAR2, SqlUtil.getDouble(rs, VAR2));
+      map.put(VAR3, SqlUtil.getDouble(rs, VAR3));
+      map.put(VAR4, SqlUtil.getDouble(rs, VAR4));
+      map.put(VAR5, SqlUtil.getDouble(rs, VAR5));
+      return map;
+    }
+  }
+
+}
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb
new file mode 100644 (file)
index 0000000..0db6cca
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+#
+# Sonar 4.3
+# SONAR-4996
+#
+class UpdateMeasuresDebtToSeconds < ActiveRecord::Migration
+
+  def self.up
+    Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.TechnicalDebtMeasureMigration')
+  end
+end
index b53d774175582572826929ffb31dd81443d8e620..478277f04bf300ca7b370ea10ac046ba45d9da5f 100644 (file)
@@ -28,6 +28,6 @@ public class DatabaseMigrationsTest {
 
   @Test
   public void check_number_of_migrations() throws Exception {
-    assertThat(DatabaseMigrations.CLASSES).hasSize(3);
+    assertThat(DatabaseMigrations.CLASSES).isNotEmpty();
   }
 }
index 398dea4d8c58b5e896b9fcbef7cba0d11e88476b..2d53bec72143d61baea671d9b964238969276561 100644 (file)
@@ -39,7 +39,7 @@ public class DebtConvertorTest {
   }
 
   @Test
-  public void convert() throws Exception {
+  public void convert_fromn_long() throws Exception {
     settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8);
 
     assertThat(convertor.createFromLong(1)).isEqualTo(60);
@@ -49,12 +49,12 @@ public class DebtConvertorTest {
   }
 
   @Test
-  public void use_default_value_for_hours_in_day_when_no_property() throws Exception {
+  public void convert_fromn_long_use_default_value_for_hours_in_day_when_no_property() throws Exception {
     assertThat(convertor.createFromLong(1)).isEqualTo(60);
   }
 
   @Test
-  public void fail_on_bad_hours_in_day_property() throws Exception {
+  public void fail_convert_fromn_long_on_bad_hours_in_day_property() throws Exception {
     try {
       settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, -2);
       convertor.createFromLong(1);
@@ -64,4 +64,15 @@ public class DebtConvertorTest {
     }
   }
 
+  @Test
+  public void convert_from_days() throws Exception {
+    settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    assertThat(convertor.createFromDays(1.0)).isEqualTo(28800);
+    assertThat(convertor.createFromDays(0.1)).isEqualTo(2880);
+
+    // Should be 1.88 but as it's a long it's truncated after comma
+    assertThat(convertor.createFromDays(0.0001)).isEqualTo(2);
+  }
+
 }
diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java
new file mode 100644 (file)
index 0000000..fb5c590
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package org.sonar.server.db.migrations.debt;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.config.Settings;
+import org.sonar.core.persistence.TestDatabase;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TechnicalDebtMeasureMigrationTest {
+
+  @ClassRule
+  public static TestDatabase db = new TestDatabase().schema(TechnicalDebtMeasureMigrationTest.class, "schema.sql");
+
+  Settings settings;
+
+  TechnicalDebtMeasureMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    settings = new Settings();
+    settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8);
+
+    migration = new TechnicalDebtMeasureMigration(db.database(), settings);
+  }
+
+  @Test
+  public void migrate_technical_debt_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_technical_debt_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_technical_debt_measures_result.xml", "project_measures");
+  }
+
+  @Test
+  public void migrate_added_technical_debt_measures() throws Exception {
+    db.prepareDbUnit(getClass(), "migrate_new_technical_debt_measures.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "migrate_new_technical_debt_measures_result.xml", "project_measures");
+  }
+
+}
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml
new file mode 100644 (file)
index 0000000..186b86b
--- /dev/null
@@ -0,0 +1,29 @@
+<dataset>
+
+  <!-- Added Technical debt metric -->
+  <metrics delete_historical_data="[null]" id="1" name="new_technical_debt" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <!-- Another metric -->
+  <metrics delete_historical_data="[null]" id="2" 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"/>
+
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.01" variation_value_2="0.02" variation_value_3="0.03" variation_value_4="0.04" variation_value_5="0.05"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.01" variation_value_2="0.02" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml
new file mode 100644 (file)
index 0000000..591506c
--- /dev/null
@@ -0,0 +1,21 @@
+<dataset>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="288" variation_value_2="576" variation_value_3="864" variation_value_4="1152" variation_value_5="1440"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="[null]" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="288" variation_value_2="576" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml
new file mode 100644 (file)
index 0000000..e7e2486
--- /dev/null
@@ -0,0 +1,35 @@
+<dataset>
+
+  <!-- Technical debt metric -->
+  <metrics delete_historical_data="[null]" id="1" name="sqale_index" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]"  domain="[null]" short_name=""
+           enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
+
+  <!-- Another metric -->
+  <metrics delete_historical_data="[null]" id="2" 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"/>
+
+
+  <!-- Value 1 day of debt -->
+  <project_measures id="1.0" VALUE="1.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="2.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.01" variation_value_2="0.02" variation_value_3="0.03" variation_value_4="0.04" variation_value_5="0.05"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="3.0" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="0.01" variation_value_2="0.02" variation_value_3="0.0" variation_value_4="0.0" variation_value_5="0.0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml
new file mode 100644 (file)
index 0000000..150674c
--- /dev/null
@@ -0,0 +1,27 @@
+<dataset>
+
+  <!-- Value 1 day, 1 hour and 1 minute of debt -->
+  <project_measures id="1" VALUE="28800" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+  <!-- Measure with variations on all period -->
+  <project_measures id="2" VALUE="57600" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="288" variation_value_2="576" variation_value_3="864" variation_value_4="1152" variation_value_5="1440"/>
+
+  <!-- Measure with some variations -->
+  <project_measures id="3" VALUE="86400" METRIC_ID="1" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="288" variation_value_2="576" variation_value_3="0" variation_value_4="0" variation_value_5="0"/>
+
+  <!-- Change on another metric, should not be touched -->
+  <project_measures id="10" VALUE="20" METRIC_ID="2" SNAPSHOT_ID="1000" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]" person_id="[null]"
+                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql
new file mode 100644 (file)
index 0000000..1e29613
--- /dev/null
@@ -0,0 +1,45 @@
+-- 4.3
+
+CREATE TABLE "PROJECT_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "VALUE" DOUBLE,
+  "METRIC_ID" INTEGER NOT NULL,
+  "SNAPSHOT_ID" INTEGER,
+  "RULE_ID" INTEGER,
+  "RULES_CATEGORY_ID" INTEGER,
+  "TEXT_VALUE" VARCHAR(96),
+  "TENDENCY" INTEGER,
+  "MEASURE_DATE" TIMESTAMP,
+  "PROJECT_ID" INTEGER,
+  "ALERT_STATUS" VARCHAR(5),
+  "ALERT_TEXT" VARCHAR(4000),
+  "URL" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(4000),
+  "RULE_PRIORITY" INTEGER,
+  "CHARACTERISTIC_ID" INTEGER,
+  "PERSON_ID" INTEGER,
+  "VARIATION_VALUE_1" DOUBLE,
+  "VARIATION_VALUE_2" DOUBLE,
+  "VARIATION_VALUE_3" DOUBLE,
+  "VARIATION_VALUE_4" DOUBLE,
+  "VARIATION_VALUE_5" DOUBLE
+);
+
+CREATE TABLE "METRICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(255),
+  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
+  "DOMAIN" VARCHAR(64),
+  "SHORT_NAME" VARCHAR(64),
+  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VAL_TYPE" VARCHAR(8),
+  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+  "ENABLED" BOOLEAN DEFAULT TRUE,
+  "ORIGIN" VARCHAR(3),
+  "WORST_VALUE" DOUBLE,
+  "BEST_VALUE" DOUBLE,
+  "OPTIMIZED_BEST_VALUE" BOOLEAN,
+  "HIDDEN" BOOLEAN,
+  "DELETE_HISTORICAL_DATA" BOOLEAN
+);