From 4e1b01c0139c80bba0c8b1075010394fe4eeb3d4 Mon Sep 17 00:00:00 2001 From: Duarte Meneses Date: Thu, 25 Jan 2018 16:43:00 +0100 Subject: [PATCH] SONAR-10321 Store rule scope in DB --- .../org/sonar/db/version/schema-h2.ddl | 1 + .../org/sonar/db/rule/RuleDefinitionDto.java | 12 +++ .../main/java/org/sonar/db/rule/RuleDto.java | 15 +++- .../org/sonar/db/rule/RuleMapper.xml | 4 + .../java/org/sonar/db/rule/RuleDaoTest.java | 8 +- .../db/rule/RuleDaoTest/insert_parameter.xml | 1 + .../db/rule/RuleDaoTest/selectEnabled.xml | 2 + .../db/rule/RuleDaoTest/selectNonManual.xml | 2 + .../select_parameters_by_rule_key.xml | 2 + .../org/sonar/db/rule/RuleDaoTest/shared.xml | 3 + .../org/sonar/db/rule/RuleDaoTest/update.xml | 1 + .../RuleDaoTest/update_parameter-result.xml | 1 + .../db/rule/RuleDaoTest/update_parameter.xml | 1 + .../migration/version/v71/AddRuleScope.java | 26 ++++++ .../db/migration/version/v71/DbVersion71.java | 5 +- .../v71/MakeScopeNotNullableInRules.java | 46 ++++++++++ .../version/v71/SetRuleScopeToMain.java | 31 +++++++ .../version/v71/AddRuleScopeTest.java | 35 ++++++++ .../version/v71/DbVersion71Test.java | 2 +- .../v71/MakeScopeNotNullableInRulesTest.java | 56 ++++++++++++ .../version/v71/SetRuleScopeToMainTest.java | 88 +++++++++++++++++++ .../version/v71/AddRuleScopeTest/rules.sql | 24 +++++ .../MakeScopeNotNullableInRulesTest/rules.sql | 25 ++++++ .../v71/SetRuleScopeToMainTest/rules.sql | 25 ++++++ .../org/sonar/server/rule/RegisterRules.java | 19 ++++ .../qualityprofile/ws/CompareActionTest.java | 2 + .../server/rule/DefaultRuleFinderTest.java | 5 ++ .../sonar/server/rule/RegisterRulesTest.java | 4 + .../server/rule/index/RuleIndexerTest.java | 2 + .../extract_directory_path.xml | 3 +- .../extract_file_path.xml | 3 +- .../many_projects.xml | 3 +- .../IssueIteratorFactoryTest/one_issue.xml | 3 +- .../index/IssueIteratorFactoryTest/shared.xml | 3 +- .../platform/BackendCleanupTest/shared.xml | 1 + 35 files changed, 455 insertions(+), 9 deletions(-) create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScope.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRules.java create mode 100644 server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMain.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest.java create mode 100644 server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest.java create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest/rules.sql create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest/rules.sql create mode 100644 server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest/rules.sql diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl index 05d3d7872bb..175424d028c 100644 --- a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -186,6 +186,7 @@ CREATE TABLE "RULES" ( "NAME" VARCHAR(200), "STATUS" VARCHAR(40), "LANGUAGE" VARCHAR(20), + "SCOPE" VARCHAR(20) NOT NULL, "DEF_REMEDIATION_FUNCTION" VARCHAR(20), "DEF_REMEDIATION_GAP_MULT" VARCHAR(20), "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java index cdd0b07a7af..0321e74d430 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java @@ -31,6 +31,7 @@ import org.apache.commons.lang.builder.HashCodeBuilder; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.RuleStatus; import org.sonar.api.rules.RuleType; +import org.sonar.db.rule.RuleDto.Scope; import static com.google.common.base.Preconditions.checkArgument; @@ -54,6 +55,7 @@ public class RuleDefinitionDto { private String gapDescription; private String systemTags; private int type; + private Scope scope; private RuleKey key; @@ -295,6 +297,15 @@ public class RuleDefinitionDto { return this; } + public Scope getScope() { + return this.scope; + } + + public RuleDefinitionDto setScope(Scope scope) { + this.scope = scope; + return this; + } + @CheckForNull public String getPluginKey() { return pluginKey; @@ -358,6 +369,7 @@ public class RuleDefinitionDto { ", key=" + key + ", createdAt=" + createdAt + ", updatedAt=" + updatedAt + + ", scope=" + scope + '}'; } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java index 46b36b523aa..86afcb2bed1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java @@ -33,6 +33,10 @@ public class RuleDto { public enum Format { HTML, MARKDOWN } + + public enum Scope { + MAIN, TEST, ALL; + } private final RuleDefinitionDto definition; private final RuleMetadataDto metadata; @@ -138,11 +142,20 @@ public class RuleDto { public String getConfigKey() { return definition.getConfigKey(); } - + public RuleDto setConfigKey(@Nullable String configKey) { definition.setConfigKey(configKey); return this; } + + public Scope getScope() { + return definition.getScope(); + } + + public RuleDto setScope(Scope scope) { + definition.setScope(scope); + return this; + } @CheckForNull public Integer getSeverity() { diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml index d1a161504b4..6cfde04506c 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -23,6 +23,7 @@ r.system_tags as "systemTagsField", r.rule_type as "type", r.plugin_key as "pluginKey", + r.scope, @@ -301,6 +302,7 @@ gap_description, system_tags, rule_type, + scope, created_at, updated_at ) @@ -323,6 +325,7 @@ #{gapDescription,jdbcType=VARCHAR}, #{systemTagsField,jdbcType=VARCHAR}, #{type,jdbcType=TINYINT}, + #{scope,jdbcType=VARCHAR}, #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT} ) @@ -347,6 +350,7 @@ def_remediation_base_effort=#{defRemediationBaseEffort,jdbcType=VARCHAR}, gap_description=#{gapDescription,jdbcType=VARCHAR}, system_tags=#{systemTagsField,jdbcType=VARCHAR}, + scope=#{scope,jdbcType=VARCHAR}, rule_type=#{type,jdbcType=TINYINT}, updated_at=#{updatedAt,jdbcType=BIGINT} where diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java index c96f3c36e1b..0cd2d997ee9 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java @@ -44,6 +44,7 @@ import org.sonar.db.RowNotFoundException; import org.sonar.db.es.RuleExtensionId; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.organization.OrganizationTesting; +import org.sonar.db.rule.RuleDto.Scope; import static com.google.common.collect.Sets.newHashSet; import static java.util.Arrays.asList; @@ -329,6 +330,7 @@ public class RuleDaoTest { .setGapDescription("squid.S115.effortToFix") .setSystemTags(newHashSet("systag1", "systag2")) .setType(RuleType.BUG) + .setScope(Scope.ALL) .setCreatedAt(1_500_000_000_000L) .setUpdatedAt(2_000_000_000_000L); underTest.insert(db.getSession(), newRule); @@ -352,6 +354,7 @@ public class RuleDaoTest { assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo("10h"); assertThat(ruleDto.getGapDescription()).isEqualTo("squid.S115.effortToFix"); assertThat(ruleDto.getSystemTags()).containsOnly("systag1", "systag2"); + assertThat(ruleDto.getScope()).isEqualTo(Scope.ALL); assertThat(ruleDto.getType()).isEqualTo(RuleType.BUG.getDbConstant()); assertThat(ruleDto.getCreatedAt()).isEqualTo(1_500_000_000_000L); assertThat(ruleDto.getUpdatedAt()).isEqualTo(2_000_000_000_000L); @@ -379,6 +382,7 @@ public class RuleDaoTest { .setDefRemediationBaseEffort("10h") .setGapDescription("squid.S115.effortToFix") .setSystemTags(newHashSet("systag1", "systag2")) + .setScope(Scope.ALL) .setType(RuleType.BUG) .setUpdatedAt(2_000_000_000_000L); @@ -402,6 +406,7 @@ public class RuleDaoTest { assertThat(ruleDto.getDefRemediationBaseEffort()).isEqualTo("10h"); assertThat(ruleDto.getGapDescription()).isEqualTo("squid.S115.effortToFix"); assertThat(ruleDto.getSystemTags()).containsOnly("systag1", "systag2"); + assertThat(ruleDto.getScope()).isEqualTo(Scope.ALL); assertThat(ruleDto.getType()).isEqualTo(RuleType.BUG.getDbConstant()); assertThat(ruleDto.getCreatedAt()).isEqualTo(1_500_000_000_000L); assertThat(ruleDto.getUpdatedAt()).isEqualTo(2_000_000_000_000L); @@ -783,8 +788,9 @@ public class RuleDaoTest { tuple(r1.getKey(), organization.getUuid(), r1Extension.getTagsAsString())); } - private static class Accumulator implements Consumer { + private static class Accumulator implements Consumer { private final List list = new ArrayList<>(); + @Override public void accept(T dto) { list.add(dto); diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml index bf6dd1ccf8e..8c39a2d111c 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/insert_parameter.xml @@ -15,6 +15,7 @@ def_remediation_gap_mult="5d" def_remediation_base_effort="10h" gap_description="squid.S115.effortToFix" + scope="MAIN" created_at="[null]" updated_at="[null]" /> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml index 66427866042..593a6a4a042 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectEnabled.xml @@ -12,6 +12,7 @@ def_remediation_gap_mult="5d" def_remediation_base_effort="10h" gap_description="squid.S115.effortToFix" + scope="MAIN" created_at="1500000000000" updated_at="1600000000000" /> @@ -27,6 +28,7 @@ def_remediation_function="[null]" def_remediation_gap_mult="[null]" def_remediation_base_effort="[null]" + scope="MAIN" gap_description="[null]" created_at="1500000000000" updated_at="1600000000000" diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml index 3d49bf1ac0a..faebb444a42 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/selectNonManual.xml @@ -8,6 +8,7 @@ description="Should avoid NULL" status="READY" description_format="HTML" + scope="MAIN" created_at="1500000000000" updated_at="1600000000000"/> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml index f96c1359147..49b9773832a 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/select_parameters_by_rule_key.xml @@ -7,6 +7,7 @@ name="Avoid Null" description="Should avoid NULL" status="READY" + scope="MAIN" created_at="1500000000000" updated_at="1600000000000"/> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml index eed68c92290..b0050d14b7f 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml @@ -10,6 +10,7 @@ plugin_config_key="AvoidNull" priority="2" is_template="[false]" + scope="MAIN" language="golo" created_at="1500000000000" updated_at="1600000000000"/> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml index 6f7b4c7f679..bb3801df484 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter-result.xml @@ -6,6 +6,7 @@ name="Avoid Null" description="Should avoid NULL" status="READY" + scope="MAIN" created_at="1500000000000" updated_at="1600000000000"/> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml index 26bc299306c..484f86c62c5 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update_parameter.xml @@ -6,6 +6,7 @@ name="Avoid Null" description="Should avoid NULL" status="READY" + scope="MAIN" created_at="1500000000000" updated_at="1600000000000"/> diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScope.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScope.java new file mode 100644 index 00000000000..8bb0fc15d4a --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScope.java @@ -0,0 +1,26 @@ +package org.sonar.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.def.VarcharColumnDef; +import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +public class AddRuleScope extends DdlChange { + + public AddRuleScope(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AddColumnsBuilder(getDialect(), "rules") + .addColumn(VarcharColumnDef.newVarcharColumnDefBuilder() + .setColumnName("scope") + .setIsNullable(true) + .setLimit(20) + .build()) + .build()); + } + +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java index 2705f099de4..bb67a4d88ed 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71.java @@ -27,6 +27,9 @@ public class DbVersion71 implements DbVersion { @Override public void addSteps(MigrationStepRegistry registry) { registry - .add(2000, "Delete settings defined in sonar.properties from PROPERTIES table", DeleteSettingsDefinedInSonarDotProperties.class); + .add(2000, "Delete settings defined in sonar.properties from PROPERTIES table", DeleteSettingsDefinedInSonarDotProperties.class) + .add(2001, "Add scope to rules", AddRuleScope.class) + .add(2002, "Set rules scope to MAIN", SetRuleScopeToMain.class) + .add(2003, "Make scope not nullable in rules", MakeScopeNotNullableInRules.class); } } diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRules.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRules.java new file mode 100644 index 00000000000..9bd077747e0 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRules.java @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder; +import org.sonar.server.platform.db.migration.step.DdlChange; + +import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; + +public class MakeScopeNotNullableInRules extends DdlChange { + private static final String TABLE_NAME = "rules"; + + public MakeScopeNotNullableInRules(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AlterColumnsBuilder(getDialect(), TABLE_NAME) + .updateColumn(newVarcharColumnDefBuilder() + .setColumnName("scope") + .setLimit(20) + .setIsNullable(false) + .build()) + .build()); + } +} diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMain.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMain.java new file mode 100644 index 00000000000..b2fb71e1b62 --- /dev/null +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMain.java @@ -0,0 +1,31 @@ +package org.sonar.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.sonar.api.rule.RuleScope; +import org.sonar.api.utils.System2; +import org.sonar.db.Database; +import org.sonar.server.platform.db.migration.step.DataChange; +import org.sonar.server.platform.db.migration.step.MassUpdate; + +public class SetRuleScopeToMain extends DataChange { + private final System2 system2; + + public SetRuleScopeToMain(Database db, System2 system2) { + super(db); + this.system2 = system2; + } + + @Override + protected void execute(Context context) throws SQLException { + long now = system2.now(); + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select("select id from rules where scope is NULL"); + massUpdate.rowPluralName("rules"); + massUpdate.update("update rules set scope=?, updated_at=? where scope is NULL"); + massUpdate.execute((row, update) -> { + update.setString(1, RuleScope.MAIN.name()); + update.setLong(2, now); + return true; + }); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest.java new file mode 100644 index 00000000000..30856ed1819 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest.java @@ -0,0 +1,35 @@ +package org.sonar.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.CoreDbTester; + +import static java.sql.Types.VARCHAR; + +public class AddRuleScopeTest { + @Rule + public final CoreDbTester dbTester = CoreDbTester.createForSchema(AddRuleScopeTest.class, "rules.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private AddRuleScope underTest = new AddRuleScope(dbTester.database()); + + @Test + public void column_is_added_to_table() throws SQLException { + underTest.execute(); + + dbTester.assertColumnDefinition("rules", "scope", VARCHAR, null, true); + } + + @Test + public void migration_is_not_reentrant() throws SQLException { + underTest.execute(); + + expectedException.expect(IllegalStateException.class); + + underTest.execute(); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java index 47b980bb2fa..c65e93d43a8 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/DbVersion71Test.java @@ -36,7 +36,7 @@ public class DbVersion71Test { @Test public void verify_migration_count() { - verifyMigrationCount(underTest, 1); + verifyMigrationCount(underTest, 4); } } diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest.java new file mode 100644 index 00000000000..192abdcc2b1 --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info 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.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import java.sql.Types; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.rule.RuleScope; +import org.sonar.db.CoreDbTester; + +public class MakeScopeNotNullableInRulesTest { + @Rule + public CoreDbTester db = CoreDbTester.createForSchema(MakeScopeNotNullableInRulesTest.class, "rules.sql"); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private MakeScopeNotNullableInRules underTest = new MakeScopeNotNullableInRules(db.database()); + + @Test + public void execute_makes_column_not_null() throws SQLException { + db.assertColumnDefinition("rules", "scope", Types.VARCHAR, null, true); + insertRow(1); + insertRow(2); + + underTest.execute(); + + db.assertColumnDefinition("rules", "scope", Types.VARCHAR, null, false); + } + + private void insertRow(int id) { + db.executeInsert( + "RULES", + "PLUGIN_RULE_KEY", "key_" + id, + "PLUGIN_NAME", "name_" + id, + "SCOPE", RuleScope.MAIN.name()); + } +} diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest.java new file mode 100644 index 00000000000..0a8c8b1398c --- /dev/null +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest.java @@ -0,0 +1,88 @@ +package org.sonar.server.platform.db.migration.version.v71; + +import java.sql.SQLException; +import javax.annotation.Nullable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.rule.RuleScope; +import org.sonar.api.utils.System2; +import org.sonar.db.CoreDbTester; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SetRuleScopeToMainTest { + @Rule + public final CoreDbTester dbTester = CoreDbTester.createForSchema(SetRuleScopeToMainTest.class, "rules.sql"); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private System2 system = new System2(); + + private SetRuleScopeToMain underTest = new SetRuleScopeToMain(dbTester.database(), system); + + @Test + public void has_no_effect_if_table_rules_is_empty() throws SQLException { + underTest.execute(); + + assertThat(dbTester.countRowsOfTable("rules")).isEqualTo(0); + } + + @Test + public void updates_rows_with_null_is_build_in_column_to_false() throws SQLException { + insertRow(1, null); + insertRow(2, null); + + assertThat(countRowsWithValue(null)).isEqualTo(2); + assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(0); + + underTest.execute(); + + assertThat(countRowsWithValue(null)).isEqualTo(0); + assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2); + } + + @Test + public void support_large_number_of_rows() throws SQLException { + for (int i = 0; i < 2_000; i++) { + insertRow(i, null); + } + + assertThat(countRowsWithValue(null)).isEqualTo(2000); + assertThat(countRowsWithValue(RuleScope.MAIN)).isZero(); + + underTest.execute(); + + assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2_000); + assertThat(countRowsWithValue(null)).isEqualTo(0); + } + + @Test + public void execute_is_reentreant() throws SQLException { + insertRow(1, null); + insertRow(2, RuleScope.MAIN); + + underTest.execute(); + + underTest.execute(); + + assertThat(countRowsWithValue(null)).isEqualTo(0); + assertThat(countRowsWithValue(RuleScope.MAIN)).isEqualTo(2); + } + + private int countRowsWithValue(@Nullable RuleScope value) { + if (value == null) { + return dbTester.countSql("select count(1) from rules where scope is null"); + } + return dbTester.countSql("select count(1) from rules where scope='" + value + "'"); + } + + private void insertRow(int id, @Nullable RuleScope scope) { + dbTester.executeInsert( + "RULES", + "PLUGIN_RULE_KEY", "key_" + id, + "PLUGIN_NAME", "name_" + id, + "SCOPE", scope == null ? null : scope.name()); + } +} diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest/rules.sql new file mode 100644 index 00000000000..7bc032ceb37 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/AddRuleScopeTest/rules.sql @@ -0,0 +1,24 @@ +CREATE TABLE "RULES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PLUGIN_KEY" VARCHAR(200), + "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, + "PLUGIN_NAME" VARCHAR(255) NOT NULL, + "DESCRIPTION" VARCHAR(16777215), + "DESCRIPTION_FORMAT" VARCHAR(20), + "PRIORITY" INTEGER, + "IS_TEMPLATE" BOOLEAN DEFAULT FALSE, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "NAME" VARCHAR(200), + "STATUS" VARCHAR(40), + "LANGUAGE" VARCHAR(20), + "DEF_REMEDIATION_FUNCTION" VARCHAR(20), + "DEF_REMEDIATION_GAP_MULT" VARCHAR(20), + "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest/rules.sql new file mode 100644 index 00000000000..1708db814f4 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/MakeScopeNotNullableInRulesTest/rules.sql @@ -0,0 +1,25 @@ +CREATE TABLE "RULES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PLUGIN_KEY" VARCHAR(200), + "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, + "PLUGIN_NAME" VARCHAR(255) NOT NULL, + "DESCRIPTION" VARCHAR(16777215), + "DESCRIPTION_FORMAT" VARCHAR(20), + "PRIORITY" INTEGER, + "IS_TEMPLATE" BOOLEAN DEFAULT FALSE, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "NAME" VARCHAR(200), + "STATUS" VARCHAR(40), + "LANGUAGE" VARCHAR(20), + "SCOPE" VARCHAR(20), + "DEF_REMEDIATION_FUNCTION" VARCHAR(20), + "DEF_REMEDIATION_GAP_MULT" VARCHAR(20), + "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); diff --git a/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest/rules.sql b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest/rules.sql new file mode 100644 index 00000000000..1708db814f4 --- /dev/null +++ b/server/sonar-db-migration/src/test/resources/org/sonar/server/platform/db/migration/version/v71/SetRuleScopeToMainTest/rules.sql @@ -0,0 +1,25 @@ +CREATE TABLE "RULES" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), + "PLUGIN_KEY" VARCHAR(200), + "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL, + "PLUGIN_NAME" VARCHAR(255) NOT NULL, + "DESCRIPTION" VARCHAR(16777215), + "DESCRIPTION_FORMAT" VARCHAR(20), + "PRIORITY" INTEGER, + "IS_TEMPLATE" BOOLEAN DEFAULT FALSE, + "TEMPLATE_ID" INTEGER, + "PLUGIN_CONFIG_KEY" VARCHAR(200), + "NAME" VARCHAR(200), + "STATUS" VARCHAR(40), + "LANGUAGE" VARCHAR(20), + "SCOPE" VARCHAR(20), + "DEF_REMEDIATION_FUNCTION" VARCHAR(20), + "DEF_REMEDIATION_GAP_MULT" VARCHAR(20), + "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20), + "GAP_DESCRIPTION" VARCHAR(4000), + "SYSTEM_TAGS" VARCHAR(4000), + "RULE_TYPE" TINYINT, + "CREATED_AT" BIGINT, + "UPDATED_AT" BIGINT +); +CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY"); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java index dcea28c7cb1..b41ec39163b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RegisterRules.java @@ -50,6 +50,7 @@ import org.sonar.db.qualityprofile.ActiveRuleDto; import org.sonar.db.qualityprofile.ActiveRuleParamDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto.Format; +import org.sonar.db.rule.RuleDto.Scope; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleRepositoryDto; import org.sonar.server.organization.OrganizationFlags; @@ -226,6 +227,7 @@ public class RegisterRules implements Startable { .setGapDescription(ruleDef.gapDescription()) .setSystemTags(ruleDef.tags()) .setType(RuleType.valueOf(ruleDef.type().name())) + .setScope(toDtoScope(ruleDef.scope())) .setCreatedAt(system2.now()) .setUpdatedAt(system2.now()); if (ruleDef.htmlDescription() != null) { @@ -240,6 +242,19 @@ public class RegisterRules implements Startable { return ruleDto; } + private static Scope toDtoScope(RulesDefinition.Scope scope) { + switch (scope) { + case ALL: + return Scope.ALL; + case MAIN: + return Scope.MAIN; + case TEST: + return Scope.TEST; + default: + throw new IllegalArgumentException("Unknown rule scope: " + scope); + } + } + private boolean mergeRule(RulesDefinition.Rule def, RuleDefinitionDto dto) { boolean changed = false; if (!StringUtils.equals(dto.getName(), def.name())) { @@ -271,6 +286,10 @@ public class RegisterRules implements Startable { dto.setStatus(def.status()); changed = true; } + if (!StringUtils.equals(dto.getScope().name(), def.scope().name())) { + dto.setScope(toDtoScope(def.scope())); + changed = true; + } if (!StringUtils.equals(dto.getLanguage(), def.repository().language())) { dto.setLanguage(def.repository().language()); changed = true; diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionTest.java index f6fcf657708..9027791549f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/CompareActionTest.java @@ -40,6 +40,7 @@ import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleRepositoryDto; +import org.sonar.db.rule.RuleDto.Scope; import org.sonar.server.language.LanguageTesting; import org.sonar.server.qualityprofile.QProfileComparison; import org.sonar.server.qualityprofile.QProfileName; @@ -203,6 +204,7 @@ public class CompareActionTest { .setName(StringUtils.capitalize(id)) .setLanguage(lang) .setSeverity(Severity.BLOCKER) + .setScope(Scope.MAIN) .setStatus(RuleStatus.READY); RuleDefinitionDto ruleDefinition = rule.getDefinition(); db.ruleDao().insert(session, ruleDefinition); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java index 6519fbc74c5..3727eea253e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/DefaultRuleFinderTest.java @@ -29,6 +29,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleDto.Scope; import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.organization.TestDefaultOrganizationProvider; @@ -49,6 +50,7 @@ public class DefaultRuleFinderTest { .setRuleKey("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck") .setRepositoryKey("checkstyle") .setSeverity(4) + .setScope(Scope.MAIN) .setStatus(RuleStatus.READY); private RuleDto rule2 = new RuleDto() @@ -57,6 +59,7 @@ public class DefaultRuleFinderTest { .setRuleKey("DisabledCheck") .setRepositoryKey("checkstyle") .setSeverity(4) + .setScope(Scope.MAIN) .setStatus(RuleStatus.REMOVED); private RuleDto rule3 = new RuleDto() @@ -65,6 +68,7 @@ public class DefaultRuleFinderTest { .setRuleKey("com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck") .setRepositoryKey("checkstyle") .setSeverity(4) + .setScope(Scope.MAIN) .setStatus(RuleStatus.READY); private RuleDto rule4 = new RuleDto() @@ -73,6 +77,7 @@ public class DefaultRuleFinderTest { .setRuleKey("CallSuperFirst") .setRepositoryKey("pmd") .setSeverity(2) + .setScope(Scope.MAIN) .setStatus(RuleStatus.READY); private DefaultRuleFinder underTest = new DefaultRuleFinder(dbClient, defaultOrganizationProvider); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java index fe64919612f..ba26b7075eb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RegisterRulesTest.java @@ -42,6 +42,7 @@ import org.sonar.db.DbTester; import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; +import org.sonar.db.rule.RuleDto.Scope; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleRepositoryDto; import org.sonar.server.es.EsTester; @@ -121,6 +122,7 @@ public class RegisterRulesTest { assertThat(rule1.getConfigKey()).isEqualTo("config1"); assertThat(rule1.getStatus()).isEqualTo(RuleStatus.BETA); assertThat(rule1.getCreatedAt()).isEqualTo(DATE1.getTime()); + assertThat(rule1.getScope()).isEqualTo(Scope.ALL); assertThat(rule1.getUpdatedAt()).isEqualTo(DATE1.getTime()); assertThat(rule1.getDefRemediationFunction()).isEqualTo(DebtRemediationFunction.Type.LINEAR_OFFSET.name()); assertThat(rule1.getDefRemediationGapMultiplier()).isEqualTo("5d"); @@ -494,6 +496,7 @@ public class RegisterRulesTest { .setRuleKey("rule1") .setRepositoryKey("findbugs") .setName("Rule One") + .setScope(Scope.ALL) .setDescription("Rule one description") .setDescriptionFormat(RuleDto.Format.HTML) .setSystemTags(newHashSet("tag1", "tag2"))); @@ -562,6 +565,7 @@ public class RegisterRulesTest { .setSeverity(BLOCKER) .setInternalKey("config1") .setTags("tag1", "tag2", "tag3") + .setScope(Scope.ALL) .setType(RuleType.CODE_SMELL) .setStatus(RuleStatus.BETA) .setGapDescription("squid.S115.effortToFix"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java index ac26dc44b5b..8c791c43a52 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/index/RuleIndexerTest.java @@ -36,6 +36,7 @@ import org.sonar.db.organization.OrganizationDto; import org.sonar.db.rule.RuleDefinitionDto; import org.sonar.db.rule.RuleDto; import org.sonar.db.rule.RuleTesting; +import org.sonar.db.rule.RuleDto.Scope; import org.sonar.server.es.EsTester; import static com.google.common.collect.Sets.newHashSet; @@ -66,6 +67,7 @@ public class RuleIndexerTest { .setIsTemplate(true) .setSystemTags(newHashSet("cwe")) .setType(RuleType.BUG) + .setScope(Scope.ALL) .setCreatedAt(1500000000000L) .setUpdatedAt(1600000000000L); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml index d914cc3a776..5af7683e247 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/index/IssueIteratorFactoryTest/extract_directory_path.xml @@ -4,7 +4,8 @@ name="Avoid Cycles" plugin_rule_key="AvoidCycles" plugin_config_key="[null]" - plugin_name="squid"/> + plugin_name="squid" + scope="MAIN"/> + plugin_name="squid" + scope="MAIN"/> + plugin_name="squid" + scope="MAIN"/> + plugin_name="squid" + scope="MAIN"/> + plugin_name="squid" + scope="MAIN"/>