]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5392 When migrating to SonarQube 4.3.X with a incompatible plugin, requirements...
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 11 Jun 2014 16:53:57 +0000 (18:53 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 11 Jun 2014 16:54:07 +0000 (18:54 +0200)
sonar-core/src/main/java/org/sonar/core/template/LoadedTemplateDto.java
sonar-core/src/main/resources/org/sonar/core/technicaldebt/db/CharacteristicMapper.xml
sonar-server/src/main/java/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRules.java
sonar-server/src/test/java/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest.java
sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/copy_requirements_from_characteristics_to_rules_result.xml
sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed.xml [new file with mode: 0644]
sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed_result.xml [new file with mode: 0644]

index 99cb9ba54474fcff830a590ac64653d09457658e..d0a52bc1c666e6e14a73cf41543b5cb6f2d8d681 100644 (file)
@@ -28,6 +28,7 @@ public final class LoadedTemplateDto {
   public static final String QUALITY_PROFILE_TYPE = "QUALITY_PROFILE";
   public static final String PERMISSION_TEMPLATE_TYPE = "PERM_TEMPLATE";
   public static final String QUALITY_GATE_TYPE = "QUALITY_GATE";
+  public static final String ONE_SHOT_TASK_TYPE = "ONE_SHOT_TASK";
 
   private Long id;
   private String key;
index ba18caf7e8aeb84ecf3eadbf0e78225f71afefcc..5857ba78a8760ae3e790f7e5bd8dab7e4c2cb003 100644 (file)
   </update>
 
   <select id="selectDeprecatedRequirements" resultType="map">
-    select id as id,
-    parent_id as parentId,
-    root_id as rootId,
-    rule_id as ruleId,
-    function_key as functionKey,
-    factor_value as coefficientValue,
-    factor_unit as coefficientUnit,
-    offset_value as offsetValue,
-    offset_unit as offsetUnit,
-    enabled as enabled
+    select id as "id",
+    parent_id as "parentId",
+    root_id as "rootId",
+    rule_id as "ruleId",
+    function_key as "functionKey",
+    factor_value as "coefficientValue",
+    factor_unit as "coefficientUnit",
+    offset_value as "offsetValue",
+    offset_unit as "offsetUnit",
+    enabled as "enabled"
     from characteristics
     where rule_id IS NOT NULL
   </select>
index 02024698f0d97e5fe024902477dd9ab70d9b18a4..10ddce7b90f6141bf2848a24988edfe1ac0c3ec2 100644 (file)
@@ -29,15 +29,14 @@ import org.apache.commons.lang.builder.EqualsBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.ServerComponent;
-import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.api.rule.RuleStatus;
-import org.sonar.api.rules.Rule;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.utils.Duration;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.technicaldebt.db.CharacteristicMapper;
+import org.sonar.core.template.LoadedTemplateDto;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.rule.RegisterRules;
 
@@ -60,29 +59,31 @@ public class CopyRequirementsFromCharacteristicsToRules implements ServerCompone
 
   private static final Logger LOGGER = LoggerFactory.getLogger(CopyRequirementsFromCharacteristicsToRules.class);
 
+  private static final String TEMPLATE_KEY = "CopyRequirementsFromCharacteristicsToRules";
+
   private final DbClient dbClient;
-  private final ServerUpgradeStatus status;
 
   /**
    * @param registerRules used only to be started after init of rules
    */
-  public CopyRequirementsFromCharacteristicsToRules(DbClient dbClient, ServerUpgradeStatus status, RegisterRules registerRules) {
+  public CopyRequirementsFromCharacteristicsToRules(DbClient dbClient, RegisterRules registerRules) {
     this.dbClient = dbClient;
-    this.status = status;
   }
 
   public void start() {
-    if (status.isUpgraded() && status.getInitialDbVersion() <= 520) {
-      doExecute();
-    }
+    doExecute();
   }
 
   private void doExecute() {
-    LOGGER.info("Copying requirement from characteristics to rules");
-    copyRequirementsFromCharacteristicsToRules();
+    if (dbClient.loadedTemplateDao().countByTypeAndKey(LoadedTemplateDto.ONE_SHOT_TASK_TYPE, TEMPLATE_KEY) == 0) {
+      LOGGER.info("Copying requirement from characteristics to rules");
+      copyRequirementsFromCharacteristicsToRules();
+
+      LOGGER.info("Deleting requirements from characteristics");
+      removeRequirementsDataFromCharacteristics();
 
-    LOGGER.info("Deleting requirements data");
-    removeRequirementsDataFromCharacteristics();
+      dbClient.loadedTemplateDao().insert(new LoadedTemplateDto(TEMPLATE_KEY, LoadedTemplateDto.ONE_SHOT_TASK_TYPE));
+    }
   }
 
   private void copyRequirementsFromCharacteristicsToRules() {
@@ -90,20 +91,30 @@ public class CopyRequirementsFromCharacteristicsToRules implements ServerCompone
 
     try {
       List<Map<String, Object>> requirementDtos = dbSession.getMapper(CharacteristicMapper.class).selectDeprecatedRequirements();
-      final Multimap<Number, RequirementDto> requirementsByRuleId = ArrayListMultimap.create();
-      for (Map<String, Object> map : requirementDtos) {
-        RequirementDto requirementDto = new RequirementDto(map);
-        requirementsByRuleId.put(requirementDto.getRuleId(), requirementDto);
-      }
+      if (requirementDtos.isEmpty()) {
+        LOGGER.info("No requirement will be copied", requirementDtos);
+
+      } else {
+        int requirementCopied = 0;
 
-      List<RuleDto> rules = dbClient.ruleDao().findAll(dbSession);
-      for (RuleDto rule : rules) {
-        Collection<RequirementDto> requirementsForRule = requirementsByRuleId.get(rule.getId());
-        if (!requirementsForRule.isEmpty()) {
-          convert(rule, requirementsForRule, dbSession);
+        final Multimap<Number, RequirementDto> requirementsByRuleId = ArrayListMultimap.create();
+        for (Map<String, Object> map : requirementDtos) {
+          RequirementDto requirementDto = new RequirementDto(map);
+          requirementsByRuleId.put(requirementDto.getRuleId(), requirementDto);
         }
+
+        List<RuleDto> rules = dbClient.ruleDao().findAll(dbSession);
+        for (RuleDto rule : rules) {
+          Collection<RequirementDto> requirementsForRule = requirementsByRuleId.get(rule.getId());
+          if (!requirementsForRule.isEmpty()) {
+            convert(rule, requirementsForRule, dbSession);
+            requirementCopied++;
+          }
+        }
+        dbSession.commit();
+
+        LOGGER.info("{} requirements have been found, {} have be copied", requirementDtos.size(), requirementCopied);
       }
-      dbSession.commit();
     } finally {
       MyBatis.closeQuietly(dbSession);
     }
@@ -174,10 +185,10 @@ public class CopyRequirementsFromCharacteristicsToRules implements ServerCompone
 
   @CheckForNull
   @VisibleForTesting
-  static String convertDuration(@Nullable Double oldValue, @Nullable String oldUnit) {
-    if (oldValue != null && oldValue > 0) {
+  static String convertDuration(@Nullable Number oldValue, @Nullable String oldUnit) {
+    if (oldValue != null && oldValue.doubleValue() > 0) {
       // As value is stored in double, we have to round it in order to have an integer (for instance, if it was 1.6, we'll use 2)
-      return Integer.toString((int) Math.round(oldValue)) + convertUnit(oldUnit);
+      return Integer.toString((int) Math.round(oldValue.doubleValue())) + convertUnit(oldUnit);
     }
     return null;
   }
@@ -220,55 +231,53 @@ public class CopyRequirementsFromCharacteristicsToRules implements ServerCompone
      * Do not use Integer because Oracle returns BigDecimal
      */
     public Number getId() {
-      return (Number) map.get("ID");
+      return (Number) map.get("id");
     }
 
     /**
      * Do not use Integer because Oracle returns BigDecimal
      */
     public Number getParentId() {
-      return (Number) map.get("PARENTID");
+      return (Number) map.get("parentId");
     }
 
     /**
      * Do not use Integer because Oracle returns BigDecimal
      */
     public Number getRuleId() {
-      return (Number) map.get("RULEID");
+      return (Number) map.get("ruleId");
     }
 
     public String getFunction() {
-      return (String) map.get("FUNCTIONKEY");
+      return (String) map.get("functionKey");
     }
 
     @CheckForNull
-    public Double getCoefficientValue() {
-      return (Double) map.get("COEFFICIENTVALUE");
+    public Number getCoefficientValue() {
+      return (Number) map.get("coefficientValue");
     }
 
 
     @CheckForNull
     public String getCoefficientUnit() {
-      return (String) map.get("COEFFICIENTUNIT");
+      return (String) map.get("coefficientUnit");
     }
 
 
     @CheckForNull
-    public Double getOffsetValue() {
-      return (Double) map.get("OFFSETVALUE");
+    public Number getOffsetValue() {
+      return (Number) map.get("offsetValue");
     }
 
 
     @CheckForNull
     public String getOffsetUnit() {
-      return (String) map.get("OFFSETUNIT");
+      return (String) map.get("offsetUnit");
     }
 
     public boolean isEnabled() {
-      return (Boolean) map.get("ENABLED");
+      return (Boolean) map.get("enabled");
     }
-
-
   }
 
 }
index 9c7cfbeeaa6ccdfc32d054bd04f7bee63d0a0c9a..ac7dcd807dcb08d2d6aedc406f3ae77c43e7d4e5 100644 (file)
@@ -25,11 +25,11 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.platform.ServerUpgradeStatus;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
 import org.sonar.core.persistence.TestDatabase;
 import org.sonar.core.rule.RuleDto;
+import org.sonar.core.template.LoadedTemplateDao;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.rule.db.RuleDao;
 
@@ -42,31 +42,27 @@ public class CopyRequirementsFromCharacteristicsToRulesTest {
   @ClassRule
   public static TestDatabase db = new TestDatabase();
 
-  @Mock
-  ServerUpgradeStatus status;
-
   @Mock
   System2 system2;
 
+  DbClient dbClient;
+
   CopyRequirementsFromCharacteristicsToRules service;
 
   @Before
   public void setUp() throws Exception {
     when(system2.now()).thenReturn(DateUtils.parseDate("2014-03-13").getTime());
-    DbClient dbClient = new DbClient(db.database(), db.myBatis(), new RuleDao(system2));
-    service = new CopyRequirementsFromCharacteristicsToRules(dbClient, status, null);
+    dbClient = new DbClient(db.database(), db.myBatis(), new RuleDao(system2), new LoadedTemplateDao(db.myBatis()));
+    service = new CopyRequirementsFromCharacteristicsToRules(dbClient, null);
   }
 
   @Test
   public void copy_requirements_from_characteristics_to_rules() throws Exception {
     db.prepareDbUnit(getClass(), "copy_requirements_from_characteristics_to_rules.xml");
 
-    when(status.isUpgraded()).thenReturn(true);
-    when(status.getInitialDbVersion()).thenReturn(498);
-
     service.start();
 
-    db.assertDbUnit(getClass(), "copy_requirements_from_characteristics_to_rules_result.xml", "rules");
+    db.assertDbUnit(getClass(), "copy_requirements_from_characteristics_to_rules_result.xml", "rules", "loaded_templates");
   }
 
   /**
@@ -76,9 +72,6 @@ public class CopyRequirementsFromCharacteristicsToRulesTest {
   public void convert_constant_issue_with_coeff_to_constant_issue_with_offset() throws Exception {
     db.prepareDbUnit(getClass(), "convert_constant_issue_with_coeff_to_constant_issue_with_offset.xml");
 
-    when(status.isUpgraded()).thenReturn(true);
-    when(status.getInitialDbVersion()).thenReturn(498);
-
     service.start();
 
     db.assertDbUnit(getClass(), "convert_constant_issue_with_coeff_to_constant_issue_with_offset_result.xml", "rules");
@@ -88,14 +81,20 @@ public class CopyRequirementsFromCharacteristicsToRulesTest {
   public void remove_requirements_data_from_characteristics() throws Exception {
     db.prepareDbUnit(getClass(), "remove_requirements_data_from_characteristics.xml");
 
-    when(status.isUpgraded()).thenReturn(true);
-    when(status.getInitialDbVersion()).thenReturn(498);
-
     service.start();
 
     db.assertDbUnit(getClass(), "remove_requirements_data_from_characteristics_result.xml", "characteristics");
   }
 
+  @Test
+  public void do_nothing_when_already_executed() throws Exception {
+    db.prepareDbUnit(getClass(), "do_nothing_when_already_executed.xml");
+
+    service.start();
+
+    db.assertDbUnit(getClass(), "do_nothing_when_already_executed_result.xml", "rules");
+  }
+
   @Test
   public void convert_duration() throws Exception {
     assertThat(CopyRequirementsFromCharacteristicsToRules.convertDuration(1.0, "h")).isEqualTo("1h");
index 9fe876218abeb10f0bf064fd5208f098263dcc7b..bc8c7c6d9253f5cb37b8910630fe437e7f77d91a 100644 (file)
@@ -73,4 +73,6 @@
          remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-03-13"
          NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
 
+  <loaded_templates id="1" kee="CopyRequirementsFromCharacteristicsToRules" template_type="ONE_SHOT_TASK"/>
+
 </dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed.xml b/sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed.xml
new file mode 100644 (file)
index 0000000..ec71824
--- /dev/null
@@ -0,0 +1,137 @@
+<dataset>
+
+  <!-- Loaded template already existing, nothing should be done -->
+  <loaded_templates id="1" kee="CopyRequirementsFromCharacteristicsToRules" template_type="ONE_SHOT_TASK"/>
+
+  <!-- Rule not linked to a requirement -> Nothing to do -->
+  <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="UselessImportCheck" plugin_name="squid" name="UselessImportCheck" description="Useless imports should be removed" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" 
+    cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to a disabled requirement -> Update rule to disable characteristic -->
+  <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="LeftCurlyBraceStartLineCheck" plugin_name="squid" name="LeftCurlyBraceStartLineCheck" description="Left curly braces should be located at the beginning of lines of code" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Removed rule linked to a disabled requirement -> Do nothing -->
+  <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="CallToFileDeleteOnExitMethod" plugin_name="squid" name="CallToFileDeleteOnExitMethod" description="CallToFileDeleteOnExitMethod" status="REMOVED"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement="[null]" with same value of debt -> Nothing to do -->
+  <rules tags="[null]" system_tags="[null]" id="4" plugin_rule_key="ObjectFinalizeOverridenCallsSuperFinalizeCheck" plugin_name="squid" name="ObjectFinalizeOverridenCallsSuperFinalizeCheck" description="super.finalize() should be called at the end of Object.finalize() implementations" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5min"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="5" plugin_rule_key="RightCurlyBraceStartLineCheck" plugin_name="squid" name="RightCurlyBraceStartLineCheck" description="Right curly braces should be located at the beginning of lines of code" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Constant per issue function (with a coefficient of 0d -> to be replaced by null)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="6" plugin_rule_key="HiddenFieldCheck" plugin_name="squid" name="HiddenFieldCheck" description="HiddenFieldCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear function (with a coefficient of 0min -> to be replaced by null)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="7" plugin_rule_key="ForLoopCounterChangedCheck" plugin_name="squid" name="ForLoopCounterChangedCheck" description="ForLoopCounterChangedCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear with offset function (with a offset of 0h -> should be replaced by 0d)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="8" plugin_rule_key="ClassVariableVisibilityCheck" plugin_name="squid" name="ClassVariableVisibilityCheck" description="ClassVariableVisibilityCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear function (with a coefficient of 0d -> should keep 0d)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="9" plugin_rule_key="SwitchLastCaseIsDefaultCheck" plugin_name="squid" name="SwitchLastCaseIsDefaultCheck" description="SwitchLastCaseIsDefaultCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- No requirement for rule 1 -->
+
+  <!-- Requirements of rule 2 -->
+  <characteristics id="1" parent_id="10" rule_id="2"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="2" parent_id="10" rule_id="2"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 3 -->
+  <characteristics id="3" parent_id="10" rule_id="3"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="4" parent_id="10" rule_id="3"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 4 -->
+  <characteristics id="5" parent_id="10" rule_id="4"
+                   function_key="linear_offset" factor_value="5.0" factor_unit="mn" offset_value="9.8" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="6" parent_id="10" rule_id="4"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 5 -->
+  <characteristics id="7" parent_id="10" rule_id="5"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="8" parent_id="10" rule_id="5"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 6 -->
+  <characteristics id="9" parent_id="10" rule_id="6"
+                   function_key="constant_issue" factor_value="0.0" factor_unit="d" offset_value="15.0" offset_unit="mn" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 7 -->
+  <characteristics id="10" parent_id="10" rule_id="7"
+                   function_key="linear" factor_value="0.0" factor_unit="mn" offset_value="0.0" offset_unit="min" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 8 -->
+  <characteristics id="11" parent_id="10" rule_id="8"
+                   function_key="linear_offset" factor_value="5.0" factor_unit="d" offset_value="0.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 9 -->
+  <characteristics id="12" parent_id="10" rule_id="9"
+                   function_key="linear" factor_value="0.0" factor_unit="d" offset_value="0.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+</dataset>
diff --git a/sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed_result.xml b/sonar-server/src/test/resources/org/sonar/server/startup/CopyRequirementsFromCharacteristicsToRulesTest/do_nothing_when_already_executed_result.xml
new file mode 100644 (file)
index 0000000..594b202
--- /dev/null
@@ -0,0 +1,134 @@
+<dataset>
+
+  <!-- Rule not linked to a requirement -> Nothing to do -->
+  <rules tags="[null]" system_tags="[null]" id="1" plugin_rule_key="UselessImportCheck" plugin_name="squid" name="UselessImportCheck" description="Useless imports should be removed" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" 
+    cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to a disabled requirement -> Update rule to disable characteristic -->
+  <rules tags="[null]" system_tags="[null]" id="2" plugin_rule_key="LeftCurlyBraceStartLineCheck" plugin_name="squid" name="LeftCurlyBraceStartLineCheck" description="Left curly braces should be located at the beginning of lines of code" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Removed rule linked to a disabled requirement -> Do nothing -->
+  <rules tags="[null]" system_tags="[null]" id="3" plugin_rule_key="CallToFileDeleteOnExitMethod" plugin_name="squid" name="CallToFileDeleteOnExitMethod" description="CallToFileDeleteOnExitMethod" status="REMOVED"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement="[null]" with same value of debt -> Nothing to do -->
+  <rules tags="[null]" system_tags="[null]" id="4" plugin_rule_key="ObjectFinalizeOverridenCallsSuperFinalizeCheck" plugin_name="squid" name="ObjectFinalizeOverridenCallsSuperFinalizeCheck" description="super.finalize() should be called at the end of Object.finalize() implementations" status="READY"
+         characteristic_id="[null]" default_characteristic_id="10"
+         remediation_function="[null]" default_remediation_function="LINEAR_OFFSET"
+         remediation_coeff="[null]" default_remediation_coeff="5min"
+         remediation_offset="[null]" default_remediation_offset="10h" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="5" plugin_rule_key="RightCurlyBraceStartLineCheck" plugin_name="squid" name="RightCurlyBraceStartLineCheck" description="Right curly braces should be located at the beginning of lines of code" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Constant per issue function (with a coefficient of 0d -> to be replaced by null)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="6" plugin_rule_key="HiddenFieldCheck" plugin_name="squid" name="HiddenFieldCheck" description="HiddenFieldCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear function (with a coefficient of 0min -> to be replaced by null)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="7" plugin_rule_key="ForLoopCounterChangedCheck" plugin_name="squid" name="ForLoopCounterChangedCheck" description="ForLoopCounterChangedCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear with offset function (with a offset of 0h -> should be replaced by 0d)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="8" plugin_rule_key="ClassVariableVisibilityCheck" plugin_name="squid" name="ClassVariableVisibilityCheck" description="ClassVariableVisibilityCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- Rule linked to one enable requirement on Linear function (with a coefficient of 0d -> should keep 0d)="[null]" with different value of debt -> Update rule -->
+  <rules tags="[null]" system_tags="[null]" id="9" plugin_rule_key="SwitchLastCaseIsDefaultCheck" plugin_name="squid" name="SwitchLastCaseIsDefaultCheck" description="SwitchLastCaseIsDefaultCheck" status="READY"
+         characteristic_id="[null]" default_characteristic_id="20"
+         remediation_function="[null]" default_remediation_function="LINEAR"
+         remediation_coeff="[null]" default_remediation_coeff="5d"
+         remediation_offset="[null]" default_remediation_offset="[null]" updated_at="2014-02-19"
+         NOTE_CREATED_AT="[null]" NOTE_DATA="[null]" NOTE_UPDATED_AT="[null]" NOTE_USER_LOGIN="[null]" PARENT_ID="[null]" PLUGIN_CONFIG_KEY="[null]" PRIORITY="[null]" cardinality="[null]" created_at="[null]" language="[null]" effort_to_fix_description="[null]"/>
+
+  <!-- No requirement for rule 1 -->
+
+  <!-- Requirements of rule 2 -->
+  <characteristics id="1" parent_id="10" rule_id="2"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="2" parent_id="10" rule_id="2"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 3 -->
+  <characteristics id="3" parent_id="10" rule_id="3"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="4" parent_id="10" rule_id="3"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 4 -->
+  <characteristics id="5" parent_id="10" rule_id="4"
+                   function_key="linear_offset" factor_value="5.0" factor_unit="mn" offset_value="9.8" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="6" parent_id="10" rule_id="4"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 5 -->
+  <characteristics id="7" parent_id="10" rule_id="5"
+                   function_key="linear_offset" factor_value="20.0" factor_unit="mn" offset_value="30.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <characteristics id="8" parent_id="10" rule_id="5"
+                   function_key="linear_offset" factor_value="30.0" factor_unit="mn" offset_value="20.0" offset_unit="h" enabled="[false]"
+                   created_at="2013-11-20" updated_at="2013-11-22" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 6 -->
+  <characteristics id="9" parent_id="10" rule_id="6"
+                   function_key="constant_issue" factor_value="0.0" factor_unit="d" offset_value="15.0" offset_unit="mn" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 7 -->
+  <characteristics id="10" parent_id="10" rule_id="7"
+                   function_key="linear" factor_value="0.0" factor_unit="mn" offset_value="0.0" offset_unit="min" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 8 -->
+  <characteristics id="11" parent_id="10" rule_id="8"
+                   function_key="linear_offset" factor_value="5.0" factor_unit="d" offset_value="0.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+  <!-- Requirements of rule 9 -->
+  <characteristics id="12" parent_id="10" rule_id="9"
+                   function_key="linear" factor_value="0.0" factor_unit="d" offset_value="0.0" offset_unit="h" enabled="[true]"
+                   created_at="2013-11-20" updated_at="[null]" ROOT_ID="[null]" KEE="[null]" name="[null]" characteristic_order="[null]"/>
+
+</dataset>