aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-03-01 10:41:59 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-03-02 14:19:36 +0100
commit325c7610b94af87a05860635831ecc4728478e29 (patch)
treea61f37a8a230617ab5f6fde80820e87d6cd14070 /sonar-db
parent284c6d1ee5deeeab127dc992c85731989c113a43 (diff)
downloadsonarqube-325c7610b94af87a05860635831ecc4728478e29.tar.gz
sonarqube-325c7610b94af87a05860635831ecc4728478e29.zip
SONAR-7329 Feed RULES.RULE_TYPE
Diffstat (limited to 'sonar-db')
-rw-r--r--sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java4
-rw-r--r--sonar-db/src/main/java/org/sonar/db/version/v55/FeedIssueTypes.java13
-rw-r--r--sonar-db/src/main/java/org/sonar/db/version/v55/FeedRulesTypes.java94
-rw-r--r--sonar-db/src/main/java/org/sonar/db/version/v55/TagsToType.java41
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql1
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DbTester.java24
-rw-r--r--sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java2
-rw-r--r--sonar-db/src/test/java/org/sonar/db/version/v55/FeedIssueTypesTest.java50
-rw-r--r--sonar-db/src/test/java/org/sonar/db/version/v55/FeedRulesTypesTest.java135
-rw-r--r--sonar-db/src/test/java/org/sonar/db/version/v55/TagsToTypeTest.java45
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/version/v55/FeedIssueTypesTest/schema.sql21
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate-result.xml87
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate.xml87
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/schema.sql9
14 files changed, 542 insertions, 71 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
index ceb4bed0ccc..550de251638 100644
--- a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
+++ b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
@@ -78,6 +78,7 @@ import org.sonar.db.version.v55.DropRulesDatesAndCharacteristics;
import org.sonar.db.version.v55.FeedActiveRulesLongDateColumns;
import org.sonar.db.version.v55.FeedIssueTypes;
import org.sonar.db.version.v55.FeedRulesLongDateColumns;
+import org.sonar.db.version.v55.FeedRulesTypes;
public class MigrationStepModule extends Module {
@Override
@@ -153,7 +154,8 @@ public class MigrationStepModule extends Module {
AddIssuesType.class,
FeedIssueTypes.class,
DropRulesDatesAndCharacteristics.class,
- DropActiveRulesDateColumns.class
+ DropActiveRulesDateColumns.class,
+ FeedRulesTypes.class
);
}
}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v55/FeedIssueTypes.java b/sonar-db/src/main/java/org/sonar/db/version/v55/FeedIssueTypes.java
index cffffb86af2..c9b4d873363 100644
--- a/sonar-db/src/main/java/org/sonar/db/version/v55/FeedIssueTypes.java
+++ b/sonar-db/src/main/java/org/sonar/db/version/v55/FeedIssueTypes.java
@@ -19,7 +19,6 @@
*/
package org.sonar.db.version.v55;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import java.sql.SQLException;
@@ -35,6 +34,7 @@ import org.sonar.db.version.SqlStatement;
import static com.google.common.collect.Lists.newArrayList;
import static org.apache.commons.lang.StringUtils.defaultString;
+import static org.sonar.db.version.v55.TagsToType.tagsToType;
/**
* Duplicates RuleTagsToTypeConverter from API on purpose. Db migration must be isolated and must not
@@ -87,15 +87,4 @@ public class FeedIssueTypes extends BaseDataChange {
}
}
- @VisibleForTesting
- static RuleType tagsToType(List<String> tags) {
- RuleType type = RuleType.CODE_SMELL;
- if (tags.contains("bug")) {
- type = RuleType.BUG;
- } else if (tags.contains("security")) {
- type = RuleType.VULNERABILITY;
- }
- return type;
- }
-
}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v55/FeedRulesTypes.java b/sonar-db/src/main/java/org/sonar/db/version/v55/FeedRulesTypes.java
new file mode 100644
index 00000000000..c0880995ed8
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/version/v55/FeedRulesTypes.java
@@ -0,0 +1,94 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v55;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Splitter;
+import java.sql.SQLException;
+import java.util.List;
+import org.sonar.api.utils.System2;
+import org.sonar.core.rule.RuleType;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+import org.sonar.db.version.MassUpdate.Handler;
+import org.sonar.db.version.Select.Row;
+import org.sonar.db.version.SqlStatement;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.apache.commons.lang.StringUtils.defaultString;
+import static org.sonar.db.version.v55.TagsToType.tagsToType;
+
+/**
+ * Duplicates RuleTagsToTypeConverter from API on purpose. Db migration must be isolated and must not
+ * depend on external code that may evolve over time.
+ *
+ * https://jira.sonarsource.com/browse/MMF-141
+ */
+public class FeedRulesTypes extends BaseDataChange {
+
+ private static final Splitter TAG_SPLITTER = Splitter.on(',');
+ private static final Joiner TAG_JOINER = Joiner.on(',').skipNulls();
+ private final System2 system;
+
+ public FeedRulesTypes(Database db, System2 system) {
+ super(db);
+ this.system = system;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate update = context.prepareMassUpdate().rowPluralName("rules");
+ update.select("SELECT id, system_tags, tags FROM rules WHERE rule_type IS NULL OR rule_type=0");
+ update.update("UPDATE rules SET rule_type=?, system_tags=?, tags=?, updated_at=? WHERE id=?");
+ update.execute(new MigrationHandler(system.now()));
+ }
+
+ private static final class MigrationHandler implements Handler {
+
+ private final long now;
+
+ private MigrationHandler(long now) {
+ this.now = now;
+ }
+
+ @Override
+ public boolean handle(Row row, SqlStatement update) throws SQLException {
+ long id = row.getLong(1);
+
+ // See algorithm to deduce type from tags in RuleTagsToTypeConverter
+ List<String> systemTags = newArrayList(TAG_SPLITTER.split(defaultString(row.getNullableString(2))));
+ List<String> userTags = newArrayList(TAG_SPLITTER.split(defaultString(row.getNullableString(3))));
+ RuleType type = tagsToType(systemTags);
+ systemTags.remove("bug");
+ systemTags.remove("security");
+ userTags.remove("bug");
+ userTags.remove("security");
+
+ update.setInt(1, type.getDbConstant());
+ update.setString(2, TAG_JOINER.join(systemTags));
+ update.setString(3, TAG_JOINER.join(userTags));
+ update.setLong(4, now);
+ update.setLong(5, id);
+ return true;
+ }
+ }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v55/TagsToType.java b/sonar-db/src/main/java/org/sonar/db/version/v55/TagsToType.java
new file mode 100644
index 00000000000..9cb63d4295f
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/version/v55/TagsToType.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v55;
+
+import java.util.List;
+import org.sonar.api.rules.RuleType;
+
+class TagsToType {
+
+ private TagsToType(){
+ // only static methods
+ }
+
+ static RuleType tagsToType(List<String> tags) {
+ RuleType type = RuleType.CODE_SMELL;
+ if (tags.contains("bug")) {
+ type = RuleType.BUG;
+ } else if (tags.contains("security")) {
+ type = RuleType.VULNERABILITY;
+ }
+ return type;
+ }
+
+}
diff --git a/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
index 9857b88f5f7..83d20947276 100644
--- a/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
+++ b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
@@ -389,6 +389,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1108');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1109');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1110');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1111');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1112');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1113');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
diff --git a/sonar-db/src/test/java/org/sonar/db/DbTester.java b/sonar-db/src/test/java/org/sonar/db/DbTester.java
index 9936840875c..64c10150619 100644
--- a/sonar-db/src/test/java/org/sonar/db/DbTester.java
+++ b/sonar-db/src/test/java/org/sonar/db/DbTester.java
@@ -19,6 +19,7 @@
*/
package org.sonar.db;
+import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import java.io.InputStream;
import java.math.BigDecimal;
@@ -62,9 +63,6 @@ import static org.junit.Assert.fail;
/**
* This class should be called using @Rule.
* Data is truncated between each tests. The schema is created between each test.
- * <p>
- * File using {@link DbTester} must be annotated with {@link org.sonar.test.DbTests} so
- * that they can be executed on all supported DBs (Oracle, MySQL, ...).
*/
public class DbTester extends ExternalResource {
@@ -135,8 +133,24 @@ public class DbTester extends ExternalResource {
try (Connection connection = db.getDatabase().getDataSource().getConnection()) {
new QueryRunner().update(connection, sql);
} catch (Exception e) {
- throw new IllegalStateException("Fail to execute sql: " + sql);
+ throw new IllegalStateException("Fail to execute sql: " + sql, e);
+ }
+ }
+
+ /**
+ * Very simple helper method to insert some data into a table.
+ * It's the responsibility of the caller to convert column values to string.
+ */
+ public void executeInsert(String table, Map<String, String> valuesByColumn){
+ if (valuesByColumn.isEmpty()) {
+ throw new IllegalArgumentException("Values cannot be empty");
}
+ String sql = "insert into " + table.toLowerCase() + " (" +
+ Joiner.on(", ").join(valuesByColumn.keySet()) +
+ ") values ('" +
+ Joiner.on("', '").join(valuesByColumn.values()) +
+ "')";
+ executeUpdateSql(sql);
}
/**
@@ -377,7 +391,7 @@ public class DbTester extends ExternalResource {
}
}
- private void closeQuietly(IDatabaseConnection connection) {
+ private void closeQuietly(@Nullable IDatabaseConnection connection) {
try {
if (connection != null) {
connection.close();
diff --git a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java b/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
index 8de7b00ca97..a4ed4bd9e31 100644
--- a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
@@ -29,6 +29,6 @@ public class MigrationStepModuleTest {
public void verify_count_of_added_MigrationStep_types() {
ComponentContainer container = new ComponentContainer();
new MigrationStepModule().configure(container);
- assertThat(container.size()).isEqualTo(60);
+ assertThat(container.size()).isEqualTo(61);
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v55/FeedIssueTypesTest.java b/sonar-db/src/test/java/org/sonar/db/version/v55/FeedIssueTypesTest.java
index 42ac6cbee1a..0998ab7f6cb 100644
--- a/sonar-db/src/test/java/org/sonar/db/version/v55/FeedIssueTypesTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/version/v55/FeedIssueTypesTest.java
@@ -19,60 +19,48 @@
*/
package org.sonar.db.version.v55;
-import java.util.Arrays;
-import java.util.Collections;
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.core.rule.RuleType;
-import org.sonar.db.DbSession;
import org.sonar.db.DbTester;
-import org.sonar.db.issue.IssueDto;
import org.sonar.db.version.MigrationStep;
-import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.sonar.db.version.v55.FeedIssueTypes.tagsToType;
public class FeedIssueTypesTest {
+ static final Joiner TAGS_JOINER = Joiner.on(",");
+
@Rule
public DbTester db = DbTester.createForSchema(System2.INSTANCE, FeedIssueTypesTest.class, "schema.sql");
@Test
- public void test_tagsToType() {
- assertThat(tagsToType(asList("misra", "bug"))).isEqualTo(RuleType.BUG);
- assertThat(tagsToType(asList("misra", "security"))).isEqualTo(RuleType.VULNERABILITY);
+ public void test_migration() throws Exception {
+ insertIssue("code_smell", "clumsy", "spring");
+ insertIssue("without_tags");
+ insertIssue("bug", "clumsy", "bug");
- // "bug" has priority on "security"
- assertThat(tagsToType(asList("security", "bug"))).isEqualTo(RuleType.BUG);
+ MigrationStep underTest = new FeedIssueTypes(db.database(), mock(System2.class));
+ underTest.execute();
- // default is "code smell"
- assertThat(tagsToType(asList("clumsy", "spring"))).isEqualTo(RuleType.CODE_SMELL);
- assertThat(tagsToType(Collections.<String>emptyList())).isEqualTo(RuleType.CODE_SMELL);
+ assertType("code_smell", RuleType.CODE_SMELL);
+ assertType("without_tags", RuleType.CODE_SMELL);
+ assertType("bug", RuleType.BUG);
}
- @Test
- public void test_migration() throws Exception {
- try (DbSession dbSession = db.getSession()) {
- IssueDto codeSmell = new IssueDto().setKee("code_smell").setTags(Arrays.asList("clumsy", "spring"));
- IssueDto withoutTags = new IssueDto().setKee("without_tags");
- IssueDto bug = new IssueDto().setKee("bug").setTags(Arrays.asList("clumsy", "bug"));
- db.getDbClient().issueDao().insert(dbSession, codeSmell, withoutTags, bug);
- dbSession.commit();
-
- MigrationStep underTest = new FeedIssueTypes(db.database(), mock(System2.class));
- underTest.execute();
-
- assertType("code_smell", RuleType.CODE_SMELL);
- assertType("without_tags", RuleType.CODE_SMELL);
- assertType("bug", RuleType.BUG);
- }
+ private void insertIssue(String key, String... tags) {
+ db.executeInsert("issues", ImmutableMap.of(
+ "kee", key,
+ "tags", TAGS_JOINER.join(tags)
+ ));
}
private void assertType(String issueKey, RuleType expectedType) {
- Number type = (Number)db.selectFirst("select * from issues where kee='" + issueKey + "'").get("ISSUE_TYPE");
+ Number type = (Number) db.selectFirst("select * from issues where kee='" + issueKey + "'").get("ISSUE_TYPE");
assertThat(type.intValue()).isEqualTo(expectedType.getDbConstant());
}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v55/FeedRulesTypesTest.java b/sonar-db/src/test/java/org/sonar/db/version/v55/FeedRulesTypesTest.java
new file mode 100644
index 00000000000..d24721e97f4
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/version/v55/FeedRulesTypesTest.java
@@ -0,0 +1,135 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v55;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.core.rule.RuleType;
+import org.sonar.db.DbTester;
+import org.sonar.db.version.MigrationStep;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class FeedRulesTypesTest {
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, FeedRulesTypesTest.class, "schema.sql");
+
+ static final Joiner TAGS_JOINER = Joiner.on(",");
+
+ System2 system2 = mock(System2.class);
+
+ static final long BEFORE = 1000L;
+ static final long NOW = 2000L;
+
+ MigrationStep underTest;
+
+ @Before
+ public void setUp() throws Exception {
+ when(system2.now()).thenReturn(NOW);
+ underTest = new FeedRulesTypes(db.database(), system2);
+ }
+
+ @Test
+ public void set_type_depending_on_system_tags() throws Exception {
+ insertRuleWithSystemTags("only_performance", "performance");
+ insertRuleWithSystemTags("no_tag");
+ insertRuleWithSystemTags("only_bug", "bug");
+ insertRuleWithSystemTags("security", "security", "test");
+ insertRuleWithSystemTags("bug_and_security", "security", "bug");
+ insertRuleWithType("type_already_exists", RuleType.BUG);
+
+ underTest.execute();
+
+ assertRule("only_performance", RuleType.CODE_SMELL, "performance", NOW);
+ assertRule("no_tag", RuleType.CODE_SMELL, "", NOW);
+ assertRule("only_bug", RuleType.BUG, "", NOW);
+ assertRule("security", RuleType.VULNERABILITY, "test", NOW);
+ assertRule("bug_and_security", RuleType.BUG, "", NOW);
+ assertRule("type_already_exists", RuleType.BUG, null, BEFORE);
+ }
+
+ @Test
+ public void remove_forbidden_user_tags() throws Exception {
+ insertRuleWithUserTags("only_performance", "performance");
+ insertRuleWithUserTags("no_tag");
+ insertRuleWithUserTags("only_bug", "bug");
+ insertRuleWithUserTags("security", "security", "test");
+ insertRuleWithUserTags("bug_and_security", "security", "bug");
+
+ underTest.execute();
+
+ assertRuleWithUserTags("only_performance", "performance", NOW);
+ assertRuleWithUserTags("no_tag", "", NOW);
+ assertRuleWithUserTags("only_bug", "", NOW);
+ assertRuleWithUserTags("security", "test", NOW);
+ assertRuleWithUserTags("bug_and_security", "", NOW);
+ }
+
+ private void assertRule(String ruleKey, RuleType expectedType, @Nullable String systemTags, long updatedAt) {
+ Map<String, Object> rule = db.selectFirst("select rule_type as \"ruleType\", system_tags as \"systemTags\", updated_at as \"updatedAt\" from rules where plugin_rule_key='"
+ + ruleKey + "'");
+ assertThat(((Number) rule.get("ruleType")).intValue()).isEqualTo(expectedType.getDbConstant());
+ assertThat(rule.get("systemTags")).isEqualTo(systemTags);
+ assertThat(rule.get("updatedAt")).isEqualTo(updatedAt);
+ }
+
+ private void assertRuleWithUserTags(String ruleKey, @Nullable String tags, long updatedAt) {
+ Map<String, Object> rule = db.selectFirst("select tags as \"tags\", updated_at as \"updatedAt\" from rules where plugin_rule_key='" + ruleKey + "'");
+ assertThat(rule.get("tags")).isEqualTo(tags);
+ assertThat(rule.get("updatedAt")).isEqualTo(updatedAt);
+ }
+
+ private void insertRuleWithSystemTags(String ruleKey, String... systemTags) {
+ db.executeInsert("rules", ImmutableMap.of(
+ "plugin_rule_key", ruleKey,
+ "system_tags", TAGS_JOINER.join(systemTags),
+ "created_at", Long.toString(BEFORE),
+ "updated_at", Long.toString(BEFORE)
+ ));
+ }
+
+ private void insertRuleWithUserTags(String ruleKey, String... userTags) {
+ db.executeInsert("rules", ImmutableMap.of(
+ "plugin_rule_key", ruleKey,
+ "tags", TAGS_JOINER.join(userTags),
+ "created_at", Long.toString(BEFORE),
+ "updated_at", Long.toString(BEFORE)
+ ));
+ }
+
+ private void insertRuleWithType(String ruleKey, RuleType type) {
+ db.executeInsert("rules", ImmutableMap.of(
+ "plugin_rule_key", ruleKey,
+ "rule_type", Integer.toString(type.getDbConstant()),
+ "created_at", Long.toString(BEFORE),
+ "updated_at", Long.toString(BEFORE)
+ ));
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v55/TagsToTypeTest.java b/sonar-db/src/test/java/org/sonar/db/version/v55/TagsToTypeTest.java
new file mode 100644
index 00000000000..a140543a595
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/version/v55/TagsToTypeTest.java
@@ -0,0 +1,45 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v55;
+
+import java.util.Collections;
+import org.junit.Test;
+import org.sonar.api.rules.RuleType;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.version.v55.TagsToType.tagsToType;
+
+public class TagsToTypeTest {
+
+ @Test
+ public void test_tagsToType() {
+ assertThat(tagsToType(asList("misra", "bug"))).isEqualTo(RuleType.BUG);
+ assertThat(tagsToType(asList("misra", "security"))).isEqualTo(RuleType.VULNERABILITY);
+
+ // "bug" has priority on "security"
+ assertThat(tagsToType(asList("security", "bug"))).isEqualTo(RuleType.BUG);
+
+ // default is "code smell"
+ assertThat(tagsToType(asList("clumsy", "spring"))).isEqualTo(RuleType.CODE_SMELL);
+ assertThat(tagsToType(Collections.<String>emptyList())).isEqualTo(RuleType.CODE_SMELL);
+ }
+
+}
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedIssueTypesTest/schema.sql b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedIssueTypesTest/schema.sql
index b7526a5d2bb..9289b3abf57 100644
--- a/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedIssueTypesTest/schema.sql
+++ b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedIssueTypesTest/schema.sql
@@ -1,29 +1,8 @@
CREATE TABLE "ISSUES" (
"ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
"KEE" VARCHAR(50) UNIQUE NOT NULL,
- "COMPONENT_UUID" VARCHAR(50),
- "PROJECT_UUID" VARCHAR(50),
- "RULE_ID" INTEGER,
- "SEVERITY" VARCHAR(10),
- "MANUAL_SEVERITY" BOOLEAN NOT NULL,
- "MESSAGE" VARCHAR(4000),
- "LINE" INTEGER,
- "EFFORT_TO_FIX" DOUBLE,
- "TECHNICAL_DEBT" INTEGER,
- "STATUS" VARCHAR(20),
- "RESOLUTION" VARCHAR(20),
- "CHECKSUM" VARCHAR(1000),
- "REPORTER" VARCHAR(255),
- "ASSIGNEE" VARCHAR(255),
- "AUTHOR_LOGIN" VARCHAR(255),
- "ACTION_PLAN_KEY" VARCHAR(50) NULL,
- "ISSUE_ATTRIBUTES" VARCHAR(4000),
"TAGS" VARCHAR(4000),
- "ISSUE_CREATION_DATE" BIGINT,
- "ISSUE_CLOSE_DATE" BIGINT,
- "ISSUE_UPDATE_DATE" BIGINT,
"CREATED_AT" BIGINT,
"UPDATED_AT" BIGINT,
- "LOCATIONS" BLOB(167772150),
"ISSUE_TYPE" TINYINT
);
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate-result.xml b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate-result.xml
new file mode 100644
index 00000000000..fd3675f51ca
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate-result.xml
@@ -0,0 +1,87 @@
+<dataset>
+
+ <!-- performance tag => type is CODE_SMELL (1) -->
+ <rules id="1" name="Null Pointer" plugin_rule_key="S001"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="performance" system_tags="cwe"
+ rule_type="1"
+ created_at="1000000000000" updated_at="2000000000000"
+ />
+
+ <!-- No tag => type is CODE_SMELL (1) -->
+ <rules id="2" name="Slow" plugin_rule_key="S002"
+ plugin_config_key="S2" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="BETA"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="[null]" system_tags="[null]"
+ rule_type="1"
+ created_at="1000000000000" updated_at="2000000000000"
+ />
+
+ <!-- bug tag => type is BUG (2) -->
+ <rules id="3" name="Rule3" plugin_rule_key="Rule3"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="" system_tags="cwe"
+ rule_type="[null]"
+ created_at="1000000000000" updated_at="2000000000000"
+ />
+
+ <!-- security tag => type is VULNERABILITY (3) -->
+ <rules id="4" name="Rule4" plugin_rule_key="Rule4"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="test" system_tags="cwe"
+ rule_type="3"
+ created_at="1000000000000" updated_at="2000000000000"
+ />
+
+ <!-- bug and security tags => type is CODE_SMELL (1) -->
+ <rules id="5" name="Rule5" plugin_rule_key="Rule5"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="bug" system_tags="cwe"
+ rule_type="1"
+ created_at="1000000000000" updated_at="2000000000000"
+ />
+
+ <!-- re-entrant migration - ignore the rules that are already fed with type -->
+ <rules id="10" name="Down" plugin_rule_key="S003"
+ plugin_config_key="S3" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="BETA"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="[null]" system_tags="[null]"
+ rule_type="1"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate.xml b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate.xml
new file mode 100644
index 00000000000..22c27deea0a
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/migrate.xml
@@ -0,0 +1,87 @@
+<dataset>
+
+ <!-- performance tag => type should be CODE_SMELL (1) -->
+ <rules id="1" name="Null Pointer" plugin_rule_key="S001"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="performance" system_tags="cwe"
+ rule_type="[null]"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+ <!-- No tag => type should be CODE_SMELL (1) -->
+ <rules id="2" name="Slow" plugin_rule_key="S002"
+ plugin_config_key="S2" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="BETA"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="[null]" system_tags="[null]"
+ rule_type="0"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+ <!-- bug tag => type should be BUG (2) -->
+ <rules id="3" name="Rule3" plugin_rule_key="Rule3"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="bug" system_tags="cwe"
+ rule_type="[null]"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+ <!-- security tag => type should be VULNERABILITY (3) -->
+ <rules id="4" name="Rule4" plugin_rule_key="Rule4"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="security,test" system_tags="cwe"
+ rule_type="[null]"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+ <!-- bug and security tags => type should be CODE_SMELL (1) -->
+ <rules id="5" name="Rule5" plugin_rule_key="Rule5"
+ plugin_config_key="S1" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="READY"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="security,bug" system_tags="cwe"
+ rule_type="[null]"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+ <!-- re-entrant migration - ignore the rules that are already fed with type -->
+ <rules id="10" name="Down" plugin_rule_key="S003"
+ plugin_config_key="S3" plugin_name="java" description="[null]" description_format="[null]" priority="4" status="BETA"
+ note_data="[null]" note_user_login="[null]" note_created_at="[null]" note_updated_at="[null]" language="java"
+ remediation_function="[null]" default_remediation_function="[null]"
+ remediation_coeff="[null]" default_remediation_coeff="[null]"
+ remediation_offset="[null]" default_remediation_offset="[null]"
+ effort_to_fix_description="[null]"
+ is_template="[false]" template_id="[null]"
+ tags="[null]" system_tags="[null]"
+ rule_type="1"
+ created_at="1000000000000" updated_at="1000000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/schema.sql b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/schema.sql
new file mode 100644
index 00000000000..838b2c25de4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/version/v55/FeedRulesTypesTest/schema.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "RULES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
+ "TAGS" VARCHAR(4000),
+ "SYSTEM_TAGS" VARCHAR(4000),
+ "RULE_TYPE" TINYINT,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
+);